From 72823ea8239cb1a421085f09ba8746c4805c1794 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 15 Sep 2023 16:14:47 +0200 Subject: [PATCH 001/235] remove uneeded folders --- .../ExtensionTypeCustomDeserializers$1.class | Bin 1089 -> 0 bytes ...ExtensionTypeCustomDeserializers$Deser.class | Bin 385 -> 0 bytes .../ExtensionTypeCustomDeserializers.class | Bin 1640 -> 0 bytes .../jackson/dataformat/JsonArrayFormat.class | Bin 1368 -> 0 bytes .../MessagePackExtensionType$Serializer.class | Bin 1674 -> 0 bytes .../dataformat/MessagePackExtensionType.class | Bin 1085 -> 0 bytes .../jackson/dataformat/MessagePackFactory.class | Bin 4943 -> 0 bytes .../dataformat/MessagePackGenerator$1.class | Bin 270 -> 0 bytes .../MessagePackGenerator$StackItem.class | Bin 1058 -> 0 bytes ...MessagePackGenerator$StackItemForArray.class | Bin 947 -> 0 bytes ...essagePackGenerator$StackItemForObject.class | Bin 944 -> 0 bytes .../dataformat/MessagePackGenerator.class | Bin 13435 -> 0 bytes .../dataformat/MessagePackKeySerializer.class | Bin 951 -> 0 bytes .../dataformat/MessagePackParser$1.class | Bin 1909 -> 0 bytes .../MessagePackParser$StackItem.class | Bin 563 -> 0 bytes .../MessagePackParser$StackItemForArray.class | Bin 430 -> 0 bytes .../MessagePackParser$StackItemForObject.class | Bin 432 -> 0 bytes .../dataformat/MessagePackParser$Type.class | Bin 1381 -> 0 bytes .../jackson/dataformat/MessagePackParser.class | Bin 15280 -> 0 bytes .../MessagePackSerializedString.class | Bin 1950 -> 0 bytes .../MessagePackSerializerFactory.class | Bin 1003 -> 0 bytes .../org/msgpack/jackson/dataformat/Tuple.class | Bin 625 -> 0 bytes 22 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers$1.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers$Deser.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/JsonArrayFormat.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackExtensionType$Serializer.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackExtensionType.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackFactory.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$1.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$StackItem.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$StackItemForArray.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$StackItemForObject.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackKeySerializer.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$1.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$StackItem.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$StackItemForArray.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$StackItemForObject.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$Type.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackSerializedString.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/MessagePackSerializerFactory.class delete mode 100644 src/main/resources/org/msgpack/jackson/dataformat/Tuple.class diff --git a/src/main/resources/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers$1.class b/src/main/resources/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers$1.class deleted file mode 100644 index 777df584fba0979bf4508fcae8991966137a3778..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1089 zcmb`H-A)rh6vzLwEnVBLZ2?8`6QMv`h^z5Zqmfz-vBCv}8?UCjLz%jrX?CUreFa}e z6N%9aAHat)o>_^J!UA`BWaos7@p@vI@lAbq z%Vh8AX&Q-_(lJ*5mFoMBNMG-%DA7i$;TvI(bnIg#KohG00$dJo3Dp2KtOc0EJXIra zeIGJ3{tktqmlu29j`JB>>TrAaPi`2V<)kyzcpP8oR)*KDt^e2vg;x6jOEh>TFd90q z(QtVONKz4KI6Zo6sMBtPv~{uzBYQ3z-op-y(&PJl2X5k0qqr^!N z12z^m^XAQC9&cv#`Tham0waY~VUIAFTehJzb@^rqN2d?hXLpr(F}gOc(9_4t=JAq{ zX3N~RvGk4=_Jz;jDJx_QHT1Be2`K~1x(i;c- zkQ;$-TE;70FEXUI%&N`(z@^>&v%5>prN!;4v3lf-;)df^jha`j^YT06fQ0ARMuq!) z&v9$qH`d?#!uCwZ-ae{}QsDVcEsV+Jmia-r-gvkwF4M8eCDS(jWrkQT|Arx6aw=hX zrY&9vwcXQz*K(a6T9o*`yi#ckh~Z^!wNv0I8wuZ46@FCx7rE8^1tC)_%a-8oy6wAW z*vc&@aLeMUDO)-5ziLm*R_hqT6^3l9?PbR<2d*n@-zc3T{EnPPh~k%|E51`y580XWw@5fU3?^v0#>0c7;*5%XxgL@NcCk)Sy-m*g;MW)Pzp z&{sGHE1W>tIY#U&;-5p`t0a5L0vJJ@?9;d&dS8pYX9-cE-2w7W6uuxnN&g0t3jXyU zCI2z>BSW4eA&NYG9?1}WSo)59gL;Clox;>HQVnP^yltV#*Bi)E+y)`sz|AOvd=x?d zUxWs_75s$$iOd;f0!bR>mw@5cY1&y@Nv$T`8t7qd0XL6YKnjZlK1x^ diff --git a/src/main/resources/org/msgpack/jackson/dataformat/JsonArrayFormat.class b/src/main/resources/org/msgpack/jackson/dataformat/JsonArrayFormat.class deleted file mode 100644 index db8f0f834bcf0277a00ecfd56692857ca85824b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1368 zcmbVM-%k@k5dOBmj+R4cK@?CBtlAdrfz>C7v5;U&Knz6^d@)OVZLeH+o4o_{zd}sJ zXyT&}{!PX>d#yyVn7}>k&P`^%nf>P5{r>awR{#Y(NuVE-dYOtNfjiooPGAOi4ctp0 zhRHbYzO9$a^X{oC@7<02*X>^j|n zxQfa#O>aRzJrE4zS}|lr$R-uhnxenkv@_bHxl^$BLEtd0vB0T=NNcp}&}D=WrhOJ4FR&FiM_2upclD+#n=UY!`2(i7z$uEfQp29dm-$%qhAbkE@!xVUn0z=g6HQG~T P#gN7T^c$JR{IjuNjBRd@ diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackExtensionType$Serializer.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackExtensionType$Serializer.class deleted file mode 100644 index 7603c1ef358c7cb4761f8cc4e9a1d1afd9f6cfd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1674 zcmb_cTTc@~6#k}^E-Xb51O!DEK`BsJ1p%cMBZvf3grtOo$7wrk7Ph<1?i8#4gkRvZ zFC~#g@zoz?JX5e2r3oRvoHMs`{mwT(e|`N1U>>h@bi>dvsw0Gl8pbq?>u811hDS<2 z)-i#YT1_f3r6Y`K4RIY^n9(q+;VDBTX}h*uVQ7g>?lFYdyqsX@O4+V>U(9EOzsoZY zowNtSx4C0~qV-8E<@uJG53B;u9+`(E0?##bT=E0Y&vR*Ri6G#X*rA*Ck`!)Wd+zSX zf=HyYUfw+5ffRlz?^I2*o-fRII&Iv!E3g}Er z3cAG$mwD^!rK~7OiXUj0(=gBA$5Myc+$vmAJi`LRNUgD(jw3AY z5FAoeF<=;|y+}*ncCFQ-?GShjixZY`Ck#6!PoCu64 z7O|w^c@!_OtTu@#l6a|Vp{ZWFek~1y8bu%a8CGv-K3+plAy6GvhUlhC6Tar~AP@n= z%+-8oG6@X5mG;@5xw&1})VZs@RHv61k|jn`x9g00KKQnRrjDKr$(vJKu`j|41>xqX zu6mAL0G*huqg?~`G^O3OvAAF)Lz^XJrB76KtlqYANHz^IE_q!4?(Z0F(z`ffxYOY9 zGCzjCtFqq1D1DgS^yLCAV2UFoducaJnvrguItBYe3vx^{QaMbLq#2^GSv@_Xzqgh2 zLi`6pC+LZvBeWbI3{RKQ@)@IN2=AYvb^jER9<7YFcp2?w=w)=ABKlpq4pm$ak#k@b z8rIN>H{^PqLTnKEHZedqVTAgJahFyRvKYir_iIYx-enSFbRVX>j;ZN$bjD}Oxb<(= e$~a894^pxBX&s_6A5`=Ro{-k*u8V@3X#WijT;zlR diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackExtensionType.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackExtensionType.class deleted file mode 100644 index 70d46f6eba0b33b2cefd249dff2f713e54fce0cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1085 zcmbVLO-~b16g{sqWoRkiAYw&80XuE&Xf#0rF`*y{rl=9ZLN>mZM;UBqaAs=2pW?=y zD;AnaBrc3@{Y}Pr-e4+{xMA_``?&X>bMBoxKYo4r3g9kor(xkn3MQtsnYJ*K#!ck3 zu`T2+6a>=iDsW}PeWL<_%&O<9V5uR)P=x|!bhxhsM488J8A*Y}7SA0EuIEM%c*vEv z%JwF`Oa3+kdn>M|9=DoR6>P|AgD+NHMH?}Qk+Yeq@5?cgnX_Xo^{OQscc#Et4q*fE_$9H$%ru&F;}ViO=m}jkqQo)4QG!Sq3=1m z_^Rt|JF*?^JffrByLo|RD|EfOz;eY8>P|DP?=$%ygdIO<%E( zNuKOgOmY$}j%NY`x;&l+bcNiL-~^$Mwm%-<1Pt!I`Ogsf>@gDg;xUYmd=gC2X(sI; z?GREJCd4Ir26;OL7~?J&k<5QW;;5b05kFp`9gY(;*V$0x!@1CLhK}Getqu(+T+1ru z3-6IMj|$&mzD3eFDtv>vrm2ct@AL~V1~0}5lA2x@3|vPi?KF#>VHLm5#Iao4aq9$7H}YC2k#@!I z%GiOn6ezuu7U)a+!0^Ni%y3C!2G4{C2AJWUC;pWV@SWY2wUQmlDRjm?tcF+7EAlus|oMw87AIhKndjurW;D_D&ohP;Ar$@hY6 zZpNVEmV#moohV5rLxCB?VPxe?SvKF6jitbr04Ii{sK{n5hVNiqK5ZztE!TXv1K(5d zvOuS;TLrDSq+52uG_Iy61;izR{S&5PJDTAvX~l{j9{Bq|%YU8t%fAHFvX;B0Tby1k zP`y_;G8Y)(YuYe4U({?{w*`_jrj<{X?7YOKa;BxHuIRR{<#h==5yTD)9JTa{tosVA|tW$1p zvKWk=v{i?9bBf+;@Ed);*3zt&PXBbu9?V&~=IDWhxfP$esjX?Lf|<%xoN~okaJZy2 zJd-m^sa4H(bZfm-OjW(%hU^kEWXi~yD+MDzJlJaGwlF42Y-&BHmmMaPt>9IGTuu6P zp{RdGQb%f1Ua$(Z=+Tr`J*QQpnv7o`Z)vo*cv!*r1x9P)(?-q1d*xs26a)Qo(J zo8B`a|39bJUSl3xa8EC}?dg_4#`z&WBehfTnu;GFsp2f2mCff>oW_ufGqO45P5e;B zkC0K3!ZQNT1vB7NxJn9nUEo{`nt;CB^-aZ(@rH^w@s=ccn@2;nvPvU^)m6^Fqhb`# z37o1$;i_R*%4O4X^p#9mp6INT+XYj_yLeB<*Kk=jX(s62RrGR9#ZRPuXK_cx`*>Z! z2P%GwpUIJ*3!L3MogX0yJTIX5*A{`3En@HE1O|h$nr>6xTB=S=XSRL8z1~8UYjI$G zUo(lkGEGiRk6oQv%+8HXT%MZGPGn}M(-#F6;?1g^JO`@BjhlMTk(Z*JdpQZ` zil)J=pZq^u19;cz%I2#Vz-gZD6-(YI1v5m=nl;G+O>GJ4C}6~!mige~hg=_;`Mdr; zdrjWg4%O<8dl8Uh2mE8tKelQIsavu<9fo;pYmy3e#~#m&Y}vgF*WASG&tBn=?vdbW z?^-$FT?m_Ar}?qrW_-md6jNiCrEM^p`{V(cS)FICX5MtT=kVb5ae)^<1O2a$Q(1m# z9p?`S;}|}N0SKJnTN|E6mn^*QGfT1Cvl_cSD=_;bT+2$$_8i|%5F^-kBz_OEiMHSI zS>Ow7W1Io2wnCIdJnJJyI4)<7BsS5W2;D;jCmDPb4W?33A;<wFTSH42KM=^%4;)`5$5aK_4X;bhe{&7GMc)?e0z&BG#^hy(d z>rU7FGD-WUxO8}TKzIk>5&@S97@-oL>uVC|y66tT90AXBDUTtlB4c%yv1n)CvjufI zaTojfJCI}(;V-m_gEb{11OhM8P|(TzjC6^{eWH^blSBvT#?IyBCJvpxkFG{^wgEli zqo4FW)3Jra%bPgzXEJ#y<4Iku!%fmnp87*HNJ>4FNVea{V^`QEA5d_2O|X}9CE97Y zBoRW#FirYNT=Z!YB=MB5(vaivMve+O*6KJy@?7>gmN^@uDyOz^bon&B*Hd+6coWBF z`NAaIHzfP}=pB;eUV3%8u$R$|SJ01Fx!qoKQ>g>u6FjZpQowd8@Uk!PHU&n=GTQeM zqW#GSzkr(T>+65%kLa6`I`o7Zl<2<@_OwuY+y|=B6RzoT%w>C%oAfPit9O{%?=rRD zV>;e(^@*W9*6|5WRW+(Pat2rEPMJrGQJ7@Tr8JM zbs~*RKgJxVBec{)$qTX CiYb-= diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$1.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$1.class deleted file mode 100644 index 8776bf3e54598b15f26db85048952c0df9dfe8a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 270 zcmbV{L5c!F3`KutbXr@%-nw%!>nTJ$!7z#oQSbz@&6Kunl~k1;&V>i?P-5J>G9mvH zNM6Y8ez^h|p_3uY&?e+7e+s2ccC`@tbBU3yEVL!qn`nS*$B56JhiQ exfp=(q5nPOQxn=X&{S{WOSPqy>kO%*XgvTM>`QI{ diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$StackItem.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$StackItem.class deleted file mode 100644 index 785474e112d4ddcc11d6191b94d0aa60475abbac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1058 zcmbVLU2hUW6g>kA3ky=DR;{&C6)RBfrXlq~XcI%CX~d5NQ=@MKjARjZ&F*5-f2E10 zQ4@cFKgxJ!SF=rPUwE0Bd+t4F&fL5E>-YDc09x3#kVDl%9#sLT)b2S!*cQn5ov|y!xvvCjr_!A`o=SIYzldbo z`=k_O$wN7vD~e`2j_ZW`0_l3=P{8PVBWf-699KP`&j!kWB?nU?SveZfhQLbwtgdF} zSP+Q{m}B+Va;4rl<%$kA&w%Gx%~L1#X`(^r2d=C9?ozrY}6=*GRjj_ScH_s0|1w;1+oLCfHV9Yk1h_kF=V~Jd3MVmi>;J(&8MymM( z={LtPz9N$xv!9t3sBkT@SpP!?b}8||0G4ry2(ZFE7OYb~MWopLg6!5em?^wY6s#!M zp`kspFXIYXvC*sKtTIkTw$_PjTN$nLiHF!gHUhivK+1mOIDXq++t~9pIFx!)<;{#QnI{ zEp!^?COzZvX*8t66e>!%db79z$RPrusBY-iR)ySsYsJ7=Ihk- N3Jv6b%@u^z;1}B%?NI;# diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$StackItemForObject.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackGenerator$StackItemForObject.class deleted file mode 100644 index fc720eaa270fbf98707a933485593fc0017e972a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 944 zcmbtTO;6iE5Pj<;HW(LD3Z+0x`K}2P7DBx=lnW9FHBh8ft;B7UY%PbxM)n4&|Efrp zPp-a#dPy(4GvoK>&FqYS{r>S2zz$xyDB-CK8#AM{o{eD^a}J(6SP-yx zqd3xg0tJ8Lqd;*#X(@q;S`@33Ubmsr53;Ii7e}!m@)E535*nur6>gjCx(Om?N#aWcOc;kMvOR?SExAk9?;j@OqeB z+X8Nq&$K_v^57uH^XdN?Ef#M@HTS)D-o0l( z=bm%l^r1KJxtEBRYiGLYHlCD49Xwfv95>y>Q#<6P$Aa(PoBkjiX6gO|$PGM$&Zc!ka@g%UtZd6k>i^J+I0^BP&O*3DI1 zt@Ap0w_YAL=)BQQD;NT=;2MF{%3Yldo8+-x?i%E7v(8)O+NkqZH*Msz!z(@ktP`q%h1dp7nHs% z{sezg?mi{ld|HrS=i=)HG9;$ILFdo7__HqloY?qA7vCh;n|1!YOu5Cyx4QT?H(k$P zkl~B+a@fURa`Bhl{1yJH&R-Mng+jls^Ea4`#z4Rf)%E$pVKdB>+Zyq8o!=NS`x}Cx zno!7hh$$}_*0N`x*%e{RiUXN)Hq|%O>}+c5tlLs^c58hb)2ya_zWu(+fInE-wbvI4 zn~};o>srk;soxBTeZA&(P%=YIo~B@^x3WLnI{-jsS1@E&ZcCnlB?b19+QFV4Gt@E| z85oRg3HEi%@);JbK3|}>vTbk3^mR7{yL^3EmDTF+4frC1A(QE>v1hFtO?!``QE3rr zjR0YPGTG`4z?>OWEHF*C&_d4S`IupdFi>nT(Btpb`CEWk@>&q4($SQYq+XOf8R(p0 zu}hrZV8q{7+2jwLZ+18N!x2nqw-`x#kt*Ikpa=&8mEFFGuO}Gl_eGKwz1f5#_#(m3 zqPS_5tdl~)U?dJ=+L*%le~%N|Tjvk>BO90k#f?o}!T!n~UpQih4)*s|#?UD*uzam9 z*ll)IkFDnvR?OchKVo7{C}IamMsW$U+g-q?H5xLQ)96+IX1-t zAhClp@fW82;v_${URMj^BgoQBlVwt^zju?_=H-|No++CWP;t6b?g6*TwwzL5LRia!Eg3;H~acwqZHjBF#UmEHE~(- zcuv%6hWx%h|Ak`bq(#}bSp*A{Uc9@mu~DezDfrpG13TLq)>!k^>ssrzW%%TGuGj)( zqGaRQw5(;0;yOWY5v}zHd?Do3rQ`Bl>kFH!R-EGl_kl?DZkxV^!E#+VO|jzHQM^^K zr#nMqAY%5KA*CZn@g|w#C~gpMx<=;_BqYUoZ7|qp`U3J!g-DiyHV^i}y)0$aAB>oR zFnqu5&;ZP^?!Pf|%38&Vv#T!{Hg!IVq}J0n7~Tsq>Y9}OB(3LkhD+iOYzP!m>Dfe5Uo z8D~KnpXsR=UdQBG*VShydUtDZFw|u>_$AjCBq57$Iu%kd81x;!+n_t>PJ_Nd-!%9h zKE`y$sPf=#wrD}~ZG*oR->PQj*A0e3W+39}3L<f_6$Zm20z3E1AN-1G%3RRwNY|DGsFYYe$oNpdd*Zqo6QB>%$Tr}&p*ZD`HKS=d_*{uO5-za*yHsng)6MTB4TZxFERtyHwNhaz@TGWfUh z{u%y(!Ot@A{f?hA_<4c-p8p{3`$vQS#D7j<#WJ|TFYt@VatWFZeL-Ku;J@%o2LF{` z#s-*p*Axu&8vF{sYVhCq?*{#Xo-*iH^mGd1O~FCzaR&c`|7q~Q_}?){j}-@TpvEZx06lM}$1ZZ!oQ%xLc*9e}mr?^_E{m zR)tJ*InA_u;w0l4#n3Wf2+g56#n|_vpfj{gO*b?bKZnxJ(6ThQp=E;)o4g9g8tf~3 z`^|{IE6F(*BrIXOZ%wFoupeO>pJZs0w8@5+BLVrOHpS3#wLGSlq*UkW@&zQA!*)Sp zdVHQl$>xdd^&#kefue|KkLd}S10gdE0%o_z7xr{3(^g3AYf}wvn)up1TE0O)K}yl4 z%cGNi%2YLRJ;mxG6G>l+AVZrW$+lvgdK~siU!`j^4XuD5*0ouNHd~uxXocEbU7KfU z9^ofb zYABGCQixUlAiKe{lMGO%mCJ$(T|2|jmTAikZH2bdpnpqRKStk1SGqG`9vndX3T9H8 z8n8wG!89$CAIE+(jtcfk|Fji@sz1=nNsh)=SBDfW#zlu#=CO!Cr=A|EUOfS1DnnZ( zNi+|et0yeIoCj&l>>r36GPKpA`1KPvUEIYJoti;!(rL8P3G|WRfG4~+I0*XiCoBI| zfxmfgHARITG@-2#pIR$Jl`vM2qAFoq1P!PH(TPg9e2uPE8`?T;JxcUMpd_{8Oy%RK zbPsC0%D6~U_A;$}C(2l=Yv?IUl9#5}B`GZ-(~@!6vNWce&sefd>+)lJ0>F(eaX(~Q zHV#&C9a~lu)Jcoxj>opt!`5zK7cF7rQ1@g)f-SvmF^EHUSPT6l3h4-@eK@^0aQihV|1y>MolS5A)T~X()n#N z!(HhPV9muOR|IW_)k_;_+$7`IheAQvEDOuG`=q30nwg}iSbW7Ys6Svq&~0Od)PcyB zF>i~zJxDpEJXBIOTG*}X5bIRs*V2O=jJ`O@O=FEPl+dF#4W_kYC}DTf65F$rvBYK7 z<;0`ekN()@4@4Ao5Emc_F)bA0<3}^3$O@VLK6FQN`rz8@3){AuB514wf-N}76sLFk ztYcV5amnslm_t3b^z^83vU>RKzC$P;VcR9e>Y(85$roUvEnI3z3)bA|65|*bsflkZ zjyhwCdBBP>lsf^HxO=1mw)F|8ZGe_U9jY)Ey*5k$Nmd_9l!{PjMwg@MA;%c#-Z)_U2e_JwwBJirk2+F z&bFGfH_OMracihCF^a7IaD70W2)o$IiAR2nr)nv2bl{MV%JQNHe@M#YOzRjFu-M@z zTo6Z|2wtU-F?BIq`7w}TRa1w&&<9K?4GJu2bNSQQ1*%YQJ6rtHPNFLfx zUOGT4=|b8_@1sV#gxcs*+C_)Sqz}?}v1%b@oW=xQr~7cu`8}P!uhadwJ4rZ4$~r|^ za{B-#Iw0zU`1=7pWQ$v^U_`UM-n%F#N>h$d4(=u&qudT2p}Z(f6&{&RV4Muy5M2TO zu7vilQYbTl=t24+X8b6Q^a9Ld%v@*ToOT0wAag!so}M=&N;55R0q&wSD+<~pG^gEW zpimeXp}7go%z{pcJ^}lFl8Wd$Dx)D=mYlkB~TRl4CYvl1L!S5=Lzoo*wP!%CK+z5{%1VtG_q6Pu61Lyqv z5fm3wlsd zT>4#FIz)M8r6*`w09Q04B37<)U|cmsbIS4^QCi(zhQ~GdTPu%M zh?lwfj&HlFoaF`1C{?$|X35h!;F|$_>xU>usH~6D27nv@ZL|q*jMAA=ssWmp0Ijv5 zwNa{z(k4Kk1k^J`lf78(8KL@NItfUw4aps$hGDu3kj?hW%~9GCrADm05zwtR;jK|R z3!p0iYOEm7Kzd0l|+7@|d>xkGetc9lbP1PvI0oH z6Z5K}$#afTJEG%V&Bv&t!yBbt_}g6$hse$tp?6m~9{V*xo&gNy_DT&KsO7bakOqCux8GfvUEjMpJ{ zBAsjU-NRPNt;oEhl18wHR+qrg$7a!!=aZ_ile%y(Lkx6piVS-$gb>eH}C z_It|{_lKQ4eEO+`lP!U35lrmlLUJ=q#vYo(3-IHwg|vzn;a6M>XbUe<0?Z-pG_0Db z1o*K|zf}Jq2KJ-k6xQ*z#%BF8T!r;2a2?ntTsN1;cn*SRN4_n>EmVN~pjfVQdJCN3 z`>+GNKAYfm0lC0yDR?ahuNC-p+ZnWwmr^-gb2;wU@(RUg4ry=FOq;pa$&>7GFju%s)6$sCX_2mAZ_j?y`WBXr>ijY9G+ zn#>((NPb7p*+?oNfgs6?A-RJt8lm@&fu|EcM?5bL&-3p9PY>|)rs4Vh1QpT`g#<>e z{evw_5hM{=vc07lg;BbA3?U+L$-z+w{!5Ks1dYCT6p}yMTr9>_oG!~d`zXC{3?42e z7hjgP{7>{}dwDTLaALXPEi24NqI~}t7(Pnbe0ds%7wE;Y7(g98$|J4;1J{mP{+Iaj z3{`4odFLIaOU77!9hP4|YWYj{@&&kx_$ppUk-iZIylK?hzm6hZbd)|Y2I((=^cP1h ze>uK9rul_O>C!Qle+|pOK5BVvOB0AE(v)1g+yI z@x$P!unj(~GF2Wqnss_b{#xumC9n&^Nt^L1Qt#jB@1wL0KmX_$+I|k&em+fO|A^P| zqHXL+@DsEGqx|Fr2=rpw+JB5iGwsuvxqn42ohpQEpy+66Gi^s)Wv! zrsL`pb``zWf}@a*!L3?)zO*&5V(Md7Lv(eloYI-MxiT-bxl4~+pK%RxWv9Yrq6Q{JDTcWwE}W# zvnWfOorJ+br+|Ug2|xi>i}0LSm?;2!yLZqV@m*pUJW|?WyA8W`{T$cLG%w!ge!|+X zXXbqpH&&aQ5Eot!d`rls711QE7@~S@(O|d|%PO&ALX&UUHfvizQCOP?#iLjJ)R3Gr zpo9Fh>IW6N#R&E-t&y1p#n@(#Z zXq^dKHK0{DiWYwHVbe7rwF3mVs3 z@1%@0<>FY)g}p*U%L4_W0s11Y%TO+U0au!WFh?6Yj57)ku3y6SdR)KkkpDUKO*EbO N{~lVUw)D(`{{sTU21)<` diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackKeySerializer.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackKeySerializer.class deleted file mode 100644 index e9836596b78aecc35960e258aea0e882a94bb079..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 951 zcma)5YflqF6g|_{uB_!D58r@1G(`=Qpoxhkd?9MY3M4foe4OqMo2k1yWM&HJzw(PD zn)n0!QN}x~lv=4_H<{ggch0?M&bj;J=hyE5o?nc}ngP~ks*<+||>R2+2H&rgTyIEVB_oAIrX2eRPM5;c~yQw!j;z;mRjqUGP_0}saTqZXBNIZ ziR7VEI=2C41I!VpmP&Hrx`sGy4I$7gOZ>TYRNlqs9oGLn$VP*DwRG1+@|E%@pM58- z6^Y!XBfXU$&%vu+1cr%0Eo!)md4?C-Bs{apA>n#@csd8#WWw>jvb~yd%Ndm?zQX+g z3pFfaiQ)O>EB!@~;n~Hm{9hD?wToecW|9{@Qy8WS9hBy8cKWi@{j;)}3Tq2DXZq8B zM##Hdzg%Z+7{-o`a^#Ur<86_VQET-fGf?n8)7X#mZ=dQXlw!C>Ye*k}IfBhoriM|9JzxbDx`ELr-%#Fve2U5!Tp5HtAizV6(Y7kV R#xX(bb&5)u#8mN|{sjpF6BYmf diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$1.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$1.class deleted file mode 100644 index 28b45abac285ecf969d3dc220779226f0a7fe6b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1909 zcmbVNOK%%h7(F+BjBVW3DWwf*+NSLg5(;%ln-tnoVyEL^>Q`+iX$YlE##6_^@kC>% zhy^P)NU%qOJqUILHA)fc3JJs-34Q<)`~U>35a*l3*iF(!D~->&=icvipZ@9JZ|?&* zhgt;Ba`${c3a}u8BYAQrZ&YEl4 zshW%*-kwS)#o1-^j>%9)!>T*YTBDk^TT4zw!!-?=D00Y0aS|t@DByY&MU)i!#U)-h z8`XHuDXm#cshVA{7_RHMQIy4OMqpN8PT+>XJg#eaLn1CjF(?t=#LXz)61XMswm?C^ z6j&6n1S+_x!4}WkQ5+Y~DwY(+xKHuzeTr|dX1ueS@m*8Zxf;=QqhY&Kb+g&Dn+mbc zRPu|dAFri~&CO=a>4mJm#)bBW?SI}*iWg6zvC3JPJ? zXXHxhJe`hrS1GrO`7hwV=E)#spd&TPU`K{1wT=u^ zhB`7r8SAosLiCpTCZb->ee2-2e**{FIVoe5?VOaol#2PxY*DW9Zl=cGJD`F~F8 zr$l#|9~RwZe?)ZHt9cWBUQJK0gJ1s!j&9ZTHF^=oAsj&feO$gF^0OGjIC%mIKJNh- zd{Ii|GM^WVT)`@uI8KUp5aFB=hi`efENBzA&w8RZw{yCG}e{f19H;m!R#KRo=3-| j)AEd&YM9}BFoNgEew-nu`8&wI0WxAC{$rj&cC!CJcjL_2 diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$StackItem.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$StackItem.class deleted file mode 100644 index eec1da6a809d41cb57b9277ed141a1019d5677c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 563 zcmb7=%SyvQ6o&svVq>SNt@q1D7lJhlBf1k2p;V|?D=6O3#k7tgwV9MmD)=6*d;vFZ z1VwP+1NczlNpzvOa&xZVf6keC|9E`^u!EgaZz91I|5W13+tihVECevc@x zLq7jx#on_GjT%5f|#h5!{Igwos_36e{j-+c-?^B$A|pkL5~m;RErJL$OSuZxPwD(--5l`<&?7Vh|bAIFuF;-G^2tDhHyz<3^0Qp>swo3@Q?FlFUzlYHL?oT-SYa?tUl8>wh v$&`nSCgOG^t@Gqy>jm`uwVz5=!UJBoAZ}HBgeEpbyW%3OVO^MpXggM)>t}HH diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$StackItemForObject.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$StackItemForObject.class deleted file mode 100644 index b7b7d03fd4c5435acd58482b02e09e314f8994e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 432 zcmbV|y-ve06orq|kWdq7$-oLi48TB;*brigRH=xcN=58WdWn)YHnLsbiwTK=2jHPl zZx~o$0ZYE;`1rH0?2pg4cK~NdC3=uCk{APl=%UuOzZ3`$uZ|vAax)`=!F8?acG(tW z?^UtjL{81pmNcrn#m)^mrz)DLaz0Vkkv(bDvq}(REylJ$Zfupcu6kl1Yq&V0vzhYh z(b!h`?8o_osb^~JsT~=6S2R?5f%La98EZ{8Unu9u37r4GlR*EwfxzisFTx%I{>p9$ vp8Ryyh}}M?T^=3pzCyfw?Z;dt^FYJgoZUM60DWw+rtAW2V3V01>oAln17>lT diff --git a/src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$Type.class b/src/main/resources/org/msgpack/jackson/dataformat/MessagePackParser$Type.class deleted file mode 100644 index 73837f596ace1f936bf49bdbd0aac3f8ca34ce7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1381 zcmbVLZBNrs6n^g3tz9WH-iC}<5oH6VC?d!vj*UqcCnI(c8%<0ZWf^WAX*Ux8g+Ig( zIubD&4WIo{#&a(QX7G#alJo32_w@96&b{~NudhDa3J?w0kMS3a^zZ}me8Uft36t%h|_cWYKde{Or8RkpWjW!rK++nwfp64WnW z*xFHe)RhwM+ zYAoJ)7b#QUr&;vmD~`R@tnJxu(b}t0Mi%W02Mo_*`9tg2(yNwJ){TZ+amtB!=dzO( zr_xwsi2S2%F22hUGAd=qYBXI^;g9i*k}OsKyp?Oyl69K3WQRi5Xx~($-gHa$(+c++ zxw5_U+_i=q{1i@UNMT(@nqjGGA}cEKnNrdWG6xvNI;P#ppq2=SuhI_6ylIPl7Y!goS6t{U0REK z#kN)jwXG{Is2I%zrB%CWt9G%r)oN>7+uF^xc2}$L{m*-ECNGl^p#Aj=zjyC_cRBZe z&pr2?bI%)IIP%ofM0C3PgqM1GiN;I4q_{+0mPxW)<1@YF=Ci!?IG?TY3NLxM)Pt5X zNy;Uu@Ngwpd6BI2@+z+O@@ifq4KIU0#~cL3s~(xtlNW&=VZ?a)hH&*CXRDl+q3$O7uI*qSSJ&M1}!TMA@bQxZx z&!?o%4PL6{Jzi?(8)eQ3w^}_U$CRNsWWW&+G|2>zQ8h}7#qGYRZ)+&r<%hb}<&MD?$Yq1ZwS~e)aqVDu%g(|-rZGvVnPwh;C{tQZ zecj5|+Uh!{Y-@6W=`1eucT@+XMu!mwX}eG92By@uP`lB_lvmRh>MGvqi$sm^&aOaW zK_);8dAan&=+WK2aKs<%C=Y?)PH=s}NMpANTUH}!0DtWvAd(u9ElptTiTVS@HU8js zqrJu-iK0W31wN_axLmh+xfaCN0;UnpO^Afa)ii&kJP?W)?M%FpX;d_{-3YD?Mf_2J zD2Te%V0>FoIBW!?1GOH1D6!c5krwL@6<5~}EOH#!BO+Md6N!epDh$AZG?xzA#$hC< za%a>CMt~=2tlt;#Uj!21PD<32?8V0;HIyAf69m%y!RR_)pa%lZ)e!hVDA-}Yr?-cC zwgilLYXy^c%dV&qu`ATMWlZUjXc!`3S7kb+ywPmH4B8fdycuj5Sdd-0^dz7UVhBiQ zg^iww(O^VEJ>fQ^I%w@QlY6;8=#QSov~5Ij9<)oB3xwEFBdPn0wYWydS z|E%%5@WTW9sdN%aJA_M1eX;KUCf*%?Cpc(c-TeSrwrSHNh+Z{ z+uMzHtI}e*tx;jMG=2|4F!0W_@c0sCI{^cu05P>qJOGW~w`P?tPIqSh@u^zcf56aZ z0K6%?;y_xSMB(wN#5)6$>|eR%cEoF$#)WX;!v1#n52iy>=j(!1$;ull==tm5Xfed{|64=PRV~sc6{-lxrmf;`b@S7(;$yJoLG@ZUl-_q&p^bMW9M=xvqk57$t-qw{%rD!TuS8k>0^c+2}(_8eCrqXofQC^*%p=WhEOkdJfI?n{_oalz}+)STe zSGvqFN{!al7@n!C3>iAzIdnL;Usq#QCP1rkx*D&tboxHMqVwszP*>SJQKxUycXTy@ zL3E-dIYP9=Npu)IL$+$b8`jk%A#)1Pgu2z$WHm)sQze-u$#gYCS2KAuHgtr00h}Sx z+EB;|PX|KS44vPN>zL6#9WAn=S-Q$qr$VReYPOoAt2~tt?XIf=&d^mMc1g{ZN#_Zm zA~i)*#k!iW7U=3Up0BIZrEQ@kXQ+H#E#gT!eTBXX%b=^pYKcx?qp#{}Dg98VA4u|= zaO*YUR*71stL0MnGwE_BPsE8IuoCu#NLOb`mmkrqGU9AWR_Ll!CM-jPD(9&>{g_^t zh6-I(N<)=2tYk>YPw7ovt&+NGsaq{eTBB-odV_w#lrb=yWs`JOtLlU&^}1TCrZAQL z=UW)R4D0F~%nF(fOy&O-IZN^Cs!>+aBYXb;YbPKVds);Yb?2pd>1q=UXI z8-1?G(0MpCYLo25X4R^z^QGjI(iRb$64fRN?tK#m=Ck&stjBK!1V&W{FT@?IeY)JP z&eWBmwo1~WvjYYQYOhINH|Y4*^BfN)0`2GqnyRK_0aeo zU0n+8gGnx9I_)^a)`mlEh(f>&CfF_`FW31r*`f(ugF_V4{gLUxoiH5DK)w zK)pCCO!H4%hT_+`1tWmo0(Yv|>R1aa1=mCzEG+b7r^#KwbjC>!l3O$kw7E$0I+NKJ7?Pj`h8h0+coE|xn&?}V2Q zPj3i%+uT4eLDZQ}adyDL>M@Eq+o^?e|$*Y$8$qAth=T;eZtWispCN(xS zRF^lkRy41zsV*;Vs%)*OY^p48s;)<1uXv>Etn83=FyeIK%z2EUU~jL+Jxs9SmZOJ5 zA-MJNOZK5#nMR299I~-MvjZi1T*M@<7hSS@}a0NAi`265lJ(Q8P{=|KWKj% zkibZlwNec%>*|i;dx5Jv)GZ;ox{B8Nveh_A(5S~dMpifijF(ZR4GpC&5`}2PZOjg7 zcrX+Aj9@X-=_6nGOc5O_bQ+=%b%;VRZ8^am9WjR9mC~zh` zJ?0mhIzP(Zb)_}Um92HnH8p^3HI#)y0mBCs=B=u(tf^?NE3L(`aCr2I4r$SlwQ9L9 zZyYu>G+M%7&Wp7@V^c#jh^AZ9SC!T@;w}Fe3zGAmn`HGeY^;e7E?5^-U^m31Da4dx zpN6Kt!PEo*72Y=pjz^HD-wQD0cA1kzHPo2r&DO|sS< zgk5e!ybt?ZEWthGVA?cT=3}?Z*~qeRRASi`6_o>OVyp$kR4#EGDcBec8Dlj;&f^WP z$_-d*j#WRb=OSUyA!cBhp0d$6c$Tw-KpfU7>LwnPbmx^>u7(Cx9_f+DP)c`C1mVi` z#-`GSrntVEU>Vc$PTX9xAK$)eoy0)IV-@90$oFG0;Cf z8WQ2MO^!QY$BM=F*tTh^jbJ!=G{si7w*nuG#U(Q<9G?3zPMB2C1Ri z^fYBk;1lIZ5@<7X#MsO>L{iNhp;F|T5?)P=djVq+q%hkNtu%9lXUu*GzMAg{YMMDB zb!LvJo0%hCXXc2rnK`0oW{&WhnInK_<_I5|Iij@4b20ZX=~tNd*La&lZu93r=>>(8 z=jEiN^b>Y2OQTY4gbTiINT-=;dWmL`^Xay-wIE{!E=`>Cj)mvUk>X&;Ts@xB1vr?o|U8MRX_NFQ*K;o3iO1I)(0~ z*>oQj(|%e)_tRPQ0F~2&w1ys{8hV7zfiRy3arV&@v<>2XDFpgDi1Ozk$oD~v{|Jh8 zq#dQXq-pdgjsDCUy{pk*H2NzOtu^pnoGB zLRwEI{W3^@A3Z;$kL>=FkPB(W$#h>u{Si6}prGqM1%jVWbRBWeJn!T6GP)d){oM$O7M)`Z`H0!-!eSzJ1FL`>Ya6h?wX>K3Qv#X0loSvY0 z2SK}dAB{Oo^IHlyb3s3y_6({{uahK33riq?sl9YYPD+dx6+H;(x0xIvYzEN+Jj?N1 z3?^;FvlkEah?<3GA)ZQ5S=>uYYWJ%Eic1%{6QHKc?7dWSFJ((zmirJbi_vn_p!3;T zZWH#IChW6NgRW;oU{@49gy|quvMbh;3Bsi%X|5bda9NDX@1_DNR-kwXO~V1G?4v4F z#b{+8t-@TZ4pDW9wx4`xTWz)V(Hb4lZ?oT&ynqMP9UqoUhSo%mC9jmj<1xPdud(mey#(J^+Fx9Z|I|z#Ne4I zS!|jpb$D71(Z|Qz-!^dFwdG_#4eY80-d|G07mOXrPd@Q}*ORcs0=@pDUA7e4I zZ&6x7VHP;GrH|SYH1ZQPgj(idY8QBIy=3&$)&#Zdd#MA|b|0qB7LfAq?x$@fsrxB< zn6^tr02N(Q(T4eg)_kE7542!+izuNB3MCC=?tY5&Q8Y1qG6(vpCq@@0<{fX%JL)j) zXvy5!PrIJ6kIO{~3f{Sps{0&gCIe0B@iTLAPU>@1Dm6K&G5T0e>Q|_9FHPvBOKQ!t zqEw77#cA13lcjC@Uc!`@4YXY@CrM7$TshOG!sJV-73DW^{(nZJU?IogE9NX%g41Ce zm*IprK&@_qx!VHU;D;*gp?6^l|3X(lja^Cqgo=C*-$>twHU9t>{6pC4k1*;8dK{(q zSh2<__za+NE zUanWq@>=yZZcs0Cqxu0it2cO^`US67AMgg(Xl`*$=8djdyva3(TU`b0b1mdH*K#&o z>v^lIo&7F9Z*zrtyXztjxGv=`*9{zU-OSyteSCpyKSx~$_(IdTyh<}aqFG`am^xuL zM7O$3^C2~)qzE@J^9Zfh7`#*(ySyLLT=tfs{sVI59D!jYu=+j9Ito>1*&Z33=#NcK zA?!&Or6nj2G{TY*&3>QUi`@&|N2m(=>OFF2WE_Rz8=jcPsY1?8?qSH0XQD^XpJ-Y+ zHx~0-cEdf;IL$H|lw&JIhm&R6EWRXe7%_n5)0sWsN2b$7bVDzF9P(ckqfdy2C&MPB zAw0chge7idOM8w3e@<4g4uOpZDOm-k-)# zqCacywwKZtri|9)ZxDkRCquW_JKeUvX$3L5E=JcU*+NWB3_9mE8OOq#4F0Mjm^HN0Y{6@;H08o3Vf5*lcm^pP0v`cw8nl*KtH zEH0o74U}c$z1@~Kn2tg6R)YS5*NtZio>TG6!*d3(iIEkIVzecPJl!byniB;)NyzeZ z_$~i8@t-ALpe6hgt>EuaC4bKZts!a!p-D+Xot@a3TW!>>NvIbAp%e8?yyxL564VC- z^3{^I+#u8fiaZMjiWu==x)oD8egXv$L=RHQO#p&CymDjTpT zCLpH{6^_j>cfg*DET>!jeRq6QNQyr?TqIrS28@%xO-!?ucq)h8e3?+ z?|G7LQzVe12|p4SZD?CnPMWHqY*k5&q~aCvCXj>2gk%Ph!_eQ zdBj@~gD@2{!XUshpD0T*L7miE%2f@Nk6$GfsdXlxRC48}B%hUBo`dPchVHRJt#g19 zZ$mV_^Nfq75(|*uOSd2Fr91F^9?us}6rQO*)n@SNe44Aa(0tVnncGTBRA*wxT=+{; z`1nbW4K#>c0OjJMBEgfrh_=Wzyf8*zEI^><&i#~LYZm4{^B9}~qH&0Z2v^@mI+M~+ zynwtaOk-4p#;F}NQSGEtkk3FqOYJgYq>*dfN{#a^xsOM`UQDkKu5)>w-E|=XP=Xi%wY%gfjEd3S$a2TiJxcPc`{}-93fF={(eWr; zWK+0kI0`p{LNU*`F=P`czk8izXEnu}`Zg4@f%XnD7aqiRLr z%I)EpFXHIlWpdt2spH3JaPk*; zfD6B;viE&Gayc3HeRmM93>%jS!2@zg0rG)?b7~!l`!W3knEpXbf54my{@HllaY&W? ze$-||2bdt!%>}h_`w$O&g0djzb|9~&@OiTCv=53;jA-v=J2?D6yn?B?TCHl7Zeg^GbV z)@XC1PJ_@af{-sp+)BJ2#fzyAc^O3g3FMTKMx6-v#n5j%as)NuSM<`M6#V~4cc=n1M{3qFe@e$-d(QQT0wMU!?p z6HBCR}?*d9^CMl2*{JczQ3ts+6tvGrCuLuMqiD+TSTZ-07t2 zy$BpB+J(Om#lsL5(g(zOJyf@L5xX0 zB5=6t{3=SiH}h&*ER5s2g>(4C!UJ5e@F^}BShMgDQx?`SZQ%^gTG+rNhVf{=qS4V3 z`I_UFM8LpiEo|a3jTtp$Zo$Bog>CFGEc!v&u7u?(C14+t34PBlamf$-pu(m7k^C4& zkK^h4GRzhIihaOCDT1Sl+fpq0fv}qwRFkRmV>lB@P_QPrc3mK-`+Nj36{i#JG8`q;n`L;hO9Uyn|nKbH1uVo_2x5pD^FsNkf zyh2@_|FCEeW)3s-MHvIVeZ(-S`bnRmlf#15& zbAg8-LWgvAD7_8%mlzJZw+8PGGM#)5Rf3P>9uOjZ3cXFjWlo{@gm770rTaDG zs@9&&?vQpm(!@3CLz^6-i6nhcv`ru;eO!*=vUqn(_7)@kRr*9? zqd&m^;omUMSxDR1g!1M-%*^h7GdnZ;&ClQ8egHVY^9mkd+sD%i3aI;d=3_^|YwJ|I zjzF=w_d%f4H6s$J^>j+_XUUN4Kn-I)Id1kslgP2k9NEuFEGH`bn3+_Llv6{Uj$}BF zWS^{7vA!UCqC#ivylc|2j)FXNJ+!18y`}jzO5pq2xGS`B+N8^P>vDOcKB>WcO2Jwn zm#}((Y_PW>Uf^M0N2zi%%RTz_Kh@IiO}Gg%R%s+phZ722(Al)UJ7Wk``etTBI?*{X z8t*8}R77XYhwDx*zyD>PLlqt>0*A&%GRdMT18=csY;2;Oyb*jfcE{sJZ%6WVI*!J85;CY*>KO1LkjHbrPjDL$7b5)%(TfDdK- zwh|7M%h%3iX1?9opWm-<0JmspP;jK8fMYREN;oZ{#-Kch$t-0sx+DI|oiUFB=V>tV zz4V?zb;BUy={)fn`ErXegj7U@MHmw9U{o^Zq)Z`oJ1=9<+<2aNekT;`wcdO>_HRTB zI&{=^6j9Qlp~P?*CxJ7W1yk<5I3pUfIC6$O<=pUKOnuW?8S_{SXvB1+D41KZfPzp`;`BGl`0M>R>I*QdC+vt From 67fbb1a39555ba195747a71cf89bda3c5bfba43b Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 15 Sep 2023 16:48:38 +0200 Subject: [PATCH 002/235] use first version of appose java --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 75d588a8..2fc67e56 100644 --- a/pom.xml +++ b/pom.xml @@ -134,7 +134,7 @@ org.apposed appose - 0.1.0-SNAPSHOT + 0.1.0 org.msgpack From 7bfada2ef66fce80502538904fffb503a6cb4361 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 15 Sep 2023 16:54:00 +0200 Subject: [PATCH 003/235] remove not needed files --- .../bioimageio/bioengine/BioEngineInput.java | 355 -------------- .../bioengine/BioEngineInputTensor.java | 229 --------- .../bioimageio/bioengine/BioEngineOutput.java | 379 --------------- .../bioengine/BioEngineOutputArray.java | 440 ------------------ .../bioimageio/bioengine/BioEngineServer.java | 323 ------------- .../bioengine/BioengineConnection.java | 5 - 6 files changed, 1731 deletions(-) delete mode 100644 src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineInput.java delete mode 100644 src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineInputTensor.java delete mode 100644 src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineOutput.java delete mode 100644 src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineOutputArray.java delete mode 100644 src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineServer.java delete mode 100644 src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioengineConnection.java diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineInput.java b/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineInput.java deleted file mode 100644 index 054eed3d..00000000 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineInput.java +++ /dev/null @@ -1,355 +0,0 @@ -package io.bioimage.modelrunner.bioimageio.bioengine; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.Buffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.zip.GZIPOutputStream; - -import org.msgpack.jackson.dataformat.MessagePackFactory; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import io.bioimage.modelrunner.bioimageio.description.weights.ModelWeight; -import io.bioimage.modelrunner.tensor.Tensor; -import net.imglib2.type.NativeType; -import net.imglib2.type.numeric.RealType; - -/** - * Class to create inputs that can be sent to the BioEngine server. - * The input tensors should be defined as an array of inputs, where - * each of the inputs can be either a String, int or any other type, - * but in case the input is an array, it should be encoded as a - * {@link HashMap}. It needs to have the key "_rtype" with the - * corresponding value "ndarray", the key "_rvalue" with an array of - * bytes corresponding to the data wanted to be encoded, a key "_rshape" - * which should contain the shape of the array and finally the "_rdtype" - * corresponding to the array datatype. - * The array of inputs should be then included in another hashmap under - * the key "inputs", together with the key "model_name" and the name of - * the model and "decode_json" true. - * There is an example defined in Python at: - * https://gist.github.com/oeway/b6a6b810f94c91bb902e80a2f788b9e2#file-access_triton_service_hyhpa-py-L22 - * - * @author Carlos Javier García López de Haro - */ -public class BioEngineInput { - /** - * Name of the model that is going to be called - */ - private String modelName; - /** - * Map containing the instances needed to provide an input to the - * server. - * The input needs to have: - * -An entry called "inputs", whose value is another Map that contains - * the info about the input tensors - * -An entry called model_name with the name of the model - * -A fixed entry called decoe_json that equals to true - */ - private HashMap kwargs = new HashMap(); - /** - * List containing encoded tensors that are going to be used by the BioEngine. - * The entries of this list can be either: - * -A @see java.util.LinkedHashMap generated by - * @see org.bioimageanalysis.icy.deepicy.model.bioimageio.BioEngineInputTensor - * for array tensors - * -A @see java.util.LinkedHashMap for non dimensional parameters - */ - private List inputs = new ArrayList(); - /** - * Models available in the BioImage.io have a model_id to identify them - */ - private String bioimageioModelId; - /** - * String key corresponding to the model name parameter in the - * {@link #kwargs} map - */ - private static String modelNameKey = "model_name"; - /** - * String key corresponding to the actual tensor inputs in the - * {@link #kwargs} map - */ - private static String inputsKey = "inputs"; - /** - * String key corresponding to the decode Json parameter in the - * {@link #kwargs} map - */ - private static String decodeJsonKey = "decode_json"; - /** - * Value corresponding to the decode Json parameter in the - * {@link #kwargs} map. It is fixed. - */ - private static boolean decodeJsonVal = true; - /** - * Key for the input of the BioEngine corresponding to the type of serialization - */ - private static String serializationKey = "serialization"; - /** - * Value for the BioEngine serialization - */ - private static String serializationVal = "imjoy"; - /** - * Key for the Bioimage.io model_id as in the rdf.yaml - */ - private static String modelIDKey = "model_id"; - /** - * Optional key to run a Bioimage.io model to specify in which weights - * the model is going to run - */ - private static String modelWeightsKey = "weight_format"; - /** - * Optional key to run a Bioimage.io model to specify in which weights - * the model is going to run - */ - private static String rdfKey = "return_rdf"; - /** - * OPtional weights selected. If no weights are proposed the default weights - * are selected - */ - private String modelWeights; - /** - * Whether the inputs have been closed or not - */ - private boolean closed = false; - - /** - * Create the Bioengine input - * @param modelName - * name of the model that is going to be called - */ - private BioEngineInput(String modelName, String modelID) { - this.modelName = modelName; - bioimageioModelId = modelID; - workaroundModelID(); - kwargs.put(modelNameKey, modelName); - if (BioEngineServer.isBioImageIoKey(modelName)) { - kwargs.put(serializationKey, serializationVal); - } else { - kwargs.put(decodeJsonKey, decodeJsonVal); - } - } - - /** TODO - * Workaround for BioImage.io model runner. It does not work with the full version, it - * only works with: major_version_/second_version - */ - private void workaroundModelID() { - if (bioimageioModelId == null) - return; - int nSubversions = bioimageioModelId.length() - bioimageioModelId.replace("/", "").length(); - if (nSubversions == 2) { - bioimageioModelId = bioimageioModelId.substring(0, bioimageioModelId.lastIndexOf("/")); - } - } - - /** - * Build the object that contains the inputs to - * the BioEngine in the corresponding format - * @param modelName - * the name of the model of interest - * @return an object that can be used to provide - * inputs to the BioEngine - */ - public static BioEngineInput buildNonBioimageioInput(String modelName) { - return new BioEngineInput(modelName, null); - } - - /** - * Build the object that contains the inputs to - * the BioEngine in the corresponding format - * @param modelName - * the name of the model of interest - * @return an object that can be used to provide - * inputs to the BioEngine - */ - public static BioEngineInput buildBioimageioInput(String modelName) { - return new BioEngineInput(BioEngineServer.bioImageIoModelName(), modelName); - } - - /** - * Build the object that contains the inputs to - * the BioEngine in the corresponding format - * @param modelName - * the name of the model of interest - * @param modelId - * the model_id of the model of interest as of in the rdf.yaml. Must be always null - * unless the wanted model comes from the bioimage.io repo. In that case modelName - * always has to be "bioengine-model-runner" - * @return an object that can be used to provide - * inputs to the BioEngine - */ - public static BioEngineInput build(String modelName, String modelId) { - if (modelId != null && !BioEngineServer.isBioImageIoKey(modelName)) { - throw new IllegalArgumentException("A non null second parameter (model_id) should " - + "only be provided in the case a model available in the BioImage.io " - + "is going to be run. In that case, the first parameter (modelName) must " - + "always be: " + BioEngineServer.bioImageIoModelName()); - } - return new BioEngineInput(modelName, modelId); - } - - /** - * MEthod to be called when no more inputs need to be defined - */ - public void setAllInputs() { - throwExceptionIfClosed(); - if (bioimageioModelId != null) { - Map auxMap = new HashMap(); - auxMap.put(inputsKey, inputs); - auxMap.put(modelIDKey, bioimageioModelId); - auxMap.put(modelIDKey, bioimageioModelId); - auxMap.put(rdfKey, true); - if (modelWeights != null) - auxMap.put(modelWeightsKey, modelWeights); - ArrayList auxList = new ArrayList(); - auxList.add(auxMap); - kwargs.put(inputsKey, auxList); - } else { - kwargs.put(inputsKey, inputs); - } - } - - /** - * MEthod to set the weight format selected in the bioengine run - * @param ww - * seleced weight format, has to be one of the allowed weight formats - */ - public void setWeights(String ww) { - modelWeights = ww.toLowerCase(); - if (!modelWeights.equals(ModelWeight.getKerasID()) && !modelWeights.equals(ModelWeight.getOnnxID()) - && !modelWeights.equals(ModelWeight.getPytorchID()) && !modelWeights.equals(ModelWeight.getTensorflowID()) - && !modelWeights.equals(ModelWeight.getTensorflowJsID()) - && !modelWeights.equals(ModelWeight.getTorchscriptID())) { - throw new IllegalArgumentException("The selected weight format (" + ww + ") " - + "does not correspond with any of the weight formats available: " - + ModelWeight.getKerasID() + ", " + ModelWeight.getTorchscriptID() + ", " + ModelWeight.getPytorchID() - + ", " + ModelWeight.getTensorflowID() + ", " + ModelWeight.getTensorflowJsID() - + ", " + ModelWeight.getOnnxID()); - } - } - - /** - * Adds the Object as a parameter input to the model. - * In this case there is no need to encode it. - * Arrays or objects with more than one value (images) - * should not be provided as inputs in this way. Call {@link #setAllInputs()} - * when there are no more inputs to define. - * @param paramKey - * the name of the input single dimension tensor - * @param param - * the value of the input single dimension tensor - */ - public void addParameterInput(String paramKey, Object param) { - throwExceptionIfClosed(); - Map pp = new HashMap(); - pp.put(paramKey, param); - inputs.add(pp); - } - - /** - * Adds the buffer as an input to the model - * @param buff - * the buffer we want as an input - * @param axesOrder - * the shape of the array of interest - * @throws Exception if the data type of the buffer is not within the allowed ones - */ - public < T extends RealType< T > & NativeType< T > > - void addTensorInput(Tensor tensor) throws Exception { - throwExceptionIfClosed(); - inputs.add(BioEngineInputTensor.build(tensor).getInputsMap()); - } - - /** - * Serialize the {@link LinkedHashMap} and compress it to be - * able to feed it to the BioEngine - * @return the serialized and compressed input to the - * BioEngine ready to be sent - * @throws JsonProcessingException if the inputs could not be - * serialized - * @throws IOException if the serialized inputs could not be compressed - */ - public byte[] serializeAndCompress() throws JsonProcessingException, IOException { - throwExceptionIfClosed(); - return compress(serialize()); - } - - /** - * Compresses an array of bytes into an smaller array of bytes - * @param serialized - * the original array of bytes - * @return the compressed array of bytes - * @throws IOException if the bytes could not be compressed - */ - public static byte[] compress(byte[] uncompressedData) throws IOException { - byte[] result = new byte[]{}; - try (ByteArrayOutputStream bos = new ByteArrayOutputStream(uncompressedData.length); - GZIPOutputStream gzipOS = new GZIPOutputStream(bos)) { - gzipOS.write(uncompressedData); - // You need to close it before using bos - gzipOS.close(); - result = bos.toByteArray(); - bos.close(); - } catch (IOException e) { - e.printStackTrace(); - } - return result; - } - - /** - * Serialize the {@link LinkedHashMap} - * @return the serialized input map - * @throws JsonProcessingException if there is an error with the - * serialization - */ - public byte[] serialize() throws JsonProcessingException { - throwExceptionIfClosed(); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - byte[] bytes = objectMapper.writeValueAsBytes(this.kwargs); - return bytes; - } - - /** - * Get the model name - * @return the modelName - */ - public String getModelName() { - throwExceptionIfClosed(); - return modelName; - } - - /** - * Free from the memory the creaated bioengine inputs - */ - public void close() { - modelName = null; - inputs = null; - kwargs = null; - bioimageioModelId = null; - closed = true; - } - - /** - * Whether the tensor is closed or not - * @return true if closed, false otherwise - */ - public boolean isClosed() { - return closed; - } - - /** - * Throw {@link IllegalStateException} if the tensor has been closed - */ - private void throwExceptionIfClosed() { - if (!closed) - return; - throw new IllegalStateException("The tensor that is trying to be modified has already been " - + "closed."); - } -} diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineInputTensor.java b/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineInputTensor.java deleted file mode 100644 index 47ec82af..00000000 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineInputTensor.java +++ /dev/null @@ -1,229 +0,0 @@ -package io.bioimage.modelrunner.bioimageio.bioengine; - -import java.nio.FloatBuffer; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.bioimage.modelrunner.numpy.DecodeImgLib2; -import io.bioimage.modelrunner.tensor.Tensor; -import net.imglib2.type.NativeType; -import net.imglib2.type.numeric.RealType; -import net.imglib2.type.numeric.integer.ByteType; -import net.imglib2.type.numeric.integer.IntType; -import net.imglib2.type.numeric.integer.ShortType; -import net.imglib2.type.numeric.real.DoubleType; -import net.imglib2.type.numeric.real.FloatType; -/** - * Class to create the map that encodes the array inputs that need to be - * passed to the BioEngine. - * The input tensors should be defined as an array of inputs, where - * each of the inputs can be either a String, int or any other type, - * but in case the input is an array, it should be encoded as a - * {@link HashMap}. It needs to have the key "_rtype" with the - * corresponding value "ndarray", the key "_rvalue" with an array of - * bytes corresponding to the data wanted to be encoded, a key "_rshape" - * which should contain the shape of the array and finally the "_rdtype" - * corresponding to the array datatype. - * The array of inputs should be then included in another hashmap under - * the key "inputs", together with the key "model_name" and the name of - * the model and "decode_json" true. - * There is an example defined in Python at: - * https://gist.github.com/oeway/b6a6b810f94c91bb902e80a2f788b9e2#file-access_triton_service_hyhpa-py-L22 - * - * @author Carlos Javier García López de Haro - */ -public class BioEngineInputTensor { - - /** - * Map containing the instances needed to provide an input to the - * server. - * The input needs to have: - * -An entry called "inputs", whose value is another Map that contains - * the info about the input tensors - * -An entry called model_name with the name of the model - * -A fixed entry called decoe_json that equals to true - */ - private Map inputs = new HashMap(); - /** - * String key corresponding to the type of the array in the - * {@link #inputs} map - */ - private static String typeKey = "_rtype"; - /** - * Value corresponding to the type of the array in the - * {@link #inputs} map - */ - private String ndarrayVal = "ndarray"; - /** - * Value corresponding to a parameter - */ - private String paramVal = "parameter"; - /** - * String key corresponding to the value of the array in the - * {@link #inputs} map - */ - private String valKey = "_rvalue"; - /** - * String key corresponding to the shape of the array in the - * {@link #inputs} map - */ - private String shapeKey = "_rshape"; - /** - * String key corresponding to the dtype of the array in the - * {@link #inputs} map - */ - private String dtypeKey = "_rdtype"; - /** - * String corresponding to the dtype of the array in the - * {@link #inputs} map - */ - private String dtypeVal; - /** - * String used as tag for the int32 np dtype - */ - private static String int32Str = "int32"; - /** - * String used as tag for the float32 np dtype - */ - private static String float32Str = "float32"; - /** - * String used as tag for the float64 np dtype - */ - private static String float64Str = "float64"; - /** - * String used as tag for the byte or int8 np dtype - */ - private static String byteStr = "int8"; - /** - * String used as tag for the byte or int16 np dtype - */ - private static String int16Str = "int16"; - - /** - * Create the BioEngine input - * @param buff - * buffer containing the information about the array of interest - * @param shape - * shape of the array of interest - * @throws Exception if the data type of the buffer is not within the allowed ones - */ - private BioEngineInputTensor(Tensor tensor) throws Exception { - this.inputs.put(typeKey, ndarrayVal); - this.inputs.put(shapeKey, tensor.getShape()); - setDType(tensor); - this.inputs.put(valKey, DecodeImgLib2.tensorDataToByteArray(tensor)); - } - - private BioEngineInputTensor(Map params) throws Exception { - this.inputs.put(typeKey, paramVal); - this.inputs.put(shapeKey, new int[] {1}); - this.inputs.put(this.dtypeKey, "BYTES"); - this.inputs.put(valKey, params); - } - - public static BioEngineInputTensor buildParamInput(Map params) throws Exception { - return new BioEngineInputTensor(params); - } - - /** - * Returns a {@link #BioEngineInputTensor(FloatBuffer, int[])} linked map - * @param buff - * buffer containing the information about the array of interest - * @param shape - * shape of the array of interest - * @return the LinkedHashMap produced by the {@link #BioEngineInputTensor(FloatBuffer, int[])} - * class. The map is actually what is used as an input in the BioEngine - * @throws Exception if the data type of the buffer is not within the allowed ones - */ - public static < T extends RealType< T > & NativeType< T > > - BioEngineInputTensor build(Tensor tensor) throws Exception { - return new BioEngineInputTensor(tensor); - } - - /** - * Convert a signed byte array into an unsigned byte array - * @param signed - * the signed byte array - * @return an unsigned byte array - */ - public static byte[] signed2unsignedByte(byte[] signed) { - byte[] unsigned = new byte[signed.length]; - int c = 0; - for (byte b : signed) - unsigned[c ++] = (byte) (b & 0xFF); - return unsigned; - } - - /** - * Set the input dType as the dtype of the data - * @throws Exception if the data type of the buffer is not within the allowed ones - */ - public < T extends RealType< T > & NativeType< T > > - void setDType(Tensor tensor) throws Exception { - if (tensor.getDataType() instanceof IntType) { - dtypeVal = int32Str; - } else if (tensor.getDataType() instanceof ByteType) { - dtypeVal = byteStr; - } else if (tensor.getDataType() instanceof FloatType) { - dtypeVal = float32Str; - } else if (tensor.getDataType() instanceof DoubleType) { - dtypeVal = float64Str; - } else if (tensor.getDataType() instanceof ShortType) { - dtypeVal = int16Str; - } else { - throw new Exception("The type of the image is not within the allowd types.\n" - + "Allowed types are: " + int32Str + ", " - + float32Str + ", " + float64Str + ", " + byteStr + ", " + int16Str + "."); - } - this.inputs.put(this.dtypeKey, dtypeVal); - } - - /** - * REturn the encoded map of the array tnsor. This is what actually - * goes into the BioEngine - * @return the encoded array input tensor - */ - public Map getInputsMap(){ - return inputs; - } - - public String getType() { - return (String) this.inputs.get(typeKey); - } - - public String getDataType() { - return (String) this.inputs.get(dtypeKey); - } - - public int[] getShape() { - @SuppressWarnings("unchecked") - List list = (List) this.inputs.get(shapeKey); - int[] array = new int[list.size()]; - for (int i = 0; i < list.size(); i ++) - array[i] = (int) list.get(i); - return array; - } - - public Object getData() { - return this.inputs.get(valKey); - } - - public void addParams(Map nParams) { - if (!this.inputs.get(typeKey).equals(paramVal)) - throw new IllegalArgumentException(); - if (this.getData() instanceof Map) { - @SuppressWarnings("unchecked") - Map nMap = (Map) getData(); - nMap.putAll(nParams); - this.inputs.put(valKey, nMap); - } else if (this.getData() instanceof byte[]) { - Map nMap = new HashMap(); - nMap.put(valKey, this.getData()); - nMap.putAll(nParams); - this.inputs.put(valKey, nMap); - } else { - throw new IllegalArgumentException("BioEngine tensor is built incorrectly."); - } - } -} diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineOutput.java b/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineOutput.java deleted file mode 100644 index a43b6f1a..00000000 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineOutput.java +++ /dev/null @@ -1,379 +0,0 @@ -package io.bioimage.modelrunner.bioimageio.bioengine; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Objects; - -import org.msgpack.jackson.dataformat.MessagePackFactory; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.exc.MismatchedInputException; -import com.google.gson.JsonParseException; - - -/** - * Class manage outputs produced by a BioEngine server. - * The output of the BioEngine is an array of bytes that encode a Map with the actual - * outputs of the model and a field called "__info__" that contains the information - * about the output produced. - * There is an example defined in Python at: - * https://gist.github.com/oeway/b6a6b810f94c91bb902e80a2f788b9e2#file-access_triton_service_hyhpa-py-L22 - * - * @author Carlos Javier García López de Haro - */ -public class BioEngineOutput { - - /** - * The deserialized output of the BioEngine server. The BioEngine encodes the - * model output into bytes so it can post the result to local consumers - * via Https Request. The deserialized output is basically the output of the - * model before the encoding by the BioEngine. - * The output is a Map that consists on: - * - An information field "__info__" containing information about the name, - * shape and data type of the outputs - * - A map for each of the individual outputs, which can be ndarrays or - * parameters - */ - public LinkedHashMap deserializedOutput = new LinkedHashMap(); - /** - * Key for the entry in the outputs HashMap that contains information - * about the other outputs of the BioEngine. This information covers - * the output names, the shape, the datatype and the size - */ - private static String outputInfoKey = "__info__"; - /** - * Key to the information about the outputs inside the __info__ - * dictionary - */ - private static String outputInfoListKey = "outputs"; - /** - * List of dictionaries, containing each of them information about - * each of the outputs. This information corresponds to the name of the - * output, the datatype, the shape and the size - */ - private List> outputsInfo; - /** - * Key in the __info__ HashMap that contains the name of each - * of teh outputs of the model - */ - private static String outputInfoNameKey = "name"; - /** - * Key in the __info__ HashMap that contains the name of the BioENgine model run. - * It can be either the name of the model or "bioimage.model-runner" if the model - * being run comes from the bioimage.io repo - */ - private static String modelNameKey = "model_name"; - /** - * Key for the field in the output dictionary that specifies whether the model - * execution has been a success or not - */ - private static String successKey = "success"; - /** - * For each output,key that defined the output object that it is. - * Currently it is only available for the type "ndarray" which corresponds - * to an image. If it does not exist, te output is assumed to be a - * parameter - */ - private static String outputRTypeKey = "_rtype"; - /** - * Key for the field of the BioEngine output dictionary that contains the results - * of the model execution for BioImage.io models ONLY - */ - private static String bioimageioResultKey = "outputs"; - /** - * Value of the {@link #outputRTypeKey} that corresponds to an - * image array - */ - private String imageArrayValue = "ndarray"; - /** - * Whether the model whose output this object represents comes from the - * BioImage.io repo - */ - private boolean bioimageio = false; - /** - * List containing the output arrays of the BioEngine model - * The entries are {@link BioEngineOuputArray} - */ - private List list = new ArrayList(); - /** - * Whether the outputs have been closed or not - */ - private boolean closed = false; - /** - * Error message displayed when there is an error of execution inside the BioEngine - */ - private static String errMsg = "Python error at the BioEngine.\n"; - - /** - * Create the Bioengine input - * @param modelName - * name of the model that is going to be called - * @throws IOException if there is any error deserializing the raw output bytes - * @throws JsonMappingException if there is any error deserializing the raw output bytes - * @throws JsonParseException if there is any error deserializing the raw output bytes - * @throws Exception if the BioEngine sends an error message after execution - */ - private BioEngineOutput(byte[] rawOutput) throws JsonParseException, - JsonMappingException, - IOException, Exception { - deserializeOutput(rawOutput); - // Remove the bytes from memory - rawOutput = null; - processOutputs(); - } - - /** - * Build the object that contains the inputs to - * the BioEngine in the corresponding format - * @param modelName - * the name of the model of interest - * @return an object that can be used to provide - * inputs to the BioEngine - * @throws IOException if there is any error deserializing the raw output bytes - * @throws JsonMappingException if there is any error deserializing the raw output bytes - * @throws JsonParseException if there is any error deserializing the raw output bytes - * @throws Exception if the BioEngine sends an error message after execution - */ - public static BioEngineOutput build(byte[] rawOutput) throws JsonParseException, JsonMappingException, IOException, - Exception { - return new BioEngineOutput(rawOutput); - } - - /** - * Creates readable outputs by the Java software from the BioEngine - * output. The BioEngine output consists in bytes for every image and - * parameter. This method will create buffers of data that can easily be - * transformed into an Icy sequence or Fiji/ImageJ image - * @throws Exception if the BioEngine sends an error message after execution - */ - private void processOutputs() throws Exception { - lookForErrors(); - setOutputsInfo(); - try { - createOutputsFromInfo(); - } catch (NullPointerException ex) { - String msg = "DeepIcy does not recognize the format of the BioEngine output. Either the " - + "output is incorrect or the format of the BioEngine has changed and DeepIcy has" - + " not adapted yet."; - // TODO MessageDialog.showDialog("Empty/Incorrect BioEngine output", msg, MessageDialog.ERROR_MESSAGE); - } catch (Exception ex) { - // TODO MessageDialog.showDialog("Empty/Incorrect BioEngine output", ex.getMessage(), MessageDialog.ERROR_MESSAGE); - } - } - - @SuppressWarnings("unchecked") - /** - * Find if the BioEngine sends any error message after execution - * @throws Exception if the BioEngine sends an error message after execution - */ - private void lookForErrors() throws Exception { - LinkedHashMap results = - (LinkedHashMap) this.deserializedOutput.get("result"); - // Special models such as cell pose do not have the same keys as the Bioimage.io models - if (results == null ||results.get("success") == null) - return; - boolean success = (boolean) results.get("success"); - if (!success) { - String msg = (String) results.get("error"); - msg = errMsg + msg; - throw new Exception(msg); - } - } - - /** - * Create readable objects from the deserialized output of the BioEngine using - * the information provided by the BioEngine - * @throws Exception if no output can be retrieved from the data returned by the BioEngine - */ - private void createOutputsFromInfo() throws Exception { - if (this.outputsInfo != null && this.outputsInfo.size() != 0) - for (LinkedHashMap output : this.outputsInfo) { - createOutput((String) output.get(outputInfoNameKey)); - } else if (this.deserializedOutput != null && this.deserializedOutput.size() != 0) { - for (String outputName : this.deserializedOutput.keySet()) - createOutput(outputName); - } - if (list == null || list.size() == 0) { - String msg = "The deserialized BioEngine output did not contain (or\n" - + "the program could not find) any information."; - throw new Exception(msg); - } - } - - /** - * Create an array output readable by Java from a single output map produced - * by the BioEngine - * @param outputName - * the name of the output of interest - * @param output - * the map containing the info of interest - */ - private void createOutputBioImageIo(String outputName, LinkedHashMap output) { - Objects.requireNonNull(output); - if (output.get(successKey) == null || !((boolean) output.get(successKey))) - return; - List> outputList = (List>) output.get(bioimageioResultKey); - Objects.requireNonNull(outputList); - createOutputsFromList(outputName, outputList); - } - - /** - * Create an array output readable by Java from a single output map produced - * by the BioEngine - * @param outputName - * the name of the output of interest - * @param output - * the map containing the info of interest - */ - private void createOutputFromMap(String outputName, LinkedHashMap output) { - if (output.get(outputRTypeKey) != null && output.get(outputRTypeKey).equals(imageArrayValue)) { - addOutputToList(outputName, output); - } - } - - /** - * Adds output to list of outputs obtained from the BioEngine - * @param outputName - * name of the output - * @param output - * output Map - */ - private void addOutputToList(String outputName, LinkedHashMap output) { - try { - this.list.add(BioEngineOutputArray.buildOutput(outputName, output)); - } catch (IllegalArgumentException ex) { - ex.printStackTrace(); - // TODO MessageDialog.showDialog("Invalid output", ex.getMessage(), MessageDialog.ERROR_MESSAGE); - } catch (Exception ex) { - ex.printStackTrace(); - // TODO MessageDialog.showDialog("Invalid output", "Error retrieving output '" + outputName + "'.", - // TODO MessageDialog.ERROR_MESSAGE); - } - } - - /** - * Create an array output readable by Java from a single output List produced - * by the BioEngine - * @param outputList - * the list containing the info of interest - */ - private void createOutputsFromList(String name, List> outputList) { - for (int i = 0; i < outputList.size(); i ++) { - LinkedHashMap output = outputList.get(i); - String outputName = name + "_" + i; - createOutputFromMap(outputName, output); - } - } - - /** - * Create an array output readable by Java from a single entry of the output map produced - * by the BioEngine - * @param outputName - * the name of the output of interest - */ - private void createOutput(String outputName) { - Object outObject = deserializedOutput.get(outputName); - if (!bioimageio && outObject instanceof LinkedHashMap) { - createOutputFromMap(outputName, (LinkedHashMap) outObject); - } else if (bioimageio && outObject instanceof LinkedHashMap) { - createOutputBioImageIo(outputName, (LinkedHashMap) outObject); - } else if (this.deserializedOutput.get(outputName) instanceof List) { - // TODO what to do with other types of output - } - } - - /** - * Set the information about the outputs. This information is obtained - * from the same output of the BioEngine - */ - public void setOutputsInfo() { - throwExceptionIfClosed(); - if (this.outputsInfo == null) { - LinkedHashMap __info__ = (LinkedHashMap) this.deserializedOutput.get(outputInfoKey); - this.outputsInfo = (List>) __info__.get(outputInfoListKey ); - bioimageio = BioEngineServer.isBioImageIoKey((String) __info__.get(modelNameKey)); - } - } - - /** - * DEserialize the byte output of the BioEngine server. Convert the bytes into the - * objects that the server produced. Set the HashMap of objects as an attribute of the - * class - * @param rawOutput - * raw bytes outputed by the server - * @throws JsonParseException if there is any error deserializing the raw output bytes - * @throws JsonMappingException if there is any error deserializing the raw output bytes - * @throws IOException if there is any error deserializing the raw output bytes - */ - private void deserializeOutput(byte[] rawOutput) throws JsonParseException, - JsonMappingException, - IOException { - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - try { - LinkedHashMap deserialized = objectMapper.readValue(rawOutput, new TypeReference>() {}); - this.deserializedOutput = deserialized; - } catch (MismatchedInputException ex) { - throw new IOException("Error: 500 Internal Server Error. " - + "Connection to the BioEngine server aborted because it was taking too long."); - } - } - - /** - * REturns the output of the BioEngine server after deserialization. - * @return the output of the BioEngine - */ - public LinkedHashMap getDeserializedOutput(){ - throwExceptionIfClosed(); - return this.deserializedOutput; - } - - /** - * Get the array outputs produced by the model called in the BioEngine - * @return the array outputs produced - */ - public List getArrayOutputs(){ - throwExceptionIfClosed(); - return this.list; - } - - /** - * Close the outputs of the BioEngine to free the memory - */ - public void close() { - list = null; - deserializedOutput = null; - outputsInfo = null; - imageArrayValue = null; - closed = true; - } - - /** - * Whether the tensor is closed or not - * @return true if closed, false otherwise - */ - public boolean isClosed() { - return closed; - } - - /** - * Throw {@link IllegalStateException} if the tensor has been closed - */ - private void throwExceptionIfClosed() { - if (!closed) - return; - throw new IllegalStateException("The tensor that is trying to be modified has already been " - + "closed."); - } - - /** - * Return the error message that is displayed when the BioEngine fails - * @return standard BioEngine error message - */ - public static String getBioEngineErrorMsg() { - return errMsg; - } -} diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineOutputArray.java b/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineOutputArray.java deleted file mode 100644 index a76b334b..00000000 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineOutputArray.java +++ /dev/null @@ -1,440 +0,0 @@ -package io.bioimage.modelrunner.bioimageio.bioengine; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.DoubleBuffer; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.nio.ShortBuffer; -import java.util.ArrayList; -import java.util.HashMap; - -import io.bioimage.modelrunner.numpy.ByteArrayUtils; - -/** - * Class that converts each of the particular output arrays produced by the BioEngine - * server into readable buffers with their corresponding shape and data type. - * The produced object can be used to create an image easily. - * - * @author Carlos Javier García López de Haro - */ -public class BioEngineOutputArray { - /** - * Name of the output image array - */ - private String name; - /** - * Array containing the shape of the output array - */ - private int[] shape; - /** - * String containing the data type of the array. - * Look at TODO to see data types supported - */ - private String dtype; - /** - * Key in the output Map corresponding to the array information. - * This array information is provided as an array of bytes. - */ - private static String dataKey = "_rvalue"; - /** - * Key in the output Map corresponding to the array shape. - */ - private static String shapeKey = "_rshape"; - /** - * Key in the output Map corresponding to the array data type. - */ - private static String dTypeKey = "_rdtype"; - /** - * Key for the float32 data type - */ - private static String float32Key = "float32"; - /** - * Key for the int32 data type - */ - private static String int32Key = "int32"; - /** - * Key for the float64 data type - */ - private static String floa64Key = "float64"; - /** - * Key for the uint16 data type - */ - private static String uint16Key = "uint16"; - /** - * Key for the int16 data type - */ - private static String int16Key = "int16"; - /** - * Key for the uint8 data type - */ - private static String uint8Key = "uint8"; - /** - * Key for the int8 data type - */ - private static String int8Key = "int8"; - /** - * Key for the boolean data type - */ - private static String boolKey = "bool"; - /** - * Buffer containing the data of the output array of the BioEngine - */ - private Buffer dataBuffer; - - /** TODO add possibility of having parameters - * TODO we need the shape of the array too - * Manage ouputs from the BioEngine to be able to be handled by a common - * Java consumer - * @param name - * Name of the output - * @param outputMap - * Map containing the data produced by the BioEngine for a particular output - * @throws IllegalArgumentException if the data type of the array is not supported - */ - private BioEngineOutputArray(String name, HashMap outputMap) throws IllegalArgumentException { - setName(name); - setShape(outputMap.get(shapeKey)); - setDType((String) outputMap.get(dTypeKey)); - setArray(outputMap.get(dataKey)); - } - - /** - * Creates a BioEngine output array in a readable way for Java consumers - * @param name - * name of the output - * @param dataType - * data type of the tensor - * @param shape - * shape of the tensor - * @param buffer - * data of the tensor as a byte array - * @return an understandable tensor - * @throws IllegalArgumentException if the data type of the array is not supported - */ - public BioEngineOutputArray(String name, String dataType, Object shape, byte[] buffer) { - setName(name); - setShape(shape); - setDType(dataType); - setArray(buffer); - } - - /** - * Create an array from the bytes received by the BioEngine and using the corresponding shape - * and data types - * @param byteArray - * the byte array that contains the array data - * @throws IllegalArgumentException if the data type of the array is not supported - */ - private void setArray(Object byteArrayObject) throws IllegalArgumentException { - byte[] byteArray = null;; - try { - byteArray = getByteArray(byteArrayObject); - } catch (Exception ex) { - throw new IllegalArgumentException("Error retrieving information from the BioEngine output '" + this.name + "'.\n" - + "The array data is not correctly defined and cannot be read, it should be either a byte array or List of bytes."); - } - - if (this.dtype.toLowerCase().equals(floa64Key)) { - this.dataBuffer = convertIntoSignedFloat64(byteArray); - } else if (this.dtype.toLowerCase().equals(float32Key)) { - this.dataBuffer = convertIntoSignedFloat32(byteArray); - } else if (this.dtype.toLowerCase().equals(int32Key)) { - this.dataBuffer = convertIntoSignedInt32(byteArray); - } else if (this.dtype.toLowerCase().equals(int16Key)) { - this.dataBuffer = convertIntoSignedShort16(byteArray); - } else if (this.dtype.toLowerCase().equals(uint16Key)) { - this.dataBuffer = convertIntoUnsignedInt16(byteArray); - } else if (this.dtype.toLowerCase().equals(int8Key)) { - this.dataBuffer = convertIntoSignedInt8(byteArray); - } else if (this.dtype.toLowerCase().equals(uint8Key)) { - this.dataBuffer = convertIntoUnignedInt8(byteArray); - } else if (this.dtype.toLowerCase().equals(boolKey)) { - this.dataBuffer = convertIntoBoolean(byteArray); - } else { - throw new IllegalArgumentException("Output array '" + this.name +"' could not be retrieved.\n" - + "Its corresponding data type '" + this.dtype + "' is not supported yet."); - } - } - - /** - * Retrieve the buffer containing the data of the output array produced - * by the BioEngine - * @return the buffer with the output array - */ - public Buffer getArray() { - return this.dataBuffer; - } - - /** - * Converts byte array into a signed integer 16 bit array stored in - * a buffer. - * @param arr - * the byte array - * @return a integer 16 buffer containing the wanted data - */ - public static ShortBuffer convertIntoSignedShort16(byte[] arr) { - return ShortBuffer.wrap(ByteArrayUtils.convertIntoSignedShort16(arr)); - } - - /** - * Converts byte array into a signed integer 32 bit array stored in - * a buffer. - * @param arr - * the byte array - * @return a int buffer containing the wanted data - */ - public static IntBuffer convertIntoSignedInt32(byte[] arr) { - return IntBuffer.wrap(ByteArrayUtils.convertIntoSignedInt32(arr)); - } - - /** - * Converts byte array into a boolean array stored in - * a buffer. - * @param arr - * the byte array - * @return a int buffer containing the wanted boolean data - */ - public static IntBuffer convertIntoBoolean(byte[] arr) { - int[] boolArr = new int[arr.length]; - for (int i = 0; i < arr.length; i ++) { - boolArr[i] = (int) arr[i]; - } - return IntBuffer.wrap(boolArr); - } - - /** - * Converts byte array into a unsigned integer 16 bit array stored in - * a buffer. - * However, as this data type does not exist in Java, the values are stored - * in an int32 array containing the values that would correspond to - * an uin16 array - * @param arr - * the byte array - * @return an int buffer containing the wanted data - */ - public static IntBuffer convertIntoUnsignedInt16(byte[] arr) { - return IntBuffer.wrap(ByteArrayUtils.convertIntoUnsignedInt16(arr)); - } - - /** - * Converts byte array into a signed integer 8 bit array stored in - * a buffer. - * However, as this data type does not exist in Java, the values are stored - * in an int32 array containing the values that would correspond to - * an int8 array - * @param arr - * @param arr - * the byte array - * @return an int buffer containing the wanted data - */ - public static ByteBuffer convertIntoSignedInt8(byte[] arr) { - return ByteBuffer.wrap(arr); - } - - /** - * Converts byte array into an unsigned integer 8 bit array stored in - * a buffer. However, as this data type does not exist in Java, the values are stored - * in an int32 array containing the values that would correspond to - * an uint8 array - * @param arr - * @param arr - * the byte array - * @return an int buffer containing the wanted data - */ - public static IntBuffer convertIntoUnignedInt8(byte[] arr) { - int[] uint8 = new int[arr.length]; - for (int i = 0; i < arr.length; i ++) { - uint8[i] = arr[i] & 0xff; - } - return IntBuffer.wrap(uint8); - } - - /** - * Converts byte array into a signed float 32 bit array stored in - * a buffer. - * @param arr - * the byte array - * @return a float buffer containing the wanted data - */ - public static FloatBuffer convertIntoSignedFloat32(byte[] arr) { - return FloatBuffer.wrap(ByteArrayUtils.convertIntoSignedFloat32(arr)); - } - - /** - * Converts byte array into a signed float 64 bit array stored in - * a buffer. - * @param arr - * the byte array - * @return a double buffer containing the wanted data - */ - public static DoubleBuffer convertIntoSignedFloat64(byte[] arr) { - return DoubleBuffer.wrap(ByteArrayUtils.convertIntoSignedFloat64(arr)); - } - - /** - * Creates a BioEngine output array in a readable way for Java consumers - * @param name - * name of the output - * @param outputMap - * Map containing the information about the output - * @return an object with ordered information about the output that can be managed - * by the consumer software - * @throws IllegalArgumentException if the data type of the array is not supported - */ - public static BioEngineOutputArray buildOutput(String name, HashMap outputMap) throws IllegalArgumentException { - return new BioEngineOutputArray(name, outputMap); - } - - /** - * Creates a BioEngine output array in a readable way for Java consumers - * @param name - * name of the output - * @param dataType - * data type of the tensor - * @param shape - * shape of the tensor - * @param buffer - * data of the tensor as a byte array - * @return an understandable tensor - * @throws IllegalArgumentException if the data type of the array is not supported - */ - public static BioEngineOutputArray buildOutput(String name, String dataType, Object shape, byte[] buffer) throws IllegalArgumentException { - return new BioEngineOutputArray(name, dataType, shape, buffer); - } - - /** - * Sets the data type of the array - * @param dtype - * the data type - */ - private void setDType(String dtype) { - this.dtype = dtype; - } - - /** - * Gets the data type of the array - * @return the data type of the array - */ - public String getDType() { - return this.dtype; - } - - /** - * Sets the shape of the array - * @param shape - * the shape of the array - * @throws IllegalArgumentException if the shape object does not correspond to an array - */ - private void setShape(Object shape) throws IllegalArgumentException{ - try { - this.shape = getIntArray(shape); - } catch (Exception ex) { - throw new IllegalArgumentException("Error retrieving information from the BioEngine output '" + this.name + "'.\n" - + "The shape is not correctly defined, it should be either an int array or ArrayList."); - } - } - - /** - * Gets the shape of the array - * @return the shape of the array - */ - public int[] getShape() { - return this.shape; - } - - /** - * Sets the name of the array - * @param name - * the name of the array - */ - private void setName(String name) { - this.name = name; - } - - /** - * Gets the name of the array - * @return the name of the array - */ - public String getName() { - return this.name; - } - - /** - * Casts an int array in an object that contains an int array - * @param shape - * the object containing teh int array - * @return teh int array - * @throws Exception if it was impossible to cast the array from the object - */ - public int[] getIntArray(Object shape) throws Exception { - int[] shapeArr = null; - if (shape != null && shape instanceof ArrayList) { - ArrayList ll = (ArrayList) shape; - shapeArr = new int [ll.size()]; - for (int c = 0; c < ll.size(); c ++) - shapeArr[c] = castUnknownToInt(ll.get(c)); - } else if (shape != null&& shape instanceof int[]){ - shapeArr = (int[]) shape; - } else if (shape != null&& shape instanceof double[]){ - double[] shapeArrDouble = (double[]) shape; - shapeArr = new int[shapeArrDouble.length]; - for (int i = 0; i < shapeArrDouble.length; i ++) { - shapeArr[i] = (int) shapeArrDouble[i]; - } - } else { - throw new Exception("Datatype of shape array cannot be casted to int or double."); - } - return shapeArr; - } - - /** - * Cast unknown number to int - * @param unknownNumber - * the unknown number - * @return the int - */ - private int castUnknownToInt(Object unknownNumber) { - if (unknownNumber instanceof Integer){ - return (int) unknownNumber; - } else if (unknownNumber instanceof Double){ - return ((Double) unknownNumber).intValue(); - } else if (unknownNumber instanceof Float){ - return ((Float) unknownNumber).intValue(); - } else if (unknownNumber instanceof Short){ - return ((Short) unknownNumber).intValue(); - } else if (unknownNumber instanceof Byte){ - return ((Byte) unknownNumber).intValue(); - } else if (unknownNumber instanceof Long){ - return ((Long) unknownNumber).intValue(); - } else if (unknownNumber instanceof Number){ - return ((Number) unknownNumber).intValue(); - } else { - throw new IllegalArgumentException("Shape of the output '" + this.name - + "' is not defined with allowed Java types."); - } - } - - /** - * Casts a byte array in an object that contains a byte array - * @param listArr - * the object containing the byte array - * @return the byte array - * @throws Exception if it was impossible to cast the array from the object - */ - public static byte[] getByteArray(Object listArr) throws Exception { - byte[] arr = null; - if (listArr != null && listArr instanceof ArrayList) { - @SuppressWarnings("unchecked") - ArrayList ll = (ArrayList) listArr; - arr = new byte[ll.size()]; - for (byte c = 0; c < ll.size(); c ++) - arr[c] = (byte) ll.get(c); - } else if (listArr != null && listArr instanceof byte[]){ - arr = (byte[]) listArr; - } else { - throw new Exception(); - } - return arr; - } -} diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineServer.java b/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineServer.java deleted file mode 100644 index 07da3275..00000000 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioEngineServer.java +++ /dev/null @@ -1,323 +0,0 @@ -package io.bioimage.modelrunner.bioimageio.bioengine; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.ProtocolException; -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import java.util.zip.GZIPOutputStream; - -import org.apache.commons.io.IOUtils; -import org.bioimageanalysis.icy.deepicy.model.description.ModelDescriptor; -import org.msgpack.jackson.dataformat.MessagePackFactory; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * Class to interact with the Bioimage.io BioEngine server. - * - * @author Carlos Javier García López de Haro - */ -public class BioEngineServer { - - /** - * Server where the BioEngine is hosted - */ - private String server; - /** - * Name of the model of interest - */ - private String modelName; - /** - * For BioEngine execution calls, the data that is going to - * be sent to the server to make inference on - */ - private byte[] data; - /** - * Name of the default model used to run a model coming from the BioImage.io repo - */ - private static String defaultBioimageIoModelName = "bioengine-model-runner"; - - /** - * Class to interact with a server that hosts the BioENgine - * @param server - * name of the server - */ - private BioEngineServer(String server) { - this.server = server; - } - - /** - * Creates a BioEngine server - * @param server - * the name of the server where the BioEngine is hosted - * @return the {@link BioEngineServer} object - */ - public static BioEngineServer build(String server) { - return new BioEngineServer(server); - } - - /** - * Gets the {@link ModelDescriptor} of the model of interest by reading - * the model rdf.yaml from the BioEngine server - * @param modelName - * model of interest - * @return the model specs - * @throws Exception if the rdf.yaml of the model does not exist or - * cannot be read properly - */ - public ModelDescriptor getModelDescriptor(String modelName) throws Exception { - this.modelName = modelName; - return ModelDescriptor.loadFromJsonTextString(getConfigStr()); - } - - /** - * Retrieves a Json file in String format from a web address containing a Json file - * @param urlStr - * the Url where the json is - * @return - * a json file in String format - * @throws MalformedURLException if the URL is not correct - * @throws ProtocolException if the server cannot be accessed - * @throws IOException if any other issue happens - */ - public static String getJsonStringFromHttpRequest(String urlStr) throws MalformedURLException, - ProtocolException, - IOException { - URL url = new URL(urlStr); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("GET"); - con.setRequestProperty("Accept-Charset", "UTF-8"); - InputStream response = con.getInputStream(); - String responseBody = null; - try (Scanner scanner = new Scanner(response)) { - responseBody = scanner.useDelimiter("\\A").next(); - } - return responseBody; - } - - /** - * Provides the String url where the rdf.yaml file (config file) - * of the wanted model is located - * @return the String URL - */ - private String getConfigUrl() { - return server + "/public/services/triton-client/get_config?model_name=" + modelName; - } - - /** - * Obtain the rdf.yaml file that contains the specifications of the model - * - */ - private String getConfigStr() { - String jsonStr = null; - try { - jsonStr = getJsonStringFromHttpRequest(getConfigUrl()); - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (ProtocolException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return jsonStr; - } - - /** - * Get the URL of to send the data to be run in the BioEngine - * @return the post BioEngine URL - */ - private String getExecutionURL() { - return server + "/public/services/triton-client/execute"; - } - - /** - * Create a post connection with the BioEngine server - * @return the connection - * @throws ProtocolExceptionif the connection with the server cannot be opened - * or the server is not found - * @throws MalformedURLException if the url is not correct - * @throws IOException if the connection with the server cannot be opened - * or the server is not found - */ - private HttpURLConnection createConnection() throws ProtocolException, - MalformedURLException, - IOException{ - URL url = new URL(getExecutionURL()); - HttpURLConnection conn= (HttpURLConnection) url.openConnection(); - conn.setDoOutput( true ); - conn.setDoInput(true); - conn.setRequestMethod( "POST" ); - conn.setRequestProperty( "Content-Type", "application/msgpack"); - conn.setRequestProperty( "Content-Encoding", "gzip"); - conn.setRequestProperty( "Content-Length", Integer.toString(data.length)); - try( DataOutputStream wr = new DataOutputStream( conn.getOutputStream())) { - wr.write(data); - wr.flush(); - } - return conn; - } - - /** - * Creates a connectio, sends information and receives a response - * @return a byte array response from the server - * @throws ProtocolExceptionif the connection with the server cannot be opened - * or the server is not found - * @throws MalformedURLException if the url is not correct - * @throws IOException if the connection with the server cannot be opened - * or the server is not found - */ - private byte[] sendDataToServerAndReceiveResponse() throws ProtocolException, - MalformedURLException, - IOException { - HttpURLConnection conn = createConnection(); - - byte[] respon; - try { - respon = IOUtils.toByteArray(conn.getInputStream()); - } catch (Exception ex) { - InputStream aa = conn.getErrorStream(); - respon = IOUtils.toByteArray(aa); - } - return respon; - } - - /** - * Sends a byte array to a model in the BioEngine server, where inference - * is performed and it fetches the output array of bytes produced by the server - * @param data - * the data corresponding to the input to the model - * @return the output of the server - * @throws ProtocolExceptionif the connection with the server cannot be opened - * or the server is not found - * @throws MalformedURLException if the url is not correct - * @throws IOException if the connection with the server cannot be opened - * or the server is not found - */ - public byte[] executeModelOnBioEngine(byte[] data) throws ProtocolException, - MalformedURLException, - IOException { - this.data = data; - byte[] result = sendDataToServerAndReceiveResponse(); - // Set received data bytes to null to save memory - this.data = null; - return result; - } - - public static byte[] compress(byte[] uncompressedData) throws IOException { - byte[] result = new byte[]{}; - try (ByteArrayOutputStream bos = new ByteArrayOutputStream(uncompressedData.length); - GZIPOutputStream gzipOS = new GZIPOutputStream(bos)) { - gzipOS.write(uncompressedData); - // You need to close it before using bos - gzipOS.close(); - result = bos.toByteArray(); - bos.close(); - } catch (IOException e) { - e.printStackTrace(); - } - return result; - } - - /** - * Whether the name of the model corresponds to the key used to run BioImage.io models - * @param name - * name of a model - * @return true if the model name correpsonds to the Bioimage.io runner and false otherwise - */ - public static boolean isBioImageIoKey(String name) { - if (name != null && name.equals(defaultBioimageIoModelName)) - return true; - else - return false; - } - - /** - * REturn the name of the model used to run the BioImage.io repo models - * @return the name of the general model runner for Bioimage.io - */ - public static String bioImageIoModelName() { - return defaultBioimageIoModelName; - } - - public static void main(String[] args) throws IOException { - float[] data = new float[196608]; - ByteBuffer byteBuffer = ByteBuffer.allocate(data.length * 4); - FloatBuffer floatBuffer = byteBuffer.asFloatBuffer(); - floatBuffer.put(data); - byte[] array = byteBuffer.array(); - int[] shape = new int[] {3, 256, 256}; - String type = "float32"; - - Map map = new HashMap(); - map.put("_rtype", "ndarray"); - map.put("_rvalue", array); - map.put("_rshape", shape); - map.put("_rdtype", type); - Map params = new HashMap(); - params.put("diameter", 30); - List inputs = new ArrayList(); - inputs.add(map); - inputs.add(params); - - Map kwargs = new HashMap(); - kwargs.put("inputs", inputs); - kwargs.put("model_name", "cellpose-python"); - kwargs.put("decode_json", true); - - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - - byte[] bytes = objectMapper.writeValueAsBytes(kwargs); - //byte[] compressed = compressByteArray(bytes); - byte[] compressed = compress(bytes); - - try { - int postDataLength = compressed.length; - String request = "https://ai.imjoy.io/public/services/triton-client/execute"; - URL url = new URL( request ); - HttpURLConnection conn= (HttpURLConnection) url.openConnection(); - conn.setDoOutput( true ); - //conn.setInstanceFollowRedirects( false ); - conn.setDoInput(true); - conn.setRequestMethod( "POST" ); - conn.setRequestProperty( "Content-Type", "application/msgpack"); - conn.setRequestProperty( "Content-Encoding", "gzip"); - conn.setRequestProperty( "Content-Length", Integer.toString( postDataLength )); - conn.setUseCaches( false ); - try( DataOutputStream wr = new DataOutputStream( conn.getOutputStream())) { - wr.write( compressed ); - wr.flush(); - } - /* - OutputStream wr = conn.getOutputStream(); - wr.write( compressed ); - wr.flush(); - wr.close(); - */ - Map> aa = conn.getHeaderFields(); - - byte[] respon = IOUtils.toByteArray(conn.getInputStream()); - //System.out.println(conn.getResponseMessage()); - - // Deserialize the byte array to a Map - Map deserialized = objectMapper.readValue(respon, new TypeReference>() {}); - Object bb = deserialized.get("mask"); - System.out.println(deserialized); // => {name=komamitsu, age=42} - } catch (Exception ex) { - ex.printStackTrace(); - } - - - } -} diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioengineConnection.java b/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioengineConnection.java deleted file mode 100644 index f839c64f..00000000 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/bioengine/BioengineConnection.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.bioimage.modelrunner.bioimageio.bioengine; - -public class BioengineConnection { - -} From 18e011d127b535a3ec194595e360dc2948667f77 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 15 Sep 2023 18:03:55 +0200 Subject: [PATCH 004/235] start creating services/runModes --- .../modelrunner/PythonConnection.java | 2 +- .../modelrunner/runmode/AbstractRunMode.java | 42 ++++++++++++++ .../modelrunner/runmode/CellposeTrain.java | 43 ++++++++++++++ .../bioimage/modelrunner/runmode/RunMode.java | 56 +++++++++++++++++++ .../AbstractTensorTransformation.java | 1 - 5 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/AbstractRunMode.java create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/CellposeTrain.java create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/RunMode.java diff --git a/src/main/java/io/bioimage/modelrunner/PythonConnection.java b/src/main/java/io/bioimage/modelrunner/PythonConnection.java index 43c09c2a..f166e3b5 100644 --- a/src/main/java/io/bioimage/modelrunner/PythonConnection.java +++ b/src/main/java/io/bioimage/modelrunner/PythonConnection.java @@ -63,7 +63,7 @@ public static void runModelInPython(List> inputTensors, //tensorMap.put(AXES_KEY, input.getAxesOrderString()); //tensorMap.put(DATA_KEY, ImgLib2ToArray.buildFloat(input.getData())); // inputMap.put(NAME_KEY, tensorMap); - inputMap.put("tensor", ImgLib2ToArray.buildFloat(input.getData())); + inputMap.put("tensor", ImgLib2ToArray.build(input.getData())); } Environment env = Appose.base(new File("C:\\Users\\angel\\git\\jep\\miniconda\\envs\\testAppose")).build(); diff --git a/src/main/java/io/bioimage/modelrunner/runmode/AbstractRunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/AbstractRunMode.java new file mode 100644 index 00000000..25afb264 --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/AbstractRunMode.java @@ -0,0 +1,42 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode; + +/** + * + * @author Carlos Garcia Lopez de Haro + * + */ +public abstract class AbstractRunMode implements RunMode +{ + + private final String name; + + protected AbstractRunMode( final String name ) + { + this.name = name; + } + + @Override + public String getName() + { + return name; + } +} diff --git a/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrain.java b/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrain.java new file mode 100644 index 00000000..66345d3c --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrain.java @@ -0,0 +1,43 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode; + +import java.util.List; + +import io.bioimage.modelrunner.tensor.Tensor; + +/** + * + * @author Carlos Garcia Lopez de Haro + * + */ +public class CellposeTrain extends AbstractRunMode { + + protected CellposeTrain(String name) { + super(name); + } + + @Override + public List> apply(Tensor... inputs) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java new file mode 100644 index 00000000..78b6959e --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -0,0 +1,56 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode; + +import java.util.List; + +import io.bioimage.modelrunner.tensor.Tensor; + +/** + * Interface for run modes that contain complex Deep Learning routines. + * + * @author Carlos Garcia Lopez de Haro + * + */ +public interface RunMode +{ + + /** + * Applies the run mode transformation to the specified input/s tensor/s. + * + * This method will execute the corresponding run mode on the wanted inputs + * and return the result provided by the run mode. Regard that the run mode + * can be anything. For example tiling + model inference + post-processing; + * simply model inference; pre-processing + model inference + * + * + * @param inputs + * the input/s tensor/s. + * @return a list of the result tensors in their corresponding datatypes. + */ + public List> apply( Tensor< ? >... inputs ); + + /** + * Returns the name of this run mode. + * + * @return the name of this run mode. + */ + public String getName(); +} diff --git a/src/main/java/io/bioimage/modelrunner/transformations/AbstractTensorTransformation.java b/src/main/java/io/bioimage/modelrunner/transformations/AbstractTensorTransformation.java index bfcdf6ec..55ec60ae 100644 --- a/src/main/java/io/bioimage/modelrunner/transformations/AbstractTensorTransformation.java +++ b/src/main/java/io/bioimage/modelrunner/transformations/AbstractTensorTransformation.java @@ -66,7 +66,6 @@ protected < R extends RealType< R > & NativeType< R > > Tensor< FloatType > make { final ImgFactory< FloatType > factory = Util.getArrayOrCellImgFactory( input.getData(), new FloatType() ); final Img< FloatType > outputImg = factory.create( input.getData() ); - // TODO improve, do not copy here. Do it directly in the method to avoid looping twice over the images RealTypeConverters.copyFromTo(input.getData(), outputImg); final Tensor< FloatType > output = Tensor.build( getName() + '_' + input.getName(), input.getAxesOrderString(), outputImg ); return output; From ad726357637ccfc772b6b9db1a9ea84f5423a5f8 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 15 Sep 2023 19:05:42 +0200 Subject: [PATCH 005/235] use forgotten run mdoe --- .../modelrunner/runmode/AbstractRunMode.java | 2 +- .../bioimage/modelrunner/runmode/RunMode.java | 262 ++++++++++++++++-- .../modelrunner/runmode/RunMode2.java | 56 ++++ .../modelrunner/transformations/RunMode.java | 241 ---------------- 4 files changed, 290 insertions(+), 271 deletions(-) create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java delete mode 100644 src/main/java/io/bioimage/modelrunner/transformations/RunMode.java diff --git a/src/main/java/io/bioimage/modelrunner/runmode/AbstractRunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/AbstractRunMode.java index 25afb264..4c567cdf 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/AbstractRunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/AbstractRunMode.java @@ -24,7 +24,7 @@ * @author Carlos Garcia Lopez de Haro * */ -public abstract class AbstractRunMode implements RunMode +public abstract class AbstractRunMode implements RunMode2 { private final String name; diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 78b6959e..8ea4db00 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -19,38 +19,242 @@ */ package io.bioimage.modelrunner.runmode; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; -import io.bioimage.modelrunner.tensor.Tensor; +import org.apposed.appose.Appose; +import org.apposed.appose.Environment; +import org.apposed.appose.Service; +import org.apposed.appose.Service.Task; -/** - * Interface for run modes that contain complex Deep Learning routines. - * - * @author Carlos Garcia Lopez de Haro - * - */ -public interface RunMode -{ +import io.bioimage.modelrunner.bioimageio.ops.OpDescription; +import io.bioimage.modelrunner.tensor.ImgLib2ToArray; +import io.bioimage.modelrunner.tensor.Tensor; +import net.imglib2.img.Img; +import net.imglib2.img.ImgFactory; +import net.imglib2.img.cell.CellImgFactory; +import net.imglib2.type.NativeType; +import net.imglib2.type.numeric.RealType; +import net.imglib2.type.numeric.real.FloatType; - /** - * Applies the run mode transformation to the specified input/s tensor/s. - * - * This method will execute the corresponding run mode on the wanted inputs - * and return the result provided by the run mode. Regard that the run mode - * can be anything. For example tiling + model inference + post-processing; - * simply model inference; pre-processing + model inference - * - * - * @param inputs - * the input/s tensor/s. - * @return a list of the result tensors in their corresponding datatypes. - */ - public List> apply( Tensor< ? >... inputs ); +public class RunMode { + + private static final String AXES_KEY = "axes"; + + private static final String SHAPE_KEY = "shape"; + + private static final String DATA_KEY = "data"; + + private static final String BMZ_CORE_IMPORTS = + "import numpy as np" + System.lineSeparator() + + "import xarray as xr" + System.lineSeparator() + + "from bioimageio.core import load_resource_description" + System.lineSeparator() + + "from bioimageio.core.resource_io.nodes import Model" + System.lineSeparator(); + private static final String OP_PACKAGE = "bioimageio.workflows"; + + + private Environment env; + private String envFileName; + private String opCode; + private String opName; + private String referencedModel; + private LinkedHashMap kwargs; + + private RunMode(OpDescription op) { + /* + envFileName = op.getCondaEnv(); + referencedModel = op.appliedOnWhichModel(); + opName = op.getMethodName(); + kwargs = op.getMethodExtraArgs(); + */ + } + + public static RunMode createRunMode(OpDescription op) { + return new RunMode(op); + } + + public void envCreation() { + if (checkRequiredEnvExists()) { + env = Appose.base(new File(envFileName)).build(); + return; + } + env = Appose.conda(new File(envFileName)).build(); + } + + public boolean checkRequiredEnvExists() { + return false; + } + + private void addImports() { + opCode += BMZ_CORE_IMPORTS; + opCode += "from " + OP_PACKAGE + " import " + opName + System.lineSeparator(); + opCode += "async def run_workflow():" + System.lineSeparator(); + } + + public < T extends RealType< T > & NativeType< T > > + void addRecreationOfTensor(Tensor tensor) { + opCode += "\t" + tensor.getName() + "_data = " + tensor.getName() + "['" + DATA_KEY + "']" + System.lineSeparator() + + "\t" + tensor.getName() + " = np.array(" + tensor.getName() + "_data).reshape("; + for (int i : tensor.getShape()) { + opCode += i + ","; + } + opCode = opCode.substring(0, opCode.length() - 1); + opCode += ")" + System.lineSeparator(); + } + + private < T extends RealType< T > & NativeType< T > > + void addCodeBody(List> inputTensors, List> outputTensors) { + opCode += "\t" + "task.update('Start running workflow')" + System.lineSeparator(); + for (Tensor output : outputTensors) + opCode += "\t" + output.getName() + ","; + opCode = opCode.substring(0, opCode.length() - 1); + opCode += " = await " + this.opName + "(" + referencedModel + + ","; + for (Tensor input : inputTensors) + opCode += input.getName() + ","; + for (String key : kwargs.keySet()) + opCode += key + "=" + key + ","; + opCode = opCode.substring(0, opCode.length() - 1); + opCode += ")" + System.lineSeparator(); + opCode += "\t" + "task.update('Finished running workflow')" + System.lineSeparator(); + for (Tensor output : outputTensors) + opCode += "\t" + "tasks['" + output.getName() + "'] = " + output.getName() + System.lineSeparator(); + opCode += "asyncio.run(run_workflow())" + System.lineSeparator(); + } + + public static void main(String[] args) { + RunMode rm = new RunMode(null); - /** - * Returns the name of this run mode. - * - * @return the name of this run mode. - */ - public String getName(); + rm.envFileName = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; + rm.env = Appose.base(new File(rm.envFileName)).build(); + rm.referencedModel = "chatty-frog"; + rm.opName = "stardist_prediction_2d"; + rm.kwargs = new LinkedHashMap(); + + final ImgFactory< FloatType > imgFactory = new CellImgFactory<>( new FloatType(), 5 ); + final Img< FloatType > img1 = imgFactory.create( 1, 512, 512, 3 ); + // Create the input tensor with the nameand axes given by the rdf.yaml file + // and add it to the list of input tensors + Tensor inpTensor = Tensor.build("input0", "byxc", img1); + List> inputs = new ArrayList>(); + inputs.add(inpTensor); + + final Img< FloatType > img2 = imgFactory.create( 1, 512, 512, 1 ); + // Create the input tensor with the nameand axes given by the rdf.yaml file + // and add it to the list of input tensors + Tensor outTensor = Tensor.build("ouput0", "byxc", img2); + List> outputs = new ArrayList>(); + outputs.add(outTensor); + + rm.run(inputs, outputs); + + } + + public < T extends RealType< T > & NativeType< T > > + void run(List> inputTensors, List> outputTensors) { + + opCode = ""; + addImports(); + + LinkedHashMap inputMap = new LinkedHashMap<>(); + for (Tensor input : inputTensors) { + HashMap tensorMap = new HashMap(); + tensorMap.put(AXES_KEY, input.getAxesOrderString()); + tensorMap.put(DATA_KEY, ImgLib2ToArray.build(input.getData())); + tensorMap.put(SHAPE_KEY, input.getShape()); + inputMap.put(input.getName(), tensorMap); + + addRecreationOfTensor(input); + } + + inputMap.putAll(kwargs); + + addCodeBody(inputTensors, outputTensors); + opCode = "import numpy as np\r\n" + + "import asyncio\r\n" + + "import numpy as np\r\n" + + "import tempfile\r\n" + + "import warnings\r\n" + + "from math import ceil\r\n" + + "from os import PathLike\r\n" + + "from pathlib import Path\r\n" + + "from typing import Dict, IO, List, Optional, Tuple, Union\r\n" + + "\r\n" + + "import xarray as xr\r\n" + + "from stardist import import_bioimageio as stardist_import_bioimageio\r\n" + + "\r\n" + + "from bioimageio.core import export_resource_package, load_resource_description\r\n" + + "from bioimageio.core.prediction_pipeline._combined_processing import CombinedProcessing\r\n" + + "from bioimageio.core.prediction_pipeline._measure_groups import compute_measures\r\n" + + "from bioimageio.core.resource_io.nodes import Model\r\n" + + "from bioimageio.spec.model import raw_nodes\r\n" + + "from bioimageio.spec.shared.raw_nodes import ResourceDescription as RawResourceDescription\r\n" + + "from bioimageio.workflows import stardist_prediction_2d\r\n" + + "input_tensor = input0['data']\r\n" + + "input_tensor = np.array(input_tensor).reshape(1,512,512,3)\r\n" + + "model_rdf = 'chatty-frog'\r\n" + + "package_path = export_resource_package(model_rdf)\r\n" + + "with tempfile.TemporaryDirectory() as tmp_dir:\r\n" + + " import_dir = Path(tmp_dir) / \"import_dir\"\r\n" + + " imported_stardist_model = stardist_import_bioimageio(package_path, import_dir)\r\n" + + "\r\n" + + "model = load_resource_description(package_path)\r\n" + + "task.update('BBBBBBBBBBBB')\r\n" + + "labels, polys = imported_stardist_model.predict_instances(\r\n" + + " input_tensor,\r\n" + + " axes=\"\".join([{\"b\": \"S\"}.get(a[0], a[0].capitalize()) for a in model.inputs[0].axes]),\r\n" + + " n_tiles=None,\r\n" + + ")\r\n" + + "\r\n" + + "if len(labels.shape) == 2: # batch dim got squeezed\r\n" + + " labels = labels[None]\r\n" + + "\r\n" + + "output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != \"c\")\r\n" + //+ "labels = labels.flatten().tolist()\r\n" + + "task.update('AAAAAAAAAAA')\r\n" + + "task.update(str(type(labels)))\r\n" + + "task.outputs['output0'] = labels\r\n"; + + try (Service python = env.python()) { + python.debug(line -> { + System.err.println(line); + }); + Task task = python.task(opCode, inputMap); + System.out.println("here"); + task.listen(event -> { + switch (event.responseType) { + case UPDATE: + System.out.println("Progress: " + task.message); + break; + case COMPLETION: + Object numer = task.outputs.get("output0"); + System.out.println("Task complete. Result: " + numer); + break; + case CANCELATION: + System.out.println("Task canceled"); + break; + case FAILURE: + System.out.println("Task failed: " + task.error); + break; + } + }); + task.waitFor(); + System.out.println("here2"); + Object result = task.outputs.get("output0"); + Object polys = task.outputs.get("polys"); + System.out.println("here3"); + if (result instanceof Integer) + System.out.print(result); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java new file mode 100644 index 00000000..8d857bd0 --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java @@ -0,0 +1,56 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode; + +import java.util.List; + +import io.bioimage.modelrunner.tensor.Tensor; + +/** + * Interface for run modes that contain complex Deep Learning routines. + * + * @author Carlos Garcia Lopez de Haro + * + */ +public interface RunMode2 +{ + + /** + * Applies the run mode transformation to the specified input/s tensor/s. + * + * This method will execute the corresponding run mode on the wanted inputs + * and return the result provided by the run mode. Regard that the run mode + * can be anything. For example tiling + model inference + post-processing; + * simply model inference; pre-processing + model inference + * + * + * @param inputs + * the input/s tensor/s. + * @return a list of the result tensors in their corresponding datatypes. + */ + public List> apply( Tensor< ? >... inputs ); + + /** + * Returns the name of this run mode. + * + * @return the name of this run mode. + */ + public String getName(); +} diff --git a/src/main/java/io/bioimage/modelrunner/transformations/RunMode.java b/src/main/java/io/bioimage/modelrunner/transformations/RunMode.java deleted file mode 100644 index 359cb474..00000000 --- a/src/main/java/io/bioimage/modelrunner/transformations/RunMode.java +++ /dev/null @@ -1,241 +0,0 @@ -package io.bioimage.modelrunner.transformations; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import org.apposed.appose.Appose; -import org.apposed.appose.Environment; -import org.apposed.appose.Service; -import org.apposed.appose.Service.Task; - -import io.bioimage.modelrunner.bioimageio.ops.OpDescription; -import io.bioimage.modelrunner.tensor.ImgLib2ToArray; -import io.bioimage.modelrunner.tensor.Tensor; -import net.imglib2.img.Img; -import net.imglib2.img.ImgFactory; -import net.imglib2.img.cell.CellImgFactory; -import net.imglib2.type.NativeType; -import net.imglib2.type.numeric.RealType; -import net.imglib2.type.numeric.real.FloatType; - -public class RunMode { - - private static final String AXES_KEY = "axes"; - - private static final String SHAPE_KEY = "shape"; - - private static final String DATA_KEY = "data"; - - private static final String BMZ_CORE_IMPORTS = - "import numpy as np" + System.lineSeparator() - + "import xarray as xr" + System.lineSeparator() - + "from bioimageio.core import load_resource_description" + System.lineSeparator() - + "from bioimageio.core.resource_io.nodes import Model" + System.lineSeparator(); - private static final String OP_PACKAGE = "bioimageio.workflows"; - - - private Environment env; - private String envFileName; - private String opCode; - private String opName; - private String referencedModel; - private LinkedHashMap kwargs; - - private RunMode(OpDescription op) { - /* - envFileName = op.getCondaEnv(); - referencedModel = op.appliedOnWhichModel(); - opName = op.getMethodName(); - kwargs = op.getMethodExtraArgs(); - */ - } - - public static RunMode createRunMode(OpDescription op) { - return new RunMode(op); - } - - public void envCreation() { - if (checkRequiredEnvExists()) { - env = Appose.base(new File(envFileName)).build(); - return; - } - env = Appose.conda(new File(envFileName)).build(); - } - - public boolean checkRequiredEnvExists() { - return false; - } - - private void addImports() { - opCode += BMZ_CORE_IMPORTS; - opCode += "from " + OP_PACKAGE + " import " + opName + System.lineSeparator(); - opCode += "async def run_workflow():" + System.lineSeparator(); - } - - public < T extends RealType< T > & NativeType< T > > - void addRecreationOfTensor(Tensor tensor) { - opCode += "\t" + tensor.getName() + "_data = " + tensor.getName() + "['" + DATA_KEY + "']" + System.lineSeparator() - + "\t" + tensor.getName() + " = np.array(" + tensor.getName() + "_data).reshape("; - for (int i : tensor.getShape()) { - opCode += i + ","; - } - opCode = opCode.substring(0, opCode.length() - 1); - opCode += ")" + System.lineSeparator(); - } - - private < T extends RealType< T > & NativeType< T > > - void addCodeBody(List> inputTensors, List> outputTensors) { - opCode += "\t" + "task.update('Start running workflow')" + System.lineSeparator(); - for (Tensor output : outputTensors) - opCode += "\t" + output.getName() + ","; - opCode = opCode.substring(0, opCode.length() - 1); - opCode += " = await " + this.opName + "(" + referencedModel - + ","; - for (Tensor input : inputTensors) - opCode += input.getName() + ","; - for (String key : kwargs.keySet()) - opCode += key + "=" + key + ","; - opCode = opCode.substring(0, opCode.length() - 1); - opCode += ")" + System.lineSeparator(); - opCode += "\t" + "task.update('Finished running workflow')" + System.lineSeparator(); - for (Tensor output : outputTensors) - opCode += "\t" + "tasks['" + output.getName() + "'] = " + output.getName() + System.lineSeparator(); - opCode += "asyncio.run(run_workflow())" + System.lineSeparator(); - } - - public static void main(String[] args) { - RunMode rm = new RunMode(null); - - rm.envFileName = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; - rm.env = Appose.base(new File(rm.envFileName)).build(); - rm.referencedModel = "chatty-frog"; - rm.opName = "stardist_prediction_2d"; - rm.kwargs = new LinkedHashMap(); - - final ImgFactory< FloatType > imgFactory = new CellImgFactory<>( new FloatType(), 5 ); - final Img< FloatType > img1 = imgFactory.create( 1, 512, 512, 3 ); - // Create the input tensor with the nameand axes given by the rdf.yaml file - // and add it to the list of input tensors - Tensor inpTensor = Tensor.build("input0", "byxc", img1); - List> inputs = new ArrayList>(); - inputs.add(inpTensor); - - final Img< FloatType > img2 = imgFactory.create( 1, 512, 512, 1 ); - // Create the input tensor with the nameand axes given by the rdf.yaml file - // and add it to the list of input tensors - Tensor outTensor = Tensor.build("ouput0", "byxc", img2); - List> outputs = new ArrayList>(); - outputs.add(outTensor); - - rm.run(inputs, outputs); - - } - - public < T extends RealType< T > & NativeType< T > > - void run(List> inputTensors, List> outputTensors) { - - opCode = ""; - addImports(); - - LinkedHashMap inputMap = new LinkedHashMap<>(); - for (Tensor input : inputTensors) { - HashMap tensorMap = new HashMap(); - tensorMap.put(AXES_KEY, input.getAxesOrderString()); - tensorMap.put(DATA_KEY, ImgLib2ToArray.build(input.getData())); - tensorMap.put(SHAPE_KEY, input.getShape()); - inputMap.put(input.getName(), tensorMap); - - addRecreationOfTensor(input); - } - - inputMap.putAll(kwargs); - - addCodeBody(inputTensors, outputTensors); - opCode = "import numpy as np\r\n" - + "import asyncio\r\n" - + "import numpy as np\r\n" - + "import tempfile\r\n" - + "import warnings\r\n" - + "from math import ceil\r\n" - + "from os import PathLike\r\n" - + "from pathlib import Path\r\n" - + "from typing import Dict, IO, List, Optional, Tuple, Union\r\n" - + "\r\n" - + "import xarray as xr\r\n" - + "from stardist import import_bioimageio as stardist_import_bioimageio\r\n" - + "\r\n" - + "from bioimageio.core import export_resource_package, load_resource_description\r\n" - + "from bioimageio.core.prediction_pipeline._combined_processing import CombinedProcessing\r\n" - + "from bioimageio.core.prediction_pipeline._measure_groups import compute_measures\r\n" - + "from bioimageio.core.resource_io.nodes import Model\r\n" - + "from bioimageio.spec.model import raw_nodes\r\n" - + "from bioimageio.spec.shared.raw_nodes import ResourceDescription as RawResourceDescription\r\n" - + "from bioimageio.workflows import stardist_prediction_2d\r\n" - + "input_tensor = input0['data']\r\n" - + "input_tensor = np.array(input_tensor).reshape(1,512,512,3)\r\n" - + "model_rdf = 'chatty-frog'\r\n" - + "package_path = export_resource_package(model_rdf)\r\n" - + "with tempfile.TemporaryDirectory() as tmp_dir:\r\n" - + " import_dir = Path(tmp_dir) / \"import_dir\"\r\n" - + " imported_stardist_model = stardist_import_bioimageio(package_path, import_dir)\r\n" - + "\r\n" - + "model = load_resource_description(package_path)\r\n" - + "task.update('BBBBBBBBBBBB')\r\n" - + "labels, polys = imported_stardist_model.predict_instances(\r\n" - + " input_tensor,\r\n" - + " axes=\"\".join([{\"b\": \"S\"}.get(a[0], a[0].capitalize()) for a in model.inputs[0].axes]),\r\n" - + " n_tiles=None,\r\n" - + ")\r\n" - + "\r\n" - + "if len(labels.shape) == 2: # batch dim got squeezed\r\n" - + " labels = labels[None]\r\n" - + "\r\n" - + "output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != \"c\")\r\n" - //+ "labels = labels.flatten().tolist()\r\n" - + "task.update('AAAAAAAAAAA')\r\n" - + "task.update(str(type(labels)))\r\n" - + "task.outputs['output0'] = labels\r\n"; - - try (Service python = env.python()) { - python.debug(line -> { - System.err.println(line); - }); - Task task = python.task(opCode, inputMap); - System.out.println("here"); - task.listen(event -> { - switch (event.responseType) { - case UPDATE: - System.out.println("Progress: " + task.message); - break; - case COMPLETION: - Object numer = task.outputs.get("output0"); - System.out.println("Task complete. Result: " + numer); - break; - case CANCELATION: - System.out.println("Task canceled"); - break; - case FAILURE: - System.out.println("Task failed: " + task.error); - break; - } - }); - task.waitFor(); - System.out.println("here2"); - Object result = task.outputs.get("output0"); - Object polys = task.outputs.get("polys"); - System.out.println("here3"); - if (result instanceof Integer) - System.out.print(result); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -} From c0324be0db5ba87d7e07e1453e856bd0455b4e10 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 18 Sep 2023 19:21:54 +0200 Subject: [PATCH 006/235] update to new tf engines tht allow unzipping --- src/main/resources/availableDLVersions.json | 102 ++++++++++---------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/main/resources/availableDLVersions.json b/src/main/resources/availableDLVersions.json index 3cd124af..a998ce55 100644 --- a/src/main/resources/availableDLVersions.json +++ b/src/main/resources/availableDLVersions.json @@ -14,7 +14,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.12.0/libtensorflow_jni-1.12.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -31,7 +31,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni_gpu/1.12.0/libtensorflow_jni_gpu-1.12.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -48,7 +48,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.12.0/libtensorflow_jni-1.12.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -65,7 +65,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.12.0/libtensorflow_jni-1.12.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -82,7 +82,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni_gpu/1.12.0/libtensorflow_jni_gpu-1.12.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -99,7 +99,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.13.1/libtensorflow_jni-1.13.1.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -116,7 +116,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni_gpu/1.13.1/libtensorflow_jni_gpu-1.13.1.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -133,7 +133,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.13.1/libtensorflow_jni-1.13.1.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -150,7 +150,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.13.1/libtensorflow_jni-1.13.1.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -167,7 +167,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni_gpu/1.13.1/libtensorflow_jni_gpu-1.13.1.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -184,7 +184,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.14.0/libtensorflow_jni-1.14.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -201,7 +201,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni_gpu/1.14.0/libtensorflow_jni_gpu-1.14.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -218,7 +218,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.14.0/libtensorflow_jni-1.14.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -235,7 +235,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.14.0/libtensorflow_jni-1.14.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -252,7 +252,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni_gpu/1.14.0/libtensorflow_jni_gpu-1.14.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -269,7 +269,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.15.0/libtensorflow_jni-1.15.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -286,7 +286,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni_gpu/1.15.0/libtensorflow_jni_gpu-1.15.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -303,7 +303,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.15.0/libtensorflow_jni-1.15.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -320,7 +320,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni/1.15.0/libtensorflow_jni-1.15.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -337,7 +337,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/libtensorflow_jni_gpu/1.15.0/libtensorflow_jni_gpu-1.15.0.jar", "https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/3.5.1/protobuf-java-3.5.1.jar", "https://repo1.maven.org/maven2/org/tensorflow/proto/1.15.0/proto-1.15.0.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.2/dl-modelrunner-tensorflow-1-0.3.2.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-1/0.3.3/dl-modelrunner-tensorflow-1-0.3.3.jar" ] }, { @@ -356,7 +356,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.2.0/tensorflow-core-api-0.2.0-windows-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.3/dl-modelrunner-tensorflow-2a-0.3.3.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.4/dl-modelrunner-tensorflow-2a-0.3.4.jar" ] }, { @@ -375,7 +375,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.2.0/tensorflow-core-api-0.2.0-windows-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.3/dl-modelrunner-tensorflow-2a-0.3.3.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.4/dl-modelrunner-tensorflow-2a-0.3.4.jar" ] }, { @@ -394,7 +394,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.2.0/tensorflow-core-api-0.2.0-linux-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.3/dl-modelrunner-tensorflow-2a-0.3.3.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.4/dl-modelrunner-tensorflow-2a-0.3.4.jar" ] }, { @@ -413,7 +413,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.2.0/tensorflow-core-api-0.2.0-linux-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.3/dl-modelrunner-tensorflow-2a-0.3.3.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.4/dl-modelrunner-tensorflow-2a-0.3.4.jar" ] }, { @@ -432,7 +432,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.2.0/tensorflow-core-api-0.2.0-macosx-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-macosx-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.3/dl-modelrunner-tensorflow-2a-0.3.3.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2a/0.3.4/dl-modelrunner-tensorflow-2a-0.3.4.jar" ] }, { @@ -451,7 +451,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.3.3/tensorflow-core-api-0.3.3-windows-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -470,7 +470,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.3.3/tensorflow-core-api-0.3.3-windows-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -489,7 +489,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.3.3/tensorflow-core-api-0.3.3-linux-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -508,7 +508,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.3.3/tensorflow-core-api-0.3.3-linux-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -527,7 +527,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.3.3/tensorflow-core-api-0.3.3-macosx-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-macosx-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -546,7 +546,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.0/tensorflow-core-api-0.4.0-windows-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -565,7 +565,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.0/tensorflow-core-api-0.4.0-windows-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -584,7 +584,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.0/tensorflow-core-api-0.4.0-linux-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -603,7 +603,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.0/tensorflow-core-api-0.4.0-linux-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -622,7 +622,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.0/tensorflow-core-api-0.4.0-macosx-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-macosx-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -641,7 +641,7 @@ "https://www.dropbox.com/s/0ptmnsjnoddthyu/tensorflow-core-api-0.4.0-SNAPSHOT.jar?dl=1", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.6-macosx-arm64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -660,7 +660,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.1/tensorflow-core-api-0.4.1-windows-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -679,7 +679,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.1/tensorflow-core-api-0.4.1-windows-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -698,7 +698,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.1/tensorflow-core-api-0.4.1-linux-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -717,7 +717,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.1/tensorflow-core-api-0.4.1-linux-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -736,7 +736,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.1/tensorflow-core-api-0.4.1-macosx-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-macosx-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -755,7 +755,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.2/tensorflow-core-api-0.4.2-windows-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -774,7 +774,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.2/tensorflow-core-api-0.4.2-windows-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -793,7 +793,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.2/tensorflow-core-api-0.4.2-linux-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -812,7 +812,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.2/tensorflow-core-api-0.4.2-linux-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -831,7 +831,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.4.2/tensorflow-core-api-0.4.2-macosx-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.6/javacpp-1.5.6-macosx-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.4/dl-modelrunner-tensorflow-2b-0.3.4.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2b/0.3.5/dl-modelrunner-tensorflow-2b-0.3.5.jar" ] }, { @@ -850,7 +850,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.5.0/tensorflow-core-api-0.5.0-windows-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.5/dl-modelrunner-tensorflow-2c-0.3.5.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.6/dl-modelrunner-tensorflow-2c-0.3.6.jar" ] }, { @@ -869,7 +869,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.5.0/tensorflow-core-api-0.5.0-windows-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8-windows-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.5/dl-modelrunner-tensorflow-2c-0.3.5.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.6/dl-modelrunner-tensorflow-2c-0.3.6.jar" ] }, { @@ -888,7 +888,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.5.0/tensorflow-core-api-0.5.0-linux-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.5/dl-modelrunner-tensorflow-2c-0.3.5.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.6/dl-modelrunner-tensorflow-2c-0.3.6.jar" ] }, { @@ -907,7 +907,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.5.0/tensorflow-core-api-0.5.0-linux-x86_64-gpu.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8-linux-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.5/dl-modelrunner-tensorflow-2c-0.3.5.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.6/dl-modelrunner-tensorflow-2c-0.3.6.jar" ] }, { @@ -926,7 +926,7 @@ "https://repo1.maven.org/maven2/org/tensorflow/tensorflow-core-api/0.5.0/tensorflow-core-api-0.5.0-macosx-x86_64.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8.jar", "https://repo1.maven.org/maven2/org/bytedeco/javacpp/1.5.8/javacpp-1.5.8-macosx-x86_64.jar", - "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.5/dl-modelrunner-tensorflow-2c-0.3.5.jar" + "https://maven.scijava.org/content/repositories/releases/io/bioimage/dl-modelrunner-tensorflow-2c/0.3.6/dl-modelrunner-tensorflow-2c-0.3.6.jar" ] }, { From 9c37d7ccf712edff804e18329dddeb33c0dc774c Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 19 Sep 2023 01:17:38 +0200 Subject: [PATCH 007/235] start designing the architecture of the ops function --- .../bioimageio/ops/OpDescription.java | 39 +++++++++++++++++++ ...Train.java => CellposeFineTuneJdllOp.java} | 21 +--------- .../runmode/CellposeInferJdllOp.java | 24 ++++++++++++ .../runmode/CellposeTrainJdllOp.java | 24 ++++++++++++ .../runmode/StardistFineTuneJdllOp.java | 24 ++++++++++++ .../runmode/StardistInferJdllOp.java | 24 ++++++++++++ 6 files changed, 136 insertions(+), 20 deletions(-) rename src/main/java/io/bioimage/modelrunner/runmode/{CellposeTrain.java => CellposeFineTuneJdllOp.java} (68%) create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/CellposeInferJdllOp.java create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/CellposeTrainJdllOp.java create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/StardistFineTuneJdllOp.java create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/StardistInferJdllOp.java diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/ops/OpDescription.java b/src/main/java/io/bioimage/modelrunner/bioimageio/ops/OpDescription.java index 120206a8..c538fed9 100644 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/ops/OpDescription.java +++ b/src/main/java/io/bioimage/modelrunner/bioimageio/ops/OpDescription.java @@ -1,8 +1,47 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ package io.bioimage.modelrunner.bioimageio.ops; import java.util.LinkedHashMap; +import java.util.List; public class OpDescription { + + private boolean isDefault = false; + + private static final List defaultOps; + static { + defaultOps + } + + public static OpDescription setupOP(String projectRepo, String opFileName, String opMethodName) { + + } + + public void setInputsInOrder(List orderedInputList) { + + } + + public void setNumberOfOuptuts(int nOutputs) { + + } public String getCondaEnv() { return ""; diff --git a/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrain.java b/src/main/java/io/bioimage/modelrunner/runmode/CellposeFineTuneJdllOp.java similarity index 68% rename from src/main/java/io/bioimage/modelrunner/runmode/CellposeTrain.java rename to src/main/java/io/bioimage/modelrunner/runmode/CellposeFineTuneJdllOp.java index 66345d3c..694731d6 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrain.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/CellposeFineTuneJdllOp.java @@ -19,25 +19,6 @@ */ package io.bioimage.modelrunner.runmode; -import java.util.List; - -import io.bioimage.modelrunner.tensor.Tensor; - -/** - * - * @author Carlos Garcia Lopez de Haro - * - */ -public class CellposeTrain extends AbstractRunMode { - - protected CellposeTrain(String name) { - super(name); - } - - @Override - public List> apply(Tensor... inputs) { - // TODO Auto-generated method stub - return null; - } +public class CellposeFineTuneJdllOp { } diff --git a/src/main/java/io/bioimage/modelrunner/runmode/CellposeInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/CellposeInferJdllOp.java new file mode 100644 index 00000000..4afd47ac --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/CellposeInferJdllOp.java @@ -0,0 +1,24 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode; + +public class CellposeInferJdllOp { + +} diff --git a/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrainJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrainJdllOp.java new file mode 100644 index 00000000..d8409d79 --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrainJdllOp.java @@ -0,0 +1,24 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode; + +public class CellposeTrainJdllOp { + +} diff --git a/src/main/java/io/bioimage/modelrunner/runmode/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/StardistFineTuneJdllOp.java new file mode 100644 index 00000000..1323e84a --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/StardistFineTuneJdllOp.java @@ -0,0 +1,24 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode; + +public class StardistFineTuneJdllOp { + +} diff --git a/src/main/java/io/bioimage/modelrunner/runmode/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/StardistInferJdllOp.java new file mode 100644 index 00000000..72717f4a --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/StardistInferJdllOp.java @@ -0,0 +1,24 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode; + +public class StardistInferJdllOp { + +} From 0eaa9f01a627c794c0a192b47a985c691cb8c501 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 19 Sep 2023 01:21:51 +0200 Subject: [PATCH 008/235] keep reorganizing the code --- .../runmode/{ => ops}/CellposeFineTuneJdllOp.java | 2 +- .../modelrunner/runmode/{ => ops}/CellposeInferJdllOp.java | 2 +- .../modelrunner/runmode/{ => ops}/CellposeTrainJdllOp.java | 2 +- .../{bioimageio => runmode}/ops/OpDescription.java | 7 ++----- .../runmode/{ => ops}/StardistFineTuneJdllOp.java | 2 +- .../modelrunner/runmode/{ => ops}/StardistInferJdllOp.java | 2 +- 6 files changed, 7 insertions(+), 10 deletions(-) rename src/main/java/io/bioimage/modelrunner/runmode/{ => ops}/CellposeFineTuneJdllOp.java (94%) rename src/main/java/io/bioimage/modelrunner/runmode/{ => ops}/CellposeInferJdllOp.java (94%) rename src/main/java/io/bioimage/modelrunner/runmode/{ => ops}/CellposeTrainJdllOp.java (94%) rename src/main/java/io/bioimage/modelrunner/{bioimageio => runmode}/ops/OpDescription.java (92%) rename src/main/java/io/bioimage/modelrunner/runmode/{ => ops}/StardistFineTuneJdllOp.java (94%) rename src/main/java/io/bioimage/modelrunner/runmode/{ => ops}/StardistInferJdllOp.java (94%) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/CellposeFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeFineTuneJdllOp.java similarity index 94% rename from src/main/java/io/bioimage/modelrunner/runmode/CellposeFineTuneJdllOp.java rename to src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeFineTuneJdllOp.java index 694731d6..701855d8 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/CellposeFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeFineTuneJdllOp.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package io.bioimage.modelrunner.runmode; +package io.bioimage.modelrunner.runmode.ops; public class CellposeFineTuneJdllOp { diff --git a/src/main/java/io/bioimage/modelrunner/runmode/CellposeInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeInferJdllOp.java similarity index 94% rename from src/main/java/io/bioimage/modelrunner/runmode/CellposeInferJdllOp.java rename to src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeInferJdllOp.java index 4afd47ac..1a1065a8 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/CellposeInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeInferJdllOp.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package io.bioimage.modelrunner.runmode; +package io.bioimage.modelrunner.runmode.ops; public class CellposeInferJdllOp { diff --git a/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrainJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeTrainJdllOp.java similarity index 94% rename from src/main/java/io/bioimage/modelrunner/runmode/CellposeTrainJdllOp.java rename to src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeTrainJdllOp.java index d8409d79..675bd237 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/CellposeTrainJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/CellposeTrainJdllOp.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package io.bioimage.modelrunner.runmode; +package io.bioimage.modelrunner.runmode.ops; public class CellposeTrainJdllOp { diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/ops/OpDescription.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java similarity index 92% rename from src/main/java/io/bioimage/modelrunner/bioimageio/ops/OpDescription.java rename to src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java index c538fed9..c5b65a8e 100644 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/ops/OpDescription.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package io.bioimage.modelrunner.bioimageio.ops; +package io.bioimage.modelrunner.runmode.ops; import java.util.LinkedHashMap; import java.util.List; @@ -26,10 +26,7 @@ public class OpDescription { private boolean isDefault = false; - private static final List defaultOps; - static { - defaultOps - } + private static final List defaultOps = null; public static OpDescription setupOP(String projectRepo, String opFileName, String opMethodName) { diff --git a/src/main/java/io/bioimage/modelrunner/runmode/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java similarity index 94% rename from src/main/java/io/bioimage/modelrunner/runmode/StardistFineTuneJdllOp.java rename to src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 1323e84a..580c6a34 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package io.bioimage.modelrunner.runmode; +package io.bioimage.modelrunner.runmode.ops; public class StardistFineTuneJdllOp { diff --git a/src/main/java/io/bioimage/modelrunner/runmode/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java similarity index 94% rename from src/main/java/io/bioimage/modelrunner/runmode/StardistInferJdllOp.java rename to src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index 72717f4a..03c9f446 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package io.bioimage.modelrunner.runmode; +package io.bioimage.modelrunner.runmode.ops; public class StardistInferJdllOp { From d580b368fdabc9c46a7884014471d660483086ba Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 19 Sep 2023 01:29:51 +0200 Subject: [PATCH 009/235] keep defininf the op structure --- .../modelrunner/runmode/ops/OpDescription.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java index c5b65a8e..1d32ca06 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java @@ -26,12 +26,22 @@ public class OpDescription { private boolean isDefault = false; + private String opDir; + private static final List defaultOps = null; public static OpDescription setupOP(String projectRepo, String opFileName, String opMethodName) { } + public void defineCondaEnv() { + + } + + protected void installOp() { + + } + public void setInputsInOrder(List orderedInputList) { } @@ -52,11 +62,11 @@ public LinkedHashMap getMethodExtraArgs() { return null; } - public String appliedOnWhichModel() { - return ""; - } - public Object[] getOutputs() { return null; } + + public String getOpDir() { + return opDir; + } } From c1f6544ea402284f13945cc67be6b6e1ce50cc3a Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 19 Sep 2023 15:05:15 +0200 Subject: [PATCH 010/235] keep improving the architecture --- .../bioimage/modelrunner/runmode/RunMode.java | 17 ++++++++++++++++- .../bioimage/modelrunner/runmode/RunMode2.java | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 8ea4db00..46b0a332 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -25,13 +25,14 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map.Entry; import org.apposed.appose.Appose; import org.apposed.appose.Environment; import org.apposed.appose.Service; import org.apposed.appose.Service.Task; -import io.bioimage.modelrunner.bioimageio.ops.OpDescription; +import io.bioimage.modelrunner.runmode.ops.OpDescription; import io.bioimage.modelrunner.tensor.ImgLib2ToArray; import io.bioimage.modelrunner.tensor.Tensor; import net.imglib2.img.Img; @@ -65,6 +66,7 @@ public class RunMode { private LinkedHashMap kwargs; private RunMode(OpDescription op) { + /* envFileName = op.getCondaEnv(); referencedModel = op.appliedOnWhichModel(); @@ -154,6 +156,19 @@ public static void main(String[] args) { } + private void convertInputMap() { + LinkedHashMap apposeInputMap = new LinkedHashMap<>(); + for (Entry entry : this.kwargs.entrySet()) { + if (entry.getValue() instanceof String) { + apposeInputMap.put(entry.getKey(), entry.getValue()); + } else if (entry.getValue() instanceof Tensor) { + + } else if (entry.getValue() instanceof Number) { + + } + } + } + public < T extends RealType< T > & NativeType< T > > void run(List> inputTensors, List> outputTensors) { diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java index 8d857bd0..4f3201f1 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java @@ -53,4 +53,6 @@ public interface RunMode2 * @return the name of this run mode. */ public String getName(); + + } From b36299388e08d692b68686e594875137a4e9c769 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 20 Sep 2023 11:48:47 +0200 Subject: [PATCH 011/235] improve the robustness of the inputs to the runmode --- .../bioimage/modelrunner/runmode/RunMode.java | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 46b0a332..dc361057 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -129,6 +129,10 @@ void addCodeBody(List> inputTensors, List> outputTensors) { } public static void main(String[] args) { + Integer[] arr = new Integer[3]; + arr[0] = 0; + Object obj = (int) 2; + boolean aa = isTypeDirectlySupported(obj.getClass()); RunMode rm = new RunMode(null); rm.envFileName = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; @@ -156,19 +160,51 @@ public static void main(String[] args) { } - private void convertInputMap() { + private < T extends RealType< T > & NativeType< T > > void convertInputMap() { LinkedHashMap apposeInputMap = new LinkedHashMap<>(); for (Entry entry : this.kwargs.entrySet()) { if (entry.getValue() instanceof String) { apposeInputMap.put(entry.getKey(), entry.getValue()); } else if (entry.getValue() instanceof Tensor) { - - } else if (entry.getValue() instanceof Number) { - + Tensor tt = (Tensor) entry.getValue(); + apposeInputMap.put(tt.getName(), tensorToMap(tt)); + } else if (!entry.getValue().getClass().isArray() + && isTypeDirectlySupported(entry.getValue().getClass())) { + apposeInputMap.put(entry.getKey(), entry.getValue()); + } else if (entry.getValue().getClass().isArray() + && isTypeDirectlySupported(entry.getValue().getClass().getComponentType())) { + apposeInputMap.put(entry.getKey(), entry.getValue()); + } else if (entry.getValue() instanceof List + && ((List) entry.getValue()).size() == 0) { + apposeInputMap.put(entry.getKey(), new Object[0]); + } else if (entry.getValue() instanceof List + && isTypeDirectlySupported(((List) entry.getValue()).get(0).getClass())) { + apposeInputMap.put(entry.getKey(), entry.getValue()); } } } + private static Object[] convertListToArray() { + + } + + private static boolean isTypeDirectlySupported(Class cl) { + if (Number.class.isAssignableFrom(cl) + || cl.isPrimitive() || String.class.isAssignableFrom(cl) ) { + return true; + } + return false; + } + + private & NativeType> + HashMap tensorToMap(Tensor tt) { + HashMap tensorMap = new HashMap(); + tensorMap.put(AXES_KEY, tt.getAxesOrderString()); + tensorMap.put(DATA_KEY, ImgLib2ToArray.build(tt.getData())); + tensorMap.put(SHAPE_KEY, tt.getShape()); + return tensorMap; + } + public < T extends RealType< T > & NativeType< T > > void run(List> inputTensors, List> outputTensors) { From 44c14bacfdda032ecb7a9a87d12b395b31338ed5 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 20 Sep 2023 12:35:41 +0200 Subject: [PATCH 012/235] start adding python code --- .../bioimage/modelrunner/runmode/RunMode.java | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index dc361057..eb523b86 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -35,6 +35,7 @@ import io.bioimage.modelrunner.runmode.ops.OpDescription; import io.bioimage.modelrunner.tensor.ImgLib2ToArray; import io.bioimage.modelrunner.tensor.Tensor; +import net.imglib2.RandomAccessibleInterval; import net.imglib2.img.Img; import net.imglib2.img.ImgFactory; import net.imglib2.img.cell.CellImgFactory; @@ -44,6 +45,8 @@ public class RunMode { + private static final String VAR_SUFFIX = "_map"; + private static final String AXES_KEY = "axes"; private static final String SHAPE_KEY = "shape"; @@ -64,6 +67,8 @@ public class RunMode { private String opName; private String referencedModel; private LinkedHashMap kwargs; + private LinkedHashMap apposeInputMap; + private String tensorRecreationCode = ""; private RunMode(OpDescription op) { @@ -161,13 +166,16 @@ public static void main(String[] args) { } private < T extends RealType< T > & NativeType< T > > void convertInputMap() { - LinkedHashMap apposeInputMap = new LinkedHashMap<>(); + apposeInputMap = new LinkedHashMap<>(); for (Entry entry : this.kwargs.entrySet()) { if (entry.getValue() instanceof String) { apposeInputMap.put(entry.getKey(), entry.getValue()); } else if (entry.getValue() instanceof Tensor) { - Tensor tt = (Tensor) entry.getValue(); - apposeInputMap.put(tt.getName(), tensorToMap(tt)); + // TODO map of tensor is not really necessary + apposeInputMap.put(entry.getKey() + VAR_SUFFIX, tensorToMap((Tensor) entry.getValue())); + } else if (entry.getValue() instanceof RandomAccessibleInterval) { + // TODO map of ImgLib2 is not really necessary + apposeInputMap.put(entry.getKey() + VAR_SUFFIX, imglib2ToMap((RandomAccessibleInterval) entry.getValue())); } else if (!entry.getValue().getClass().isArray() && isTypeDirectlySupported(entry.getValue().getClass())) { apposeInputMap.put(entry.getKey(), entry.getValue()); @@ -179,15 +187,15 @@ && isTypeDirectlySupported(entry.getValue().getClass().getComponentType())) { apposeInputMap.put(entry.getKey(), new Object[0]); } else if (entry.getValue() instanceof List && isTypeDirectlySupported(((List) entry.getValue()).get(0).getClass())) { - apposeInputMap.put(entry.getKey(), entry.getValue()); + apposeInputMap.put(entry.getKey(), ((List) entry.getValue()).toArray()); + } else { + throw new IllegalArgumentException("The type of the input argument: '" + + entry.getKey() + "' is not supported (" + + entry.getValue().getClass()); } } } - private static Object[] convertListToArray() { - - } - private static boolean isTypeDirectlySupported(Class cl) { if (Number.class.isAssignableFrom(cl) || cl.isPrimitive() || String.class.isAssignableFrom(cl) ) { @@ -205,6 +213,23 @@ HashMap tensorToMap(Tensor tt) { return tensorMap; } + private & NativeType> + void addCodeToRecreateTensor(String ogName, String givenName, Tensor tensor) { + // This line wants to recreate the original numpy array. Shouldlook like: + // input0 = np.array(input0_map['data']).reshape([1, 1, 512, 512]) + this.tensorRecreationCode += ogName " = np.array(" + + givenName + "['" + DATA_KEY + "']" + ").reshape("; + + } + + private & NativeType> + HashMap imglib2ToMap(RandomAccessibleInterval rai) { + HashMap tensorMap = new HashMap(); + tensorMap.put(DATA_KEY, ImgLib2ToArray.build(rai)); + tensorMap.put(SHAPE_KEY, rai.dimensionsAsLongArray()); + return tensorMap; + } + public < T extends RealType< T > & NativeType< T > > void run(List> inputTensors, List> outputTensors) { From 560a6f833c0d75712bdfe3fd0f6c432eae876b38 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 20 Sep 2023 13:33:15 +0200 Subject: [PATCH 013/235] add code to recreate numpy array and tensor --- .../bioimage/modelrunner/runmode/RunMode.java | 58 ++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index eb523b86..be2c6547 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -45,7 +45,9 @@ public class RunMode { - private static final String VAR_SUFFIX = "_map"; + private static final String IMPORT_XARRAY = "import xarray as xr" + System.lineSeparator(); + + private static final String IMPORT_NUMPY = "import numpy as np" + System.lineSeparator(); private static final String AXES_KEY = "axes"; @@ -54,9 +56,7 @@ public class RunMode { private static final String DATA_KEY = "data"; private static final String BMZ_CORE_IMPORTS = - "import numpy as np" + System.lineSeparator() - + "import xarray as xr" + System.lineSeparator() - + "from bioimageio.core import load_resource_description" + System.lineSeparator() + "from bioimageio.core import load_resource_description" + System.lineSeparator() + "from bioimageio.core.resource_io.nodes import Model" + System.lineSeparator(); private static final String OP_PACKAGE = "bioimageio.workflows"; @@ -69,6 +69,7 @@ public class RunMode { private LinkedHashMap kwargs; private LinkedHashMap apposeInputMap; private String tensorRecreationCode = ""; + private String importsCode = ""; private RunMode(OpDescription op) { @@ -171,11 +172,13 @@ private < T extends RealType< T > & NativeType< T > > void convertInputMap() { if (entry.getValue() instanceof String) { apposeInputMap.put(entry.getKey(), entry.getValue()); } else if (entry.getValue() instanceof Tensor) { - // TODO map of tensor is not really necessary - apposeInputMap.put(entry.getKey() + VAR_SUFFIX, tensorToMap((Tensor) entry.getValue())); + Object tensorArr = ImgLib2ToArray.build(((Tensor) entry.getValue()).getData()); + apposeInputMap.put(entry.getKey(), tensorArr); + addCodeToRecreateTensor(entry.getKey(), (Tensor) entry.getValue()); } else if (entry.getValue() instanceof RandomAccessibleInterval) { - // TODO map of ImgLib2 is not really necessary - apposeInputMap.put(entry.getKey() + VAR_SUFFIX, imglib2ToMap((RandomAccessibleInterval) entry.getValue())); + Object imgArr = ImgLib2ToArray.build(((RandomAccessibleInterval) entry.getValue())); + apposeInputMap.put(entry.getKey(), imgArr); + addCodeToRecreateNumpyArray(entry.getKey(), (RandomAccessibleInterval) entry.getValue()); } else if (!entry.getValue().getClass().isArray() && isTypeDirectlySupported(entry.getValue().getClass())) { apposeInputMap.put(entry.getKey(), entry.getValue()); @@ -214,12 +217,39 @@ HashMap tensorToMap(Tensor tt) { } private & NativeType> - void addCodeToRecreateTensor(String ogName, String givenName, Tensor tensor) { - // This line wants to recreate the original numpy array. Shouldlook like: - // input0 = np.array(input0_map['data']).reshape([1, 1, 512, 512]) - this.tensorRecreationCode += ogName " = np.array(" - + givenName + "['" + DATA_KEY + "']" + ").reshape("; - + void addCodeToRecreateTensor(String ogName, Tensor tensor) { + if (!importsCode.contains(IMPORT_XARRAY)) + importsCode += IMPORT_XARRAY; + if (!importsCode.contains(IMPORT_NUMPY)) + importsCode += IMPORT_NUMPY; + // This line wants to recreate the original numpy array. Should look like: + // input0 = xr.DataArray(np.array(input0).reshape([1, 1, 512, 512]), dims=["b", "c", "y", "x"], name="input0") + this.tensorRecreationCode += ogName + " = xr.DataArray(np.array(" + ogName + ").reshape(["; + for (int ll : tensor.getShape()) + tensorRecreationCode += ll + ", "; + tensorRecreationCode = + tensorRecreationCode.substring(0, tensorRecreationCode.length() - 2); + tensorRecreationCode += "]), dims=["; + for (String ss : tensor.getAxesOrderString().split("")) + tensorRecreationCode += "\"" + ss + "\", "; + tensorRecreationCode = + tensorRecreationCode.substring(0, tensorRecreationCode.length() - 2); + tensorRecreationCode += "], name=" + tensor.getName() + "])"; + tensorRecreationCode += System.lineSeparator(); + } + + private & NativeType> + void addCodeToRecreateNumpyArray(String ogName, RandomAccessibleInterval rai) { + if (!importsCode.contains(IMPORT_NUMPY)) + importsCode += IMPORT_NUMPY; + // This line wants to recreate the original numpy array. Should look like: + // np_arr = np.array(np_arr).reshape([1, 1, 512, 512]) + tensorRecreationCode += ogName + " = np.array(" + ogName + ").reshape(["; + for (long ll : rai.dimensionsAsLongArray()) + tensorRecreationCode += ll + ", "; + tensorRecreationCode = + tensorRecreationCode.substring(0, tensorRecreationCode.length() - 2); + tensorRecreationCode += System.lineSeparator(); } private & NativeType> From d356486357bcb363514d8a843c3cb9c249707f39 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 20 Sep 2023 14:43:30 +0200 Subject: [PATCH 014/235] keep developing the support for runmode --- .../bioimage/modelrunner/runmode/RunMode.java | 68 +++++++++++++------ .../runmode/ops/OpDescription.java | 8 +++ 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index be2c6547..cb59e211 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -26,6 +26,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; +import java.util.stream.IntStream; import org.apposed.appose.Appose; import org.apposed.appose.Environment; @@ -55,6 +56,19 @@ public class RunMode { private static final String DATA_KEY = "data"; + private static final String TENSOR_KEY = "tensor"; + + private static final String NP_ARR_KEY = "np_arr"; + + private static final String STANDARD_KEY = "standard"; + + private static final String OUTPUT_REFORMATING = + "if isinstance(%s, np.ndarray):" + System.lineSeparator() + + "\t" + + "elif isinstance(%s, np.ndarray):" + System.lineSeparator() + + "\t" + + ;; + private static final String BMZ_CORE_IMPORTS = "from bioimageio.core import load_resource_description" + System.lineSeparator() + "from bioimageio.core.resource_io.nodes import Model" + System.lineSeparator(); @@ -66,13 +80,18 @@ public class RunMode { private String opCode; private String opName; private String referencedModel; + private OpDescription op; private LinkedHashMap kwargs; private LinkedHashMap apposeInputMap; private String tensorRecreationCode = ""; private String importsCode = ""; + private String opMethodCode = ""; + private String retrieveResultsCode = ""; + List outputNames = new ArrayList(); private RunMode(OpDescription op) { - + this.op = op; + IntStream.range(0, op.getNumberOfOutputs()).forEach(i -> outputNames.add("output" + i)); /* envFileName = op.getCondaEnv(); referencedModel = op.appliedOnWhichModel(); @@ -98,20 +117,37 @@ public boolean checkRequiredEnvExists() { } private void addImports() { - opCode += BMZ_CORE_IMPORTS; - opCode += "from " + OP_PACKAGE + " import " + opName + System.lineSeparator(); - opCode += "async def run_workflow():" + System.lineSeparator(); + opCode += BMZ_CORE_IMPORTS + op.getOpImport() + System.lineSeparator(); } - public < T extends RealType< T > & NativeType< T > > - void addRecreationOfTensor(Tensor tensor) { - opCode += "\t" + tensor.getName() + "_data = " + tensor.getName() + "['" + DATA_KEY + "']" + System.lineSeparator() - + "\t" + tensor.getName() + " = np.array(" + tensor.getName() + "_data).reshape("; - for (int i : tensor.getShape()) { - opCode += i + ","; + private void opExecutionCode() { + opMethodCode += op.getMethodName() + "("; + for (String key : this.apposeInputMap.keySet()) + opMethodCode += key + ","; + opMethodCode += ")" + System.lineSeparator(); + } + + private void retrieveResultsCode() { + retrieveResultsCode = "task.update('Preparing outputs')" + System.lineSeparator(); + + for (String outN : this.outputNames) { + retrieveResultsCode += "if isinstance(" + outN + ", np.ndarray):" + System.lineSeparator() + + "\t" + + "elif isinstance(" + outN + ", np.ndarray):" + System.lineSeparator() + + "\t" + + ; } - opCode = opCode.substring(0, opCode.length() - 1); - opCode += ")" + System.lineSeparator(); + + + "\r\n" + + "if len(labels.shape) == 2: # batch dim got squeezed\r\n" + + " labels = labels[None]\r\n" + + "\r\n" + + "output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != \"c\")\r\n" + //+ "labels = labels.flatten().tolist()\r\n" + + "task.update('AAAAAAAAAAA')\r\n" + + "task.update(str(type(labels)))\r\n" + + "task.outputs['output0'] = labels\r\n"; + } private < T extends RealType< T > & NativeType< T > > @@ -252,14 +288,6 @@ void addCodeToRecreateNumpyArray(String ogName, RandomAccessibleInterval rai) tensorRecreationCode += System.lineSeparator(); } - private & NativeType> - HashMap imglib2ToMap(RandomAccessibleInterval rai) { - HashMap tensorMap = new HashMap(); - tensorMap.put(DATA_KEY, ImgLib2ToArray.build(rai)); - tensorMap.put(SHAPE_KEY, rai.dimensionsAsLongArray()); - return tensorMap; - } - public < T extends RealType< T > & NativeType< T > > void run(List> inputTensors, List> outputTensors) { diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java index 1d32ca06..2707fdc5 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java @@ -34,6 +34,14 @@ public static OpDescription setupOP(String projectRepo, String opFileName, Strin } + public String getOpImport() { + return ""; + } + + public int getNumberOfOutputs() { + return 0; + } + public void defineCondaEnv() { } From 1075e7fb60d2ee3ca447d482e0b3c0881243501c Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 20 Sep 2023 16:47:17 +0200 Subject: [PATCH 015/235] add code snippet that helps reformating ouptuts in pytohn --- .../bioimage/modelrunner/runmode/RunMode.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index cb59e211..160cbd76 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -56,18 +56,33 @@ public class RunMode { private static final String DATA_KEY = "data"; + private static final String NAME_KEY = "data"; + private static final String TENSOR_KEY = "tensor"; private static final String NP_ARR_KEY = "np_arr"; private static final String STANDARD_KEY = "standard"; + // TODO add support for list of objects private static final String OUTPUT_REFORMATING = - "if isinstance(%s, np.ndarray):" + System.lineSeparator() - + "\t" + "if isinstance(%s, xr.DataArray):" + System.lineSeparator() + + "\ttypes_list.append(" + TENSOR_KEY + ")" + System.lineSeparator() + + "\t%s = {\"" + DATA_KEY + "\": %s.values.flatten().tolist(), \"" + + SHAPE_KEY + "\": %s.shape, \"" + AXES_KEY + "\": %s.dims," + + "\"" + NAME_KEY + "\": %s.name}" + System.lineSeparator() + "elif isinstance(%s, np.ndarray):" + System.lineSeparator() - + "\t" - + ;; + + "\ttypes_list.append(" + NP_ARR_KEY + ")" + System.lineSeparator() + + "\t%s = {\"" + DATA_KEY + "\": %s.flatten().tolist(), \"" + + SHAPE_KEY + "\": %s.shape}" + System.lineSeparator() + + "elif isinstance(%s, list) and len(%s) == 0:" + System.lineSeparator() + + "\ttypes_list.append(" + STANDARD_KEY + ")" + System.lineSeparator() + + "elif isinstance(%s, list) and isinstance(%s[0], list):" + System.lineSeparator() + + "\ttypes_list.append(" + TENSOR_KEY + ")" + System.lineSeparator() + + "\t" + System.lineSeparator() + + "else:" + System.lineSeparator() + + "\ttypes_list.append(" + STANDARD_KEY + ")" + System.lineSeparator() + + "\t" + System.lineSeparator(); private static final String BMZ_CORE_IMPORTS = "from bioimageio.core import load_resource_description" + System.lineSeparator() From 7d78d30104ea3c8dfb875fdb11b5b4c95b4f3474 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 20 Sep 2023 16:58:56 +0200 Subject: [PATCH 016/235] remove unused code --- .../bioimage/modelrunner/runmode/RunMode.java | 56 ++----------------- 1 file changed, 6 insertions(+), 50 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 160cbd76..847636ac 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -82,19 +82,16 @@ public class RunMode { + "\t" + System.lineSeparator() + "else:" + System.lineSeparator() + "\ttypes_list.append(" + STANDARD_KEY + ")" + System.lineSeparator() - + "\t" + System.lineSeparator(); + + "task.outputs['%s'] = %s" + System.lineSeparator(); private static final String BMZ_CORE_IMPORTS = "from bioimageio.core import load_resource_description" + System.lineSeparator() + "from bioimageio.core.resource_io.nodes import Model" + System.lineSeparator(); - private static final String OP_PACKAGE = "bioimageio.workflows"; private Environment env; private String envFileName; private String opCode; - private String opName; - private String referencedModel; private OpDescription op; private LinkedHashMap kwargs; private LinkedHashMap apposeInputMap; @@ -143,46 +140,14 @@ private void opExecutionCode() { } private void retrieveResultsCode() { - retrieveResultsCode = "task.update('Preparing outputs')" + System.lineSeparator(); + retrieveResultsCode = "task.update('Preparing outputs')" + System.lineSeparator() + + "types_list = []" + System.lineSeparator() ; for (String outN : this.outputNames) { - retrieveResultsCode += "if isinstance(" + outN + ", np.ndarray):" + System.lineSeparator() - + "\t" - + "elif isinstance(" + outN + ", np.ndarray):" + System.lineSeparator() - + "\t" - + ; + String code = String.format(OUTPUT_REFORMATING, outN, outN, outN, outN, outN, outN, + outN, outN, outN, outN, outN, outN, outN, outN); + retrieveResultsCode += code; } - - + "\r\n" - + "if len(labels.shape) == 2: # batch dim got squeezed\r\n" - + " labels = labels[None]\r\n" - + "\r\n" - + "output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != \"c\")\r\n" - //+ "labels = labels.flatten().tolist()\r\n" - + "task.update('AAAAAAAAAAA')\r\n" - + "task.update(str(type(labels)))\r\n" - + "task.outputs['output0'] = labels\r\n"; - - } - - private < T extends RealType< T > & NativeType< T > > - void addCodeBody(List> inputTensors, List> outputTensors) { - opCode += "\t" + "task.update('Start running workflow')" + System.lineSeparator(); - for (Tensor output : outputTensors) - opCode += "\t" + output.getName() + ","; - opCode = opCode.substring(0, opCode.length() - 1); - opCode += " = await " + this.opName + "(" + referencedModel - + ","; - for (Tensor input : inputTensors) - opCode += input.getName() + ","; - for (String key : kwargs.keySet()) - opCode += key + "=" + key + ","; - opCode = opCode.substring(0, opCode.length() - 1); - opCode += ")" + System.lineSeparator(); - opCode += "\t" + "task.update('Finished running workflow')" + System.lineSeparator(); - for (Tensor output : outputTensors) - opCode += "\t" + "tasks['" + output.getName() + "'] = " + output.getName() + System.lineSeparator(); - opCode += "asyncio.run(run_workflow())" + System.lineSeparator(); } public static void main(String[] args) { @@ -258,15 +223,6 @@ private static boolean isTypeDirectlySupported(Class cl) { return false; } - private & NativeType> - HashMap tensorToMap(Tensor tt) { - HashMap tensorMap = new HashMap(); - tensorMap.put(AXES_KEY, tt.getAxesOrderString()); - tensorMap.put(DATA_KEY, ImgLib2ToArray.build(tt.getData())); - tensorMap.put(SHAPE_KEY, tt.getShape()); - return tensorMap; - } - private & NativeType> void addCodeToRecreateTensor(String ogName, Tensor tensor) { if (!importsCode.contains(IMPORT_XARRAY)) From de4b8e20a8c5187d3243c9b70dea95bfe4651d21 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 20 Sep 2023 17:51:41 +0200 Subject: [PATCH 017/235] add op interface --- .../modelrunner/runmode/ops/OpInterface.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java new file mode 100644 index 00000000..c2b6130f --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java @@ -0,0 +1,65 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode.ops; + +import java.util.List; + +/** + * Interface that every OP needs to implement to be able to be run as a RunMode + * @author Carlos Garcia Lopez de Haro + * + */ +public interface OpInterface { + /** + * The imports that need to be added to the Python code to run the OP + * @return a String containing a Python snippet with the imports needed to use the + * OP + */ + public String getOpImport(); + /** + * Number of outputs that the OP method will produce + * @return number of ouptuts that the OP method will produce + */ + public int getNumberOfOutputs(); + + public void installOp(); + /** + * Set the inputs to the OP in order + * @param orderedInputList + * the inputs we want to provide to the OP in the same order as they are defined in the OP + */ + public void setInputsInOrder(List orderedInputList); + /** + * Get the Conda env needed to run the OP + * + * @return the Conda env required to run the OP + */ + public String getCondaEnv(); + /** + * The name of the method that is used to call the OP + * @return a String with the name of the method used to call the OP + */ + public String getMethodName(); + /** + * Directory where the OP is stored + * @return tirectory where the OP is stored + */ + public String getOpDir(); +} From a876d4147a8bacba5d620bcb6bdba20732107827 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 20 Sep 2023 19:13:12 +0200 Subject: [PATCH 018/235] start creating the python part of the op --- .../op_environments/stardist_environment.yaml | 15 ++++++ .../runmode/ops/StardistInferJdllOp.java | 46 ++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 python/op_environments/stardist_environment.yaml diff --git a/python/op_environments/stardist_environment.yaml b/python/op_environments/stardist_environment.yaml new file mode 100644 index 00000000..57fd0706 --- /dev/null +++ b/python/op_environments/stardist_environment.yaml @@ -0,0 +1,15 @@ +name: stardist +channels: + - conda-forge + - defaults +dependencies: + - bioimageio.core + - black + - conda-build + - dask + - mypy + - pip + - python==3.9.* + - stardist + - tensorflow==2.* + - xarray \ No newline at end of file diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index 03c9f446..fb16cecf 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -19,6 +19,50 @@ */ package io.bioimage.modelrunner.runmode.ops; -public class StardistInferJdllOp { +import java.util.List; + +public class StardistInferJdllOp implements OpInterface { + + @Override + public String getOpImport() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getNumberOfOutputs() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void installOp() { + // TODO Auto-generated method stub + + } + + @Override + public void setInputsInOrder(List orderedInputList) { + // TODO Auto-generated method stub + + } + + @Override + public String getCondaEnv() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getMethodName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getOpDir() { + // TODO Auto-generated method stub + return null; + } } From d0217178e0ff4f6d1d3f0d33149b08223e45cb13 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 21 Sep 2023 01:21:20 +0200 Subject: [PATCH 019/235] add python file with stardist inference --- .../op_environments/stardist_environment.yaml | 2 +- .../stardist_inference/stardist_inference.py | 121 ++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 python/ops/stardist_inference/stardist_inference.py diff --git a/python/op_environments/stardist_environment.yaml b/python/op_environments/stardist_environment.yaml index 57fd0706..10d70777 100644 --- a/python/op_environments/stardist_environment.yaml +++ b/python/op_environments/stardist_environment.yaml @@ -1,4 +1,4 @@ -name: stardist +name: stardist_op channels: - conda-forge - defaults diff --git a/python/ops/stardist_inference/stardist_inference.py b/python/ops/stardist_inference/stardist_inference.py new file mode 100644 index 00000000..82679339 --- /dev/null +++ b/python/ops/stardist_inference/stardist_inference.py @@ -0,0 +1,121 @@ +import tempfile +import warnings +from math import ceil +from os import PathLike +from pathlib import Path +from typing import Dict, IO, List, Optional, Tuple, Union + +import xarray as xr +from stardist import import_bioimageio as stardist_import_bioimageio + +from bioimageio.core import export_resource_package, load_resource_description +from bioimageio.core.prediction_pipeline._combined_processing import CombinedProcessing +from bioimageio.core.prediction_pipeline._measure_groups import compute_measures +from bioimageio.core.resource_io.nodes import Model +from bioimageio.spec.model import raw_nodes +from bioimageio.spec.shared.common import AXIS_LETTER_TO_NAME, AXIS_NAME_TO_LETTER +from bioimageio.spec.shared.raw_nodes import ResourceDescription as RawResourceDescription + + +def stardist_prediction_2d( + model_rdf: Union[str, PathLike, dict, IO, bytes, raw_nodes.URI, RawResourceDescription], + input_tensor: xr.DataArray, + tile: Optional[Dict[str, int]] = None, +) -> Tuple[xr.DataArray, dict]: + """stardist prediction 2d + + A workflow to apply a stardist model and the stardist postprocessing. + This workflow is loosely based on https://nbviewer.org/github/stardist/stardist/blob/master/examples/2D/3_prediction.ipynb + + .. code-block:: yaml + authors: [{name: Fynn Beuttenmüller, github_user: fynnbe}] + cite: + - text: BioImage.IO + doi: 10.1101/2022.06.07.495102 + - text: "Stardist: Cell Detection with Star-Convex Polygons" + doi: 10.1007/978-3-030-00934-2_30 + - text: "Stardist: Star-convex Polyhedra for 3D Object Detection and Segmentation in Microscopy" + doi: 10.1109/WACV45572.2020.9093435 + + Args: + model_rdf: the (source/raw) model RDF that describes the stardist model to be used for inference + input_tensor: raw input + axes: + - type: batch + - type: channel + - type: space + name: y + - type: space + name: x + tile: Tile shape for model input. Defaults to no tiling. Currently ignored for preprocessing. + + Returns: + labels. Labels of detected objects + axes: + - type: batch + - type: space + name: y + - type: space + name: x + + polys. Dictionary describing the labeled object's polygons + """ + # todo: use inference_with_dask for model inference and then apply stardist postprocessing. + # outputs = await inference_with_dask(model_rdf, input_tensor, boundary_mode=boundary_mode, enable_preprocessing=enable_preprocessing, enable_postprocessing=True, tiles=[tile]) + # assert len(outputs) == 1 + # output = outputs["output"] + + package_path = export_resource_package(model_rdf) + with tempfile.TemporaryDirectory() as tmp_dir: + import_dir = Path(tmp_dir) / "import_dir" + imported_stardist_model = stardist_import_bioimageio(package_path, import_dir) + + model = load_resource_description(package_path) + assert isinstance(model, Model) + if len(model.inputs) != 1: + raise NotImplementedError("Multiple inputs for stardist models not yet implemented") + + if len(model.outputs) != 1: + raise NotImplementedError("Multiple outputs for stardist models not yet implemented") + + # rename tensor axes to single letters to match model RDF + map_axes = {k: v for k, v in AXIS_NAME_TO_LETTER.items() if k in input_tensor.dims} + if map_axes: + input_tensor = input_tensor.rename(map_axes) + + prep = CombinedProcessing.from_tensor_specs(model.inputs) + ipt_name = model.inputs[0].name + sample = {ipt_name: input_tensor} + computed_measures = compute_measures(prep.required_measures, sample=sample) + prep.apply(sample, computed_measures) + + preprocessed_input = sample[ipt_name] + map_axes_back = {k: v for k, v in AXIS_LETTER_TO_NAME.items() if k in preprocessed_input.dims} + if map_axes_back: + preprocessed_input = preprocessed_input.rename(map_axes_back) + + input_axis_order = [AXIS_LETTER_TO_NAME.get(a, a) for a in model.inputs[0].axes] + if tile is None: + n_tiles: Optional[List[int]] = None + else: + n_tiles = [] + for a in input_axis_order: + t = tile[a] + s = preprocessed_input.sizes[a] + n_tiles.append(max(ceil(s / t), 1)) + + warnings.warn(f"translated tile {tile} to n_tiles: {n_tiles} for stardist library.") + + img = preprocessed_input.transpose(*input_axis_order).to_numpy() + labels, polys = imported_stardist_model.predict_instances( + img, + axes="".join([{"b": "S"}.get(a[0], a[0].capitalize()) for a in model.inputs[0].axes]), + n_tiles=n_tiles, + ) + + if len(labels.shape) == 2: # batch dim got squeezed + labels = labels[None] + + output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != "c") + assert output_axes_wo_channels == tuple("byx") + return xr.DataArray(labels, dims=output_axes_wo_channels), polys From 7ad969307b2b8bbc1ce75decaaf0b79be0ba22c0 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 21 Sep 2023 16:37:00 +0200 Subject: [PATCH 020/235] keep improving the stardist op --- .../stardist_inference/stardist_inference.py | 117 +++++++++++++++++- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/python/ops/stardist_inference/stardist_inference.py b/python/ops/stardist_inference/stardist_inference.py index 82679339..eb61cfbf 100644 --- a/python/ops/stardist_inference/stardist_inference.py +++ b/python/ops/stardist_inference/stardist_inference.py @@ -2,8 +2,10 @@ import warnings from math import ceil from os import PathLike +from os import path from pathlib import Path from typing import Dict, IO, List, Optional, Tuple, Union +from csbdeep.utils import axes_check_and_normalize, normalize, _raise import xarray as xr from stardist import import_bioimageio as stardist_import_bioimageio @@ -13,9 +15,108 @@ from bioimageio.core.prediction_pipeline._measure_groups import compute_measures from bioimageio.core.resource_io.nodes import Model from bioimageio.spec.model import raw_nodes -from bioimageio.spec.shared.common import AXIS_LETTER_TO_NAME, AXIS_NAME_TO_LETTER from bioimageio.spec.shared.raw_nodes import ResourceDescription as RawResourceDescription +import numpy as np + +RDF_YAML_SUFF = 'rdf.yaml' +RDF_YAML_SUFF_DEPR = 'model.yaml' + +STARDIST_OP_NAME = 'stardist_op' + +def stardist_prediction_2d_mine( + model_rdf: Union[str, PathLike, dict, IO, bytes, raw_nodes.URI, RawResourceDescription], + input_tensor: xr.DataArray, + tile: Optional[Dict[str, int]] = None, +) -> Tuple[xr.DataArray, dict]: + model = None + if isinstance(model_rdf, str) \ + and (model_rdf.endswith(RDF_YAML_SUFF_DEPR) or model_rdf.endswith(RDF_YAML_SUFF)) \ + and path.exists(model_rdf): + import shutil + from csbdeep.utils import save_json + from stardist.models import StarDist2D, StarDist3D + biomodel = load_resource_description(model_rdf) + + # read the stardist specific content + if 'stardist' not in biomodel.config: + raise(RuntimeError("bioimage.io model not compatible")) + config = biomodel.config['stardist']['config'] + thresholds = biomodel.config['stardist']['thresholds'] + weights = biomodel.config['stardist']['weights'] + + # make sure that the keras weights are in the attachments + weights_file = None + for f in biomodel.attachments.files: + if f.name == weights and f.exists(): + weights_file = f + break + weights_file is not None or _raise(FileNotFoundError(f"couldn't find weights file '{weights}'")) + + # save the config and threshold to json, and weights to hdf5 to enable loading as stardist model + # copy bioimageio files to separate sub-folder + outpath = Path(Path(path.dirname(model_rdf)) / STARDIST_OP_NAME) + + outpath.mkdir(parents=True) + save_json(config, str(outpath / 'config.json')) + save_json(thresholds, str(outpath / 'thresholds.json')) + shutil.copy(str(weights_file), str(outpath / "weights_bioimageio.h5")) + + model_class = (StarDist2D if config['n_dim'] == 2 else StarDist3D) + imported_stardist_model = model_class(None, outpath.name, basedir=str(outpath.parent)) + + assert isinstance(biomodel, Model) + if len(model.inputs) != 1: + raise NotImplementedError("Multiple inputs for stardist models not yet implemented") + + if len(model.outputs) != 1: + raise NotImplementedError("Multiple outputs for stardist models not yet implemented") + + # rename tensor axes to single letters to match model RDF + #map_axes = {k: v for k, v in AXIS_NAME_TO_LETTER.items() if k in input_tensor.dims} + map_axes = "byxc" + if map_axes: + input_tensor = input_tensor.rename(map_axes) + + prep = CombinedProcessing.from_tensor_specs(model.inputs) + ipt_name = model.inputs[0].name + sample = {ipt_name: input_tensor} + computed_measures = compute_measures(prep.required_measures, sample=sample) + prep.apply(sample, computed_measures) + + preprocessed_input = sample[ipt_name] + #map_axes_back = {k: v for k, v in AXIS_LETTER_TO_NAME.items() if k in preprocessed_input.dims} + map_axes_back = "byxc" + if map_axes_back: + preprocessed_input = preprocessed_input.rename(map_axes_back) + + #input_axis_order = [AXIS_LETTER_TO_NAME.get(a, a) for a in model.inputs[0].axes] + input_axis_order = "byxc" + if tile is None: + n_tiles: Optional[List[int]] = None + else: + n_tiles = [] + for a in input_axis_order: + t = tile[a] + s = preprocessed_input.sizes[a] + n_tiles.append(max(ceil(s / t), 1)) + + warnings.warn(f"translated tile {tile} to n_tiles: {n_tiles} for stardist library.") + + img = preprocessed_input.transpose(*input_axis_order).to_numpy() + labels, polys = imported_stardist_model.predict_instances( + img, + axes="".join([{"b": "S"}.get(a[0], a[0].capitalize()) for a in model.inputs[0].axes]), + n_tiles=n_tiles, + ) + + if len(labels.shape) == 2: # batch dim got squeezed + labels = labels[None] + + output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != "c") + assert output_axes_wo_channels == tuple("byx") + return xr.DataArray(labels, dims=output_axes_wo_channels), polys + def stardist_prediction_2d( model_rdf: Union[str, PathLike, dict, IO, bytes, raw_nodes.URI, RawResourceDescription], @@ -79,7 +180,8 @@ def stardist_prediction_2d( raise NotImplementedError("Multiple outputs for stardist models not yet implemented") # rename tensor axes to single letters to match model RDF - map_axes = {k: v for k, v in AXIS_NAME_TO_LETTER.items() if k in input_tensor.dims} + #map_axes = {k: v for k, v in AXIS_NAME_TO_LETTER.items() if k in input_tensor.dims} + map_axes = "byxc" if map_axes: input_tensor = input_tensor.rename(map_axes) @@ -90,11 +192,13 @@ def stardist_prediction_2d( prep.apply(sample, computed_measures) preprocessed_input = sample[ipt_name] - map_axes_back = {k: v for k, v in AXIS_LETTER_TO_NAME.items() if k in preprocessed_input.dims} + #map_axes_back = {k: v for k, v in AXIS_LETTER_TO_NAME.items() if k in preprocessed_input.dims} + map_axes_back = "byxc" if map_axes_back: preprocessed_input = preprocessed_input.rename(map_axes_back) - input_axis_order = [AXIS_LETTER_TO_NAME.get(a, a) for a in model.inputs[0].axes] + #input_axis_order = [AXIS_LETTER_TO_NAME.get(a, a) for a in model.inputs[0].axes] + input_axis_order = "byxc" if tile is None: n_tiles: Optional[List[int]] = None else: @@ -119,3 +223,8 @@ def stardist_prediction_2d( output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != "c") assert output_axes_wo_channels == tuple("byx") return xr.DataArray(labels, dims=output_axes_wo_channels), polys + +arr = np.zeros((1, 208, 208, 3)) +xarr = xr.DataArray(arr, dims=["b", "y", "x", "c"], name="input") +model_path = r'C:\Users\angel\OneDrive\Documentos\pasteur\git\model-runner-java\models\StarDist H&E Nuclei Segmentation_06092023_020924\rdf.yaml' +stardist_prediction_2d_mine(model_path, xarr) From 2e8a17a71c9ce1e91743570f44685bc3844d0edf Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 21 Sep 2023 18:06:04 +0200 Subject: [PATCH 021/235] keep improving the stardist op --- python/ops/stardist_inference/stardist_inference.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/python/ops/stardist_inference/stardist_inference.py b/python/ops/stardist_inference/stardist_inference.py index eb61cfbf..7011bbd5 100644 --- a/python/ops/stardist_inference/stardist_inference.py +++ b/python/ops/stardist_inference/stardist_inference.py @@ -6,6 +6,7 @@ from pathlib import Path from typing import Dict, IO, List, Optional, Tuple, Union from csbdeep.utils import axes_check_and_normalize, normalize, _raise +from bioimageio.spec import load_raw_resource_description import xarray as xr from stardist import import_bioimageio as stardist_import_bioimageio @@ -13,6 +14,7 @@ from bioimageio.core import export_resource_package, load_resource_description from bioimageio.core.prediction_pipeline._combined_processing import CombinedProcessing from bioimageio.core.prediction_pipeline._measure_groups import compute_measures +from bioimageio.core.resource_io.utils import resolve_raw_node, resolve_source from bioimageio.core.resource_io.nodes import Model from bioimageio.spec.model import raw_nodes from bioimageio.spec.shared.raw_nodes import ResourceDescription as RawResourceDescription @@ -36,7 +38,7 @@ def stardist_prediction_2d_mine( import shutil from csbdeep.utils import save_json from stardist.models import StarDist2D, StarDist3D - biomodel = load_resource_description(model_rdf) + biomodel = load_raw_resource_description(model_rdf, update_to_format="latest") # read the stardist specific content if 'stardist' not in biomodel.config: @@ -47,15 +49,20 @@ def stardist_prediction_2d_mine( # make sure that the keras weights are in the attachments weights_file = None + fs = biomodel.attachments.files + resolve_source(str(fs[2]), Path(model_rdf), Path( + r'C:\Users\angel\OneDrive\Documentos\pasteur\git\model-runner-java\models\StarDist H&E Nuclei Segmentation_06092023_020924\stardist_op\weights_bioimageio.h5')) for f in biomodel.attachments.files: if f.name == weights and f.exists(): weights_file = f break weights_file is not None or _raise(FileNotFoundError(f"couldn't find weights file '{weights}'")) + # save the config and threshold to json, and weights to hdf5 to enable loading as stardist model # copy bioimageio files to separate sub-folder outpath = Path(Path(path.dirname(model_rdf)) / STARDIST_OP_NAME) + resolve_source(weights_file, biomodel.root_path, str(outpath / "weights_bioimageio.h5")) outpath.mkdir(parents=True) save_json(config, str(outpath / 'config.json')) @@ -226,5 +233,6 @@ def stardist_prediction_2d( arr = np.zeros((1, 208, 208, 3)) xarr = xr.DataArray(arr, dims=["b", "y", "x", "c"], name="input") +model_path = "chatty-frog" model_path = r'C:\Users\angel\OneDrive\Documentos\pasteur\git\model-runner-java\models\StarDist H&E Nuclei Segmentation_06092023_020924\rdf.yaml' stardist_prediction_2d_mine(model_path, xarr) From 09b5e29216c2d246aacfae77a11a07eb7e06e22d Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 21 Sep 2023 18:46:37 +0200 Subject: [PATCH 022/235] keep improving the stardist op --- .../stardist_inference/stardist_inference.py | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/python/ops/stardist_inference/stardist_inference.py b/python/ops/stardist_inference/stardist_inference.py index 7011bbd5..ac9cb50c 100644 --- a/python/ops/stardist_inference/stardist_inference.py +++ b/python/ops/stardist_inference/stardist_inference.py @@ -49,11 +49,8 @@ def stardist_prediction_2d_mine( # make sure that the keras weights are in the attachments weights_file = None - fs = biomodel.attachments.files - resolve_source(str(fs[2]), Path(model_rdf), Path( - r'C:\Users\angel\OneDrive\Documentos\pasteur\git\model-runner-java\models\StarDist H&E Nuclei Segmentation_06092023_020924\stardist_op\weights_bioimageio.h5')) for f in biomodel.attachments.files: - if f.name == weights and f.exists(): + if str(f).endswith("/" + weights): weights_file = f break weights_file is not None or _raise(FileNotFoundError(f"couldn't find weights file '{weights}'")) @@ -62,18 +59,20 @@ def stardist_prediction_2d_mine( # save the config and threshold to json, and weights to hdf5 to enable loading as stardist model # copy bioimageio files to separate sub-folder outpath = Path(Path(path.dirname(model_rdf)) / STARDIST_OP_NAME) - resolve_source(weights_file, biomodel.root_path, str(outpath / "weights_bioimageio.h5")) - outpath.mkdir(parents=True) + outpath.mkdir(parents=True, exist_ok=True) save_json(config, str(outpath / 'config.json')) save_json(thresholds, str(outpath / 'thresholds.json')) - shutil.copy(str(weights_file), str(outpath / "weights_bioimageio.h5")) + if path.exists(Path(path.dirname(model_rdf)) / weights): + shutil.copy(str(weights_file), str(outpath / "weights_bioimageio.h5")) + else: + resolve_source(weights_file, Path(model_rdf), Path(str(outpath / "weights_bioimageio.h5"))) model_class = (StarDist2D if config['n_dim'] == 2 else StarDist3D) imported_stardist_model = model_class(None, outpath.name, basedir=str(outpath.parent)) - assert isinstance(biomodel, Model) - if len(model.inputs) != 1: + #assert isinstance(biomodel, Model) + if len(biomodel.inputs) != 1: raise NotImplementedError("Multiple inputs for stardist models not yet implemented") if len(model.outputs) != 1: @@ -81,7 +80,7 @@ def stardist_prediction_2d_mine( # rename tensor axes to single letters to match model RDF #map_axes = {k: v for k, v in AXIS_NAME_TO_LETTER.items() if k in input_tensor.dims} - map_axes = "byxc" + map_axes = None if map_axes: input_tensor = input_tensor.rename(map_axes) @@ -93,7 +92,7 @@ def stardist_prediction_2d_mine( preprocessed_input = sample[ipt_name] #map_axes_back = {k: v for k, v in AXIS_LETTER_TO_NAME.items() if k in preprocessed_input.dims} - map_axes_back = "byxc" + map_axes_back = None if map_axes_back: preprocessed_input = preprocessed_input.rename(map_axes_back) From a20f8dbcb81f831a54b957a6c7e89f8f992f0cfb Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 21 Sep 2023 19:26:35 +0200 Subject: [PATCH 023/235] keep improving the stardist op --- .../stardist_inference/stardist_inference.py | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/python/ops/stardist_inference/stardist_inference.py b/python/ops/stardist_inference/stardist_inference.py index ac9cb50c..fc6fed8b 100644 --- a/python/ops/stardist_inference/stardist_inference.py +++ b/python/ops/stardist_inference/stardist_inference.py @@ -14,13 +14,16 @@ from bioimageio.core import export_resource_package, load_resource_description from bioimageio.core.prediction_pipeline._combined_processing import CombinedProcessing from bioimageio.core.prediction_pipeline._measure_groups import compute_measures -from bioimageio.core.resource_io.utils import resolve_raw_node, resolve_source +from bioimageio.core.resource_io.utils import SourceNodeTransformer, resolve_source, RawNodeTypeTransformer from bioimageio.core.resource_io.nodes import Model +from bioimageio.core.resource_io.io_ import nodes from bioimageio.spec.model import raw_nodes from bioimageio.spec.shared.raw_nodes import ResourceDescription as RawResourceDescription import numpy as np +from bioimageio.spec.shared.node_transformer import UriNodeTransformer + RDF_YAML_SUFF = 'rdf.yaml' RDF_YAML_SUFF_DEPR = 'model.yaml' @@ -39,7 +42,19 @@ def stardist_prediction_2d_mine( from csbdeep.utils import save_json from stardist.models import StarDist2D, StarDist3D biomodel = load_raw_resource_description(model_rdf, update_to_format="latest") - + """ + rd = UriNodeTransformer(root_path=biomodel.root_path, uri_only_if_in_package=True).transform( + biomodel) + rd2 = UriNodeTransformer(root_path=biomodel.root_path, uri_only_if_in_package=False).transform( + biomodel) + aa = isinstance(rd, Model) + rd = SourceNodeTransformer().transform(rd) + cc = isinstance(rd, Model) + rd = RawNodeTypeTransformer(nodes).transform(rd) + cc = isinstance(rd, Model) + model = load_resource_description(model_rdf) + """ + biomodel = RawNodeTypeTransformer(nodes).transform(biomodel) # read the stardist specific content if 'stardist' not in biomodel.config: raise(RuntimeError("bioimage.io model not compatible")) @@ -75,7 +90,7 @@ def stardist_prediction_2d_mine( if len(biomodel.inputs) != 1: raise NotImplementedError("Multiple inputs for stardist models not yet implemented") - if len(model.outputs) != 1: + if len(biomodel.outputs) != 1: raise NotImplementedError("Multiple outputs for stardist models not yet implemented") # rename tensor axes to single letters to match model RDF @@ -84,8 +99,8 @@ def stardist_prediction_2d_mine( if map_axes: input_tensor = input_tensor.rename(map_axes) - prep = CombinedProcessing.from_tensor_specs(model.inputs) - ipt_name = model.inputs[0].name + prep = CombinedProcessing.from_tensor_specs(biomodel.inputs) + ipt_name = biomodel.inputs[0].name sample = {ipt_name: input_tensor} computed_measures = compute_measures(prep.required_measures, sample=sample) prep.apply(sample, computed_measures) @@ -112,14 +127,14 @@ def stardist_prediction_2d_mine( img = preprocessed_input.transpose(*input_axis_order).to_numpy() labels, polys = imported_stardist_model.predict_instances( img, - axes="".join([{"b": "S"}.get(a[0], a[0].capitalize()) for a in model.inputs[0].axes]), + axes="".join([{"b": "S"}.get(a[0], a[0].capitalize()) for a in biomodel.inputs[0].axes]), n_tiles=n_tiles, ) if len(labels.shape) == 2: # batch dim got squeezed labels = labels[None] - output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != "c") + output_axes_wo_channels = tuple(a for a in biomodel.outputs[0].axes if a != "c") assert output_axes_wo_channels == tuple("byx") return xr.DataArray(labels, dims=output_axes_wo_channels), polys From affd1755a0f4ccf3229dbbbe8e840f0ae39d4e0a Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 22 Sep 2023 12:14:20 +0200 Subject: [PATCH 024/235] keep improving the op interface and stardist op --- .../modelrunner/runmode/ops/OpInterface.java | 19 ++++-- .../runmode/ops/StardistInferJdllOp.java | 60 ++++++++++++++++--- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java index c2b6130f..69817a99 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java @@ -19,7 +19,7 @@ */ package io.bioimage.modelrunner.runmode.ops; -import java.util.List; +import java.util.LinkedHashMap; /** * Interface that every OP needs to implement to be able to be run as a RunMode @@ -38,14 +38,21 @@ public interface OpInterface { * @return number of ouptuts that the OP method will produce */ public int getNumberOfOutputs(); - + /** + * Check whether the OP is installed or not + * @return true if the OP is installed ot false otherwise + */ + public boolean isOpInstalled(); + /** + * Method that installs the OP to be ready to be used + */ public void installOp(); /** - * Set the inputs to the OP in order - * @param orderedInputList - * the inputs we want to provide to the OP in the same order as they are defined in the OP + * Get a LinkedHashMap contianing the inputs defined for the OP + * @return an ordered map with the inputs to the OP, where the key + * is the variable name and the object is the variable */ - public void setInputsInOrder(List orderedInputList); + public LinkedHashMap getOpInputs(); /** * Get the Conda env needed to run the OP * diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index fb16cecf..7cc418e4 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -19,9 +19,43 @@ */ package io.bioimage.modelrunner.runmode.ops; -import java.util.List; +import java.util.LinkedHashMap; +import io.bioimage.modelrunner.tensor.Tensor; +import net.imglib2.type.NativeType; +import net.imglib2.type.numeric.RealType; + +/** + * Code for the JDLL OP that allows running the whole stardist model (pre-processing + model executio + * + post-processing and tiling) in Python using Appose + * @author Carlos Javier Garcia Lopez de Haro + * + */ public class StardistInferJdllOp implements OpInterface { + + private String modelName; + + private Tensor inputTensor; + + private LinkedHashMap inputsMap; + + private final String CONDA_ENV_YAML_FILE = ""; + + private final static String MODEL_KEY = "model"; + + private final static String INPUT_TENSOR_KEY = "input_tensor"; + + private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; + + private static final int N_STARDIST_OUTPUTS = 2; + + public void setModel(String modelName) { + this.modelName = modelName; + } + + public < T extends RealType< T > & NativeType< T > > void setInputTensor(Tensor tensor) { + inputTensor = tensor; + } @Override public String getOpImport() { @@ -31,8 +65,7 @@ public String getOpImport() { @Override public int getNumberOfOutputs() { - // TODO Auto-generated method stub - return 0; + return N_STARDIST_OUTPUTS; } @Override @@ -42,9 +75,11 @@ public void installOp() { } @Override - public void setInputsInOrder(List orderedInputList) { - // TODO Auto-generated method stub - + public LinkedHashMap getOpInputs() { + inputsMap = new LinkedHashMap(); + inputsMap.put(MODEL_KEY, modelName); + inputsMap.put(INPUT_TENSOR_KEY, inputTensor); + return this.inputsMap; } @Override @@ -55,8 +90,7 @@ public String getCondaEnv() { @Override public String getMethodName() { - // TODO Auto-generated method stub - return null; + return OP_METHOD_NAME; } @Override @@ -65,4 +99,14 @@ public String getOpDir() { return null; } + @Override + public boolean isOpInstalled() { + // TODO Auto-generated method stub + return false; + } + + public static boolean isModelCompatible() { + + } + } From 69bff4dd8464772054687d06254a304c9f3ff4cd Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 22 Sep 2023 12:49:18 +0200 Subject: [PATCH 025/235] keep designing the structure of the stardist OP --- .../runmode/ops/StardistInferJdllOp.java | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index 7cc418e4..ef082dd2 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -19,7 +19,11 @@ */ package io.bioimage.modelrunner.runmode.ops; +import java.io.File; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; +import java.util.Objects; import io.bioimage.modelrunner.tensor.Tensor; import net.imglib2.type.NativeType; @@ -49,7 +53,14 @@ public class StardistInferJdllOp implements OpInterface { private static final int N_STARDIST_OUTPUTS = 2; - public void setModel(String modelName) { + public void setModel(String modelName) throws IllegalArgumentException { + Objects.requireNonNull(modelName, "The modelName input argument cannot be null."); + if (new File(modelName).isFile() && !isModelFileStardist(modelName)) + throw new IllegalArgumentException("The file selected does not correspond to " + + "the rdf.yaml file of a Bioiamge.io Stardist model."); + else if (!isModelNameStardist(modelName)) + throw new IllegalArgumentException("The model name provided does not correspond to a valid" + + " Stardist model present in the Bioimage.io online reposritory."); this.modelName = modelName; } @@ -105,8 +116,55 @@ public boolean isOpInstalled() { return false; } - public static boolean isModelCompatible() { - + /** + * Check whether a model file or a model name (model name, model ID or model nickname) + * correspond to a stardist model. + * The model name has to correspond to a stardist model present in the bioimage.io, for + * example: 'chatty-frog' + * @param modelName + * file path or name of a stardist model + * @return true if it corresponds to a stardsit model or false otherwise + */ + public static boolean isModelCompatible(String modelName) { + if (modelName == null) + return false; + if (new File(modelName).isFile()) + return isModelFileStardist(modelName); + else { + return isModelNameStardist(modelName); + } + } + + /** + * Whether the rdf.yaml file corresponding to a model contains + * the information to load a stardist model or not. + * @param modelFile + * rdf.yaml file that should correspond to a stardist model + * @return true if the rdf.yaml represents a stardist model and false otherwise + */ + public static boolean isModelFileStardist(String modelFile) { + return true; + } + + /** + * Whether the model name (in the rdf.yaml any field among: 'name', 'nickname' or 'id') + * corresponds to a stardist model of the Bioiamge.io onlie repository or not + * @param modelName + * a String corresponding to any of the following fields of the rdf.yaml file of a stardist + * model: 'name', 'nickname' or 'id' + * @return true if it actually corresponds to astardist model or false otherwise + */ + public static boolean isModelNameStardist(String modelName) { + return true; + } + + /** + * Returns a list containing all the model names that corresponds to + * StarDist models existing in the Bioimage.io online repository. + * @return list of StarDist model names from the Bioimage.io repository + */ + public static List fetchStarDistModelNamesFromBioImage(){ + return new ArrayList(); } } From f0c1d18b33b06d45db665c94dbdb377d88fe72cb Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 22 Sep 2023 12:59:22 +0200 Subject: [PATCH 026/235] keep improving the robustness of stardist op --- .../runmode/ops/StardistInferJdllOp.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index ef082dd2..3b6038ae 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -25,7 +25,10 @@ import java.util.List; import java.util.Objects; +import io.bioimage.modelrunner.bioimageio.BioimageioRepo; +import io.bioimage.modelrunner.bioimageio.description.ModelDescriptor; import io.bioimage.modelrunner.tensor.Tensor; +import io.bioimage.modelrunner.utils.Constants; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; @@ -39,7 +42,7 @@ public class StardistInferJdllOp implements OpInterface { private String modelName; - private Tensor inputTensor; + private Tensor inputTensor; private LinkedHashMap inputsMap; @@ -51,6 +54,8 @@ public class StardistInferJdllOp implements OpInterface { private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; + private static final String STARDIST_FIELD_KEY = "stardist"; + private static final int N_STARDIST_OUTPUTS = 2; public void setModel(String modelName) throws IllegalArgumentException { @@ -87,6 +92,9 @@ public void installOp() { @Override public LinkedHashMap getOpInputs() { + Objects.requireNonNull(modelName, "The model of interest needs to be defined first."); + Objects.requireNonNull(inputTensor, "The input tensor has not been defined. Please, define" + + " it with the method 'setInputTensor(Tensor tensor)'"); inputsMap = new LinkedHashMap(); inputsMap.put(MODEL_KEY, modelName); inputsMap.put(INPUT_TENSOR_KEY, inputTensor); @@ -143,7 +151,14 @@ public static boolean isModelCompatible(String modelName) { * @return true if the rdf.yaml represents a stardist model and false otherwise */ public static boolean isModelFileStardist(String modelFile) { - return true; + if (new File(modelFile).getName().equals(Constants.RDF_FNAME) == false) + return false; + try { + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(modelFile); + return descriptor.getConfig().getSpecMap().keySet().contains(STARDIST_FIELD_KEY); + } catch (Exception e) { + return false; + } } /** @@ -155,6 +170,8 @@ public static boolean isModelFileStardist(String modelFile) { * @return true if it actually corresponds to astardist model or false otherwise */ public static boolean isModelNameStardist(String modelName) { + BioimageioRepo br = BioimageioRepo.connect(); + ModelDescriptor model = br.selectByName(modelName); return true; } From dea3ff07a6d97b8ac701599c204ec24d0a968cb8 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 22 Sep 2023 16:44:54 +0200 Subject: [PATCH 027/235] improve the logic retrieving mdoels from teh bioimage.io repo --- .../bioimageio/BioimageioRepo.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java b/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java index 1776cd21..8473a6eb 100644 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java +++ b/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java @@ -23,7 +23,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; import java.util.ArrayList; @@ -77,7 +76,7 @@ public class BioimageioRepo { */ private static List modelNicknames; - private LinkedHashMap models; + private static LinkedHashMap models; private Consumer consumer; @@ -123,10 +122,24 @@ public static BioimageioRepo connect(Consumer consumer) { return new BioimageioRepo(consumer); } + /** + * Refresh the list of models fetched from the Bioimage.io. + * Connects to the Bioimage.io website and retrieves all the models available + */ + public void refresh() { + models = null; + listAllModels(false); + } + /** * Method that connects to the BioImage.io API and retrieves the models available * at the Bioimage.io model repository. - * The models are specified at: {@link #location} + * The models are specified at: {@link #location}. + * Once the method has been called, the list of models is not refreshed (that means + * the method does not check the list of Bioimage.io models and returns what + * was obtained with the first call) unless the method {@link #refresh()} + * is used, {@link #refresh()} actually calls again this method to retrieve the list from zero, + * if not the same list as the one retrieved for the first time calling the method is used.. * @param verbose * whether to print in the terminal and send that printed information in the consumer (if it * exists) or not From a81f890f5d20293b200aa593c14b2c81629fb30c Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 22 Sep 2023 16:48:36 +0200 Subject: [PATCH 028/235] add helper methods to find stardist models --- .../runmode/ops/StardistInferJdllOp.java | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index 3b6038ae..a4f0e966 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -24,6 +24,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; import io.bioimage.modelrunner.bioimageio.BioimageioRepo; import io.bioimage.modelrunner.bioimageio.description.ModelDescriptor; @@ -171,8 +172,14 @@ public static boolean isModelFileStardist(String modelFile) { */ public static boolean isModelNameStardist(String modelName) { BioimageioRepo br = BioimageioRepo.connect(); - ModelDescriptor model = br.selectByName(modelName); - return true; + if (br.selectByName(modelName) != null) { + return br.selectByName(modelName).getConfig().getSpecMap().keySet().contains(STARDIST_FIELD_KEY); + } else if (br.selectByID(modelName) != null) { + return br.selectByID(modelName).getConfig().getSpecMap().keySet().contains(STARDIST_FIELD_KEY); + } else if (br.selectByNickname(modelName) != null) { + return br.selectByNickname(modelName).getConfig().getSpecMap().keySet().contains(STARDIST_FIELD_KEY); + } + return false; } /** @@ -180,8 +187,38 @@ public static boolean isModelNameStardist(String modelName) { * StarDist models existing in the Bioimage.io online repository. * @return list of StarDist model names from the Bioimage.io repository */ - public static List fetchStarDistModelNamesFromBioImage(){ - return new ArrayList(); + public static List fetchStarDistModelNamesFromBioImage() { + BioimageioRepo br = BioimageioRepo.connect(); + List stardistModels = br.listAllModels(false).values().stream() + .filter(md -> md.getConfig().getSpecMap().keySet().contains(STARDIST_FIELD_KEY)) + .map(md -> md.getName()).collect(Collectors.toList()); + return stardistModels; + } + + /** + * Returns a list containing all the model nicknames that corresponds to + * StarDist models existing in the Bioimage.io online repository. + * @return list of StarDist model nicknames from the Bioimage.io repository + */ + public static List fetchStarDistModelNicknamesFromBioImage() { + BioimageioRepo br = BioimageioRepo.connect(); + List stardistModels = br.listAllModels(false).values().stream() + .filter(md -> md.getConfig().getSpecMap().keySet().contains(STARDIST_FIELD_KEY)) + .map(md -> md.getNickname()).collect(Collectors.toList()); + return stardistModels; + } + + /** + * Returns a list containing all the model IDs that corresponds to + * StarDist models existing in the Bioimage.io online repository. + * @return list of StarDist model IDs from the Bioimage.io repository + */ + public static List fetchStarDistModelIdsFromBioImage() { + BioimageioRepo br = BioimageioRepo.connect(); + List stardistModels = br.listAllModels(false).values().stream() + .filter(md -> md.getConfig().getSpecMap().keySet().contains(STARDIST_FIELD_KEY)) + .map(md -> md.getModelID()).collect(Collectors.toList()); + return stardistModels; } } From 0d1348cd741225144048b958781832ea6e0f7d59 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 22 Sep 2023 18:15:53 +0200 Subject: [PATCH 029/235] add OP constructor --- .../runmode/ops/StardistInferJdllOp.java | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index a4f0e966..d37fcf52 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -20,7 +20,6 @@ package io.bioimage.modelrunner.runmode.ops; import java.io.File; -import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; @@ -45,9 +44,11 @@ public class StardistInferJdllOp implements OpInterface { private Tensor inputTensor; - private LinkedHashMap inputsMap; + private String opFilePath; + + private String envPath; - private final String CONDA_ENV_YAML_FILE = ""; + private LinkedHashMap inputsMap; private final static String MODEL_KEY = "model"; @@ -59,6 +60,28 @@ public class StardistInferJdllOp implements OpInterface { private static final int N_STARDIST_OUTPUTS = 2; + private static final String STARDIST_OP_FNAME = "stardist_inference.py"; + + /** + * Create a StarDist inference OP to execute the whole stardist model in Python + * with its pre- and post-processing + * @param + * ImgLib2 data types accepted by the OP + * @param modelName + * name of the model + * @param tensor + * input tensor for stardist + * @return the OP can be run to use stardist + */ + public static < T extends RealType< T > & NativeType< T > > + StardistInferJdllOp create(String modelName, Tensor tensor) { + StardistInferJdllOp op = new StardistInferJdllOp(); + op.setModel(modelName); + op.setInputTensor(tensor); + op.installOp(); + return op; + } + public void setModel(String modelName) throws IllegalArgumentException { Objects.requireNonNull(modelName, "The modelName input argument cannot be null."); if (new File(modelName).isFile() && !isModelFileStardist(modelName)) @@ -76,8 +99,7 @@ public < T extends RealType< T > & NativeType< T > > void setInputTensor(Tensor< @Override public String getOpImport() { - // TODO Auto-generated method stub - return null; + return "import " + STARDIST_OP_FNAME.substring(0, STARDIST_OP_FNAME.indexOf(".py")); } @Override @@ -87,8 +109,12 @@ public int getNumberOfOutputs() { @Override public void installOp() { - // TODO Auto-generated method stub - + // TODO this method checks if the OP file is at its correponding folder. + // TODO if not unpack the python file and located (where??) + opFilePath = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\python\\ops\\stardist_inference"; + // TODO check if the env has also been created + // TODO if not create it (where??) + envPath = ""; } @Override @@ -104,8 +130,7 @@ public LinkedHashMap getOpInputs() { @Override public String getCondaEnv() { - // TODO Auto-generated method stub - return null; + return envPath; } @Override @@ -115,13 +140,12 @@ public String getMethodName() { @Override public String getOpDir() { - // TODO Auto-generated method stub - return null; + return opFilePath; } @Override public boolean isOpInstalled() { - // TODO Auto-generated method stub + // TODO maybe remove this method? Make the check at installOp? return false; } From 4c62a6b2fe8f320b199d9c0e8844bc1b9b770e0c Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 22 Sep 2023 18:22:32 +0200 Subject: [PATCH 030/235] use OP interface --- .../java/io/bioimage/modelrunner/runmode/RunMode.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 847636ac..e28d0382 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -34,6 +34,7 @@ import org.apposed.appose.Service.Task; import io.bioimage.modelrunner.runmode.ops.OpDescription; +import io.bioimage.modelrunner.runmode.ops.OpInterface; import io.bioimage.modelrunner.tensor.ImgLib2ToArray; import io.bioimage.modelrunner.tensor.Tensor; import net.imglib2.RandomAccessibleInterval; @@ -92,7 +93,7 @@ public class RunMode { private Environment env; private String envFileName; private String opCode; - private OpDescription op; + private OpInterface op; private LinkedHashMap kwargs; private LinkedHashMap apposeInputMap; private String tensorRecreationCode = ""; @@ -101,7 +102,7 @@ public class RunMode { private String retrieveResultsCode = ""; List outputNames = new ArrayList(); - private RunMode(OpDescription op) { + private RunMode(OpInterface op) { this.op = op; IntStream.range(0, op.getNumberOfOutputs()).forEach(i -> outputNames.add("output" + i)); /* @@ -112,7 +113,7 @@ private RunMode(OpDescription op) { */ } - public static RunMode createRunMode(OpDescription op) { + public static RunMode createRunMode(OpInterface op) { return new RunMode(op); } @@ -159,8 +160,6 @@ public static void main(String[] args) { rm.envFileName = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; rm.env = Appose.base(new File(rm.envFileName)).build(); - rm.referencedModel = "chatty-frog"; - rm.opName = "stardist_prediction_2d"; rm.kwargs = new LinkedHashMap(); final ImgFactory< FloatType > imgFactory = new CellImgFactory<>( new FloatType(), 5 ); @@ -273,12 +272,10 @@ void run(List> inputTensors, List> outputTensors) { tensorMap.put(SHAPE_KEY, input.getShape()); inputMap.put(input.getName(), tensorMap); - addRecreationOfTensor(input); } inputMap.putAll(kwargs); - addCodeBody(inputTensors, outputTensors); opCode = "import numpy as np\r\n" + "import asyncio\r\n" + "import numpy as np\r\n" From fd7d49f78e9e8466262e56b3073be006777959f3 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 22 Sep 2023 18:53:42 +0200 Subject: [PATCH 031/235] try to make a working example --- .../bioimage/modelrunner/runmode/RunMode.java | 169 ++++++++++++------ .../runmode/ops/StardistInferJdllOp.java | 23 ++- 2 files changed, 134 insertions(+), 58 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index e28d0382..03722813 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -85,16 +85,14 @@ public class RunMode { + "\ttypes_list.append(" + STANDARD_KEY + ")" + System.lineSeparator() + "task.outputs['%s'] = %s" + System.lineSeparator(); - private static final String BMZ_CORE_IMPORTS = - "from bioimageio.core import load_resource_description" + System.lineSeparator() - + "from bioimageio.core.resource_io.nodes import Model" + System.lineSeparator(); + private static final String DEFAULT_IMPORT = + "import sys" + System.lineSeparator(); private Environment env; private String envFileName; private String opCode; private OpInterface op; - private LinkedHashMap kwargs; private LinkedHashMap apposeInputMap; private String tensorRecreationCode = ""; private String importsCode = ""; @@ -105,6 +103,18 @@ public class RunMode { private RunMode(OpInterface op) { this.op = op; IntStream.range(0, op.getNumberOfOutputs()).forEach(i -> outputNames.add("output" + i)); + addImports(); + convertInputMap(); + opExecutionCode(); + retrieveResultsCode(); + + opCode = importsCode + System.lineSeparator() + tensorRecreationCode + + System.lineSeparator() + opMethodCode + System.lineSeparator() + + retrieveResultsCode; + System.out.println(opCode); + + + /* envFileName = op.getCondaEnv(); referencedModel = op.appliedOnWhichModel(); @@ -117,6 +127,47 @@ public static RunMode createRunMode(OpInterface op) { return new RunMode(op); } + public void testRunModel() { + env = Appose.base(new File(this.op.getCondaEnv())).build(); + try (Service python = env.python()) { + python.debug(line -> { + System.err.println(line); + }); + Task task = python.task(opCode, apposeInputMap); + System.out.println("here"); + task.listen(event -> { + switch (event.responseType) { + case UPDATE: + System.out.println("Progress: " + task.message); + break; + case COMPLETION: + Object numer = task.outputs.get("output0"); + System.out.println("Task complete. Result: " + numer); + break; + case CANCELATION: + System.out.println("Task canceled"); + break; + case FAILURE: + System.out.println("Task failed: " + task.error); + break; + } + }); + task.waitFor(); + System.out.println("here2"); + Object result = task.outputs.get("output0"); + Object polys = task.outputs.get("output1"); + System.out.println("here3"); + if (result instanceof Integer) + System.out.print(result); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public void envCreation() { if (checkRequiredEnvExists()) { env = Appose.base(new File(envFileName)).build(); @@ -130,60 +181,14 @@ public boolean checkRequiredEnvExists() { } private void addImports() { - opCode += BMZ_CORE_IMPORTS + op.getOpImport() + System.lineSeparator(); - } - - private void opExecutionCode() { - opMethodCode += op.getMethodName() + "("; - for (String key : this.apposeInputMap.keySet()) - opMethodCode += key + ","; - opMethodCode += ")" + System.lineSeparator(); - } - - private void retrieveResultsCode() { - retrieveResultsCode = "task.update('Preparing outputs')" + System.lineSeparator() - + "types_list = []" + System.lineSeparator() ; - - for (String outN : this.outputNames) { - String code = String.format(OUTPUT_REFORMATING, outN, outN, outN, outN, outN, outN, - outN, outN, outN, outN, outN, outN, outN, outN); - retrieveResultsCode += code; - } - } - - public static void main(String[] args) { - Integer[] arr = new Integer[3]; - arr[0] = 0; - Object obj = (int) 2; - boolean aa = isTypeDirectlySupported(obj.getClass()); - RunMode rm = new RunMode(null); - - rm.envFileName = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; - rm.env = Appose.base(new File(rm.envFileName)).build(); - rm.kwargs = new LinkedHashMap(); - - final ImgFactory< FloatType > imgFactory = new CellImgFactory<>( new FloatType(), 5 ); - final Img< FloatType > img1 = imgFactory.create( 1, 512, 512, 3 ); - // Create the input tensor with the nameand axes given by the rdf.yaml file - // and add it to the list of input tensors - Tensor inpTensor = Tensor.build("input0", "byxc", img1); - List> inputs = new ArrayList>(); - inputs.add(inpTensor); - - final Img< FloatType > img2 = imgFactory.create( 1, 512, 512, 1 ); - // Create the input tensor with the nameand axes given by the rdf.yaml file - // and add it to the list of input tensors - Tensor outTensor = Tensor.build("ouput0", "byxc", img2); - List> outputs = new ArrayList>(); - outputs.add(outTensor); - - rm.run(inputs, outputs); - + importsCode = DEFAULT_IMPORT + + "sys.path.append('" + op.getOpDir() + "')" + System.lineSeparator() + + op.getOpImport() + System.lineSeparator(); } private < T extends RealType< T > & NativeType< T > > void convertInputMap() { apposeInputMap = new LinkedHashMap<>(); - for (Entry entry : this.kwargs.entrySet()) { + for (Entry entry : this.op.getOpInputs().entrySet()) { if (entry.getValue() instanceof String) { apposeInputMap.put(entry.getKey(), entry.getValue()); } else if (entry.getValue() instanceof Tensor) { @@ -258,6 +263,60 @@ void addCodeToRecreateNumpyArray(String ogName, RandomAccessibleInterval rai) tensorRecreationCode += System.lineSeparator(); } + private void opExecutionCode() { + opMethodCode = ""; + for (String outN : this.outputNames) { + opMethodCode += outN + ", "; + } + opMethodCode = + opMethodCode.substring(0, opMethodCode.length() - 2); + opMethodCode += " = "; + opMethodCode += op.getMethodName() + "("; + for (String key : this.apposeInputMap.keySet()) + opMethodCode += key + ","; + opMethodCode += ")" + System.lineSeparator(); + } + + private void retrieveResultsCode() { + retrieveResultsCode = "task.update('Preparing outputs')" + System.lineSeparator() + + "types_list = []" + System.lineSeparator() ; + + for (String outN : this.outputNames) { + String code = String.format(OUTPUT_REFORMATING, outN, outN, outN, outN, outN, outN, + outN, outN, outN, outN, outN, outN, outN, outN, outN, outN); + retrieveResultsCode += code; + } + } + + public static void main(String[] args) { + Integer[] arr = new Integer[3]; + arr[0] = 0; + Object obj = (int) 2; + boolean aa = isTypeDirectlySupported(obj.getClass()); + RunMode rm = new RunMode(null); + + rm.envFileName = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; + rm.env = Appose.base(new File(rm.envFileName)).build(); + + final ImgFactory< FloatType > imgFactory = new CellImgFactory<>( new FloatType(), 5 ); + final Img< FloatType > img1 = imgFactory.create( 1, 512, 512, 3 ); + // Create the input tensor with the nameand axes given by the rdf.yaml file + // and add it to the list of input tensors + Tensor inpTensor = Tensor.build("input0", "byxc", img1); + List> inputs = new ArrayList>(); + inputs.add(inpTensor); + + final Img< FloatType > img2 = imgFactory.create( 1, 512, 512, 1 ); + // Create the input tensor with the nameand axes given by the rdf.yaml file + // and add it to the list of input tensors + Tensor outTensor = Tensor.build("ouput0", "byxc", img2); + List> outputs = new ArrayList>(); + outputs.add(outTensor); + + rm.run(inputs, outputs); + + } + public < T extends RealType< T > & NativeType< T > > void run(List> inputTensors, List> outputTensors) { @@ -274,7 +333,7 @@ void run(List> inputTensors, List> outputTensors) { } - inputMap.putAll(kwargs); + inputMap.putAll(null); opCode = "import numpy as np\r\n" + "import asyncio\r\n" diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index d37fcf52..a6d58621 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -27,10 +27,15 @@ import io.bioimage.modelrunner.bioimageio.BioimageioRepo; import io.bioimage.modelrunner.bioimageio.description.ModelDescriptor; +import io.bioimage.modelrunner.runmode.RunMode; import io.bioimage.modelrunner.tensor.Tensor; import io.bioimage.modelrunner.utils.Constants; +import net.imglib2.img.Img; +import net.imglib2.img.ImgFactory; +import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; +import net.imglib2.type.numeric.real.FloatType; /** * Code for the JDLL OP that allows running the whole stardist model (pre-processing + model executio @@ -62,6 +67,18 @@ public class StardistInferJdllOp implements OpInterface { private static final String STARDIST_OP_FNAME = "stardist_inference.py"; + + public static void main(String[] args) { + final ImgFactory< FloatType > imgFactory = new ArrayImgFactory<>( new FloatType() ); + final Img< FloatType > img1 = imgFactory.create( 1, 512, 512, 3 ); + Tensor inpTensor = Tensor.build("input0", "byxc", img1); + String modelName = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models\\StarDist H&E Nuclei Segmentation_06092023_020924\\rdf.yaml"; + StardistInferJdllOp op = create(modelName, inpTensor); + RunMode rm = RunMode.createRunMode(op); + rm.testRunModel(); + System.out.print(false); + } + /** * Create a StarDist inference OP to execute the whole stardist model in Python * with its pre- and post-processing @@ -87,7 +104,7 @@ public void setModel(String modelName) throws IllegalArgumentException { if (new File(modelName).isFile() && !isModelFileStardist(modelName)) throw new IllegalArgumentException("The file selected does not correspond to " + "the rdf.yaml file of a Bioiamge.io Stardist model."); - else if (!isModelNameStardist(modelName)) + else if (!(new File(modelName).isFile()) && !isModelNameStardist(modelName)) throw new IllegalArgumentException("The model name provided does not correspond to a valid" + " Stardist model present in the Bioimage.io online reposritory."); this.modelName = modelName; @@ -114,7 +131,7 @@ public void installOp() { opFilePath = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\python\\ops\\stardist_inference"; // TODO check if the env has also been created // TODO if not create it (where??) - envPath = ""; + envPath = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\my_new_project"; } @Override @@ -179,7 +196,7 @@ public static boolean isModelFileStardist(String modelFile) { if (new File(modelFile).getName().equals(Constants.RDF_FNAME) == false) return false; try { - ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(modelFile); + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(modelFile, false); return descriptor.getConfig().getSpecMap().keySet().contains(STARDIST_FIELD_KEY); } catch (Exception e) { return false; From 119d52031e38b7e120688ca2aa428e13d0a44761 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 25 Sep 2023 19:08:06 +0200 Subject: [PATCH 032/235] remove running the code --- python/ops/stardist_inference/stardist_inference.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ops/stardist_inference/stardist_inference.py b/python/ops/stardist_inference/stardist_inference.py index fc6fed8b..5faff7d0 100644 --- a/python/ops/stardist_inference/stardist_inference.py +++ b/python/ops/stardist_inference/stardist_inference.py @@ -245,8 +245,8 @@ def stardist_prediction_2d( assert output_axes_wo_channels == tuple("byx") return xr.DataArray(labels, dims=output_axes_wo_channels), polys -arr = np.zeros((1, 208, 208, 3)) -xarr = xr.DataArray(arr, dims=["b", "y", "x", "c"], name="input") -model_path = "chatty-frog" -model_path = r'C:\Users\angel\OneDrive\Documentos\pasteur\git\model-runner-java\models\StarDist H&E Nuclei Segmentation_06092023_020924\rdf.yaml' -stardist_prediction_2d_mine(model_path, xarr) +#arr = np.zeros((1, 208, 208, 3)) +#xarr = xr.DataArray(arr, dims=["b", "y", "x", "c"], name="input") +#model_path = "chatty-frog" +#model_path = r'C:\Users\angel\OneDrive\Documentos\pasteur\git\model-runner-java\models\StarDist H&E Nuclei Segmentation_06092023_020924\rdf.yaml' +#stardist_prediction_2d_mine(model_path, xarr) From 4eb1ab7871dda8de64167f402de20d8006af1965 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 27 Sep 2023 20:06:53 +0200 Subject: [PATCH 033/235] correct erros in python script created to run the op --- .../io/bioimage/modelrunner/runmode/RunMode.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 03722813..2378ff7b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -57,7 +57,7 @@ public class RunMode { private static final String DATA_KEY = "data"; - private static final String NAME_KEY = "data"; + private static final String NAME_KEY = "name"; private static final String TENSOR_KEY = "tensor"; @@ -134,7 +134,6 @@ public void testRunModel() { System.err.println(line); }); Task task = python.task(opCode, apposeInputMap); - System.out.println("here"); task.listen(event -> { switch (event.responseType) { case UPDATE: @@ -182,8 +181,9 @@ public boolean checkRequiredEnvExists() { private void addImports() { importsCode = DEFAULT_IMPORT - + "sys.path.append('" + op.getOpDir() + "')" + System.lineSeparator() - + op.getOpImport() + System.lineSeparator(); + + "sys.path.append(r'" + op.getOpDir() + "')" + System.lineSeparator() + + op.getOpImport() + System.lineSeparator() + + "task.update('Imports')" + System.lineSeparator(); } private < T extends RealType< T > & NativeType< T > > void convertInputMap() { @@ -233,6 +233,8 @@ void addCodeToRecreateTensor(String ogName, Tensor tensor) { importsCode += IMPORT_XARRAY; if (!importsCode.contains(IMPORT_NUMPY)) importsCode += IMPORT_NUMPY; + tensorRecreationCode = ""; + tensorRecreationCode += "task.update('input conv')" + System.lineSeparator(); // This line wants to recreate the original numpy array. Should look like: // input0 = xr.DataArray(np.array(input0).reshape([1, 1, 512, 512]), dims=["b", "c", "y", "x"], name="input0") this.tensorRecreationCode += ogName + " = xr.DataArray(np.array(" + ogName + ").reshape(["; @@ -245,7 +247,7 @@ void addCodeToRecreateTensor(String ogName, Tensor tensor) { tensorRecreationCode += "\"" + ss + "\", "; tensorRecreationCode = tensorRecreationCode.substring(0, tensorRecreationCode.length() - 2); - tensorRecreationCode += "], name=" + tensor.getName() + "])"; + tensorRecreationCode += "], name=\"" + tensor.getName() + "\")"; tensorRecreationCode += System.lineSeparator(); } @@ -260,11 +262,12 @@ void addCodeToRecreateNumpyArray(String ogName, RandomAccessibleInterval rai) tensorRecreationCode += ll + ", "; tensorRecreationCode = tensorRecreationCode.substring(0, tensorRecreationCode.length() - 2); - tensorRecreationCode += System.lineSeparator(); + tensorRecreationCode += "])" + System.lineSeparator(); } private void opExecutionCode() { opMethodCode = ""; + opMethodCode += "task.update('method')" + System.lineSeparator(); for (String outN : this.outputNames) { opMethodCode += outN + ", "; } From 0bfbb5816943d2360f72ff3fbc041486399aa0e8 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 27 Sep 2023 20:25:22 +0200 Subject: [PATCH 034/235] keep improving the code to run external ops --- src/main/java/io/bioimage/modelrunner/runmode/RunMode.java | 6 ++++-- .../io/bioimage/modelrunner/runmode/ops/OpInterface.java | 2 +- .../modelrunner/runmode/ops/StardistInferJdllOp.java | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 2378ff7b..9a897bdb 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -98,10 +98,12 @@ public class RunMode { private String importsCode = ""; private String opMethodCode = ""; private String retrieveResultsCode = ""; + private String moduleName; List outputNames = new ArrayList(); private RunMode(OpInterface op) { this.op = op; + this.moduleName = op.getOpPythonFilename().substring(0, op.getOpPythonFilename().length() - 3); IntStream.range(0, op.getNumberOfOutputs()).forEach(i -> outputNames.add("output" + i)); addImports(); convertInputMap(); @@ -182,7 +184,7 @@ public boolean checkRequiredEnvExists() { private void addImports() { importsCode = DEFAULT_IMPORT + "sys.path.append(r'" + op.getOpDir() + "')" + System.lineSeparator() - + op.getOpImport() + System.lineSeparator() + + "import " + moduleName + System.lineSeparator() + "task.update('Imports')" + System.lineSeparator(); } @@ -274,7 +276,7 @@ private void opExecutionCode() { opMethodCode = opMethodCode.substring(0, opMethodCode.length() - 2); opMethodCode += " = "; - opMethodCode += op.getMethodName() + "("; + opMethodCode += moduleName + "." + op.getMethodName() + "("; for (String key : this.apposeInputMap.keySet()) opMethodCode += key + ","; opMethodCode += ")" + System.lineSeparator(); diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java index 69817a99..01cdd99b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java @@ -32,7 +32,7 @@ public interface OpInterface { * @return a String containing a Python snippet with the imports needed to use the * OP */ - public String getOpImport(); + public String getOpPythonFilename(); /** * Number of outputs that the OP method will produce * @return number of ouptuts that the OP method will produce diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index a6d58621..660c56fb 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -115,8 +115,8 @@ public < T extends RealType< T > & NativeType< T > > void setInputTensor(Tensor< } @Override - public String getOpImport() { - return "import " + STARDIST_OP_FNAME.substring(0, STARDIST_OP_FNAME.indexOf(".py")); + public String getOpPythonFilename() { + return STARDIST_OP_FNAME; } @Override @@ -131,7 +131,7 @@ public void installOp() { opFilePath = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\python\\ops\\stardist_inference"; // TODO check if the env has also been created // TODO if not create it (where??) - envPath = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\my_new_project"; + envPath = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; } @Override From f7a04cf0d8f3630d36d1ed12a1aac80ee2f04cd0 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 28 Sep 2023 17:10:01 +0200 Subject: [PATCH 035/235] correct error in the python code --- .../java/io/bioimage/modelrunner/runmode/RunMode.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 9a897bdb..689eab00 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -68,21 +68,21 @@ public class RunMode { // TODO add support for list of objects private static final String OUTPUT_REFORMATING = "if isinstance(%s, xr.DataArray):" + System.lineSeparator() - + "\ttypes_list.append(" + TENSOR_KEY + ")" + System.lineSeparator() + + "\ttypes_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() + "\t%s = {\"" + DATA_KEY + "\": %s.values.flatten().tolist(), \"" + SHAPE_KEY + "\": %s.shape, \"" + AXES_KEY + "\": %s.dims," + "\"" + NAME_KEY + "\": %s.name}" + System.lineSeparator() + "elif isinstance(%s, np.ndarray):" + System.lineSeparator() - + "\ttypes_list.append(" + NP_ARR_KEY + ")" + System.lineSeparator() + + "\ttypes_list.append(\"" + NP_ARR_KEY + "\")" + System.lineSeparator() + "\t%s = {\"" + DATA_KEY + "\": %s.flatten().tolist(), \"" + SHAPE_KEY + "\": %s.shape}" + System.lineSeparator() + "elif isinstance(%s, list) and len(%s) == 0:" + System.lineSeparator() - + "\ttypes_list.append(" + STANDARD_KEY + ")" + System.lineSeparator() + + "\ttypes_list.append(\"" + STANDARD_KEY + "\")" + System.lineSeparator() + "elif isinstance(%s, list) and isinstance(%s[0], list):" + System.lineSeparator() - + "\ttypes_list.append(" + TENSOR_KEY + ")" + System.lineSeparator() + + "\ttypes_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() + "\t" + System.lineSeparator() + "else:" + System.lineSeparator() - + "\ttypes_list.append(" + STANDARD_KEY + ")" + System.lineSeparator() + + "\ttypes_list.append(\"" + STANDARD_KEY + "\")" + System.lineSeparator() + "task.outputs['%s'] = %s" + System.lineSeparator(); private static final String DEFAULT_IMPORT = From 007e72a08fc2616b0f9a3dd5b9301df04777ede1 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 28 Sep 2023 18:04:51 +0200 Subject: [PATCH 036/235] add method with helpers to write scripts for appose --- .../modelrunner/runmode/RunModeScripts.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java new file mode 100644 index 00000000..cf1781d9 --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -0,0 +1,62 @@ +package io.bioimage.modelrunner.runmode; + +public class RunModeScripts { + + protected static final String AXES_KEY = "axes"; + + protected static final String SHAPE_KEY = "shape"; + + protected static final String DATA_KEY = "data"; + + protected static final String NAME_KEY = "name"; + + protected static final String NP_METHOD = "convertNpIntoDic"; + + protected static final String XR_METHOD = "convertXrIntoDic"; + + protected static final String LIST_METHOD = "convertListIntoSupportedist"; + + protected static final String DICT_METHOD = "convertDicIntoDic"; + + /** + * Script that contains all the methods neeed to convert python types + * into Appose supported types (primitive types and dics and lists of them) + */ + protected static final String TYPE_CONVERSION_METHODS_SCRIPT = "" + + "def " + NP_METHOD + "(np_arr):" + System.lineSeparator() + + " return {\"" + DATA_KEY + "\": np_arr.flatten().tolist(), \"" + SHAPE_KEY + "\": np_arr.shape}" + System.lineSeparator() + + "" + System.lineSeparator() + + "def " + XR_METHOD + "(xr_arr):" + System.lineSeparator() + + " return {\"" + DATA_KEY + "\": xr_arr.values.flatten().tolist(), \"" + SHAPE_KEY + "\": xr_arr.shape, \"" + AXES_KEY + "\": xr_arr.dims,\"" + NAME_KEY + "\": xr_arr.name}" + System.lineSeparator() + + "" + System.lineSeparator() + + "def " + LIST_METHOD + "(list_ob):" + System.lineSeparator() + + " n_list = []" + System.lineSeparator() + + " for value in list_ob:" + System.lineSeparator() + + " if isinstance(value, xr.DataArray):" + System.lineSeparator() + + " n_list.append(" + XR_METHOD + "(value))" + System.lineSeparator() + + " elif isinstance(value, np.ndarray):" + System.lineSeparator() + + " n_list.append(" + NP_METHOD + "(value))" + System.lineSeparator() + + " elif isinstance(value, dict):" + System.lineSeparator() + + " n_list.append(" + DICT_METHOD + "(value))" + System.lineSeparator() + + " elif isinstance(value, list):" + System.lineSeparator() + + " n_list.append(" + LIST_METHOD + "(value))" + System.lineSeparator() + + " else:" + System.lineSeparator() + + " n_list.append(value)" + System.lineSeparator() + + " return n_list" + System.lineSeparator() + + "" + System.lineSeparator() + + "def " + DICT_METHOD + "(dic):" + System.lineSeparator() + + " n_dic = {}" + System.lineSeparator() + + " for key, value in d.items():" + System.lineSeparator() + + " if isinstance(value, xr.DataArray):" + System.lineSeparator() + + " n_dic[key] = " + XR_METHOD + "(value)" + System.lineSeparator() + + " elif isinstance(value, np.ndarray):" + System.lineSeparator() + + " n_dic[key] = " + NP_METHOD + "(value)" + System.lineSeparator() + + " elif isinstance(value, dict):" + System.lineSeparator() + + " n_dic[key] = " + DICT_METHOD + "(value)" + System.lineSeparator() + + " elif isinstance(value, list):" + System.lineSeparator() + + " n_dic[key] = " + LIST_METHOD + "(value)" + System.lineSeparator() + + " else:" + System.lineSeparator() + + " n_dic[key] = value" + System.lineSeparator() + + " return n_dic"; + +} From c947099e5f278b6ec5d3b61e6874d331d9ece55c Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 28 Sep 2023 18:26:42 +0200 Subject: [PATCH 037/235] correct small bug --- .../java/io/bioimage/modelrunner/runmode/RunModeScripts.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index cf1781d9..61566a59 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -46,7 +46,7 @@ public class RunModeScripts { + "" + System.lineSeparator() + "def " + DICT_METHOD + "(dic):" + System.lineSeparator() + " n_dic = {}" + System.lineSeparator() - + " for key, value in d.items():" + System.lineSeparator() + + " for key, value in dic.items():" + System.lineSeparator() + " if isinstance(value, xr.DataArray):" + System.lineSeparator() + " n_dic[key] = " + XR_METHOD + "(value)" + System.lineSeparator() + " elif isinstance(value, np.ndarray):" + System.lineSeparator() From 32ba956a19b8dcc61ec5e66b21f600bf8ce0e9d5 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 28 Sep 2023 20:00:15 +0200 Subject: [PATCH 038/235] avoid depending on locals to make the type comparison --- .../io/bioimage/modelrunner/runmode/RunModeScripts.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index 61566a59..3ccbaa4e 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -32,9 +32,9 @@ public class RunModeScripts { + "def " + LIST_METHOD + "(list_ob):" + System.lineSeparator() + " n_list = []" + System.lineSeparator() + " for value in list_ob:" + System.lineSeparator() - + " if isinstance(value, xr.DataArray):" + System.lineSeparator() + + " if str(type(value)) == \"\":" + System.lineSeparator() + " n_list.append(" + XR_METHOD + "(value))" + System.lineSeparator() - + " elif isinstance(value, np.ndarray):" + System.lineSeparator() + + " elif str(type(value)) == \"\":" + System.lineSeparator() + " n_list.append(" + NP_METHOD + "(value))" + System.lineSeparator() + " elif isinstance(value, dict):" + System.lineSeparator() + " n_list.append(" + DICT_METHOD + "(value))" + System.lineSeparator() @@ -47,9 +47,9 @@ public class RunModeScripts { + "def " + DICT_METHOD + "(dic):" + System.lineSeparator() + " n_dic = {}" + System.lineSeparator() + " for key, value in dic.items():" + System.lineSeparator() - + " if isinstance(value, xr.DataArray):" + System.lineSeparator() + + " if str(type(value)) == \"\":" + System.lineSeparator() + " n_dic[key] = " + XR_METHOD + "(value)" + System.lineSeparator() - + " elif isinstance(value, np.ndarray):" + System.lineSeparator() + + " elif str(type(value)) == \"\":" + System.lineSeparator() + " n_dic[key] = " + NP_METHOD + "(value)" + System.lineSeparator() + " elif isinstance(value, dict):" + System.lineSeparator() + " n_dic[key] = " + DICT_METHOD + "(value)" + System.lineSeparator() From c597a603f4cd552b7344b43693c3844a5cc1171f Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Thu, 28 Sep 2023 20:00:33 +0200 Subject: [PATCH 039/235] keep improving the run mode --- .../bioimage/modelrunner/runmode/RunMode.java | 63 ++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 689eab00..5032d41b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -51,14 +51,6 @@ public class RunMode { private static final String IMPORT_NUMPY = "import numpy as np" + System.lineSeparator(); - private static final String AXES_KEY = "axes"; - - private static final String SHAPE_KEY = "shape"; - - private static final String DATA_KEY = "data"; - - private static final String NAME_KEY = "name"; - private static final String TENSOR_KEY = "tensor"; private static final String NP_ARR_KEY = "np_arr"; @@ -68,22 +60,26 @@ public class RunMode { // TODO add support for list of objects private static final String OUTPUT_REFORMATING = "if isinstance(%s, xr.DataArray):" + System.lineSeparator() - + "\ttypes_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() - + "\t%s = {\"" + DATA_KEY + "\": %s.values.flatten().tolist(), \"" - + SHAPE_KEY + "\": %s.shape, \"" + AXES_KEY + "\": %s.dims," - + "\"" + NAME_KEY + "\": %s.name}" + System.lineSeparator() + + " task.update('is data array')" + System.lineSeparator() + + " types_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() + + " %s = " + RunModeScripts.XR_METHOD + "(%s)" + System.lineSeparator() + "elif isinstance(%s, np.ndarray):" + System.lineSeparator() - + "\ttypes_list.append(\"" + NP_ARR_KEY + "\")" + System.lineSeparator() - + "\t%s = {\"" + DATA_KEY + "\": %s.flatten().tolist(), \"" - + SHAPE_KEY + "\": %s.shape}" + System.lineSeparator() - + "elif isinstance(%s, list) and len(%s) == 0:" + System.lineSeparator() - + "\ttypes_list.append(\"" + STANDARD_KEY + "\")" + System.lineSeparator() - + "elif isinstance(%s, list) and isinstance(%s[0], list):" + System.lineSeparator() - + "\ttypes_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() - + "\t" + System.lineSeparator() + + " task.update('np array')" + System.lineSeparator() + + " types_list.append(\"" + NP_ARR_KEY + "\")" + System.lineSeparator() + + " %s = " + RunModeScripts.NP_METHOD + "(%s)" + System.lineSeparator() + + "elif isinstance(%s, list):" + System.lineSeparator() + + " task.update('is list')" + System.lineSeparator() + + " types_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() + + " %s = " + RunModeScripts.LIST_METHOD + "(%s)" + System.lineSeparator() + + "elif isinstance(%s, dict):" + System.lineSeparator() + + " task.update('is dict')" + System.lineSeparator() + + " task.update(str(output1))" + System.lineSeparator() + + " types_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() + + " %s = " + RunModeScripts.DICT_METHOD + "(%s)" + System.lineSeparator() + "else:" + System.lineSeparator() - + "\ttypes_list.append(\"" + STANDARD_KEY + "\")" + System.lineSeparator() - + "task.outputs['%s'] = %s" + System.lineSeparator(); + + " task.update('standard')" + System.lineSeparator() + + " task.update(str(type(%s)))" + System.lineSeparator() + + " types_list.append(\"" + STANDARD_KEY + "\")" + System.lineSeparator(); private static final String DEFAULT_IMPORT = "import sys" + System.lineSeparator(); @@ -98,6 +94,7 @@ public class RunMode { private String importsCode = ""; private String opMethodCode = ""; private String retrieveResultsCode = ""; + private String taskOutputCode = ""; private String moduleName; List outputNames = new ArrayList(); @@ -110,9 +107,15 @@ private RunMode(OpInterface op) { opExecutionCode(); retrieveResultsCode(); - opCode = importsCode + System.lineSeparator() + tensorRecreationCode - + System.lineSeparator() + opMethodCode + System.lineSeparator() - + retrieveResultsCode; + opCode = importsCode + System.lineSeparator() + + RunModeScripts.TYPE_CONVERSION_METHODS_SCRIPT + System.lineSeparator() + + tensorRecreationCode + System.lineSeparator() + + opMethodCode + System.lineSeparator() + + "globals()['convertNpIntoDic'] = convertNpIntoDic" + System.lineSeparator() + + "task.update(str(globals().keys()))" + System.lineSeparator() + + "task.update(str(locals().keys()))" + System.lineSeparator() + + retrieveResultsCode + System.lineSeparator() + + taskOutputCode; System.out.println(opCode); @@ -288,8 +291,10 @@ private void retrieveResultsCode() { for (String outN : this.outputNames) { String code = String.format(OUTPUT_REFORMATING, outN, outN, outN, outN, outN, outN, - outN, outN, outN, outN, outN, outN, outN, outN, outN, outN); + outN, outN, outN, outN, outN, outN, outN); retrieveResultsCode += code; + taskOutputCode += String.format("task.outputs['%s'] = %s", outN, outN) + + System.lineSeparator(); } } @@ -331,9 +336,9 @@ void run(List> inputTensors, List> outputTensors) { LinkedHashMap inputMap = new LinkedHashMap<>(); for (Tensor input : inputTensors) { HashMap tensorMap = new HashMap(); - tensorMap.put(AXES_KEY, input.getAxesOrderString()); - tensorMap.put(DATA_KEY, ImgLib2ToArray.build(input.getData())); - tensorMap.put(SHAPE_KEY, input.getShape()); + tensorMap.put(RunModeScripts.AXES_KEY, input.getAxesOrderString()); + tensorMap.put(RunModeScripts.DATA_KEY, ImgLib2ToArray.build(input.getData())); + tensorMap.put(RunModeScripts.SHAPE_KEY, input.getShape()); inputMap.put(input.getName(), tensorMap); } From ee1cb7fc85fafae4d62c3458dd526f7df13fdac4 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 00:51:23 +0200 Subject: [PATCH 040/235] add methods created to globals --- .../io/bioimage/modelrunner/runmode/RunModeScripts.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index 3ccbaa4e..c094628e 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -14,7 +14,7 @@ public class RunModeScripts { protected static final String XR_METHOD = "convertXrIntoDic"; - protected static final String LIST_METHOD = "convertListIntoSupportedist"; + protected static final String LIST_METHOD = "convertListIntoSupportedList"; protected static final String DICT_METHOD = "convertDicIntoDic"; @@ -57,6 +57,10 @@ public class RunModeScripts { + " n_dic[key] = " + LIST_METHOD + "(value)" + System.lineSeparator() + " else:" + System.lineSeparator() + " n_dic[key] = value" + System.lineSeparator() - + " return n_dic"; + + " return n_dic" + System.lineSeparator() + + "globals()['" + XR_METHOD + "'] = " + XR_METHOD + System.lineSeparator() + + "globals()['" + NP_METHOD + "'] = " + NP_METHOD + System.lineSeparator() + + "globals()['" + DICT_METHOD + "'] = " + DICT_METHOD + System.lineSeparator() + + "globals()['" + LIST_METHOD + "'] = " + LIST_METHOD + System.lineSeparator(); } From 5676c22f2775dfd9e6ea48b3ad49f8cda3d474db Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 01:45:26 +0200 Subject: [PATCH 041/235] kee improving the runmode --- .../bioimage/modelrunner/runmode/RunMode.java | 196 +++--------------- .../modelrunner/runmode/RunModeScripts.java | 35 +++- 2 files changed, 62 insertions(+), 169 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 5032d41b..d664ce33 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -22,9 +22,9 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.stream.IntStream; @@ -33,53 +33,34 @@ import org.apposed.appose.Service; import org.apposed.appose.Service.Task; -import io.bioimage.modelrunner.runmode.ops.OpDescription; import io.bioimage.modelrunner.runmode.ops.OpInterface; import io.bioimage.modelrunner.tensor.ImgLib2ToArray; import io.bioimage.modelrunner.tensor.Tensor; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.img.Img; -import net.imglib2.img.ImgFactory; -import net.imglib2.img.cell.CellImgFactory; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; -import net.imglib2.type.numeric.real.FloatType; public class RunMode { private static final String IMPORT_XARRAY = "import xarray as xr" + System.lineSeparator(); - private static final String IMPORT_NUMPY = "import numpy as np" + System.lineSeparator(); - - private static final String TENSOR_KEY = "tensor"; - - private static final String NP_ARR_KEY = "np_arr"; - - private static final String STANDARD_KEY = "standard"; + private static final String IMPORT_NUMPY = "import numpy as np" + System.lineSeparator(); // TODO add support for list of objects private static final String OUTPUT_REFORMATING = "if isinstance(%s, xr.DataArray):" + System.lineSeparator() + " task.update('is data array')" + System.lineSeparator() - + " types_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() + " %s = " + RunModeScripts.XR_METHOD + "(%s)" + System.lineSeparator() + "elif isinstance(%s, np.ndarray):" + System.lineSeparator() + " task.update('np array')" + System.lineSeparator() - + " types_list.append(\"" + NP_ARR_KEY + "\")" + System.lineSeparator() + " %s = " + RunModeScripts.NP_METHOD + "(%s)" + System.lineSeparator() + "elif isinstance(%s, list):" + System.lineSeparator() + " task.update('is list')" + System.lineSeparator() - + " types_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() + " %s = " + RunModeScripts.LIST_METHOD + "(%s)" + System.lineSeparator() + "elif isinstance(%s, dict):" + System.lineSeparator() + " task.update('is dict')" + System.lineSeparator() + " task.update(str(output1))" + System.lineSeparator() - + " types_list.append(\"" + TENSOR_KEY + "\")" + System.lineSeparator() - + " %s = " + RunModeScripts.DICT_METHOD + "(%s)" + System.lineSeparator() - + "else:" + System.lineSeparator() - + " task.update('standard')" + System.lineSeparator() - + " task.update(str(type(%s)))" + System.lineSeparator() - + " types_list.append(\"" + STANDARD_KEY + "\")" + System.lineSeparator(); + + " %s = " + RunModeScripts.DICT_METHOD + "(%s)" + System.lineSeparator(); private static final String DEFAULT_IMPORT = "import sys" + System.lineSeparator(); @@ -111,21 +92,9 @@ private RunMode(OpInterface op) { + RunModeScripts.TYPE_CONVERSION_METHODS_SCRIPT + System.lineSeparator() + tensorRecreationCode + System.lineSeparator() + opMethodCode + System.lineSeparator() - + "globals()['convertNpIntoDic'] = convertNpIntoDic" + System.lineSeparator() - + "task.update(str(globals().keys()))" + System.lineSeparator() - + "task.update(str(locals().keys()))" + System.lineSeparator() + retrieveResultsCode + System.lineSeparator() + taskOutputCode; System.out.println(opCode); - - - - /* - envFileName = op.getCondaEnv(); - referencedModel = op.appliedOnWhichModel(); - opName = op.getMethodName(); - kwargs = op.getMethodExtraArgs(); - */ } public static RunMode createRunMode(OpInterface op) { @@ -154,10 +123,16 @@ public void testRunModel() { case FAILURE: System.out.println("Task failed: " + task.error); break; + case LAUNCH: + System.out.println("LAunched code"); + break; + default: + break; } }); task.waitFor(); System.out.println("here2"); + Map aa = task.outputs; Object result = task.outputs.get("output0"); Object polys = task.outputs.get("output1"); System.out.println("here3"); @@ -172,6 +147,25 @@ public void testRunModel() { } } + private Map recreateOutputObjects(Map apposeOuts) { + LinkedHashMap jdllOuts = new LinkedHashMap(); + for (Entry entry : apposeOuts.entrySet()) { + Object value = entry.getValue(); + + if (value instanceof Map && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY) != null + && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.TENSOR_KEY) ) { + + } else if (value instanceof Map && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY) != null + && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.NP_ARR_KEY) ) { + + } else if (value instanceof Map) { + + } else if (value instanceof List) { + + } + } + } + public void envCreation() { if (checkRequiredEnvExists()) { env = Appose.base(new File(envFileName)).build(); @@ -286,8 +280,7 @@ private void opExecutionCode() { } private void retrieveResultsCode() { - retrieveResultsCode = "task.update('Preparing outputs')" + System.lineSeparator() - + "types_list = []" + System.lineSeparator() ; + retrieveResultsCode = "task.update('Preparing outputs')" + System.lineSeparator(); for (String outN : this.outputNames) { String code = String.format(OUTPUT_REFORMATING, outN, outN, outN, outN, outN, outN, @@ -297,135 +290,4 @@ private void retrieveResultsCode() { + System.lineSeparator(); } } - - public static void main(String[] args) { - Integer[] arr = new Integer[3]; - arr[0] = 0; - Object obj = (int) 2; - boolean aa = isTypeDirectlySupported(obj.getClass()); - RunMode rm = new RunMode(null); - - rm.envFileName = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; - rm.env = Appose.base(new File(rm.envFileName)).build(); - - final ImgFactory< FloatType > imgFactory = new CellImgFactory<>( new FloatType(), 5 ); - final Img< FloatType > img1 = imgFactory.create( 1, 512, 512, 3 ); - // Create the input tensor with the nameand axes given by the rdf.yaml file - // and add it to the list of input tensors - Tensor inpTensor = Tensor.build("input0", "byxc", img1); - List> inputs = new ArrayList>(); - inputs.add(inpTensor); - - final Img< FloatType > img2 = imgFactory.create( 1, 512, 512, 1 ); - // Create the input tensor with the nameand axes given by the rdf.yaml file - // and add it to the list of input tensors - Tensor outTensor = Tensor.build("ouput0", "byxc", img2); - List> outputs = new ArrayList>(); - outputs.add(outTensor); - - rm.run(inputs, outputs); - - } - - public < T extends RealType< T > & NativeType< T > > - void run(List> inputTensors, List> outputTensors) { - - opCode = ""; - addImports(); - - LinkedHashMap inputMap = new LinkedHashMap<>(); - for (Tensor input : inputTensors) { - HashMap tensorMap = new HashMap(); - tensorMap.put(RunModeScripts.AXES_KEY, input.getAxesOrderString()); - tensorMap.put(RunModeScripts.DATA_KEY, ImgLib2ToArray.build(input.getData())); - tensorMap.put(RunModeScripts.SHAPE_KEY, input.getShape()); - inputMap.put(input.getName(), tensorMap); - - } - - inputMap.putAll(null); - - opCode = "import numpy as np\r\n" - + "import asyncio\r\n" - + "import numpy as np\r\n" - + "import tempfile\r\n" - + "import warnings\r\n" - + "from math import ceil\r\n" - + "from os import PathLike\r\n" - + "from pathlib import Path\r\n" - + "from typing import Dict, IO, List, Optional, Tuple, Union\r\n" - + "\r\n" - + "import xarray as xr\r\n" - + "from stardist import import_bioimageio as stardist_import_bioimageio\r\n" - + "\r\n" - + "from bioimageio.core import export_resource_package, load_resource_description\r\n" - + "from bioimageio.core.prediction_pipeline._combined_processing import CombinedProcessing\r\n" - + "from bioimageio.core.prediction_pipeline._measure_groups import compute_measures\r\n" - + "from bioimageio.core.resource_io.nodes import Model\r\n" - + "from bioimageio.spec.model import raw_nodes\r\n" - + "from bioimageio.spec.shared.raw_nodes import ResourceDescription as RawResourceDescription\r\n" - + "from bioimageio.workflows import stardist_prediction_2d\r\n" - + "input_tensor = input0['data']\r\n" - + "input_tensor = np.array(input_tensor).reshape(1,512,512,3)\r\n" - + "model_rdf = 'chatty-frog'\r\n" - + "package_path = export_resource_package(model_rdf)\r\n" - + "with tempfile.TemporaryDirectory() as tmp_dir:\r\n" - + " import_dir = Path(tmp_dir) / \"import_dir\"\r\n" - + " imported_stardist_model = stardist_import_bioimageio(package_path, import_dir)\r\n" - + "\r\n" - + "model = load_resource_description(package_path)\r\n" - + "task.update('BBBBBBBBBBBB')\r\n" - + "labels, polys = imported_stardist_model.predict_instances(\r\n" - + " input_tensor,\r\n" - + " axes=\"\".join([{\"b\": \"S\"}.get(a[0], a[0].capitalize()) for a in model.inputs[0].axes]),\r\n" - + " n_tiles=None,\r\n" - + ")\r\n" - + "\r\n" - + "if len(labels.shape) == 2: # batch dim got squeezed\r\n" - + " labels = labels[None]\r\n" - + "\r\n" - + "output_axes_wo_channels = tuple(a for a in model.outputs[0].axes if a != \"c\")\r\n" - //+ "labels = labels.flatten().tolist()\r\n" - + "task.update('AAAAAAAAAAA')\r\n" - + "task.update(str(type(labels)))\r\n" - + "task.outputs['output0'] = labels\r\n"; - - try (Service python = env.python()) { - python.debug(line -> { - System.err.println(line); - }); - Task task = python.task(opCode, inputMap); - System.out.println("here"); - task.listen(event -> { - switch (event.responseType) { - case UPDATE: - System.out.println("Progress: " + task.message); - break; - case COMPLETION: - Object numer = task.outputs.get("output0"); - System.out.println("Task complete. Result: " + numer); - break; - case CANCELATION: - System.out.println("Task canceled"); - break; - case FAILURE: - System.out.println("Task failed: " + task.error); - break; - } - }); - task.waitFor(); - System.out.println("here2"); - Object result = task.outputs.get("output0"); - Object polys = task.outputs.get("polys"); - System.out.println("here3"); - if (result instanceof Integer) - System.out.print(result); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } } diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index c094628e..fce917fa 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -1,5 +1,26 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ package io.bioimage.modelrunner.runmode; +import io.bioimage.modelrunner.bioimageio.download.DownloadModel; + public class RunModeScripts { protected static final String AXES_KEY = "axes"; @@ -18,16 +39,26 @@ public class RunModeScripts { protected static final String DICT_METHOD = "convertDicIntoDic"; + protected static final String APPOSE_DT_KEY = DownloadModel.addTimeStampToFileName("appose_data_type_", true); + + protected static final String TENSOR_KEY = "tensor"; + + protected static final String NP_ARR_KEY = "np_arr"; + /** * Script that contains all the methods neeed to convert python types * into Appose supported types (primitive types and dics and lists of them) */ protected static final String TYPE_CONVERSION_METHODS_SCRIPT = "" + "def " + NP_METHOD + "(np_arr):" + System.lineSeparator() - + " return {\"" + DATA_KEY + "\": np_arr.flatten().tolist(), \"" + SHAPE_KEY + "\": np_arr.shape}" + System.lineSeparator() + + " return {\"" + DATA_KEY + "\": np_arr.flatten().tolist(), \"" + SHAPE_KEY + + "\": np_arr.shape, \"" + APPOSE_DT_KEY + "\": \"" + + NP_ARR_KEY + "\"}" + System.lineSeparator() + "" + System.lineSeparator() + "def " + XR_METHOD + "(xr_arr):" + System.lineSeparator() - + " return {\"" + DATA_KEY + "\": xr_arr.values.flatten().tolist(), \"" + SHAPE_KEY + "\": xr_arr.shape, \"" + AXES_KEY + "\": xr_arr.dims,\"" + NAME_KEY + "\": xr_arr.name}" + System.lineSeparator() + + " return {\"" + DATA_KEY + "\": xr_arr.values.flatten().tolist(), \"" + SHAPE_KEY + + "\": xr_arr.shape, \"" + AXES_KEY + "\": xr_arr.dims,\"" + NAME_KEY + + "\": xr_arr.name, \"" + APPOSE_DT_KEY + "\": \"" + TENSOR_KEY + "\"}" + System.lineSeparator() + "" + System.lineSeparator() + "def " + LIST_METHOD + "(list_ob):" + System.lineSeparator() + " n_list = []" + System.lineSeparator() From 705246d01e99e7fe57e9e4adaba08e1169be4c47 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 02:08:47 +0200 Subject: [PATCH 042/235] start organizing the retrieval of appose outputs into jdll --- .../bioimage/modelrunner/runmode/RunMode.java | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index d664ce33..a04b9f02 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -37,6 +37,7 @@ import io.bioimage.modelrunner.tensor.ImgLib2ToArray; import io.bioimage.modelrunner.tensor.Tensor; import net.imglib2.RandomAccessibleInterval; +import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; @@ -147,7 +148,7 @@ public void testRunModel() { } } - private Map recreateOutputObjects(Map apposeOuts) { + private static Map recreateOutputObjects(Map apposeOuts) { LinkedHashMap jdllOuts = new LinkedHashMap(); for (Entry entry : apposeOuts.entrySet()) { Object value = entry.getValue(); @@ -159,9 +160,14 @@ private Map recreateOutputObjects(Map apposeOuts && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.NP_ARR_KEY) ) { } else if (value instanceof Map) { - + jdllOuts.put(entry.getKey(), recreateOutputObjects((Map) value)); } else if (value instanceof List) { - + jdllOuts.put(entry.getKey(), createListFromApposeOutput((List) value)); + } else if (isTypeDirectlySupported(value.getClass())) { + jdllOuts.put(entry.getKey(), value); + } else { + throw new IllegalArgumentException("Type of output named: '" + entry.getKey() + + "' not supported (" + value.getClass() + ")."); } } } @@ -290,4 +296,40 @@ private void retrieveResultsCode() { + System.lineSeparator(); } } + + private static < T extends RealType< T > & NativeType< T > > + Tensor createTensorFromApposeOutput(Map apposeTensor) { + ArrayImgFactory factory = new ArrayImgFactory(new T()); + return null; + } + + private static < T extends RealType< T > & NativeType< T > > + RandomAccessibleInterval createImgLib2ArrFromApposeOutput(Map apposeTensor) { + ArrayImgFactory factory = new ArrayImgFactory(); + return null; + } + + private static List createListFromApposeOutput(List list) { + List nList = new ArrayList(); + for (Object value : list) { + + if (value instanceof Map && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY) != null + && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.TENSOR_KEY) ) { + + } else if (value instanceof Map && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY) != null + && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.NP_ARR_KEY) ) { + + } else if (value instanceof Map) { + nList.add(recreateOutputObjects((Map) value)); + } else if (value instanceof List) { + nList.add(createListFromApposeOutput((List) value)); + } else if (isTypeDirectlySupported(value.getClass())) { + nList.add(value); + } else { + throw new IllegalArgumentException("Type of output" + + " not supported (" + value.getClass() + ")."); + } + } + return nList; + } } From 4bdc2ccbef870a6f0e770fd539b645dbff16278b Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 13:07:35 +0200 Subject: [PATCH 043/235] add datatype to appose maps of tensors and np arrays --- .../io/bioimage/modelrunner/runmode/RunModeScripts.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index fce917fa..95b0eb49 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -31,6 +31,8 @@ public class RunModeScripts { protected static final String NAME_KEY = "name"; + protected static final String DTYPE_KEY = "dtype"; + protected static final String NP_METHOD = "convertNpIntoDic"; protected static final String XR_METHOD = "convertXrIntoDic"; @@ -53,12 +55,14 @@ public class RunModeScripts { + "def " + NP_METHOD + "(np_arr):" + System.lineSeparator() + " return {\"" + DATA_KEY + "\": np_arr.flatten().tolist(), \"" + SHAPE_KEY + "\": np_arr.shape, \"" + APPOSE_DT_KEY + "\": \"" - + NP_ARR_KEY + "\"}" + System.lineSeparator() + + NP_ARR_KEY + "\", \"" + DTYPE_KEY + "\": np_arr.dtype.str}" + System.lineSeparator() + "" + System.lineSeparator() + "def " + XR_METHOD + "(xr_arr):" + System.lineSeparator() + " return {\"" + DATA_KEY + "\": xr_arr.values.flatten().tolist(), \"" + SHAPE_KEY + "\": xr_arr.shape, \"" + AXES_KEY + "\": xr_arr.dims,\"" + NAME_KEY - + "\": xr_arr.name, \"" + APPOSE_DT_KEY + "\": \"" + TENSOR_KEY + "\"}" + System.lineSeparator() + + "\": xr_arr.name, \"" + APPOSE_DT_KEY + "\": \"" + TENSOR_KEY + "\", " + + "\"" + DTYPE_KEY + "\": xr_arr.values.dtype.str}" + + System.lineSeparator() + "" + System.lineSeparator() + "def " + LIST_METHOD + "(list_ob):" + System.lineSeparator() + " n_list = []" + System.lineSeparator() From e942f475188338e3bd8c228a672be9de0d3e4151 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 13:41:48 +0200 Subject: [PATCH 044/235] method to convert appose np arrays back into imglib2 --- .../modelrunner/tensor/ArrayToImgLib2.java | 421 ++++++++++++++++++ 1 file changed, 421 insertions(+) create mode 100644 src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java new file mode 100644 index 00000000..eecca83f --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java @@ -0,0 +1,421 @@ +/*- + * #%L + * This project complements the DL-model runner acting as the engine that works loading models + * and making inference with Java API for Tensorflow 1. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.tensor; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import io.bioimage.modelrunner.tensor.Tensor; +import io.bioimage.modelrunner.utils.IndexingUtils; +import net.imglib2.Cursor; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.img.Img; +import net.imglib2.img.array.ArrayImgFactory; +import net.imglib2.type.NativeType; +import net.imglib2.type.Type; +import net.imglib2.type.numeric.RealType; +import net.imglib2.type.numeric.integer.ByteType; +import net.imglib2.type.numeric.integer.IntType; +import net.imglib2.type.numeric.integer.LongType; +import net.imglib2.type.numeric.integer.ShortType; +import net.imglib2.type.numeric.real.DoubleType; +import net.imglib2.type.numeric.real.FloatType; + +/** + * A {@link Img} builder from {@link ByteBuffer} objects + * + * @author Carlos Garcia Lopez de Haro + */ +public final class ArrayToImgLib2 { + + /** + * Not used (Utility class). + */ + private ArrayToImgLib2() + { + } + + /** + * Creates a {@link Tensor} from the information stored in a {@link ByteBuffer} + * + * @param + * the type of the generated tensor + * @param buff + * byte buffer to get the tensor info from + * @return the tensor generated from the bytebuffer + * @throws IllegalArgumentException if the data type of the tensor saved in the bytebuffer is + * not supported + */ + @SuppressWarnings("unchecked") + public static < T extends RealType< T > & NativeType< T > > Tensor + buildTensor(Object array, long[] shape, String axes, String dtype, String name) + throws IllegalArgumentException + { + return Tensor.build(name, axes, (RandomAccessibleInterval) build(array, shape, dtype)); + } + + /** + * Creates a {@link Img} from the information stored in a {@link ByteBuffer} + * + * @param + * data type of the image + * @param byteBuff + * The bytebyuffer that contains info to create a tenosr or a {@link Img} + * @return The imglib2 image {@link Img} built from the bytebuffer info. + * @throws IllegalArgumentException if the data type of the tensor saved in the bytebuffer is + * not supported + */ + @SuppressWarnings("unchecked") + public static > Img build(Object array, long[] shape, String dtype) throws IllegalArgumentException + { + if (!array.getClass().isArray()) { + throw new IllegalArgumentException(""); + } + if (shape.length == 0) + return null; + + Img data; + switch (dtype) + { + case "int8": + data = (Img) buildInt8(array, shape); + break; + case "uint8": + data = (Img) buildUint8(array, shape); + break; + case "int16": + data = (Img) buildInt16(array, shape); + break; + case "uint16": + data = (Img) buildUint16(array, shape); + break; + case "int32": + data = (Img) buildInt32(array, shape); + break; + case "uint32": + data = (Img) buildUint32(array, shape); + break; + case "int64": + data = (Img) buildInt64(array, shape); + break; + case "float16": + data = (Img) buildFloat16(array, shape); + break; + case "float32": + data = (Img) buildFloat32(array, shape); + break; + case "float64": + data = (Img) buildFloat64(array, shape); + break; + default: + throw new IllegalArgumentException("Unsupported tensor type: " + dtype); + } + return data; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt8(Object array, long[] tensorShape) + { + if (!array.getClass().getComponentType().equals(byte.class) + && !Byte.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Trying to build ImgLib2 array of data type " + + "'int8' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(byte.class)) { + return buildInt8((byte[]) array, tensorShape); + } else { + return buildInt8((Byte[]) array, tensorShape); + } + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt8(Byte[] tensor, long[] tensorShape) + { + final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); + final Img< ByteType > outputImg = (Img) factory.create(tensorShape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + tensorShape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt8(byte[] tensor, long[] tensorShape) + { + final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); + final Img< ByteType > outputImg = (Img) factory.create(tensorShape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + tensorShape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a ShortType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt16(Object array, long[] tensorShape) + { + if (!array.getClass().getComponentType().equals(short.class) + && !Short.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Trying to build ImgLib2 array of data type " + + "'int16' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(short.class)) { + return buildInt16((short[]) array, tensorShape); + } else { + return buildInt16((Short[]) array, tensorShape); + } + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt16(Short[] tensor, long[] tensorShape) + { + final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); + final Img< ShortType > outputImg = (Img) factory.create(tensorShape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + tensorShape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt16(short[] tensor, long[] tensorShape) + { + final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); + final Img< ShortType > outputImg = (Img) factory.create(tensorShape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + tensorShape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt32(Object array, long[] tensorShape) + { + if (!array.getClass().getComponentType().equals(int.class) + && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Trying to build ImgLib2 array of data type " + + "'int32' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(byte.class)) { + return buildInt32((int[]) array, tensorShape); + } else { + return buildInt32((Integer[]) array, tensorShape); + } + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt32(Integer[] tensor, long[] tensorShape) + { + final ArrayImgFactory< IntType > factory = new ArrayImgFactory<>( new IntType() ); + final Img< IntType > outputImg = (Img) factory.create(tensorShape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + tensorShape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt32(int[] tensor, long[] tensorShape) + { + final ArrayImgFactory< IntType > factory = new ArrayImgFactory<>( new IntType() ); + final Img< IntType > outputImg = (Img) factory.create(tensorShape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + tensorShape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a LongType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt64(Object array, long[] tensorShape) + { + if (!array.getClass().getComponentType().equals(long.class) + && !Long.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Trying to build ImgLib2 array of data type " + + "'int64' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(long.class)) { + return buildInt64((long[]) array, tensorShape); + } else { + return buildInt64((Long[]) array, tensorShape); + } + } + + /** + * Builds a LongType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt64(Long[] tensor, long[] tensorShape) + { + final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); + final Img< LongType > outputImg = (Img) factory.create(tensorShape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + tensorShape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a LongType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt64(long[] tensor, long[] tensorShape) + { + final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); + final Img< LongType > outputImg = (Img) factory.create(tensorShape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + tensorShape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } +} From 7f2a34446917dcac9b356d687bb6ecf938f7f5d4 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 15:29:42 +0200 Subject: [PATCH 045/235] improve robustness of appose tensor retrieval with data types --- .../modelrunner/tensor/ArrayToImgLib2.java | 305 +++++++++++++++--- 1 file changed, 264 insertions(+), 41 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java index eecca83f..a3c41dbf 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.IntStream; import io.bioimage.modelrunner.tensor.Tensor; import io.bioimage.modelrunner.utils.IndexingUtils; @@ -40,6 +41,7 @@ import net.imglib2.type.numeric.integer.IntType; import net.imglib2.type.numeric.integer.LongType; import net.imglib2.type.numeric.integer.ShortType; +import net.imglib2.type.numeric.integer.UnsignedIntType; import net.imglib2.type.numeric.real.DoubleType; import net.imglib2.type.numeric.real.FloatType; @@ -70,7 +72,7 @@ private ArrayToImgLib2() */ @SuppressWarnings("unchecked") public static < T extends RealType< T > & NativeType< T > > Tensor - buildTensor(Object array, long[] shape, String axes, String dtype, String name) + buildTensor(Object array, Integer[] shape, String axes, String dtype, String name) throws IllegalArgumentException { return Tensor.build(name, axes, (RandomAccessibleInterval) build(array, shape, dtype)); @@ -88,7 +90,7 @@ private ArrayToImgLib2() * not supported */ @SuppressWarnings("unchecked") - public static > Img build(Object array, long[] shape, String dtype) throws IllegalArgumentException + public static > Img build(Object array, Integer[] shape, String dtype) throws IllegalArgumentException { if (!array.getClass().isArray()) { throw new IllegalArgumentException(""); @@ -145,16 +147,19 @@ public static > Img build(Object array, long[] shape, Strin * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(Object array, long[] tensorShape) + private static Img buildInt8(Object array, Integer[] tensorShape) { if (!array.getClass().getComponentType().equals(byte.class) - && !Byte.class.isAssignableFrom(array.getClass().getComponentType())) { - throw new IllegalArgumentException("Trying to build ImgLib2 array of data type " + && !Byte.class.isAssignableFrom(array.getClass().getComponentType()) + && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + "'int8' using Java array of class: " + array.getClass().getComponentType()); } else if (array.getClass().getComponentType().equals(byte.class)) { return buildInt8((byte[]) array, tensorShape); - } else { + } else if (Byte.class.isAssignableFrom(array.getClass().getComponentType())) { return buildInt8((Byte[]) array, tensorShape); + } else { + return buildInt8((Integer[]) array, tensorShape); } } @@ -168,15 +173,16 @@ private static Img buildInt8(Object array, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(Byte[] tensor, long[] tensorShape) + private static Img buildInt8(Byte[] tensor, Integer[] tensorShape) { final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); - final Img< ByteType > outputImg = (Img) factory.create(tensorShape); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< ByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - tensorShape); + shape); tensorCursor.get().set(tensor[i]); } return outputImg; @@ -192,15 +198,41 @@ private static Img buildInt8(Byte[] tensor, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(byte[] tensor, long[] tensorShape) + private static Img buildInt8(Integer[] tensor, Integer[] tensorShape) { final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); - final Img< ByteType > outputImg = (Img) factory.create(tensorShape); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< ByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - tensorShape); + shape); + tensorCursor.get().set(tensor[i].byteValue()); + } + return outputImg; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt8(byte[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< ByteType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); tensorCursor.get().set(tensor[i]); } return outputImg; @@ -216,16 +248,19 @@ private static Img buildInt8(byte[] tensor, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(Object array, long[] tensorShape) + private static Img buildInt16(Object array, Integer[] tensorShape) { if (!array.getClass().getComponentType().equals(short.class) - && !Short.class.isAssignableFrom(array.getClass().getComponentType())) { - throw new IllegalArgumentException("Trying to build ImgLib2 array of data type " + && !Short.class.isAssignableFrom(array.getClass().getComponentType()) + && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + "'int16' using Java array of class: " + array.getClass().getComponentType()); } else if (array.getClass().getComponentType().equals(short.class)) { return buildInt16((short[]) array, tensorShape); - } else { + } else if (Short.class.isAssignableFrom(array.getClass().getComponentType())) { return buildInt16((Short[]) array, tensorShape); + } else { + return buildInt16((Integer[]) array, tensorShape); } } @@ -239,15 +274,16 @@ private static Img buildInt16(Object array, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(Short[] tensor, long[] tensorShape) + private static Img buildInt16(Short[] tensor, Integer[] tensorShape) { final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); - final Img< ShortType > outputImg = (Img) factory.create(tensorShape); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< ShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - tensorShape); + shape); tensorCursor.get().set(tensor[i]); } return outputImg; @@ -263,15 +299,41 @@ private static Img buildInt16(Short[] tensor, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(short[] tensor, long[] tensorShape) + private static Img buildInt16(Integer[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< ShortType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i].shortValue()); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt16(short[] tensor, Integer[] tensorShape) { final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); - final Img< ShortType > outputImg = (Img) factory.create(tensorShape); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< ShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - tensorShape); + shape); tensorCursor.get().set(tensor[i]); } return outputImg; @@ -287,13 +349,13 @@ private static Img buildInt16(short[] tensor, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt32(Object array, long[] tensorShape) + private static Img buildInt32(Object array, Integer[] tensorShape) { if (!array.getClass().getComponentType().equals(int.class) && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { - throw new IllegalArgumentException("Trying to build ImgLib2 array of data type " + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + "'int32' using Java array of class: " + array.getClass().getComponentType()); - } else if (array.getClass().getComponentType().equals(byte.class)) { + } else if (array.getClass().getComponentType().equals(int.class)) { return buildInt32((int[]) array, tensorShape); } else { return buildInt32((Integer[]) array, tensorShape); @@ -310,15 +372,16 @@ private static Img buildInt32(Object array, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt32(Integer[] tensor, long[] tensorShape) + private static Img buildInt32(Integer[] tensor, Integer[] tensorShape) { final ArrayImgFactory< IntType > factory = new ArrayImgFactory<>( new IntType() ); - final Img< IntType > outputImg = (Img) factory.create(tensorShape); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< IntType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - tensorShape); + shape); tensorCursor.get().set(tensor[i]); } return outputImg; @@ -334,15 +397,145 @@ private static Img buildInt32(Integer[] tensor, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt32(int[] tensor, long[] tensorShape) + private static Img buildInt32(int[] tensor, Integer[] tensorShape) { final ArrayImgFactory< IntType > factory = new ArrayImgFactory<>( new IntType() ); - final Img< IntType > outputImg = (Img) factory.create(tensorShape); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< IntType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - tensorShape); + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint32(Object array, Integer[] tensorShape) + { + if (!array.getClass().getComponentType().equals(int.class) + && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) + && !Long.class.isAssignableFrom(array.getClass().getComponentType()) + && !array.getClass().getComponentType().equals(long.class)) { + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + + "'uint32' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(int.class)) { + return buildUint32((int[]) array, tensorShape); + } else if (array.getClass().getComponentType().equals(long.class)) { + return buildUint32((long[]) array, tensorShape); + } else if (Long.class.isAssignableFrom(array.getClass().getComponentType())) { + return buildUint32((Long[]) array, tensorShape); + } else { + return buildUint32((Integer[]) array, tensorShape); + } + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint32(Integer[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint32(int[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint32(Long[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint32(long[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); tensorCursor.get().set(tensor[i]); } return outputImg; @@ -358,16 +551,19 @@ private static Img buildInt32(int[] tensor, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(Object array, long[] tensorShape) + private static Img buildInt64(Object array, Integer[] tensorShape) { if (!array.getClass().getComponentType().equals(long.class) - && !Long.class.isAssignableFrom(array.getClass().getComponentType())) { - throw new IllegalArgumentException("Trying to build ImgLib2 array of data type " + && !Long.class.isAssignableFrom(array.getClass().getComponentType()) + && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + "'int64' using Java array of class: " + array.getClass().getComponentType()); } else if (array.getClass().getComponentType().equals(long.class)) { return buildInt64((long[]) array, tensorShape); - } else { + } else if (Long.class.isAssignableFrom(array.getClass().getComponentType())) { return buildInt64((Long[]) array, tensorShape); + } else { + return buildInt64((Integer[]) array, tensorShape); } } @@ -381,15 +577,16 @@ private static Img buildInt64(Object array, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(Long[] tensor, long[] tensorShape) + private static Img buildInt64(Long[] tensor, Integer[] tensorShape) { final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); - final Img< LongType > outputImg = (Img) factory.create(tensorShape); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< LongType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - tensorShape); + shape); tensorCursor.get().set(tensor[i]); } return outputImg; @@ -405,15 +602,41 @@ private static Img buildInt64(Long[] tensor, long[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(long[] tensor, long[] tensorShape) + private static Img buildInt64(Integer[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< LongType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i].longValue()); + } + return outputImg; + } + + /** + * Builds a LongType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt64(long[] tensor, Integer[] tensorShape) { final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); - final Img< LongType > outputImg = (Img) factory.create(tensorShape); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< LongType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - tensorShape); + shape); tensorCursor.get().set(tensor[i]); } return outputImg; From 7ee237ac12587409bb0233e816aaacb77835375d Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 15:40:34 +0200 Subject: [PATCH 046/235] keep improving the robustness of data type conversion --- .../modelrunner/tensor/ArrayToImgLib2.java | 342 +++++++++++++++++- 1 file changed, 329 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java index a3c41dbf..8f53418c 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java @@ -41,7 +41,9 @@ import net.imglib2.type.numeric.integer.IntType; import net.imglib2.type.numeric.integer.LongType; import net.imglib2.type.numeric.integer.ShortType; +import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.type.numeric.integer.UnsignedIntType; +import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.DoubleType; import net.imglib2.type.numeric.real.FloatType; @@ -98,38 +100,38 @@ public static > Img build(Object array, Integer[] shape, St if (shape.length == 0) return null; - Img data; + Img data; switch (dtype) { case "int8": - data = (Img) buildInt8(array, shape); + data = (Img) buildInt8(array, shape); break; case "uint8": - data = (Img) buildUint8(array, shape); + data = (Img) buildUint8(array, shape); break; case "int16": - data = (Img) buildInt16(array, shape); + data = (Img) buildInt16(array, shape); break; case "uint16": - data = (Img) buildUint16(array, shape); + data = (Img) buildUint16(array, shape); break; case "int32": - data = (Img) buildInt32(array, shape); + data = (Img) buildInt32(array, shape); break; case "uint32": - data = (Img) buildUint32(array, shape); + data = (Img) buildUint32(array, shape); break; case "int64": - data = (Img) buildInt64(array, shape); + data = (Img) buildInt64(array, shape); break; case "float16": - data = (Img) buildFloat16(array, shape); + data = (Img) buildFloat16(array, shape); break; case "float32": - data = (Img) buildFloat32(array, shape); + data = (Img) buildFloat32(array, shape); break; case "float64": - data = (Img) buildFloat64(array, shape); + data = (Img) buildFloat64(array, shape); break; default: throw new IllegalArgumentException("Unsupported tensor type: " + dtype); @@ -151,9 +153,12 @@ private static Img buildInt8(Object array, Integer[] tensorShape) { if (!array.getClass().getComponentType().equals(byte.class) && !Byte.class.isAssignableFrom(array.getClass().getComponentType()) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { + && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) + && !array.getClass().getComponentType().equals(int.class)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + "'int8' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(byte.class)) { + return buildInt8((int[]) array, tensorShape); } else if (array.getClass().getComponentType().equals(byte.class)) { return buildInt8((byte[]) array, tensorShape); } else if (Byte.class.isAssignableFrom(array.getClass().getComponentType())) { @@ -238,6 +243,160 @@ private static Img buildInt8(byte[] tensor, Integer[] tensorShape) return outputImg; } + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt8(int[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< ByteType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set((byte) tensor[i]); + } + return outputImg; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint8(Object array, Integer[] tensorShape) + { + if (!array.getClass().getComponentType().equals(byte.class) + && !Byte.class.isAssignableFrom(array.getClass().getComponentType()) + && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) + && !array.getClass().getComponentType().equals(int.class)) { + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + + "'int8' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(byte.class)) { + return buildUint8((int[]) array, tensorShape); + } else if (array.getClass().getComponentType().equals(byte.class)) { + return buildUint8((byte[]) array, tensorShape); + } else if (Byte.class.isAssignableFrom(array.getClass().getComponentType())) { + return buildUint8((Byte[]) array, tensorShape); + } else { + return buildUint8((Integer[]) array, tensorShape); + } + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint8(Byte[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint8(Integer[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i].byteValue()); + } + return outputImg; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint8(byte[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a ByteType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint8(int[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set((byte) tensor[i]); + } + return outputImg; + } + /** * Builds a ShortType {@link Img} from the information stored in a byte buffer. * The shape of the image that was previously retrieved from the buffer @@ -252,11 +411,14 @@ private static Img buildInt16(Object array, Integer[] tensorShape) { if (!array.getClass().getComponentType().equals(short.class) && !Short.class.isAssignableFrom(array.getClass().getComponentType()) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { + && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) + && !array.getClass().getComponentType().equals(int.class)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + "'int16' using Java array of class: " + array.getClass().getComponentType()); } else if (array.getClass().getComponentType().equals(short.class)) { return buildInt16((short[]) array, tensorShape); + } else if (array.getClass().getComponentType().equals(int.class)) { + return buildInt16((int[]) array, tensorShape); } else if (Short.class.isAssignableFrom(array.getClass().getComponentType())) { return buildInt16((Short[]) array, tensorShape); } else { @@ -339,6 +501,160 @@ private static Img buildInt16(short[] tensor, Integer[] tensorShape) return outputImg; } + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildInt16(int[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< ShortType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set((short) tensor[i]); + } + return outputImg; + } + + /** + * Builds a ShortType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint16(Object array, Integer[] tensorShape) + { + if (!array.getClass().getComponentType().equals(short.class) + && !Short.class.isAssignableFrom(array.getClass().getComponentType()) + && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) + && !array.getClass().getComponentType().equals(short.class)) { + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + + "'int16' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(short.class)) { + return buildUint16((short[]) array, tensorShape); + } else if (array.getClass().getComponentType().equals(int.class)) { + return buildUint16((int[]) array, tensorShape); + } else if (Short.class.isAssignableFrom(array.getClass().getComponentType())) { + return buildUint16((Short[]) array, tensorShape); + } else { + return buildUint16((Integer[]) array, tensorShape); + } + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint16(Short[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint16(Integer[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i].shortValue()); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint16(short[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a IntType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildUint16(int[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + /** * Builds a ByteType {@link Img} from the information stored in a byte buffer. * The shape of the image that was previously retrieved from the buffer From 49b7c2f5fe0aea95a126a1f1040771873005287e Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 23:13:26 +0200 Subject: [PATCH 047/235] finalize class that converts appose tensor into jdll tensor --- .../modelrunner/tensor/ArrayToImgLib2.java | 212 +++++++++++++++++- 1 file changed, 203 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java index 8f53418c..4ad04642 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java @@ -20,15 +20,10 @@ */ package io.bioimage.modelrunner.tensor; +import java.math.BigDecimal; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.IntStream; -import io.bioimage.modelrunner.tensor.Tensor; import io.bioimage.modelrunner.utils.IndexingUtils; import net.imglib2.Cursor; import net.imglib2.RandomAccessibleInterval; @@ -124,9 +119,6 @@ public static > Img build(Object array, Integer[] shape, St case "int64": data = (Img) buildInt64(array, shape); break; - case "float16": - data = (Img) buildFloat16(array, shape); - break; case "float32": data = (Img) buildFloat32(array, shape); break; @@ -957,4 +949,206 @@ private static Img buildInt64(long[] tensor, Integer[] tensorShape) } return outputImg; } + + /** + * Builds a FloatType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildFloat32(Object array, Integer[] tensorShape) + { + if (!array.getClass().getComponentType().equals(float.class) + && !Float.class.isAssignableFrom(array.getClass().getComponentType()) + && !BigDecimal.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + + "'float32' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(float.class)) { + return buildFloat32((float[]) array, tensorShape); + } else if (Float.class.isAssignableFrom(array.getClass().getComponentType())) { + return buildFloat32((Float[]) array, tensorShape); + } else { + return buildFloat32((BigDecimal[]) array, tensorShape); + } + } + + /** + * Builds a FloatType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildFloat32(Float[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< FloatType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a FloatType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildFloat32(BigDecimal[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< FloatType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i].longValue()); + } + return outputImg; + } + + /** + * Builds a FloatType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildFloat32(float[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< FloatType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a DoubleType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildFloat64(Object array, Integer[] tensorShape) + { + if (!array.getClass().getComponentType().equals(double.class) + && !Double.class.isAssignableFrom(array.getClass().getComponentType()) + && !BigDecimal.class.isAssignableFrom(array.getClass().getComponentType())) { + throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + + "'float64' using Java array of class: " + array.getClass().getComponentType()); + } else if (array.getClass().getComponentType().equals(double.class)) { + return buildFloat64((double[]) array, tensorShape); + } else if (Double.class.isAssignableFrom(array.getClass().getComponentType())) { + return buildFloat64((Double[]) array, tensorShape); + } else { + return buildFloat64((BigDecimal[]) array, tensorShape); + } + } + + /** + * Builds a DoubleType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildFloat64(Double[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< DoubleType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } + + /** + * Builds a DoubleType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildFloat64(BigDecimal[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< DoubleType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i].longValue()); + } + return outputImg; + } + + /** + * Builds a DoubleType {@link Img} from the information stored in a byte buffer. + * The shape of the image that was previously retrieved from the buffer + * @param tensor + * byte buffer containing the information of the a tenosr, the position in the buffer + * should not be at zero but right after the header. + * @param tensorShape + * shape of the image to generate, it has been retrieved from the byte buffer + * @return image specified in the bytebuffer + */ + private static Img buildFloat64(double[] tensor, Integer[] tensorShape) + { + final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); + long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + final Img< DoubleType > outputImg = (Img) factory.create(shape); + Cursor tensorCursor= outputImg.cursor(); + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), + shape); + tensorCursor.get().set(tensor[i]); + } + return outputImg; + } } From 1cc1a871f06a1488a8932d969239d6c8ccc8dd0d Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Fri, 29 Sep 2023 23:50:08 +0200 Subject: [PATCH 048/235] correct casting --- .../modelrunner/tensor/ArrayToImgLib2.java | 149 +++++++++--------- 1 file changed, 75 insertions(+), 74 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java index 4ad04642..ee5a569f 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java @@ -22,6 +22,7 @@ import java.math.BigDecimal; import java.nio.ByteBuffer; +import java.util.List; import java.util.stream.IntStream; import io.bioimage.modelrunner.utils.IndexingUtils; @@ -69,7 +70,7 @@ private ArrayToImgLib2() */ @SuppressWarnings("unchecked") public static < T extends RealType< T > & NativeType< T > > Tensor - buildTensor(Object array, Integer[] shape, String axes, String dtype, String name) + buildTensor(Object array, List shape, String axes, String dtype, String name) throws IllegalArgumentException { return Tensor.build(name, axes, (RandomAccessibleInterval) build(array, shape, dtype)); @@ -87,12 +88,12 @@ private ArrayToImgLib2() * not supported */ @SuppressWarnings("unchecked") - public static > Img build(Object array, Integer[] shape, String dtype) throws IllegalArgumentException + public static > Img build(Object array, List shape, String dtype) throws IllegalArgumentException { if (!array.getClass().isArray()) { throw new IllegalArgumentException(""); } - if (shape.length == 0) + if (shape.size() == 0) return null; Img data; @@ -141,7 +142,7 @@ public static > Img build(Object array, Integer[] shape, St * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(Object array, Integer[] tensorShape) + private static Img buildInt8(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(byte.class) && !Byte.class.isAssignableFrom(array.getClass().getComponentType()) @@ -170,10 +171,10 @@ private static Img buildInt8(Object array, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(Byte[] tensor, Integer[] tensorShape) + private static Img buildInt8(Byte[] tensor, List tensorShape) { final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< ByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -195,10 +196,10 @@ private static Img buildInt8(Byte[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(Integer[] tensor, Integer[] tensorShape) + private static Img buildInt8(Integer[] tensor, List tensorShape) { final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< ByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -220,10 +221,10 @@ private static Img buildInt8(Integer[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(byte[] tensor, Integer[] tensorShape) + private static Img buildInt8(byte[] tensor, List tensorShape) { final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< ByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -245,10 +246,10 @@ private static Img buildInt8(byte[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(int[] tensor, Integer[] tensorShape) + private static Img buildInt8(int[] tensor, List tensorShape) { final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< ByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -270,7 +271,7 @@ private static Img buildInt8(int[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint8(Object array, Integer[] tensorShape) + private static Img buildUint8(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(byte.class) && !Byte.class.isAssignableFrom(array.getClass().getComponentType()) @@ -299,10 +300,10 @@ private static Img buildUint8(Object array, Integer[] tensorSh * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint8(Byte[] tensor, Integer[] tensorShape) + private static Img buildUint8(Byte[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -324,10 +325,10 @@ private static Img buildUint8(Byte[] tensor, Integer[] tensorS * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint8(Integer[] tensor, Integer[] tensorShape) + private static Img buildUint8(Integer[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -349,10 +350,10 @@ private static Img buildUint8(Integer[] tensor, Integer[] tens * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint8(byte[] tensor, Integer[] tensorShape) + private static Img buildUint8(byte[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -374,10 +375,10 @@ private static Img buildUint8(byte[] tensor, Integer[] tensorS * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint8(int[] tensor, Integer[] tensorShape) + private static Img buildUint8(int[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -399,7 +400,7 @@ private static Img buildUint8(int[] tensor, Integer[] tensorSh * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(Object array, Integer[] tensorShape) + private static Img buildInt16(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(short.class) && !Short.class.isAssignableFrom(array.getClass().getComponentType()) @@ -428,10 +429,10 @@ private static Img buildInt16(Object array, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(Short[] tensor, Integer[] tensorShape) + private static Img buildInt16(Short[] tensor, List tensorShape) { final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< ShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -453,10 +454,10 @@ private static Img buildInt16(Short[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(Integer[] tensor, Integer[] tensorShape) + private static Img buildInt16(Integer[] tensor, List tensorShape) { final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< ShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -478,10 +479,10 @@ private static Img buildInt16(Integer[] tensor, Integer[] tensorShape * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(short[] tensor, Integer[] tensorShape) + private static Img buildInt16(short[] tensor, List tensorShape) { final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< ShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -503,10 +504,10 @@ private static Img buildInt16(short[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(int[] tensor, Integer[] tensorShape) + private static Img buildInt16(int[] tensor, List tensorShape) { final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< ShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -528,7 +529,7 @@ private static Img buildInt16(int[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint16(Object array, Integer[] tensorShape) + private static Img buildUint16(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(short.class) && !Short.class.isAssignableFrom(array.getClass().getComponentType()) @@ -557,10 +558,10 @@ private static Img buildUint16(Object array, Integer[] tensor * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint16(Short[] tensor, Integer[] tensorShape) + private static Img buildUint16(Short[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -582,10 +583,10 @@ private static Img buildUint16(Short[] tensor, Integer[] tens * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint16(Integer[] tensor, Integer[] tensorShape) + private static Img buildUint16(Integer[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -607,10 +608,10 @@ private static Img buildUint16(Integer[] tensor, Integer[] te * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint16(short[] tensor, Integer[] tensorShape) + private static Img buildUint16(short[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -632,10 +633,10 @@ private static Img buildUint16(short[] tensor, Integer[] tens * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint16(int[] tensor, Integer[] tensorShape) + private static Img buildUint16(int[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -657,7 +658,7 @@ private static Img buildUint16(int[] tensor, Integer[] tensor * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt32(Object array, Integer[] tensorShape) + private static Img buildInt32(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(int.class) && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { @@ -680,10 +681,10 @@ private static Img buildInt32(Object array, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt32(Integer[] tensor, Integer[] tensorShape) + private static Img buildInt32(Integer[] tensor, List tensorShape) { final ArrayImgFactory< IntType > factory = new ArrayImgFactory<>( new IntType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< IntType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -705,10 +706,10 @@ private static Img buildInt32(Integer[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt32(int[] tensor, Integer[] tensorShape) + private static Img buildInt32(int[] tensor, List tensorShape) { final ArrayImgFactory< IntType > factory = new ArrayImgFactory<>( new IntType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< IntType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -730,7 +731,7 @@ private static Img buildInt32(int[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint32(Object array, Integer[] tensorShape) + private static Img buildUint32(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(int.class) && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) @@ -759,10 +760,10 @@ private static Img buildUint32(Object array, Integer[] tensorSh * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint32(Integer[] tensor, Integer[] tensorShape) + private static Img buildUint32(Integer[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -784,10 +785,10 @@ private static Img buildUint32(Integer[] tensor, Integer[] tens * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint32(int[] tensor, Integer[] tensorShape) + private static Img buildUint32(int[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -809,10 +810,10 @@ private static Img buildUint32(int[] tensor, Integer[] tensorSh * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint32(Long[] tensor, Integer[] tensorShape) + private static Img buildUint32(Long[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -834,10 +835,10 @@ private static Img buildUint32(Long[] tensor, Integer[] tensorS * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint32(long[] tensor, Integer[] tensorShape) + private static Img buildUint32(long[] tensor, List tensorShape) { final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -859,7 +860,7 @@ private static Img buildUint32(long[] tensor, Integer[] tensorS * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(Object array, Integer[] tensorShape) + private static Img buildInt64(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(long.class) && !Long.class.isAssignableFrom(array.getClass().getComponentType()) @@ -885,10 +886,10 @@ private static Img buildInt64(Object array, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(Long[] tensor, Integer[] tensorShape) + private static Img buildInt64(Long[] tensor, List tensorShape) { final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< LongType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -910,10 +911,10 @@ private static Img buildInt64(Long[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(Integer[] tensor, Integer[] tensorShape) + private static Img buildInt64(Integer[] tensor, List tensorShape) { final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< LongType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -935,10 +936,10 @@ private static Img buildInt64(Integer[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(long[] tensor, Integer[] tensorShape) + private static Img buildInt64(long[] tensor, List tensorShape) { final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< LongType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -960,7 +961,7 @@ private static Img buildInt64(long[] tensor, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat32(Object array, Integer[] tensorShape) + private static Img buildFloat32(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(float.class) && !Float.class.isAssignableFrom(array.getClass().getComponentType()) @@ -986,10 +987,10 @@ private static Img buildFloat32(Object array, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat32(Float[] tensor, Integer[] tensorShape) + private static Img buildFloat32(Float[] tensor, List tensorShape) { final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< FloatType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -1011,10 +1012,10 @@ private static Img buildFloat32(Float[] tensor, Integer[] tensorShape * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat32(BigDecimal[] tensor, Integer[] tensorShape) + private static Img buildFloat32(BigDecimal[] tensor, List tensorShape) { final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< FloatType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -1036,10 +1037,10 @@ private static Img buildFloat32(BigDecimal[] tensor, Integer[] tensor * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat32(float[] tensor, Integer[] tensorShape) + private static Img buildFloat32(float[] tensor, List tensorShape) { final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< FloatType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -1061,7 +1062,7 @@ private static Img buildFloat32(float[] tensor, Integer[] tensorShape * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat64(Object array, Integer[] tensorShape) + private static Img buildFloat64(Object array, List tensorShape) { if (!array.getClass().getComponentType().equals(double.class) && !Double.class.isAssignableFrom(array.getClass().getComponentType()) @@ -1087,10 +1088,10 @@ private static Img buildFloat64(Object array, Integer[] tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat64(Double[] tensor, Integer[] tensorShape) + private static Img buildFloat64(Double[] tensor, List tensorShape) { final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< DoubleType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -1112,10 +1113,10 @@ private static Img buildFloat64(Double[] tensor, Integer[] tensorSha * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat64(BigDecimal[] tensor, Integer[] tensorShape) + private static Img buildFloat64(BigDecimal[] tensor, List tensorShape) { final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< DoubleType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { @@ -1137,10 +1138,10 @@ private static Img buildFloat64(BigDecimal[] tensor, Integer[] tenso * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat64(double[] tensor, Integer[] tensorShape) + private static Img buildFloat64(double[] tensor, List tensorShape) { final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); - long[] shape = IntStream.range(0, tensorShape.length).mapToLong(i -> tensorShape[i]).toArray(); + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); final Img< DoubleType > outputImg = (Img) factory.create(shape); Cursor tensorCursor= outputImg.cursor(); while (tensorCursor.hasNext()) { From cd88f5ae097f729d010314e93d2f36c1848a1440 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Sat, 30 Sep 2023 01:09:07 +0200 Subject: [PATCH 049/235] Change the casting from array to List and change the name of the class --- ...ArrayToImgLib2.java => ListToImgLib2.java} | 571 ++++-------------- 1 file changed, 103 insertions(+), 468 deletions(-) rename src/main/java/io/bioimage/modelrunner/tensor/{ArrayToImgLib2.java => ListToImgLib2.java} (53%) diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java b/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java similarity index 53% rename from src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java rename to src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java index ee5a569f..0dfbdf06 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/ArrayToImgLib2.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java @@ -48,12 +48,12 @@ * * @author Carlos Garcia Lopez de Haro */ -public final class ArrayToImgLib2 { +public final class ListToImgLib2 { /** * Not used (Utility class). */ - private ArrayToImgLib2() + private ListToImgLib2() { } @@ -70,7 +70,7 @@ private ArrayToImgLib2() */ @SuppressWarnings("unchecked") public static < T extends RealType< T > & NativeType< T > > Tensor - buildTensor(Object array, List shape, String axes, String dtype, String name) + buildTensor(List array, List shape, String axes, String dtype, String name) throws IllegalArgumentException { return Tensor.build(name, axes, (RandomAccessibleInterval) build(array, shape, dtype)); @@ -88,11 +88,10 @@ private ArrayToImgLib2() * not supported */ @SuppressWarnings("unchecked") - public static > Img build(Object array, List shape, String dtype) throws IllegalArgumentException + public static > Img build(List array, List shape, String dtype) throws IllegalArgumentException { - if (!array.getClass().isArray()) { - throw new IllegalArgumentException(""); - } + if (array.size() == 0) + return null; if (shape.size() == 0) return null; @@ -142,22 +141,16 @@ public static > Img build(Object array, List shape * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(Object array, List tensorShape) + private static Img buildInt8(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(byte.class) - && !Byte.class.isAssignableFrom(array.getClass().getComponentType()) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) - && !array.getClass().getComponentType().equals(int.class)) { + if (!(array.get(0) instanceof Byte) + && !(array.get(0) instanceof Integer)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'int8' using Java array of class: " + array.getClass().getComponentType()); - } else if (array.getClass().getComponentType().equals(byte.class)) { - return buildInt8((int[]) array, tensorShape); - } else if (array.getClass().getComponentType().equals(byte.class)) { - return buildInt8((byte[]) array, tensorShape); - } else if (Byte.class.isAssignableFrom(array.getClass().getComponentType())) { - return buildInt8((Byte[]) array, tensorShape); + + "'int8' using Java array of class: " + array.get(0).getClass()); + } else if (array.get(0) instanceof Integer) { + return buildInt8FromInteger((List) array, tensorShape); } else { - return buildInt8((Integer[]) array, tensorShape); + return buildInt8FromByte((List) array, tensorShape); } } @@ -171,57 +164,7 @@ private static Img buildInt8(Object array, List tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(Byte[] tensor, List tensorShape) - { - final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< ByteType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a ByteType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildInt8(Integer[] tensor, List tensorShape) - { - final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< ByteType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i].byteValue()); - } - return outputImg; - } - - /** - * Builds a ByteType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildInt8(byte[] tensor, List tensorShape) + private static Img buildInt8FromByte(List tensor, List tensorShape) { final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -231,7 +174,7 @@ private static Img buildInt8(byte[] tensor, List tensorShape) tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -246,7 +189,7 @@ private static Img buildInt8(byte[] tensor, List tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt8(int[] tensor, List tensorShape) + private static Img buildInt8FromInteger(List tensor, List tensorShape) { final ArrayImgFactory< ByteType > factory = new ArrayImgFactory<>( new ByteType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -256,7 +199,7 @@ private static Img buildInt8(int[] tensor, List tensorShape) tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set((byte) tensor[i]); + tensorCursor.get().set(tensor.get(i).byteValue()); } return outputImg; } @@ -271,22 +214,16 @@ private static Img buildInt8(int[] tensor, List tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint8(Object array, List tensorShape) + private static Img buildUint8(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(byte.class) - && !Byte.class.isAssignableFrom(array.getClass().getComponentType()) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) - && !array.getClass().getComponentType().equals(int.class)) { + if (!(array.get(0) instanceof Byte) + && !(array.get(0) instanceof Integer)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'int8' using Java array of class: " + array.getClass().getComponentType()); - } else if (array.getClass().getComponentType().equals(byte.class)) { - return buildUint8((int[]) array, tensorShape); - } else if (array.getClass().getComponentType().equals(byte.class)) { - return buildUint8((byte[]) array, tensorShape); - } else if (Byte.class.isAssignableFrom(array.getClass().getComponentType())) { - return buildUint8((Byte[]) array, tensorShape); + + "'int8' using Java array of class: " + array.get(0).getClass()); + } else if (array.get(0) instanceof Byte) { + return buildUint8FromByte((List) array, tensorShape); } else { - return buildUint8((Integer[]) array, tensorShape); + return buildUint8FromInteger((List) array, tensorShape); } } @@ -300,32 +237,7 @@ private static Img buildUint8(Object array, List tens * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint8(Byte[] tensor, List tensorShape) - { - final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a ByteType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildUint8(Integer[] tensor, List tensorShape) + private static Img buildUint8FromByte(List tensor, List tensorShape) { final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -335,7 +247,7 @@ private static Img buildUint8(Integer[] tensor, List tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i].byteValue()); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -350,7 +262,7 @@ private static Img buildUint8(Integer[] tensor, List * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint8(byte[] tensor, List tensorShape) + private static Img buildUint8FromInteger(List tensor, List tensorShape) { final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -360,32 +272,7 @@ private static Img buildUint8(byte[] tensor, List ten tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a ByteType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildUint8(int[] tensor, List tensorShape) - { - final ArrayImgFactory< UnsignedByteType > factory = new ArrayImgFactory<>( new UnsignedByteType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< UnsignedByteType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set((byte) tensor[i]); + tensorCursor.get().set(tensor.get(i).byteValue()); } return outputImg; } @@ -400,22 +287,16 @@ private static Img buildUint8(int[] tensor, List tens * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(Object array, List tensorShape) + private static Img buildInt16(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(short.class) - && !Short.class.isAssignableFrom(array.getClass().getComponentType()) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) - && !array.getClass().getComponentType().equals(int.class)) { + if (!(array.get(0) instanceof Short) + && !(array.get(0) instanceof Integer)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'int16' using Java array of class: " + array.getClass().getComponentType()); - } else if (array.getClass().getComponentType().equals(short.class)) { - return buildInt16((short[]) array, tensorShape); - } else if (array.getClass().getComponentType().equals(int.class)) { - return buildInt16((int[]) array, tensorShape); - } else if (Short.class.isAssignableFrom(array.getClass().getComponentType())) { - return buildInt16((Short[]) array, tensorShape); + + "'int16' using Java array of class: " + array.get(0).getClass()); + } else if (array.get(0) instanceof Short) { + return buildInt16FromShort((List) array, tensorShape); } else { - return buildInt16((Integer[]) array, tensorShape); + return buildInt16FromInteger((List) array, tensorShape); } } @@ -429,7 +310,7 @@ private static Img buildInt16(Object array, List tensorShape * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(Short[] tensor, List tensorShape) + private static Img buildInt16FromShort(List tensor, List tensorShape) { final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -439,7 +320,7 @@ private static Img buildInt16(Short[] tensor, List tensorSha tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -454,7 +335,7 @@ private static Img buildInt16(Short[] tensor, List tensorSha * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt16(Integer[] tensor, List tensorShape) + private static Img buildInt16FromInteger(List tensor, List tensorShape) { final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -464,57 +345,7 @@ private static Img buildInt16(Integer[] tensor, List tensorS tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i].shortValue()); - } - return outputImg; - } - - /** - * Builds a IntType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildInt16(short[] tensor, List tensorShape) - { - final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< ShortType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a IntType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildInt16(int[] tensor, List tensorShape) - { - final ArrayImgFactory< ShortType > factory = new ArrayImgFactory<>( new ShortType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< ShortType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set((short) tensor[i]); + tensorCursor.get().set(tensor.get(i).shortValue()); } return outputImg; } @@ -529,22 +360,16 @@ private static Img buildInt16(int[] tensor, List tensorShape * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint16(Object array, List tensorShape) + private static Img buildUint16(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(short.class) - && !Short.class.isAssignableFrom(array.getClass().getComponentType()) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) - && !array.getClass().getComponentType().equals(short.class)) { + if (!(array.get(0) instanceof Short) + && !(array.get(0) instanceof Integer)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'int16' using Java array of class: " + array.getClass().getComponentType()); - } else if (array.getClass().getComponentType().equals(short.class)) { - return buildUint16((short[]) array, tensorShape); - } else if (array.getClass().getComponentType().equals(int.class)) { - return buildUint16((int[]) array, tensorShape); - } else if (Short.class.isAssignableFrom(array.getClass().getComponentType())) { - return buildUint16((Short[]) array, tensorShape); + + "'uint16' using Java array of class: " + array.get(0).getClass()); + } else if (array.get(0) instanceof Short) { + return buildUint16FromShort((List) array, tensorShape); } else { - return buildUint16((Integer[]) array, tensorShape); + return buildUint16FromInteger((List) array, tensorShape); } } @@ -558,57 +383,7 @@ private static Img buildUint16(Object array, List te * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint16(Short[] tensor, List tensorShape) - { - final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a IntType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildUint16(Integer[] tensor, List tensorShape) - { - final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< UnsignedShortType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i].shortValue()); - } - return outputImg; - } - - /** - * Builds a IntType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildUint16(short[] tensor, List tensorShape) + private static Img buildUint16FromShort(List tensor, List tensorShape) { final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -618,7 +393,7 @@ private static Img buildUint16(short[] tensor, List tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -633,7 +408,7 @@ private static Img buildUint16(short[] tensor, List * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint16(int[] tensor, List tensorShape) + private static Img buildUint16FromInteger(List tensor, List tensorShape) { final ArrayImgFactory< UnsignedShortType > factory = new ArrayImgFactory<>( new UnsignedShortType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -643,7 +418,7 @@ private static Img buildUint16(int[] tensor, List te tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -658,16 +433,13 @@ private static Img buildUint16(int[] tensor, List te * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt32(Object array, List tensorShape) + private static Img buildInt32(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(int.class) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { + if (!(array.get(0) instanceof Integer)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'int32' using Java array of class: " + array.getClass().getComponentType()); - } else if (array.getClass().getComponentType().equals(int.class)) { - return buildInt32((int[]) array, tensorShape); + + "'int32' using Java array of class: " + array.get(0).getClass()); } else { - return buildInt32((Integer[]) array, tensorShape); + return buildInt32FromInteger((List) array, tensorShape); } } @@ -681,32 +453,7 @@ private static Img buildInt32(Object array, List tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt32(Integer[] tensor, List tensorShape) - { - final ArrayImgFactory< IntType > factory = new ArrayImgFactory<>( new IntType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< IntType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a IntType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildInt32(int[] tensor, List tensorShape) + private static Img buildInt32FromInteger(List tensor, List tensorShape) { final ArrayImgFactory< IntType > factory = new ArrayImgFactory<>( new IntType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -716,7 +463,7 @@ private static Img buildInt32(int[] tensor, List tensorShape) tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -731,22 +478,16 @@ private static Img buildInt32(int[] tensor, List tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint32(Object array, List tensorShape) + private static Img buildUint32(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(int.class) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType()) - && !Long.class.isAssignableFrom(array.getClass().getComponentType()) - && !array.getClass().getComponentType().equals(long.class)) { + if (!(array.get(0) instanceof Long) + && !(array.get(0) instanceof Integer)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'uint32' using Java array of class: " + array.getClass().getComponentType()); - } else if (array.getClass().getComponentType().equals(int.class)) { - return buildUint32((int[]) array, tensorShape); - } else if (array.getClass().getComponentType().equals(long.class)) { - return buildUint32((long[]) array, tensorShape); - } else if (Long.class.isAssignableFrom(array.getClass().getComponentType())) { - return buildUint32((Long[]) array, tensorShape); + + "'uint32' using Java array of class: " + array.get(0).getClass()); + } else if (array.get(0) instanceof Long) { + return buildUint32FromLong((List) array, tensorShape); } else { - return buildUint32((Integer[]) array, tensorShape); + return buildUint32FromInteger((List) array, tensorShape); } } @@ -760,7 +501,7 @@ private static Img buildUint32(Object array, List tens * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint32(Integer[] tensor, List tensorShape) + private static Img buildUint32FromInteger(List tensor, List tensorShape) { final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -770,7 +511,7 @@ private static Img buildUint32(Integer[] tensor, List tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -785,7 +526,7 @@ private static Img buildUint32(Integer[] tensor, List * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildUint32(int[] tensor, List tensorShape) + private static Img buildUint32FromLong(List tensor, List tensorShape) { final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -795,57 +536,7 @@ private static Img buildUint32(int[] tensor, List tens tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a IntType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildUint32(Long[] tensor, List tensorShape) - { - final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a IntType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildUint32(long[] tensor, List tensorShape) - { - final ArrayImgFactory< UnsignedIntType > factory = new ArrayImgFactory<>( new UnsignedIntType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< UnsignedIntType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -860,19 +551,16 @@ private static Img buildUint32(long[] tensor, List ten * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(Object array, List tensorShape) + private static Img buildInt64(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(long.class) - && !Long.class.isAssignableFrom(array.getClass().getComponentType()) - && !Integer.class.isAssignableFrom(array.getClass().getComponentType())) { + if (!(array.get(0) instanceof Long) + && !(array.get(0) instanceof Integer)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'int64' using Java array of class: " + array.getClass().getComponentType()); + + "'int64' using Java array of class: " + array.get(0).getClass()); } else if (array.getClass().getComponentType().equals(long.class)) { - return buildInt64((long[]) array, tensorShape); - } else if (Long.class.isAssignableFrom(array.getClass().getComponentType())) { - return buildInt64((Long[]) array, tensorShape); + return buildInt64FromLong((List) array, tensorShape); } else { - return buildInt64((Integer[]) array, tensorShape); + return buildInt64FromInteger((List) array, tensorShape); } } @@ -886,7 +574,7 @@ private static Img buildInt64(Object array, List tensorShape) * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(Long[] tensor, List tensorShape) + private static Img buildInt64FromLong(List tensor, List tensorShape) { final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -896,7 +584,7 @@ private static Img buildInt64(Long[] tensor, List tensorShape tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -911,7 +599,7 @@ private static Img buildInt64(Long[] tensor, List tensorShape * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildInt64(Integer[] tensor, List tensorShape) + private static Img buildInt64FromInteger(List tensor, List tensorShape) { final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -921,32 +609,7 @@ private static Img buildInt64(Integer[] tensor, List tensorSh tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i].longValue()); - } - return outputImg; - } - - /** - * Builds a LongType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildInt64(long[] tensor, List tensorShape) - { - final ArrayImgFactory< LongType > factory = new ArrayImgFactory<>( new LongType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< LongType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -961,19 +624,16 @@ private static Img buildInt64(long[] tensor, List tensorShape * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat32(Object array, List tensorShape) + private static Img buildFloat32(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(float.class) - && !Float.class.isAssignableFrom(array.getClass().getComponentType()) - && !BigDecimal.class.isAssignableFrom(array.getClass().getComponentType())) { + if (!(array.get(0) instanceof Float) + && !(array.get(0) instanceof BigDecimal)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'float32' using Java array of class: " + array.getClass().getComponentType()); + + "'float32' using Java array of class: " + array.get(0).getClass()); } else if (array.getClass().getComponentType().equals(float.class)) { - return buildFloat32((float[]) array, tensorShape); - } else if (Float.class.isAssignableFrom(array.getClass().getComponentType())) { - return buildFloat32((Float[]) array, tensorShape); + return buildFloat32FromFloat((List) array, tensorShape); } else { - return buildFloat32((BigDecimal[]) array, tensorShape); + return buildFloat32FromBigDecimal((List) array, tensorShape); } } @@ -987,32 +647,7 @@ private static Img buildFloat32(Object array, List tensorSha * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat32(Float[] tensor, List tensorShape) - { - final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); - long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); - final Img< FloatType > outputImg = (Img) factory.create(shape); - Cursor tensorCursor= outputImg.cursor(); - while (tensorCursor.hasNext()) { - tensorCursor.fwd(); - int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), - shape); - tensorCursor.get().set(tensor[i]); - } - return outputImg; - } - - /** - * Builds a FloatType {@link Img} from the information stored in a byte buffer. - * The shape of the image that was previously retrieved from the buffer - * @param tensor - * byte buffer containing the information of the a tenosr, the position in the buffer - * should not be at zero but right after the header. - * @param tensorShape - * shape of the image to generate, it has been retrieved from the byte buffer - * @return image specified in the bytebuffer - */ - private static Img buildFloat32(BigDecimal[] tensor, List tensorShape) + private static Img buildFloat32FromFloat(List tensor, List tensorShape) { final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -1022,7 +657,7 @@ private static Img buildFloat32(BigDecimal[] tensor, List te tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i].longValue()); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -1037,7 +672,7 @@ private static Img buildFloat32(BigDecimal[] tensor, List te * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat32(float[] tensor, List tensorShape) + private static Img buildFloat32FromBigDecimal(List tensor, List tensorShape) { final ArrayImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -1047,7 +682,7 @@ private static Img buildFloat32(float[] tensor, List tensorS tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i).floatValue()); } return outputImg; } @@ -1062,19 +697,19 @@ private static Img buildFloat32(float[] tensor, List tensorS * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat64(Object array, List tensorShape) + private static Img buildFloat64(List array, List tensorShape) { - if (!array.getClass().getComponentType().equals(double.class) - && !Double.class.isAssignableFrom(array.getClass().getComponentType()) - && !BigDecimal.class.isAssignableFrom(array.getClass().getComponentType())) { + if (!(array.get(0) instanceof Float) + && !(array.get(0) instanceof Double) + && !(array.get(0) instanceof BigDecimal)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " - + "'float64' using Java array of class: " + array.getClass().getComponentType()); - } else if (array.getClass().getComponentType().equals(double.class)) { - return buildFloat64((double[]) array, tensorShape); - } else if (Double.class.isAssignableFrom(array.getClass().getComponentType())) { - return buildFloat64((Double[]) array, tensorShape); + + "'float64' using Java array of class: " + array.get(0).getClass()); + } else if (array.get(0) instanceof Float) { + return buildFloat64FromFloat((List) array, tensorShape); + } else if (array.get(0) instanceof Double) { + return buildFloat64FromDouble((List) array, tensorShape); } else { - return buildFloat64((BigDecimal[]) array, tensorShape); + return buildFloat64FromBigDecimal((List) array, tensorShape); } } @@ -1088,7 +723,7 @@ private static Img buildFloat64(Object array, List tensorSh * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat64(Double[] tensor, List tensorShape) + private static Img buildFloat64FromDouble(List tensor, List tensorShape) { final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -1098,7 +733,7 @@ private static Img buildFloat64(Double[] tensor, List tenso tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -1113,7 +748,7 @@ private static Img buildFloat64(Double[] tensor, List tenso * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat64(BigDecimal[] tensor, List tensorShape) + private static Img buildFloat64FromFloat(List tensor, List tensorShape) { final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -1123,7 +758,7 @@ private static Img buildFloat64(BigDecimal[] tensor, List t tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i].longValue()); + tensorCursor.get().set(tensor.get(i)); } return outputImg; } @@ -1138,7 +773,7 @@ private static Img buildFloat64(BigDecimal[] tensor, List t * shape of the image to generate, it has been retrieved from the byte buffer * @return image specified in the bytebuffer */ - private static Img buildFloat64(double[] tensor, List tensorShape) + private static Img buildFloat64FromBigDecimal(List tensor, List tensorShape) { final ArrayImgFactory< DoubleType > factory = new ArrayImgFactory<>( new DoubleType() ); long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); @@ -1148,7 +783,7 @@ private static Img buildFloat64(double[] tensor, List tenso tensorCursor.fwd(); int i = IndexingUtils.multidimensionalIntoFlatIndex(tensorCursor.positionAsLongArray(), shape); - tensorCursor.get().set(tensor[i]); + tensorCursor.get().set(tensor.get(i).doubleValue()); } return outputImg; } From 08689d15f53a568801e05781058719c98bda9c34 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Sat, 30 Sep 2023 01:25:58 +0200 Subject: [PATCH 050/235] keep correcting ouput conversion --- .../bioimage/modelrunner/runmode/RunMode.java | 37 +++++++++++-------- .../modelrunner/tensor/ListToImgLib2.java | 4 +- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index a04b9f02..a9a4941b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -34,10 +34,10 @@ import org.apposed.appose.Service.Task; import io.bioimage.modelrunner.runmode.ops.OpInterface; +import io.bioimage.modelrunner.tensor.ListToImgLib2; import io.bioimage.modelrunner.tensor.ImgLib2ToArray; import io.bioimage.modelrunner.tensor.Tensor; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; @@ -102,8 +102,9 @@ public static RunMode createRunMode(OpInterface op) { return new RunMode(op); } - public void testRunModel() { + public Map testRunModel() { env = Appose.base(new File(this.op.getCondaEnv())).build(); + Map outputs = null; try (Service python = env.python()) { python.debug(line -> { System.err.println(line); @@ -133,12 +134,7 @@ public void testRunModel() { }); task.waitFor(); System.out.println("here2"); - Map aa = task.outputs; - Object result = task.outputs.get("output0"); - Object polys = task.outputs.get("output1"); - System.out.println("here3"); - if (result instanceof Integer) - System.out.print(result); + outputs = recreateOutputObjects(task.outputs); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -146,19 +142,23 @@ public void testRunModel() { // TODO Auto-generated catch block e.printStackTrace(); } + return outputs; } + @SuppressWarnings("unchecked") private static Map recreateOutputObjects(Map apposeOuts) { LinkedHashMap jdllOuts = new LinkedHashMap(); for (Entry entry : apposeOuts.entrySet()) { Object value = entry.getValue(); if (value instanceof Map && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY) != null - && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.TENSOR_KEY) ) { - + && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.TENSOR_KEY) ) { + if (((Map) value).get(RunModeScripts.NAME_KEY) == null) + ((Map) value).put(RunModeScripts.NAME_KEY, entry.getKey()); + jdllOuts.put(entry.getKey(), createTensorFromApposeOutput((Map) value)); } else if (value instanceof Map && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY) != null - && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.NP_ARR_KEY) ) { - + && ((Map) value).get(RunModeScripts.APPOSE_DT_KEY).equals(RunModeScripts.NP_ARR_KEY) ) { + jdllOuts.put(entry.getKey(), createImgLib2ArrFromApposeOutput((Map) value)); } else if (value instanceof Map) { jdllOuts.put(entry.getKey(), recreateOutputObjects((Map) value)); } else if (value instanceof List) { @@ -170,6 +170,7 @@ private static Map recreateOutputObjects(Map app + "' not supported (" + value.getClass() + ")."); } } + return jdllOuts; } public void envCreation() { @@ -299,14 +300,18 @@ private void retrieveResultsCode() { private static < T extends RealType< T > & NativeType< T > > Tensor createTensorFromApposeOutput(Map apposeTensor) { - ArrayImgFactory factory = new ArrayImgFactory(new T()); - return null; + return ListToImgLib2.buildTensor((List) apposeTensor.get(RunModeScripts.DATA_KEY), + (List) apposeTensor.get(RunModeScripts.SHAPE_KEY), + (String) apposeTensor.get(RunModeScripts.AXES_KEY), + (String) apposeTensor.get(RunModeScripts.DTYPE_KEY), + (String) apposeTensor.get(RunModeScripts.NAME_KEY)); } private static < T extends RealType< T > & NativeType< T > > RandomAccessibleInterval createImgLib2ArrFromApposeOutput(Map apposeTensor) { - ArrayImgFactory factory = new ArrayImgFactory(); - return null; + return ListToImgLib2.build((List) apposeTensor.get(RunModeScripts.DATA_KEY), + (List) apposeTensor.get(RunModeScripts.SHAPE_KEY), + (String) apposeTensor.get(RunModeScripts.DTYPE_KEY)); } private static List createListFromApposeOutput(List list) { diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java b/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java index 0dfbdf06..1580d48b 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java @@ -557,7 +557,7 @@ private static Img buildInt64(List array, List tensorShape) && !(array.get(0) instanceof Integer)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + "'int64' using Java array of class: " + array.get(0).getClass()); - } else if (array.getClass().getComponentType().equals(long.class)) { + } else if (array.get(0) instanceof Long) { return buildInt64FromLong((List) array, tensorShape); } else { return buildInt64FromInteger((List) array, tensorShape); @@ -630,7 +630,7 @@ private static Img buildFloat32(List array, List tensorShape && !(array.get(0) instanceof BigDecimal)) { throw new IllegalArgumentException("Unable to build ImgLib2 array of data type " + "'float32' using Java array of class: " + array.get(0).getClass()); - } else if (array.getClass().getComponentType().equals(float.class)) { + } else if (array.get(0) instanceof Float) { return buildFloat32FromFloat((List) array, tensorShape); } else { return buildFloat32FromBigDecimal((List) array, tensorShape); From 457b952b3eacd3f60a11c7b85e59f1390631fd04 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Sat, 30 Sep 2023 01:29:15 +0200 Subject: [PATCH 051/235] refactor mehtod --- src/main/java/io/bioimage/modelrunner/runmode/RunMode.java | 2 +- .../bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index a9a4941b..4f20a499 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -102,7 +102,7 @@ public static RunMode createRunMode(OpInterface op) { return new RunMode(op); } - public Map testRunModel() { + public Map runOP() { env = Appose.base(new File(this.op.getCondaEnv())).build(); Map outputs = null; try (Service python = env.python()) { diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index 660c56fb..7f1ac6a6 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -22,6 +22,7 @@ import java.io.File; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -75,7 +76,7 @@ public static void main(String[] args) { String modelName = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models\\StarDist H&E Nuclei Segmentation_06092023_020924\\rdf.yaml"; StardistInferJdllOp op = create(modelName, inpTensor); RunMode rm = RunMode.createRunMode(op); - rm.testRunModel(); + Map aa = rm.runOP(); System.out.print(false); } From c3ef82e9521b00cea85981043658de524afb3479 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Sat, 30 Sep 2023 02:00:30 +0200 Subject: [PATCH 052/235] good test run for stardist --- .../modelrunner/runmode/RunModeScripts.java | 10 ++-- .../modelrunner/tensor/ListToImgLib2.java | 56 +++++++++++++++++-- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index 95b0eb49..814ca481 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -53,15 +53,18 @@ public class RunModeScripts { */ protected static final String TYPE_CONVERSION_METHODS_SCRIPT = "" + "def " + NP_METHOD + "(np_arr):" + System.lineSeparator() + + " np_arr = np_arr.astype(\"uint8\")" + System.lineSeparator() + " return {\"" + DATA_KEY + "\": np_arr.flatten().tolist(), \"" + SHAPE_KEY + "\": np_arr.shape, \"" + APPOSE_DT_KEY + "\": \"" - + NP_ARR_KEY + "\", \"" + DTYPE_KEY + "\": np_arr.dtype.str}" + System.lineSeparator() + + NP_ARR_KEY + "\", \"" + DTYPE_KEY + "\": str(np_arr.dtype)}" + System.lineSeparator() + "" + System.lineSeparator() + "def " + XR_METHOD + "(xr_arr):" + System.lineSeparator() + + " xr_arr = xr_arr.astype(\"int64\")" + System.lineSeparator() + + " xr_arr[0] = 1" + System.lineSeparator() + " return {\"" + DATA_KEY + "\": xr_arr.values.flatten().tolist(), \"" + SHAPE_KEY - + "\": xr_arr.shape, \"" + AXES_KEY + "\": xr_arr.dims,\"" + NAME_KEY + + "\": xr_arr.shape, \"" + AXES_KEY + "\": \"\".join(xr_arr.dims),\"" + NAME_KEY + "\": xr_arr.name, \"" + APPOSE_DT_KEY + "\": \"" + TENSOR_KEY + "\", " - + "\"" + DTYPE_KEY + "\": xr_arr.values.dtype.str}" + + "\"" + DTYPE_KEY + "\": str(xr_arr.values.dtype)}" + System.lineSeparator() + "" + System.lineSeparator() + "def " + LIST_METHOD + "(list_ob):" + System.lineSeparator() @@ -97,5 +100,4 @@ public class RunModeScripts { + "globals()['" + NP_METHOD + "'] = " + NP_METHOD + System.lineSeparator() + "globals()['" + DICT_METHOD + "'] = " + DICT_METHOD + System.lineSeparator() + "globals()['" + LIST_METHOD + "'] = " + LIST_METHOD + System.lineSeparator(); - } diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java b/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java index 1580d48b..33ffe6d5 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/ListToImgLib2.java @@ -88,11 +88,9 @@ private ListToImgLib2() * not supported */ @SuppressWarnings("unchecked") - public static > Img build(List array, List shape, String dtype) throws IllegalArgumentException + public static < T extends RealType< T > & NativeType< T > > Img build(List array, List shape, String dtype) throws IllegalArgumentException { - if (array.size() == 0) - return null; - if (shape.size() == 0) + if (shape.size() == 0 || array.size() == 0) return null; Img data; @@ -130,6 +128,56 @@ public static > Img build(List array, List shape, } return data; } + + @SuppressWarnings("unchecked") + private static < T extends RealType< T > & NativeType< T > > Img createEmptyArray(List tensorShape, String dtype) { + long[] shape = IntStream.range(0, tensorShape.size()).mapToLong(i -> tensorShape.get(i)).toArray(); + + final Img data; + final ArrayImgFactory factory; + switch (dtype) + { + case "int8": + factory = new ArrayImgFactory<>( new ByteType() ); + data = (Img) factory.create(shape); + break; + case "uint8": + factory = new ArrayImgFactory<>( new UnsignedByteType() ); + data = (Img) factory.create(shape); + break; + case "int16": + factory = new ArrayImgFactory<>( new ShortType() ); + data = (Img) factory.create(shape); + break; + case "uint16": + factory = new ArrayImgFactory<>( new UnsignedShortType() ); + data = (Img) factory.create(shape); + break; + case "int32": + factory = new ArrayImgFactory<>( new IntType() ); + data = (Img) factory.create(shape); + break; + case "uint32": + factory = new ArrayImgFactory<>( new UnsignedIntType() ); + data = (Img) factory.create(shape); + break; + case "int64": + factory = new ArrayImgFactory<>( new LongType() ); + data = (Img) factory.create(shape); + break; + case "float32": + factory = new ArrayImgFactory<>( new FloatType() ); + data = (Img) factory.create(shape); + break; + case "float64": + factory = new ArrayImgFactory<>( new DoubleType() ); + data = (Img) factory.create(shape); + break; + default: + throw new IllegalArgumentException("Unsupported tensor type: " + dtype); + } + return data; + } /** * Builds a ByteType {@link Img} from the information stored in a byte buffer. From ec7242dc2fb2a81fd0c981d68f736751c0c216a5 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Sun, 1 Oct 2023 15:06:42 +0200 Subject: [PATCH 053/235] create fine tune op --- .../stardist_fine_tune/stardist_fine_tune.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 python/ops/stardist_fine_tune/stardist_fine_tune.py diff --git a/python/ops/stardist_fine_tune/stardist_fine_tune.py b/python/ops/stardist_fine_tune/stardist_fine_tune.py new file mode 100644 index 00000000..8c5d7cbf --- /dev/null +++ b/python/ops/stardist_fine_tune/stardist_fine_tune.py @@ -0,0 +1,57 @@ +import xarray as xr +from stardist.models import StarDist2D + +import os +import shutil + +def assertions(model, images, ground_truth, new_model_dir): + + assert isinstance(model, str), "The input argument 'model' must be a string, either the name" \ + + " of one of the default pre-trained Stardist models or the directory to a pre-trained Stardist model" + + assert isinstance(new_model_dir, str), "The input argument 'new_model_dir' must be a string. It is the path" \ + + " where the fine tuned stardist model will be saved." + + assert isinstance(images, xr.DataArray), "the training samples should be a xr.DataArray" + assert isinstance(ground_truth, xr.DataArray), "the ground thruth should be a xr.DataArray" + + assert images.ndim == 4, "the training samples array must have 4 dimensions" + assert ground_truth.ndim == 4, "the training samples array must have 4 dimensions" + + assert "".join(images.dims) == "bcyx", "the training samples axes order should be 'bcyx', not '" + "".join(images.dims) + "' as provided." + assert "".join(ground_truth.dims) == "bcyx", "the ground truth samples axes order should be 'bcyx', not '" + "".join(ground_truth.dims) + "' as provided." + + axes_dict = {"batch size": 0, "width": 3, "height": 2} + + for ks, vs in axes_dict.items(): + assert images.shape[vs] == ground_truth.shape[vs], "The training samples " \ + + "and the ground truth need to have the same " + ks + " : " + + images.shape[vs] + " vs " + ground_truth.shape[vs] + + +def finetune_stardist(model, images, ground_truth, new_model_dir, epochs=5, lr=1e-5, batch_size=16): + """ + model: String, path to pretrained model or pretrained model from the stardsit available + images: list of tensors or single tensor? If a list of tensors, it would need to be ensured taht they all have same dims, + or reconstruct to have same dims. Check the number of channels and check if the channels of the images coincide + Also for a path, check that it has the needed files fo a stardist model + ground_truth: list of tensors or single tensor? It needs to have the same type and size than images + + new_model_dir: directory where the new model will be saved, save one imput and output sample + + epochs and batch_size might have a warning for CPu if selected too large + """ + assertions(model, images, ground_truth, new_model_dir) + if () + + model = StarDist2D(None, model) + # change some training params + model.config.train_patch_size = (images.shape["width"], images.shape["height"]) + model.config.train_batch_size = images.shape["batch size"] + model.config.train_learning_rate = lr + model.config.train_epochs = epochs + + # finetune on new data + history = model.train(X,Y, validation_data=(X,Y)) + + return history.loss, history.rest_losses \ No newline at end of file From 14ce012aace158cd413e244484b6863ae10ac7cd Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 2 Oct 2023 14:07:09 +0200 Subject: [PATCH 054/235] start creating the op for finetuning a stardist model --- .../runmode/ops/StardistFineTuneJdllOp.java | 137 +++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 580c6a34..6000e0a0 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -19,6 +19,141 @@ */ package io.bioimage.modelrunner.runmode.ops; -public class StardistFineTuneJdllOp { +import java.io.File; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Objects; + +import io.bioimage.modelrunner.tensor.Tensor; +import net.imglib2.type.NativeType; +import net.imglib2.type.numeric.RealType; + +public class StardistFineTuneJdllOp implements OpInterface { + + private String model; + + private String nModelPath; + + private float lr = (float) 1e-5; + + private int batchSize = 16; + + private Tensor inputTensor; + + private String opFilePath; + + private String envPath; + + private LinkedHashMap inputsMap; + + private final static String MODEL_KEY = "model"; + + private final static String INPUT_TENSOR_KEY = "input_tensor"; + + private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; + + private static final String STARDIST_FIELD_KEY = "stardist"; + + private static final int N_STARDIST_OUTPUTS = 1; + + private static final String STARDIST_OP_FNAME = "stardist_inference.py"; + + /** + * Create a JDLL OP to fine tune a stardist model with the wanted data. + * In order to set the data we want to fine tune the model on, use {@link #setFineTuningData(List, List)} + * or {@link #setFineTuningData(Tensor, Tensor)}. The batch size and learning rates + * can also be modified by with {@link #setBatchSize(int)} and {@link #setLearingRate(float)}. + * By default the batch size is 16 and the learning rate 1e-5. + * @param modelToFineTune + * Pre-trained model that is going to be fine tuned on the user's data, it + * can be either a model existing in the users machine or a model existing in the model + * zoo. If it is a model existing in th emodel zoo, it will have to be downloaded first. + * @param newModelDir + * directory where the new model will be saved + * @return a JDLL OP that can be used together with {@link RunMode} to fine tune a StarDist + * model on the user's data + */ + public StardistFineTuneJdllOp create(String modelToFineTune, String newModelDir) { + StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); + op.setModel(modelToFineTune); + op.nModelPath = newModelDir; + return op; + } + + public < T extends RealType< T > & NativeType< T > > + void setFineTuningData(List> trainingSamples, List> groundTruth) { + + } + + public < T extends RealType< T > & NativeType< T > > + void setFineTuningData(Tensor trainingSamples, Tensor groundTruth) { + + } + + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + public void setLearingRate(float learningRate) { + this.lr = learningRate; + } + + @Override + public String getOpPythonFilename() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getNumberOfOutputs() { + return N_STARDIST_OUTPUTS; + } + + @Override + public boolean isOpInstalled() { + // TODO Auto-generated method stub + return false; + } + + @Override + public void installOp() { + // TODO Auto-generated method stub + + } + + @Override + public LinkedHashMap getOpInputs() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getCondaEnv() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getMethodName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getOpDir() { + // TODO Auto-generated method stub + return null; + } + + public void setModel(String modelName) throws IllegalArgumentException { + Objects.requireNonNull(modelName, "The modelName input argument cannot be null."); + if (new File(modelName).isFile() && !StardistInferJdllOp.isModelFileStardist(modelName)) + throw new IllegalArgumentException("The file selected does not correspond to " + + "the rdf.yaml file of a Bioiamge.io Stardist model."); + else if (!(new File(modelName).isFile()) && !StardistInferJdllOp.isModelNameStardist(modelName)) + throw new IllegalArgumentException("The model name provided does not correspond to a valid" + + " Stardist model present in the Bioimage.io online reposritory."); + this.model = modelName; + } } From 38c50439e2afec10ce1789907bec2478b3e26791 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 2 Oct 2023 14:23:27 +0200 Subject: [PATCH 055/235] create the structure of the fine tune stardist op --- .../runmode/ops/StardistFineTuneJdllOp.java | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 6000e0a0..2e47e82e 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -27,6 +27,8 @@ import io.bioimage.modelrunner.tensor.Tensor; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; +import net.imglib2.type.numeric.integer.UnsignedShortType; +import net.imglib2.type.numeric.real.FloatType; public class StardistFineTuneJdllOp implements OpInterface { @@ -38,7 +40,9 @@ public class StardistFineTuneJdllOp implements OpInterface { private int batchSize = 16; - private Tensor inputTensor; + private Tensor trainingSamples; + + private Tensor groundTruth; private String opFilePath; @@ -48,11 +52,17 @@ public class StardistFineTuneJdllOp implements OpInterface { private final static String MODEL_KEY = "model"; - private final static String INPUT_TENSOR_KEY = "input_tensor"; + private final static String NEW_MODEL_DIR_KEY = "n_model_dir"; - private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; + private final static String TRAIN_SAMPLES_KEY = "train_samples"; + + private final static String GROUND_TRUTH_KEY = "ground_truth"; + + private final static String BATCH_SIZE_KEY = "batch_size"; - private static final String STARDIST_FIELD_KEY = "stardist"; + private final static String LR_KEY = "learning_rate"; + + private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; private static final int N_STARDIST_OUTPUTS = 1; @@ -100,8 +110,7 @@ public void setLearingRate(float learningRate) { @Override public String getOpPythonFilename() { - // TODO Auto-generated method stub - return null; + return STARDIST_OP_FNAME; } @Override @@ -112,37 +121,44 @@ public int getNumberOfOutputs() { @Override public boolean isOpInstalled() { // TODO Auto-generated method stub - return false; + return true; } @Override public void installOp() { - // TODO Auto-generated method stub - + // TODO this method checks if the OP file is at its correponding folder. + // TODO if not unpack the python file and located (where??) + opFilePath = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\python\\ops\\stardist_inference"; + // TODO check if the env has also been created + // TODO if not create it (where??) + envPath = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; } @Override public LinkedHashMap getOpInputs() { - // TODO Auto-generated method stub - return null; + inputsMap = new LinkedHashMap(); + inputsMap.put(MODEL_KEY, this.model); + inputsMap.put(NEW_MODEL_DIR_KEY, this.nModelPath); + inputsMap.put(TRAIN_SAMPLES_KEY, this.trainingSamples); + inputsMap.put(GROUND_TRUTH_KEY, this.groundTruth); + inputsMap.put(BATCH_SIZE_KEY, this.batchSize); + inputsMap.put(LR_KEY, this.lr); + return inputsMap; } @Override public String getCondaEnv() { - // TODO Auto-generated method stub - return null; + return envPath; } @Override public String getMethodName() { - // TODO Auto-generated method stub - return null; + return OP_METHOD_NAME; } @Override public String getOpDir() { - // TODO Auto-generated method stub - return null; + return opFilePath; } public void setModel(String modelName) throws IllegalArgumentException { From d35cdfd3974722a9e5ccfb1a502c7e1fc014b7e7 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 2 Oct 2023 14:44:04 +0200 Subject: [PATCH 056/235] check that the training samples are in the correct datatype --- .../runmode/ops/StardistFineTuneJdllOp.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 2e47e82e..4da529c8 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -29,6 +29,7 @@ import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; +import net.imglib2.util.Util; public class StardistFineTuneJdllOp implements OpInterface { @@ -97,7 +98,9 @@ void setFineTuningData(List> trainingSamples, List> groundTr public < T extends RealType< T > & NativeType< T > > void setFineTuningData(Tensor trainingSamples, Tensor groundTruth) { - + checkTrainAndGroundTruthDimensions(trainingSamples, groundTruth); + setTrainingSamples(trainingSamples); + setGroundTruth(groundTruth); } public void setBatchSize(int batchSize) { @@ -171,5 +174,28 @@ else if (!(new File(modelName).isFile()) && !StardistInferJdllOp.isModelNameStar + " Stardist model present in the Bioimage.io online reposritory."); this.model = modelName; } + + private < T extends RealType< T > & NativeType< T > > + void checkTrainAndGroundTruthDimensions(Tensor trainingSamples, Tensor groundTruth) { + + } + + private < T extends RealType< T > & NativeType< T > > + void setTrainingSamples(Tensor trainingSamples) { + if (!(Util.getTypeFromInterval(trainingSamples.getData()) instanceof FloatType)) { + this.trainingSamples = Tensor.createCopyOfTensorInWantedDataType(trainingSamples, new FloatType()); + } else { + this.trainingSamples = (Tensor) trainingSamples; + } + } + + private < T extends RealType< T > & NativeType< T > > + void setGroundTruth(Tensor groundTruth) { + if (!(Util.getTypeFromInterval(groundTruth.getData()) instanceof UnsignedShortType)) { + this.groundTruth = Tensor.createCopyOfTensorInWantedDataType(groundTruth, new UnsignedShortType()); + } else { + this.groundTruth = (Tensor) groundTruth; + } + } } From f0fa5c42d317eef97c9d964bba1bdc9397d55f1e Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 2 Oct 2023 15:26:00 +0200 Subject: [PATCH 057/235] improve the stardist fine tune robustness --- .../runmode/ops/StardistFineTuneJdllOp.java | 68 ++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 4da529c8..7dd83ed7 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -20,10 +20,12 @@ package io.bioimage.modelrunner.runmode.ops; import java.io.File; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; +import io.bioimage.modelrunner.bioimageio.description.ModelDescriptor; import io.bioimage.modelrunner.tensor.Tensor; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; @@ -37,10 +39,16 @@ public class StardistFineTuneJdllOp implements OpInterface { private String nModelPath; + private int nChannelsModel; + private float lr = (float) 1e-5; private int batchSize = 16; + private int epochs = 1; + + private boolean downloadStardistPretrained = false; + private Tensor trainingSamples; private Tensor groundTruth; @@ -51,6 +59,19 @@ public class StardistFineTuneJdllOp implements OpInterface { private LinkedHashMap inputsMap; + private static final List PRETRAINED_3C_STARDIST_MODELS; + static { + PRETRAINED_3C_STARDIST_MODELS = new ArrayList(); + PRETRAINED_3C_STARDIST_MODELS.add("2D_versatile_fluo"); + PRETRAINED_3C_STARDIST_MODELS.add("2D_paper_dsb2018"); + } + + private static final List PRETRAINED_1C_STARDIST_MODELS; + static { + PRETRAINED_1C_STARDIST_MODELS = new ArrayList(); + PRETRAINED_1C_STARDIST_MODELS.add("2D_versatile_he"); + } + private final static String MODEL_KEY = "model"; private final static String NEW_MODEL_DIR_KEY = "n_model_dir"; @@ -63,18 +84,27 @@ public class StardistFineTuneJdllOp implements OpInterface { private final static String LR_KEY = "learning_rate"; + private final static String EPOCHS_KEY = "learning_rate"; + + private final static String DOWNLOAD_STARDIST_KEY = "download_pretrained_stardist"; + private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; private static final int N_STARDIST_OUTPUTS = 1; private static final String STARDIST_OP_FNAME = "stardist_inference.py"; + private static final String STARDIST_2D_AXES = "bxyc"; + + private static final String STARDIST_3D_AXES = "bxyzc"; + /** * Create a JDLL OP to fine tune a stardist model with the wanted data. * In order to set the data we want to fine tune the model on, use {@link #setFineTuningData(List, List)} * or {@link #setFineTuningData(Tensor, Tensor)}. The batch size and learning rates * can also be modified by with {@link #setBatchSize(int)} and {@link #setLearingRate(float)}. * By default the batch size is 16 and the learning rate 1e-5. + * To set the number of epochs: {@link #setEpochs(int)}, default is 1. * @param modelToFineTune * Pre-trained model that is going to be fine tuned on the user's data, it * can be either a model existing in the users machine or a model existing in the model @@ -88,6 +118,12 @@ public StardistFineTuneJdllOp create(String modelToFineTune, String newModelDir) StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); op.setModel(modelToFineTune); op.nModelPath = newModelDir; + try { + op.findNChannels(); + } catch (Exception e) { + throw new IllegalArgumentException("Unable to correctly read the rdf.yaml file " + + "of Bioimage.io StarDist model at :" + this.model, e); + } return op; } @@ -110,6 +146,10 @@ public void setBatchSize(int batchSize) { public void setLearingRate(float learningRate) { this.lr = learningRate; } + + public void setEpochs(int epochs) { + this.epochs = epochs; + } @Override public String getOpPythonFilename() { @@ -146,6 +186,8 @@ public LinkedHashMap getOpInputs() { inputsMap.put(GROUND_TRUTH_KEY, this.groundTruth); inputsMap.put(BATCH_SIZE_KEY, this.batchSize); inputsMap.put(LR_KEY, this.lr); + inputsMap.put(EPOCHS_KEY, this.epochs); + inputsMap.put(DOWNLOAD_STARDIST_KEY, this.downloadStardistPretrained); return inputsMap; } @@ -166,6 +208,11 @@ public String getOpDir() { public void setModel(String modelName) throws IllegalArgumentException { Objects.requireNonNull(modelName, "The modelName input argument cannot be null."); + if (PRETRAINED_1C_STARDIST_MODELS.contains(modelName) || PRETRAINED_3C_STARDIST_MODELS.contains(modelName)) { + this.model = modelName; + this.downloadStardistPretrained = true; + return; + } if (new File(modelName).isFile() && !StardistInferJdllOp.isModelFileStardist(modelName)) throw new IllegalArgumentException("The file selected does not correspond to " + "the rdf.yaml file of a Bioiamge.io Stardist model."); @@ -175,8 +222,17 @@ else if (!(new File(modelName).isFile()) && !StardistInferJdllOp.isModelNameStar this.model = modelName; } + private void setUpStardistModelFromBioimageio() { + + } + + private void setUpStardistModelFromLocal() { + + } + private < T extends RealType< T > & NativeType< T > > void checkTrainAndGroundTruthDimensions(Tensor trainingSamples, Tensor groundTruth) { + if (trainingSamples.getAxesOrderString().toLowerCase().equals(STARDIST_2D_AXES)) } @@ -197,5 +253,15 @@ void setGroundTruth(Tensor groundTruth) { this.groundTruth = (Tensor) groundTruth; } } - + + private void findNChannels() throws Exception { + if (this.downloadStardistPretrained && PRETRAINED_1C_STARDIST_MODELS.contains(this.model)) { + this.nChannelsModel = 1; + } else if (this.downloadStardistPretrained && PRETRAINED_3C_STARDIST_MODELS.contains(this.model)) { + this.nChannelsModel = 3; + } + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(model, false); + int cInd = descriptor.getInputTensors().get(0).getAxesOrder().indexOf("c"); + nChannelsModel = descriptor.getInputTensors().get(0).getShape().getPatchMinimumSize()[cInd]; + } } From 47b0843010f7e7bc279ba7908c599aeaa802c403 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 2 Oct 2023 18:05:53 +0200 Subject: [PATCH 058/235] keep adding the logic to handle finetuning models --- .../runmode/ops/StardistFineTuneJdllOp.java | 104 +++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 7dd83ed7..8ef4ba9b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -20,19 +20,43 @@ package io.bioimage.modelrunner.runmode.ops; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; +import io.bioimage.modelrunner.bioimageio.BioimageioRepo; import io.bioimage.modelrunner.bioimageio.description.ModelDescriptor; +import io.bioimage.modelrunner.bioimageio.download.DownloadModel; +import io.bioimage.modelrunner.engine.installation.FileDownloader; import io.bioimage.modelrunner.tensor.Tensor; +import io.bioimage.modelrunner.utils.Constants; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; import net.imglib2.util.Util; +/** + * TODO + * TODO + * TODO + * TODO + * TODO add support for stardist 3D + * + * + * + * Class that defines the methods needed to fine tune a StarDist pre-trained model + * using JDLL and Python with Appose. + * @author Carlos Javier Garcia Lopez de Haro + * + */ public class StardistFineTuneJdllOp implements OpInterface { private String model; @@ -86,6 +110,8 @@ public class StardistFineTuneJdllOp implements OpInterface { private final static String EPOCHS_KEY = "learning_rate"; + private static final String STARDIST_WEIGHTS_FILE = "stardist_weights.h5"; + private final static String DOWNLOAD_STARDIST_KEY = "download_pretrained_stardist"; private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; @@ -116,8 +142,8 @@ public class StardistFineTuneJdllOp implements OpInterface { */ public StardistFineTuneJdllOp create(String modelToFineTune, String newModelDir) { StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); - op.setModel(modelToFineTune); op.nModelPath = newModelDir; + op.setModel(modelToFineTune); try { op.findNChannels(); } catch (Exception e) { @@ -222,10 +248,50 @@ else if (!(new File(modelName).isFile()) && !StardistInferJdllOp.isModelNameStar this.model = modelName; } - private void setUpStardistModelFromBioimageio() { + private void setUpStardistModelFromBioimageio() throws IOException, InterruptedException { + BioimageioRepo br = BioimageioRepo.connect(); + if (br.selectByName(model) != null) { + model = br.downloadByName(model, nModelPath); + } else if (br.selectByID(model) != null) { + model = br.downloadModelByID(model, nModelPath); + } else if (br.selectByNickname(model) != null) { + model = br.downloadByNickame(model, nModelPath); + } + File folder = new File(model); + String fineTuned = folder.getParent() + File.separator + "finetuned_" + folder.getName(); + File renamedFolder = new File(fineTuned); + if (folder.renameTo(renamedFolder)) + model = fineTuned; + downloadBioimageioStardistWeights(); + } + + private void downloadBioimageioStardistWeights() throws IOException, Exception { + File stardistSubfolder = new File(this.model, "stardist"); + String rdfYamlFN = this.model + File.separator + Constants.RDF_FNAME; + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfYamlFN); + downloadFileFromInternet(getKerasWeigthsLink(descriptor), + new File(stardistSubfolder, STARDIST_WEIGHTS_FILE)); + } + private static String getKerasWeigthsLink(ModelDescriptor descriptor) throws IOException { + Object yamlFiles = descriptor.getAttachments().get("files"); + if (yamlFiles == null || !(yamlFiles instanceof List)) + throw new IllegalArgumentException(""); + for (String url : (List) yamlFiles) { + try { + if (DownloadModel.getFileNameFromURLString(url).equals(STARDIST_WEIGHTS_FILE)) + return url; + } catch (MalformedURLException e) { + } + } + throw new IOException("Stardist rdf.yaml file at : " + descriptor.getModelPath() + + " is invalid, as it does not contain the URL to StarDist Keras weights in " + + "the attachements field. Look for a StarDist model on the Bioimage.io " + + "repository for an example of a correct version."); + } + private void setUpStardistModelFromLocal() { } @@ -264,4 +330,38 @@ private void findNChannels() throws Exception { int cInd = descriptor.getInputTensors().get(0).getAxesOrder().indexOf("c"); nChannelsModel = descriptor.getInputTensors().get(0).getShape().getPatchMinimumSize()[cInd]; } + + /** + * Method that downloads the model selected from the internet, + * copies it and unzips it into the models folder + * @param downloadURL + * url of the file to be downloaded + * @param targetFile + * file where the file from the url will be downloaded too + */ + public static void downloadFileFromInternet(String downloadURL, File targetFile) { + FileOutputStream fos = null; + ReadableByteChannel rbc = null; + try { + URL website = new URL(downloadURL); + rbc = Channels.newChannel(website.openStream()); + // Create the new model file as a zip + fos = new FileOutputStream(targetFile); + // Send the correct parameters to the progress screen + FileDownloader downloader = new FileDownloader(rbc, fos); + downloader.call(); + } catch (IOException e) { + String msg = "The link for the file: " + targetFile.getName() + " is broken."; + new IOException(msg, e).printStackTrace(); + } finally { + try { + if (fos != null) + fos.close(); + if (rbc != null) + rbc.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } } From 75c5ad7d6681c2dbd54fc56ff19146f979ea5440 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 2 Oct 2023 18:42:05 +0200 Subject: [PATCH 059/235] keep improving the way stardist is fine tuned --- .../runmode/ops/StardistFineTuneJdllOp.java | 70 +++++++++++++++++-- .../runmode/ops/StardistInferJdllOp.java | 2 +- .../bioimage/modelrunner/utils/YAMLUtils.java | 27 ++++++- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 8ef4ba9b..93600a73 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -26,17 +26,24 @@ import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Objects; +import org.yaml.snakeyaml.Yaml; + import io.bioimage.modelrunner.bioimageio.BioimageioRepo; import io.bioimage.modelrunner.bioimageio.description.ModelDescriptor; import io.bioimage.modelrunner.bioimageio.download.DownloadModel; import io.bioimage.modelrunner.engine.installation.FileDownloader; import io.bioimage.modelrunner.tensor.Tensor; import io.bioimage.modelrunner.utils.Constants; +import io.bioimage.modelrunner.utils.YAMLUtils; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.UnsignedShortType; @@ -96,6 +103,14 @@ public class StardistFineTuneJdllOp implements OpInterface { PRETRAINED_1C_STARDIST_MODELS.add("2D_versatile_he"); } + private final static String STARDIST_CONFIG_KEY = "config"; + + private final static String CONFIG_JSON = "config.json"; + + private final static String STARDIST_THRES_KEY = "thresholds"; + + private final static String THRES_JSON = "thresholds.json"; + private final static String MODEL_KEY = "model"; private final static String NEW_MODEL_DIR_KEY = "n_model_dir"; @@ -265,14 +280,59 @@ private void setUpStardistModelFromBioimageio() throws IOException, InterruptedE downloadBioimageioStardistWeights(); } - private void downloadBioimageioStardistWeights() throws IOException, Exception { - File stardistSubfolder = new File(this.model, "stardist"); + private void downloadBioimageioStardistWeights() throws IllegalArgumentException, + IOException, Exception { + File stardistSubfolder = new File(this.model, StardistInferJdllOp.STARDIST_FIELD_KEY); + if (!stardistSubfolder.exists()) { + if (!stardistSubfolder.mkdirs()) { + throw new IOException("Unable to create folder named 'stardist' at: " + this.model); + } + } String rdfYamlFN = this.model + File.separator + Constants.RDF_FNAME; ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfYamlFN); - downloadFileFromInternet(getKerasWeigthsLink(descriptor), - new File(stardistSubfolder, STARDIST_WEIGHTS_FILE)); - + setUpKerasWeights(descriptor); + setUpConfigs(descriptor); + } + + private void setUpConfigs(ModelDescriptor descriptor) throws IOException { + Object stardistInfo = descriptor.getConfig().getSpecMap().get(StardistInferJdllOp.STARDIST_FIELD_KEY); + if (stardistInfo == null || !(stardistInfo instanceof Map)) { + throw new IllegalArgumentException("The rdf.yaml file of the Bioimage.io StarDist " + + "model at: " + this.model + " is invalid. The field config>stardist is missing." + + " Look for StarDist models in the Bioimage.io repo to see how the rdf.yaml should look like."); + } + Object config = ((Map) stardistInfo).get(STARDIST_CONFIG_KEY); + if (config == null || !(config instanceof Map)) { + throw new IllegalArgumentException("The rdf.yaml file of the Bioimage.io StarDist " + + "model at: " + this.model + " is invalid. The field config>stardist>" + STARDIST_CONFIG_KEY + " is missing." + + " Look for StarDist models in the Bioimage.io repo to see how the rdf.yaml should look like."); + } + Object thres = ((Map) stardistInfo).get(STARDIST_THRES_KEY); + if (thres == null || !(thres instanceof Map)) { + throw new IllegalArgumentException("The rdf.yaml file of the Bioimage.io StarDist " + + "model at: " + this.model + " is invalid. The field config>stardist>" + STARDIST_THRES_KEY + " is missing." + + " Look for StarDist models in the Bioimage.io repo to see how the rdf.yaml should look like."); + } + String subfolder = this.model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; + YAMLUtils.writeYamlFile(subfolder + File.separator + CONFIG_JSON, (Map) config); + YAMLUtils.writeYamlFile(opFilePath + File.separator + THRES_JSON, (Map) thres); + } + + private void setUpKerasWeights(ModelDescriptor descriptor) throws IOException { + String stardistWeights = this.model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; + stardistWeights += File.separator + STARDIST_WEIGHTS_FILE; + if (new File(stardistWeights).exists()) + return; + String stardistWeightsParent = this.model + File.separator + STARDIST_WEIGHTS_FILE; + if (new File(stardistWeights).exists()) { + try { + Files.copy(Paths.get(stardistWeightsParent), Paths.get(stardistWeights), StandardCopyOption.REPLACE_EXISTING); + return; + } catch (IOException e) { + } + } + downloadFileFromInternet(getKerasWeigthsLink(descriptor), new File(stardistWeights)); } private static String getKerasWeigthsLink(ModelDescriptor descriptor) throws IOException { diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index 7f1ac6a6..3ff8894e 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -62,7 +62,7 @@ public class StardistInferJdllOp implements OpInterface { private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; - private static final String STARDIST_FIELD_KEY = "stardist"; + protected static final String STARDIST_FIELD_KEY = "stardist"; private static final int N_STARDIST_OUTPUTS = 2; diff --git a/src/main/java/io/bioimage/modelrunner/utils/YAMLUtils.java b/src/main/java/io/bioimage/modelrunner/utils/YAMLUtils.java index 6a8b87e4..22f224dc 100644 --- a/src/main/java/io/bioimage/modelrunner/utils/YAMLUtils.java +++ b/src/main/java/io/bioimage/modelrunner/utils/YAMLUtils.java @@ -22,18 +22,20 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; /** * Utility class for YAML files and data structures. * - * @author Daniel Felipe Gonzalez Obando + * @author Daniel Felipe Gonzalez Obando and Carlos Garcia Lopez de Haro */ public class YAMLUtils { @@ -176,4 +178,27 @@ public static float[] castListToFloatArray(List list) } } + /** + * Method that writes a Map into a YAML file in the path defined + * @param filePath + * path to the yaml file that will be created + * @param data + * data to be written into the yaml file + * @throws IOException if there is any problem writting the yaml file + */ + public static void writeYamlFile(String filePath, Map data) throws IOException { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setPrettyFlow(true); + + // Creating Yaml instance with options + Yaml yaml = new Yaml(options); + + try (FileWriter writer = new FileWriter(filePath)) { + // Writing Map to YAML + yaml.dump(data, writer); + } catch (IOException e) { + throw e; + } + } } From 11f82a593bffe478e726ab0bee45999fa3a83a4e Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 2 Oct 2023 19:16:51 +0200 Subject: [PATCH 060/235] change the config before finetuning depending on the images and params --- .../runmode/ops/StardistFineTuneJdllOp.java | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 93600a73..5768faec 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -119,11 +119,13 @@ public class StardistFineTuneJdllOp implements OpInterface { private final static String GROUND_TRUTH_KEY = "ground_truth"; - private final static String BATCH_SIZE_KEY = "batch_size"; + private final static String PATCH_SIZE_KEY = "train_patch_size"; - private final static String LR_KEY = "learning_rate"; + private final static String BATCH_SIZE_KEY = "train_batch_size"; - private final static String EPOCHS_KEY = "learning_rate"; + private final static String LR_KEY = "train_learning_rate"; + + private final static String EPOCHS_KEY = "train_epochs"; private static final String STARDIST_WEIGHTS_FILE = "stardist_weights.h5"; @@ -178,6 +180,7 @@ void setFineTuningData(Tensor trainingSamples, Tensor groundTruth) { checkTrainAndGroundTruthDimensions(trainingSamples, groundTruth); setTrainingSamples(trainingSamples); setGroundTruth(groundTruth); + setUpConfigs(); } public void setBatchSize(int batchSize) { @@ -288,13 +291,31 @@ private void downloadBioimageioStardistWeights() throws IllegalArgumentException throw new IOException("Unable to create folder named 'stardist' at: " + this.model); } } - String rdfYamlFN = this.model + File.separator + Constants.RDF_FNAME; - ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfYamlFN); - setUpKerasWeights(descriptor); - setUpConfigs(descriptor); + setUpKerasWeights(); + } + + private void setUpConfigs() throws IOException, Exception { + if (new File(model + File.separator + Constants.RDF_FNAME).exists()) { + setUpConfigsBioimageio(); + } else if (!(new File(model + File.separator + CONFIG_JSON).exists())) { + throw new IOException("Missing necessary file for StarDist: " + CONFIG_JSON); + } else if (!(new File(model + File.separator + THRES_JSON).exists())) { + throw new IOException("Missing necessary file for StarDist: " + THRES_JSON); + } else { + Map config = YAMLUtils.load(model + File.separator + CONFIG_JSON); + Map thres = YAMLUtils.load(model + File.separator + THRES_JSON); + int w = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("x")]; + int h = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("y")]; + config.put(PATCH_SIZE_KEY, new int[] {w, h}); + config.put(BATCH_SIZE_KEY, this.batchSize); + config.put(LR_KEY, this.lr); + config.put(EPOCHS_KEY, this.epochs); + YAMLUtils.writeYamlFile(model + File.separator + CONFIG_JSON, (Map) config); + } } - private void setUpConfigs(ModelDescriptor descriptor) throws IOException { + private void setUpConfigsBioimageio() throws IOException, Exception { + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(this.model + File.separator + Constants.RDF_FNAME); Object stardistInfo = descriptor.getConfig().getSpecMap().get(StardistInferJdllOp.STARDIST_FIELD_KEY); if (stardistInfo == null || !(stardistInfo instanceof Map)) { @@ -315,11 +336,19 @@ private void setUpConfigs(ModelDescriptor descriptor) throws IOException { + " Look for StarDist models in the Bioimage.io repo to see how the rdf.yaml should look like."); } String subfolder = this.model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; + int w = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("x")]; + int h = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("y")]; + ((Map) config).put(PATCH_SIZE_KEY, new int[] {w, h}); + ((Map) config).put(BATCH_SIZE_KEY, this.batchSize); + ((Map) config).put(LR_KEY, this.lr); + ((Map) config).put(EPOCHS_KEY, this.epochs); YAMLUtils.writeYamlFile(subfolder + File.separator + CONFIG_JSON, (Map) config); YAMLUtils.writeYamlFile(opFilePath + File.separator + THRES_JSON, (Map) thres); } - private void setUpKerasWeights(ModelDescriptor descriptor) throws IOException { + private void setUpKerasWeights() throws IOException, Exception { + String rdfYamlFN = this.model + File.separator + Constants.RDF_FNAME; + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfYamlFN); String stardistWeights = this.model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; stardistWeights += File.separator + STARDIST_WEIGHTS_FILE; if (new File(stardistWeights).exists()) From dfeb4192684f51954f16e87fcf3cc42ed3ab9aa0 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 2 Oct 2023 20:02:23 +0200 Subject: [PATCH 061/235] add checkers for the training data --- .../runmode/ops/StardistFineTuneJdllOp.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 5768faec..d16d4b1b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -49,6 +49,8 @@ import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; import net.imglib2.util.Util; +import net.imglib2.view.IntervalView; +import net.imglib2.view.Views; /** * TODO @@ -387,7 +389,26 @@ private void setUpStardistModelFromLocal() { private < T extends RealType< T > & NativeType< T > > void checkTrainAndGroundTruthDimensions(Tensor trainingSamples, Tensor groundTruth) { - if (trainingSamples.getAxesOrderString().toLowerCase().equals(STARDIST_2D_AXES)) + String axes = trainingSamples.getAxesOrderString(); + if (axes.length() != STARDIST_2D_AXES.length()) + throw new IllegalArgumentException("Training sample tensors should have for dimensions (" + + STARDIST_2D_AXES + "), but it has " + axes.length() + " (" + axes + ")."); + for (int c = 0; c < STARDIST_2D_AXES.length(); c ++) { + int trueInd = STARDIST_2D_AXES.indexOf(STARDIST_2D_AXES.split("")[c]); + if (trueInd == -1) + throw new IllegalArgumentException("The training samples provided should have dimension '" + + STARDIST_2D_AXES.split("")[c] + "' in the axes order, but it does not (" + axes + ")."); + else if (trueInd == c) { + c ++; + continue; + } + IntervalView wrapImg = Views.permute(trainingSamples.getData(), trueInd, c); + trainingSamples = Tensor.build(trainingSamples.getName(), axes, wrapImg); + c = 0; + } + + // TODO check that train and ground truth have the same + if } From 7ece4cb05bd9a00b965a26d32438b0cc668ff5e2 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 12:51:41 +0200 Subject: [PATCH 062/235] check the input tensor and gt dims for stardist finetuning --- .../runmode/ops/StardistFineTuneJdllOp.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index d16d4b1b..a70fb78d 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -143,6 +143,8 @@ public class StardistFineTuneJdllOp implements OpInterface { private static final String STARDIST_3D_AXES = "bxyzc"; + private static final String GROUNDTRUTH_AXES = "bxy"; + /** * Create a JDLL OP to fine tune a stardist model with the wanted data. * In order to set the data we want to fine tune the model on, use {@link #setFineTuningData(List, List)} @@ -412,6 +414,51 @@ else if (trueInd == c) { } + private static < T extends RealType< T > & NativeType< T > > + void checkTrainingSamplesTensorDimsForStardist(Tensor trainingSamples) { + String axes = trainingSamples.getAxesOrderString(); + String stardistAxes = STARDIST_2D_AXES; + if (axes.length() == 5) + stardistAxes = STARDIST_3D_AXES; + else if (axes.length() < 5) + throw new IllegalArgumentException("Training input tensors should have 4 dimensions (" + + STARDIST_2D_AXES + ") or 5 (" + STARDIST_3D_AXES + "), but it has " + axes.length() + " (" + axes + ")."); + + checkDimOrderAndTranspose(trainingSamples, stardistAxes, "training input"); + } + + private static < T extends RealType< T > & NativeType< T > > + void checkGroundTruthTensorDimsForStardist(Tensor gt) { + String axes = gt.getAxesOrderString(); + String stardistAxes = GROUNDTRUTH_AXES; + if (axes.length() != GROUNDTRUTH_AXES.length()) + throw new IllegalArgumentException("Ground truth tensors should have 3 dimensions (" + + GROUNDTRUTH_AXES + "), but it has " + axes.length() + " (" + axes + ")."); + + checkDimOrderAndTranspose(gt, stardistAxes, "ground truth"); + } + + private static < T extends RealType< T > & NativeType< T > > + void checkDimOrderAndTranspose(Tensor tensor, String stardistAxes, String errMsgObject) { + for (int c = 0; c < stardistAxes.length(); c ++) { + String axes = tensor.getAxesOrderString(); + int trueInd = axes.indexOf(stardistAxes.split("")[c]); + if (trueInd == -1) + throw new IllegalArgumentException("The " + errMsgObject + " tensors provided should have dimension '" + + stardistAxes.split("")[c] + "' in the axes order, but it does not (" + axes + ")."); + else if (trueInd == c) { + c ++; + continue; + } + IntervalView wrapImg = Views.permute(tensor.getData(), trueInd, c); + StringBuilder nAxes = new StringBuilder(axes); + nAxes.setCharAt(c, stardistAxes.charAt(c)); + nAxes.setCharAt(trueInd, axes.charAt(c)); + tensor = Tensor.build(tensor.getName(), nAxes.toString(), wrapImg); + c = 0; + } + } + private < T extends RealType< T > & NativeType< T > > void setTrainingSamples(Tensor trainingSamples) { if (!(Util.getTypeFromInterval(trainingSamples.getData()) instanceof FloatType)) { From 684b29ad9749e6a5abc018e60e4eb830b79a9cd8 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 14:23:50 +0200 Subject: [PATCH 063/235] improve python code for fine tuning --- .../stardist_fine_tune/stardist_fine_tune.py | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/python/ops/stardist_fine_tune/stardist_fine_tune.py b/python/ops/stardist_fine_tune/stardist_fine_tune.py index 8c5d7cbf..79f554ae 100644 --- a/python/ops/stardist_fine_tune/stardist_fine_tune.py +++ b/python/ops/stardist_fine_tune/stardist_fine_tune.py @@ -3,12 +3,14 @@ import os import shutil +import os + def assertions(model, images, ground_truth, new_model_dir): assert isinstance(model, str), "The input argument 'model' must be a string, either the name" \ + " of one of the default pre-trained Stardist models or the directory to a pre-trained Stardist model" - + assert isinstance(new_model_dir, str), "The input argument 'new_model_dir' must be a string. It is the path" \ + " where the fine tuned stardist model will be saved." @@ -18,18 +20,18 @@ def assertions(model, images, ground_truth, new_model_dir): assert images.ndim == 4, "the training samples array must have 4 dimensions" assert ground_truth.ndim == 4, "the training samples array must have 4 dimensions" - assert "".join(images.dims) == "bcyx", "the training samples axes order should be 'bcyx', not '" + "".join(images.dims) + "' as provided." - assert "".join(ground_truth.dims) == "bcyx", "the ground truth samples axes order should be 'bcyx', not '" + "".join(ground_truth.dims) + "' as provided." + assert "".join(images.dims) == "bxyc", "the training samples axes order should be 'bxyc', not '" + "".join(images.dims) + "' as provided." + assert "".join(ground_truth.dims) == "bxy", "the ground truth samples axes order should be 'bxy', not '" + "".join(ground_truth.dims) + "' as provided." - axes_dict = {"batch size": 0, "width": 3, "height": 2} + axes_dict = {"batch size": 0, "width": 1, "height": 2} for ks, vs in axes_dict.items(): assert images.shape[vs] == ground_truth.shape[vs], "The training samples " \ - + "and the ground truth need to have the same " + ks + " : " + + "and the ground truth need to have the same " + ks + " : " + images.shape[vs] + " vs " + ground_truth.shape[vs] -def finetune_stardist(model, images, ground_truth, new_model_dir, epochs=5, lr=1e-5, batch_size=16): +def finetune_stardist(model, images, ground_truth, new_model_dir): """ model: String, path to pretrained model or pretrained model from the stardsit available images: list of tensors or single tensor? If a list of tensors, it would need to be ensured taht they all have same dims, @@ -42,16 +44,13 @@ def finetune_stardist(model, images, ground_truth, new_model_dir, epochs=5, lr=1 epochs and batch_size might have a warning for CPu if selected too large """ assertions(model, images, ground_truth, new_model_dir) - if () model = StarDist2D(None, model) - # change some training params - model.config.train_patch_size = (images.shape["width"], images.shape["height"]) - model.config.train_batch_size = images.shape["batch size"] - model.config.train_learning_rate = lr - model.config.train_epochs = epochs # finetune on new data history = model.train(X,Y, validation_data=(X,Y)) + model.keras_model.save("test.h5") + model.export_TF() + return history.loss, history.rest_losses \ No newline at end of file From f067756358592fa8e6645b02f1a9b700bbb20a43 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 16:04:09 +0200 Subject: [PATCH 064/235] design the structure of finetuning --- .../runmode/ops/StardistFineTuneJdllOp.java | 168 ++++++++++++------ 1 file changed, 116 insertions(+), 52 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index a70fb78d..ea3ca265 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -29,14 +29,12 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import org.yaml.snakeyaml.Yaml; - import io.bioimage.modelrunner.bioimageio.BioimageioRepo; import io.bioimage.modelrunner.bioimageio.description.ModelDescriptor; import io.bioimage.modelrunner.bioimageio.download.DownloadModel; @@ -70,6 +68,8 @@ public class StardistFineTuneJdllOp implements OpInterface { private String model; + private String nModelParentPath; + private String nModelPath; private int nChannelsModel; @@ -92,17 +92,17 @@ public class StardistFineTuneJdllOp implements OpInterface { private LinkedHashMap inputsMap; - private static final List PRETRAINED_3C_STARDIST_MODELS; + private static final Map PRETRAINED_3C_STARDIST_MODELS; static { - PRETRAINED_3C_STARDIST_MODELS = new ArrayList(); - PRETRAINED_3C_STARDIST_MODELS.add("2D_versatile_fluo"); - PRETRAINED_3C_STARDIST_MODELS.add("2D_paper_dsb2018"); + PRETRAINED_3C_STARDIST_MODELS = new HashMap(); + PRETRAINED_3C_STARDIST_MODELS.put("2D_versatile_fluo", "fearless-crab"); + PRETRAINED_3C_STARDIST_MODELS.put("2D_paper_dsb2018", null); } - private static final List PRETRAINED_1C_STARDIST_MODELS; + private static final Map PRETRAINED_1C_STARDIST_MODELS; static { - PRETRAINED_1C_STARDIST_MODELS = new ArrayList(); - PRETRAINED_1C_STARDIST_MODELS.add("2D_versatile_he"); + PRETRAINED_1C_STARDIST_MODELS = new HashMap(); + PRETRAINED_1C_STARDIST_MODELS.put("2D_versatile_he", "chatty-frog"); } private final static String STARDIST_CONFIG_KEY = "config"; @@ -131,9 +131,11 @@ public class StardistFineTuneJdllOp implements OpInterface { private static final String STARDIST_WEIGHTS_FILE = "stardist_weights.h5"; + private static final String KERAS_SUFFIX_FILE = ".h5"; + private final static String DOWNLOAD_STARDIST_KEY = "download_pretrained_stardist"; - private static final String OP_METHOD_NAME = "stardist_prediction_2d_mine"; + private static final String OP_METHOD_NAME = "finetune_stardist"; private static final int N_STARDIST_OUTPUTS = 1; @@ -155,15 +157,51 @@ public class StardistFineTuneJdllOp implements OpInterface { * @param modelToFineTune * Pre-trained model that is going to be fine tuned on the user's data, it * can be either a model existing in the users machine or a model existing in the model - * zoo. If it is a model existing in th emodel zoo, it will have to be downloaded first. + * zoo. If it is a model existing in the model zoo, it will have to be downloaded first. * @param newModelDir - * directory where the new model will be saved + * directory where the new finetuned model folder will be saved. + * @return a JDLL OP that can be used together with {@link RunMode} to fine tune a StarDist + * model on the user's data + * @throws InterruptedException + * @throws IOException + * @throws Exception + */ + public StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, String newModelDir) throws IOException, InterruptedException, Exception { + Objects.requireNonNull(modelToFineTune, ""); + Objects.requireNonNull(modelToFineTune, ""); + StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); + op.nModelParentPath = newModelDir; + op.setModel(modelToFineTune); + try { + op.findNChannels(); + } catch (Exception e) { + throw new IllegalArgumentException("Unable to correctly read the rdf.yaml file " + + "of Bioimage.io StarDist model at :" + this.model, e); + } + return op; + } + + /** + * Create a JDLL OP to fine tune a stardist model with the wanted data. + * In order to set the data we want to fine tune the model on, use {@link #setFineTuningData(List, List)} + * or {@link #setFineTuningData(Tensor, Tensor)}. The batch size and learning rates + * can also be modified by with {@link #setBatchSize(int)} and {@link #setLearingRate(float)}. + * By default the batch size is 16 and the learning rate 1e-5. + * To set the number of epochs: {@link #setEpochs(int)}, default is 1. + * @param modelToFineTune + * Pre-trained model that is going to be fine tuned on the user's data, it + * can be either a model existing in the users machine or a model existing in the model + * zoo. If it is a model existing in the model zoo, it will have to be downloaded first. * @return a JDLL OP that can be used together with {@link RunMode} to fine tune a StarDist * model on the user's data + * @throws InterruptedException + * @throws IOException + * @throws Exception */ - public StardistFineTuneJdllOp create(String modelToFineTune, String newModelDir) { + public StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) throws IOException, InterruptedException, Exception { + Objects.requireNonNull(modelToFineTune, ""); StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); - op.nModelPath = newModelDir; + op.nModelParentPath = newModelDir; op.setModel(modelToFineTune); try { op.findNChannels(); @@ -180,7 +218,7 @@ void setFineTuningData(List> trainingSamples, List> groundTr } public < T extends RealType< T > & NativeType< T > > - void setFineTuningData(Tensor trainingSamples, Tensor groundTruth) { + void setFineTuningData(Tensor trainingSamples, Tensor groundTruth) throws IOException, Exception { checkTrainAndGroundTruthDimensions(trainingSamples, groundTruth); setTrainingSamples(trainingSamples); setGroundTruth(groundTruth); @@ -232,9 +270,6 @@ public LinkedHashMap getOpInputs() { inputsMap.put(NEW_MODEL_DIR_KEY, this.nModelPath); inputsMap.put(TRAIN_SAMPLES_KEY, this.trainingSamples); inputsMap.put(GROUND_TRUTH_KEY, this.groundTruth); - inputsMap.put(BATCH_SIZE_KEY, this.batchSize); - inputsMap.put(LR_KEY, this.lr); - inputsMap.put(EPOCHS_KEY, this.epochs); inputsMap.put(DOWNLOAD_STARDIST_KEY, this.downloadStardistPretrained); return inputsMap; } @@ -254,11 +289,13 @@ public String getOpDir() { return opFilePath; } - public void setModel(String modelName) throws IllegalArgumentException { + public void setModel(String modelName) throws IOException, InterruptedException, Exception { Objects.requireNonNull(modelName, "The modelName input argument cannot be null."); - if (PRETRAINED_1C_STARDIST_MODELS.contains(modelName) || PRETRAINED_3C_STARDIST_MODELS.contains(modelName)) { + if (PRETRAINED_1C_STARDIST_MODELS.keySet().contains(modelName) + || PRETRAINED_3C_STARDIST_MODELS.keySet().contains(modelName)) { this.model = modelName; this.downloadStardistPretrained = true; + setUpStardistModelFromStardistRepo(); return; } if (new File(modelName).isFile() && !StardistInferJdllOp.isModelFileStardist(modelName)) @@ -267,17 +304,36 @@ public void setModel(String modelName) throws IllegalArgumentException { else if (!(new File(modelName).isFile()) && !StardistInferJdllOp.isModelNameStardist(modelName)) throw new IllegalArgumentException("The model name provided does not correspond to a valid" + " Stardist model present in the Bioimage.io online reposritory."); + else if (!(new File(modelName).isFile())) + setUpStardistModelFromBioimageio(); this.model = modelName; } - private void setUpStardistModelFromBioimageio() throws IOException, InterruptedException { + private void setUpStardistModelFromStardistRepo() throws IOException, InterruptedException, Exception { + if (PRETRAINED_1C_STARDIST_MODELS.get(model) != null) { + model = PRETRAINED_1C_STARDIST_MODELS.get(model); + setUpStardistModelFromBioimageio(); + } else if (PRETRAINED_3C_STARDIST_MODELS.get(model) != null) { + model = PRETRAINED_3C_STARDIST_MODELS.get(model); + setUpStardistModelFromBioimageio(); + } else { + // TODO what to do with 2D_paper_dsb2018 and DEMO model (they dont have model card) + // TODO what to do with 2D_paper_dsb2018 and DEMO model (they dont have model card) + // TODO what to do with 2D_paper_dsb2018 and DEMO model (they dont have model card) + // TODO what to do with 2D_paper_dsb2018 and DEMO model (they dont have model card) + // TODO what to do with 2D_paper_dsb2018 and DEMO model (they dont have model card) + // TODO what to do with 2D_paper_dsb2018 and DEMO model (they dont have model card) + } + } + + private void setUpStardistModelFromBioimageio() throws IOException, InterruptedException, Exception { BioimageioRepo br = BioimageioRepo.connect(); if (br.selectByName(model) != null) { - model = br.downloadByName(model, nModelPath); + model = br.downloadByName(model, nModelParentPath); } else if (br.selectByID(model) != null) { - model = br.downloadModelByID(model, nModelPath); + model = br.downloadModelByID(model, nModelParentPath); } else if (br.selectByNickname(model) != null) { - model = br.downloadByNickame(model, nModelPath); + model = br.downloadByNickame(model, nModelParentPath); } File folder = new File(model); String fineTuned = folder.getParent() + File.separator + "finetuned_" + folder.getName(); @@ -307,7 +363,6 @@ private void setUpConfigs() throws IOException, Exception { throw new IOException("Missing necessary file for StarDist: " + THRES_JSON); } else { Map config = YAMLUtils.load(model + File.separator + CONFIG_JSON); - Map thres = YAMLUtils.load(model + File.separator + THRES_JSON); int w = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("x")]; int h = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("y")]; config.put(PATCH_SIZE_KEY, new int[] {w, h}); @@ -318,6 +373,7 @@ private void setUpConfigs() throws IOException, Exception { } } + @SuppressWarnings("unchecked") private void setUpConfigsBioimageio() throws IOException, Exception { ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(this.model + File.separator + Constants.RDF_FNAME); Object stardistInfo = descriptor.getConfig().getSpecMap().get(StardistInferJdllOp.STARDIST_FIELD_KEY); @@ -368,6 +424,7 @@ private void setUpKerasWeights() throws IOException, Exception { downloadFileFromInternet(getKerasWeigthsLink(descriptor), new File(stardistWeights)); } + @SuppressWarnings("unchecked") private static String getKerasWeigthsLink(ModelDescriptor descriptor) throws IOException { Object yamlFiles = descriptor.getAttachments().get("files"); if (yamlFiles == null || !(yamlFiles instanceof List)) @@ -391,31 +448,31 @@ private void setUpStardistModelFromLocal() { private < T extends RealType< T > & NativeType< T > > void checkTrainAndGroundTruthDimensions(Tensor trainingSamples, Tensor groundTruth) { - String axes = trainingSamples.getAxesOrderString(); - if (axes.length() != STARDIST_2D_AXES.length()) - throw new IllegalArgumentException("Training sample tensors should have for dimensions (" - + STARDIST_2D_AXES + "), but it has " + axes.length() + " (" + axes + ")."); - for (int c = 0; c < STARDIST_2D_AXES.length(); c ++) { - int trueInd = STARDIST_2D_AXES.indexOf(STARDIST_2D_AXES.split("")[c]); - if (trueInd == -1) - throw new IllegalArgumentException("The training samples provided should have dimension '" - + STARDIST_2D_AXES.split("")[c] + "' in the axes order, but it does not (" + axes + ")."); - else if (trueInd == c) { - c ++; - continue; - } - IntervalView wrapImg = Views.permute(trainingSamples.getData(), trueInd, c); - trainingSamples = Tensor.build(trainingSamples.getName(), axes, wrapImg); - c = 0; - } - - // TODO check that train and ground truth have the same - if + checkTrainingSamplesTensorDimsForStardist(trainingSamples); + checkGroundTruthTensorDimsForStardist(groundTruth); + + int trW = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("x")]; + int trH = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("y")]; + int trB = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("b")]; + int gtW = groundTruth.getShape()[groundTruth.getAxesOrderString().indexOf("x")]; + int gtH = groundTruth.getShape()[groundTruth.getAxesOrderString().indexOf("y")]; + int gtB = groundTruth.getShape()[groundTruth.getAxesOrderString().indexOf("b")]; + + if (gtW != trW) + throw new IllegalArgumentException("Training samples (" + trW + ") and ground truth (" + + gtW + ") width (x-axis) must be the same."); + if (trH != gtH) + throw new IllegalArgumentException("Training samples (" + trH + ") and ground truth (" + + gtH + ") height (y-axis) must be the same."); + if (trB != gtB) + throw new IllegalArgumentException("Training samples (" + trB + ") and ground truth (" + + gtB + ") batch size (b-axis) must be the same."); + } private static < T extends RealType< T > & NativeType< T > > - void checkTrainingSamplesTensorDimsForStardist(Tensor trainingSamples) { + void checkTrainingSamplesTensorDimsForStardist(Tensor trainingSamples) { String axes = trainingSamples.getAxesOrderString(); String stardistAxes = STARDIST_2D_AXES; if (axes.length() == 5) @@ -428,7 +485,7 @@ else if (axes.length() < 5) } private static < T extends RealType< T > & NativeType< T > > - void checkGroundTruthTensorDimsForStardist(Tensor gt) { + void checkGroundTruthTensorDimsForStardist(Tensor gt) { String axes = gt.getAxesOrderString(); String stardistAxes = GROUNDTRUTH_AXES; if (axes.length() != GROUNDTRUTH_AXES.length()) @@ -439,7 +496,7 @@ void checkGroundTruthTensorDimsForStardist(Tensor gt) { } private static < T extends RealType< T > & NativeType< T > > - void checkDimOrderAndTranspose(Tensor tensor, String stardistAxes, String errMsgObject) { + void checkDimOrderAndTranspose(Tensor tensor, String stardistAxes, String errMsgObject) { for (int c = 0; c < stardistAxes.length(); c ++) { String axes = tensor.getAxesOrderString(); int trueInd = axes.indexOf(stardistAxes.split("")[c]); @@ -459,15 +516,22 @@ else if (trueInd == c) { } } + @SuppressWarnings("unchecked") private < T extends RealType< T > & NativeType< T > > void setTrainingSamples(Tensor trainingSamples) { - if (!(Util.getTypeFromInterval(trainingSamples.getData()) instanceof FloatType)) { + int tensorChannels = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("c")]; + if (nChannelsModel != tensorChannels) + throw new IllegalArgumentException("The pre-trained selected model only supports " + + nChannelsModel + "-channel inputs whereas the provided training input tensor " + + "has " + tensorChannels + " channels."); + if (!(Util.getTypeFromInterval(trainingSamples.getData()) instanceof FloatType)) { this.trainingSamples = Tensor.createCopyOfTensorInWantedDataType(trainingSamples, new FloatType()); } else { this.trainingSamples = (Tensor) trainingSamples; } } + @SuppressWarnings("unchecked") private < T extends RealType< T > & NativeType< T > > void setGroundTruth(Tensor groundTruth) { if (!(Util.getTypeFromInterval(groundTruth.getData()) instanceof UnsignedShortType)) { @@ -478,9 +542,9 @@ void setGroundTruth(Tensor groundTruth) { } private void findNChannels() throws Exception { - if (this.downloadStardistPretrained && PRETRAINED_1C_STARDIST_MODELS.contains(this.model)) { + if (this.downloadStardistPretrained && PRETRAINED_1C_STARDIST_MODELS.keySet().contains(this.model)) { this.nChannelsModel = 1; - } else if (this.downloadStardistPretrained && PRETRAINED_3C_STARDIST_MODELS.contains(this.model)) { + } else if (this.downloadStardistPretrained && PRETRAINED_3C_STARDIST_MODELS.keySet().contains(this.model)) { this.nChannelsModel = 3; } ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(model, false); From 15e08560d2a87527ff580341ebe4cf77a49db8e8 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 16:44:01 +0200 Subject: [PATCH 065/235] try to get prototype ready --- .../stardist_fine_tune/stardist_fine_tune.py | 6 ++-- .../runmode/ops/StardistFineTuneJdllOp.java | 33 +++++++++++-------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/python/ops/stardist_fine_tune/stardist_fine_tune.py b/python/ops/stardist_fine_tune/stardist_fine_tune.py index 79f554ae..7d0d53b2 100644 --- a/python/ops/stardist_fine_tune/stardist_fine_tune.py +++ b/python/ops/stardist_fine_tune/stardist_fine_tune.py @@ -4,6 +4,7 @@ import os import shutil import os +from pathlib import Path def assertions(model, images, ground_truth, new_model_dir): @@ -50,7 +51,8 @@ def finetune_stardist(model, images, ground_truth, new_model_dir): # finetune on new data history = model.train(X,Y, validation_data=(X,Y)) - model.keras_model.save("test.h5") - model.export_TF() + Path(new_model_dir).mkdir(parents=True, exist_ok=True) + model.keras_model.save(new_model_dir) + model.export_TF(os.path.join(os.path.dirname(new_model_dir), "tf_weights.zip")) return history.loss, history.rest_losses \ No newline at end of file diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index ea3ca265..2b0b2b93 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -139,7 +139,7 @@ public class StardistFineTuneJdllOp implements OpInterface { private static final int N_STARDIST_OUTPUTS = 1; - private static final String STARDIST_OP_FNAME = "stardist_inference.py"; + private static final String STARDIST_OP_FNAME = "stardist_fine_tune.py"; private static final String STARDIST_2D_AXES = "bxyc"; @@ -167,8 +167,10 @@ public class StardistFineTuneJdllOp implements OpInterface { * @throws Exception */ public StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, String newModelDir) throws IOException, InterruptedException, Exception { - Objects.requireNonNull(modelToFineTune, ""); - Objects.requireNonNull(modelToFineTune, ""); + Objects.requireNonNull(modelToFineTune, "modelToFineTune' cannot be null. It should correspond to either a Bioimage.io " + + "folder containing a StarDist model, the nickname of a StarDist model in the Bioimage.io (example: chatty-frog) " + + "or to one if the StarDist pre-trained available weigths (example: )"); + Objects.requireNonNull(newModelDir, ""); StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); op.nModelParentPath = newModelDir; op.setModel(modelToFineTune); @@ -182,7 +184,8 @@ public StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, Strin } /** - * Create a JDLL OP to fine tune a stardist model with the wanted data. + * Create a JDLL OP to fine tune a stardist model with the wanted data inplace. + * The model created overwrites the weights of the pre-trained model used for finetuning. * In order to set the data we want to fine tune the model on, use {@link #setFineTuningData(List, List)} * or {@link #setFineTuningData(Tensor, Tensor)}. The batch size and learning rates * can also be modified by with {@link #setBatchSize(int)} and {@link #setLearingRate(float)}. @@ -201,7 +204,6 @@ public StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, Strin public StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) throws IOException, InterruptedException, Exception { Objects.requireNonNull(modelToFineTune, ""); StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); - op.nModelParentPath = newModelDir; op.setModel(modelToFineTune); try { op.findNChannels(); @@ -257,7 +259,7 @@ public boolean isOpInstalled() { public void installOp() { // TODO this method checks if the OP file is at its correponding folder. // TODO if not unpack the python file and located (where??) - opFilePath = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\python\\ops\\stardist_inference"; + opFilePath = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\python\\ops\\\\stardist_fine_tune"; // TODO check if the env has also been created // TODO if not create it (where??) envPath = "C:\\Users\\angel\\git\\jep\\miniconda\\envs\\stardist"; @@ -267,10 +269,10 @@ public void installOp() { public LinkedHashMap getOpInputs() { inputsMap = new LinkedHashMap(); inputsMap.put(MODEL_KEY, this.model); - inputsMap.put(NEW_MODEL_DIR_KEY, this.nModelPath); inputsMap.put(TRAIN_SAMPLES_KEY, this.trainingSamples); inputsMap.put(GROUND_TRUTH_KEY, this.groundTruth); - inputsMap.put(DOWNLOAD_STARDIST_KEY, this.downloadStardistPretrained); + inputsMap.put(NEW_MODEL_DIR_KEY, this.nModelPath); + // TODO remove inputsMap.put(DOWNLOAD_STARDIST_KEY, this.downloadStardistPretrained); return inputsMap; } @@ -340,11 +342,13 @@ private void setUpStardistModelFromBioimageio() throws IOException, InterruptedE File renamedFolder = new File(fineTuned); if (folder.renameTo(renamedFolder)) model = fineTuned; + this.nModelPath = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; downloadBioimageioStardistWeights(); } private void downloadBioimageioStardistWeights() throws IllegalArgumentException, IOException, Exception { + File stardistSubfolder = new File(this.model, StardistInferJdllOp.STARDIST_FIELD_KEY); if (!stardistSubfolder.exists()) { if (!stardistSubfolder.mkdirs()) { @@ -395,15 +399,14 @@ private void setUpConfigsBioimageio() throws IOException, Exception { + "model at: " + this.model + " is invalid. The field config>stardist>" + STARDIST_THRES_KEY + " is missing." + " Look for StarDist models in the Bioimage.io repo to see how the rdf.yaml should look like."); } - String subfolder = this.model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; int w = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("x")]; int h = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("y")]; ((Map) config).put(PATCH_SIZE_KEY, new int[] {w, h}); ((Map) config).put(BATCH_SIZE_KEY, this.batchSize); ((Map) config).put(LR_KEY, this.lr); ((Map) config).put(EPOCHS_KEY, this.epochs); - YAMLUtils.writeYamlFile(subfolder + File.separator + CONFIG_JSON, (Map) config); - YAMLUtils.writeYamlFile(opFilePath + File.separator + THRES_JSON, (Map) thres); + YAMLUtils.writeYamlFile(model + File.separator + CONFIG_JSON, (Map) config); + YAMLUtils.writeYamlFile(model + File.separator + THRES_JSON, (Map) thres); } private void setUpKerasWeights() throws IOException, Exception { @@ -411,9 +414,10 @@ private void setUpKerasWeights() throws IOException, Exception { ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfYamlFN); String stardistWeights = this.model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; stardistWeights += File.separator + STARDIST_WEIGHTS_FILE; - if (new File(stardistWeights).exists()) - return; String stardistWeightsParent = this.model + File.separator + STARDIST_WEIGHTS_FILE; + model = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; + if (new File(stardistWeights).exists()) + return; if (new File(stardistWeights).exists()) { try { Files.copy(Paths.get(stardistWeightsParent), Paths.get(stardistWeights), StandardCopyOption.REPLACE_EXISTING); @@ -547,7 +551,8 @@ private void findNChannels() throws Exception { } else if (this.downloadStardistPretrained && PRETRAINED_3C_STARDIST_MODELS.keySet().contains(this.model)) { this.nChannelsModel = 3; } - ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(model, false); + String rdfFileName = new File(model).getParentFile() + File.separator + Constants.RDF_FNAME; + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfFileName, false); int cInd = descriptor.getInputTensors().get(0).getAxesOrder().indexOf("c"); nChannelsModel = descriptor.getInputTensors().get(0).getShape().getPatchMinimumSize()[cInd]; } From 0258107a6edddc742af8f8e0d7a763979b44e481 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 16:50:16 +0200 Subject: [PATCH 066/235] correct small errors --- .../runmode/ops/StardistFineTuneJdllOp.java | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 2b0b2b93..c10eb771 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -39,9 +39,13 @@ import io.bioimage.modelrunner.bioimageio.description.ModelDescriptor; import io.bioimage.modelrunner.bioimageio.download.DownloadModel; import io.bioimage.modelrunner.engine.installation.FileDownloader; +import io.bioimage.modelrunner.runmode.RunMode; import io.bioimage.modelrunner.tensor.Tensor; import io.bioimage.modelrunner.utils.Constants; import io.bioimage.modelrunner.utils.YAMLUtils; +import net.imglib2.img.Img; +import net.imglib2.img.ImgFactory; +import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.UnsignedShortType; @@ -141,11 +145,25 @@ public class StardistFineTuneJdllOp implements OpInterface { private static final String STARDIST_OP_FNAME = "stardist_fine_tune.py"; - private static final String STARDIST_2D_AXES = "bxyc"; + private static final String STARDIST_2D_AXES = "byxc"; - private static final String STARDIST_3D_AXES = "bxyzc"; + private static final String STARDIST_3D_AXES = "bzyxc"; - private static final String GROUNDTRUTH_AXES = "bxy"; + private static final String GROUNDTRUTH_AXES = "byx"; + + + public static void main(String[] args) throws IOException, InterruptedException, Exception { + final ImgFactory< FloatType > imgFactory = new ArrayImgFactory<>( new FloatType() ); + final Img< FloatType > img1 = imgFactory.create( 2, 64, 64, 3 ); + final ImgFactory< FloatType > gtFactory = new ArrayImgFactory<>( new FloatType() ); + final Img< FloatType > gt = gtFactory.create( 2, 64, 64 ); + Tensor inpTensor = Tensor.build("input0", "bxy", img1); + String modelName = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models"; + StardistFineTuneJdllOp op = finetuneAndCreateNew("chatty-frog", modelName); + RunMode rm = RunMode.createRunMode(op); + Map aa = rm.runOP(); + System.out.print(false); + } /** * Create a JDLL OP to fine tune a stardist model with the wanted data. @@ -166,7 +184,7 @@ public class StardistFineTuneJdllOp implements OpInterface { * @throws IOException * @throws Exception */ - public StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, String newModelDir) throws IOException, InterruptedException, Exception { + public static StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, String newModelDir) throws IOException, InterruptedException, Exception { Objects.requireNonNull(modelToFineTune, "modelToFineTune' cannot be null. It should correspond to either a Bioimage.io " + "folder containing a StarDist model, the nickname of a StarDist model in the Bioimage.io (example: chatty-frog) " + "or to one if the StarDist pre-trained available weigths (example: )"); @@ -178,7 +196,7 @@ public StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, Strin op.findNChannels(); } catch (Exception e) { throw new IllegalArgumentException("Unable to correctly read the rdf.yaml file " - + "of Bioimage.io StarDist model at :" + this.model, e); + + "of Bioimage.io StarDist model at :" + new File(op.model).getParent(), e); } return op; } @@ -201,7 +219,7 @@ public StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, Strin * @throws IOException * @throws Exception */ - public StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) throws IOException, InterruptedException, Exception { + public static StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) throws IOException, InterruptedException, Exception { Objects.requireNonNull(modelToFineTune, ""); StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); op.setModel(modelToFineTune); @@ -209,7 +227,7 @@ public StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) throws IOE op.findNChannels(); } catch (Exception e) { throw new IllegalArgumentException("Unable to correctly read the rdf.yaml file " - + "of Bioimage.io StarDist model at :" + this.model, e); + + "of Bioimage.io StarDist model at :" + new File(op.model).getParent(), e); } return op; } From 528250f2200e972b87ca26dfb2565ddcac871abc Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 16:57:39 +0200 Subject: [PATCH 067/235] add robustness --- .../bioimage/modelrunner/runmode/ops/OpInterface.java | 4 +++- .../runmode/ops/StardistFineTuneJdllOp.java | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java index 01cdd99b..18290b56 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java @@ -19,6 +19,7 @@ */ package io.bioimage.modelrunner.runmode.ops; +import java.io.IOException; import java.util.LinkedHashMap; /** @@ -51,8 +52,9 @@ public interface OpInterface { * Get a LinkedHashMap contianing the inputs defined for the OP * @return an ordered map with the inputs to the OP, where the key * is the variable name and the object is the variable + * @throws Exception if there is any error handling the inputs to the Python OP */ - public LinkedHashMap getOpInputs(); + public LinkedHashMap getOpInputs() throws Exception ; /** * Get the Conda env needed to run the OP * diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index c10eb771..b312585b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -155,11 +155,16 @@ public class StardistFineTuneJdllOp implements OpInterface { public static void main(String[] args) throws IOException, InterruptedException, Exception { final ImgFactory< FloatType > imgFactory = new ArrayImgFactory<>( new FloatType() ); final Img< FloatType > img1 = imgFactory.create( 2, 64, 64, 3 ); + Tensor inpTensor = Tensor.build("input0", "byxc", img1); final ImgFactory< FloatType > gtFactory = new ArrayImgFactory<>( new FloatType() ); final Img< FloatType > gt = gtFactory.create( 2, 64, 64 ); - Tensor inpTensor = Tensor.build("input0", "bxy", img1); + Tensor gtTensor = Tensor.build("gt", "byx", gt); String modelName = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models"; StardistFineTuneJdllOp op = finetuneAndCreateNew("chatty-frog", modelName); + op.setBatchSize(2); + op.setEpochs(2); + op.setFineTuningData(inpTensor, gtTensor); + op.setLearingRate((float) 1e-5); RunMode rm = RunMode.createRunMode(op); Map aa = rm.runOP(); System.out.print(false); @@ -242,7 +247,6 @@ void setFineTuningData(Tensor trainingSamples, Tensor groundTruth) throws checkTrainAndGroundTruthDimensions(trainingSamples, groundTruth); setTrainingSamples(trainingSamples); setGroundTruth(groundTruth); - setUpConfigs(); } public void setBatchSize(int batchSize) { @@ -284,13 +288,14 @@ public void installOp() { } @Override - public LinkedHashMap getOpInputs() { + public LinkedHashMap getOpInputs() throws IOException, Exception { inputsMap = new LinkedHashMap(); inputsMap.put(MODEL_KEY, this.model); inputsMap.put(TRAIN_SAMPLES_KEY, this.trainingSamples); inputsMap.put(GROUND_TRUTH_KEY, this.groundTruth); inputsMap.put(NEW_MODEL_DIR_KEY, this.nModelPath); // TODO remove inputsMap.put(DOWNLOAD_STARDIST_KEY, this.downloadStardistPretrained); + setUpConfigs(); return inputsMap; } From 50adc0e119351935527405fa472a0677e91f2b00 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 17:00:50 +0200 Subject: [PATCH 068/235] increase robustness to possible errors in the inputs to the service --- .../io/bioimage/modelrunner/runmode/RunMode.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 4f20a499..4b735a88 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -80,12 +80,16 @@ public class RunMode { private String moduleName; List outputNames = new ArrayList(); - private RunMode(OpInterface op) { + private RunMode(OpInterface op) throws Exception { this.op = op; this.moduleName = op.getOpPythonFilename().substring(0, op.getOpPythonFilename().length() - 3); IntStream.range(0, op.getNumberOfOutputs()).forEach(i -> outputNames.add("output" + i)); addImports(); - convertInputMap(); + try { + convertInputMap(); + } catch (Exception e) { + throw new Exception("Error unpacking the Java inputs into the Python Appose process.", e); + } opExecutionCode(); retrieveResultsCode(); @@ -98,7 +102,7 @@ private RunMode(OpInterface op) { System.out.println(opCode); } - public static RunMode createRunMode(OpInterface op) { + public static RunMode createRunMode(OpInterface op) throws Exception { return new RunMode(op); } @@ -192,8 +196,10 @@ private void addImports() { + "task.update('Imports')" + System.lineSeparator(); } - private < T extends RealType< T > & NativeType< T > > void convertInputMap() { + private < T extends RealType< T > & NativeType< T > > void convertInputMap() throws Exception { apposeInputMap = new LinkedHashMap<>(); + if (op.getOpInputs() == null) + return; for (Entry entry : this.op.getOpInputs().entrySet()) { if (entry.getValue() instanceof String) { apposeInputMap.put(entry.getKey(), entry.getValue()); From 989dab77981c64a55ce263706ee34db0ee4d3bf7 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 17:04:41 +0200 Subject: [PATCH 069/235] keep improving robustness --- .../modelrunner/runmode/ops/StardistFineTuneJdllOp.java | 8 +++++++- .../modelrunner/runmode/ops/StardistInferJdllOp.java | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index b312585b..42c41dd7 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -288,9 +288,15 @@ public void installOp() { } @Override - public LinkedHashMap getOpInputs() throws IOException, Exception { + public LinkedHashMap getOpInputs() throws Exception { inputsMap = new LinkedHashMap(); + Objects.requireNonNull(trainingSamples, "Please make sure that the training samples have " + + "been provided and that they are not null.Use the method: " + + "setFineTuningData(Tensor trainingSamples, Tensor groundTruth)"); inputsMap.put(MODEL_KEY, this.model); + Objects.requireNonNull(groundTruth, "Please make sure that the ground truth has " + + "been provided and that it is not null.Use the method: " + + "setFineTuningData(Tensor trainingSamples, Tensor groundTruth)"); inputsMap.put(TRAIN_SAMPLES_KEY, this.trainingSamples); inputsMap.put(GROUND_TRUTH_KEY, this.groundTruth); inputsMap.put(NEW_MODEL_DIR_KEY, this.nModelPath); diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java index 3ff8894e..737c1909 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistInferJdllOp.java @@ -69,7 +69,7 @@ public class StardistInferJdllOp implements OpInterface { private static final String STARDIST_OP_FNAME = "stardist_inference.py"; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { final ImgFactory< FloatType > imgFactory = new ArrayImgFactory<>( new FloatType() ); final Img< FloatType > img1 = imgFactory.create( 1, 512, 512, 3 ); Tensor inpTensor = Tensor.build("input0", "byxc", img1); From 655be760993b779577796ec25319ad46eb53bd88 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 17:19:59 +0200 Subject: [PATCH 070/235] correct error finding nickname --- .../bioimageio/description/ModelDescriptor.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/description/ModelDescriptor.java b/src/main/java/io/bioimage/modelrunner/bioimageio/description/ModelDescriptor.java index c855fdcc..04664406 100644 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/description/ModelDescriptor.java +++ b/src/main/java/io/bioimage/modelrunner/bioimageio/description/ModelDescriptor.java @@ -194,9 +194,6 @@ private static ModelDescriptor buildModelDescription(Map yamlEle case "name": modelDescription.name = (String) fieldElement; break; - case "nickname": - modelDescription.nickname = (String) fieldElement; - break; case "timestamp": modelDescription.timestamp = fieldElement.toString(); break; @@ -296,7 +293,9 @@ private static ModelDescriptor buildModelDescription(Map yamlEle throw new IOException("Invalid model element: " + field + "->" + e.getMessage()); } } - + Object bio = modelDescription.config.getSpecMap().get("bioimageio"); + if ((bio != null) && (bio instanceof Map)) + modelDescription.nickname = (String) (((Map) bio).get("nickname")); modelDescription.addBioEngine(); if (modelDescription.localModelPath != null) modelDescription.addModelPath(new File(modelDescription.localModelPath).toPath()); From e87fc81f43b4182409ee2142a74bbff940d8fc57 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 17:33:58 +0200 Subject: [PATCH 071/235] increase robustness --- .../bioimageio/BioimageioRepo.java | 4 ++- .../runmode/ops/StardistFineTuneJdllOp.java | 32 +++++++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java b/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java index 8473a6eb..d7b1f8c3 100644 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java +++ b/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java @@ -399,7 +399,9 @@ public ModelDescriptor selectByID(String modelID) { */ public ModelDescriptor selectByNickname(String nickname) { Entry modelEntry = this.listAllModels(false).entrySet().stream() - .filter(ee -> ee.getValue().getNickname().equals(nickname)).findFirst().orElse(null); + .filter(ee -> ee.getValue().getNickname() != null + && ee.getValue().getNickname().equals(nickname)) + .findFirst().orElse(null); if (modelEntry != null) return modelEntry.getValue(); return null; diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 42c41dd7..a0852428 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -192,11 +192,13 @@ public static void main(String[] args) throws IOException, InterruptedException, public static StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, String newModelDir) throws IOException, InterruptedException, Exception { Objects.requireNonNull(modelToFineTune, "modelToFineTune' cannot be null. It should correspond to either a Bioimage.io " + "folder containing a StarDist model, the nickname of a StarDist model in the Bioimage.io (example: chatty-frog) " - + "or to one if the StarDist pre-trained available weigths (example: )"); - Objects.requireNonNull(newModelDir, ""); + + "or to one if the StarDist pre-trained available weigths (example: 2D_versatile_fluo)"); + Objects.requireNonNull(newModelDir, "newModelDir' cannot be null. It should be a path to the directory where" + + " the we want the fine tuned model to be saved."); StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); op.nModelParentPath = newModelDir; - op.setModel(modelToFineTune); + op.model = modelToFineTune; + op.setModel(); try { op.findNChannels(); } catch (Exception e) { @@ -227,7 +229,8 @@ public static StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune public static StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) throws IOException, InterruptedException, Exception { Objects.requireNonNull(modelToFineTune, ""); StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); - op.setModel(modelToFineTune); + op.model = modelToFineTune; + op.setModel(); try { op.findNChannels(); } catch (Exception e) { @@ -320,24 +323,27 @@ public String getOpDir() { return opFilePath; } - public void setModel(String modelName) throws IOException, InterruptedException, Exception { - Objects.requireNonNull(modelName, "The modelName input argument cannot be null."); - if (PRETRAINED_1C_STARDIST_MODELS.keySet().contains(modelName) - || PRETRAINED_3C_STARDIST_MODELS.keySet().contains(modelName)) { - this.model = modelName; + public void setModel() throws IOException, InterruptedException, Exception { + Objects.requireNonNull(model, "The modelName input argument cannot be null."); + if (PRETRAINED_1C_STARDIST_MODELS.keySet().contains(model) + || PRETRAINED_3C_STARDIST_MODELS.keySet().contains(model)) { this.downloadStardistPretrained = true; setUpStardistModelFromStardistRepo(); return; } - if (new File(modelName).isFile() && !StardistInferJdllOp.isModelFileStardist(modelName)) + if (new File(model).isFile() && !StardistInferJdllOp.isModelFileStardist(model)) throw new IllegalArgumentException("The file selected does not correspond to " + "the rdf.yaml file of a Bioiamge.io Stardist model."); - else if (!(new File(modelName).isFile()) && !StardistInferJdllOp.isModelNameStardist(modelName)) + else if (!(new File(model).isFile()) && !StardistInferJdllOp.isModelNameStardist(model)) throw new IllegalArgumentException("The model name provided does not correspond to a valid" + " Stardist model present in the Bioimage.io online reposritory."); - else if (!(new File(modelName).isFile())) + else if (!(new File(model).isFile())) setUpStardistModelFromBioimageio(); - this.model = modelName; + else + throw new IllegalArgumentException("Cannot recognise the model provided as a StarDist model. " + + "You can provide either the name of a StarDist model in the Bioimage.io, the path" + + " to a Bioimage.io StarDist model (parent dir of the rdf.yaml file) or the name of" + + " a pre-trained StarDist model."); } private void setUpStardistModelFromStardistRepo() throws IOException, InterruptedException, Exception { From 68dae34a9e544b8b0baab91750b8f602aa92520d Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 17:35:26 +0200 Subject: [PATCH 072/235] increase robustness --- .../io/bioimage/modelrunner/bioimageio/BioimageioRepo.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java b/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java index d7b1f8c3..a47d7d5d 100644 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java +++ b/src/main/java/io/bioimage/modelrunner/bioimageio/BioimageioRepo.java @@ -29,6 +29,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Map.Entry; import java.util.function.Consumer; @@ -374,6 +375,7 @@ public static boolean isModelOnTheBioengineById(String id) throws IOException { * @return the {@link ModelDescriptor} of the model */ public ModelDescriptor selectByID(String modelID) { + Objects.requireNonNull(modelID, "Argument 'modelID' cannot be null."); Entry modelEntry = this.listAllModels(false).entrySet().stream() .filter(ee -> { String id = ee.getValue().getModelID(); @@ -398,6 +400,7 @@ public ModelDescriptor selectByID(String modelID) { * @return the {@link ModelDescriptor} of the model */ public ModelDescriptor selectByNickname(String nickname) { + Objects.requireNonNull(nickname, "Argument 'nickname' cannot be null."); Entry modelEntry = this.listAllModels(false).entrySet().stream() .filter(ee -> ee.getValue().getNickname() != null && ee.getValue().getNickname().equals(nickname)) @@ -415,6 +418,7 @@ public ModelDescriptor selectByNickname(String nickname) { * @return the {@link ModelDescriptor} of the model */ public ModelDescriptor selectByName(String name) { + Objects.requireNonNull(name, "Argument 'name' cannot be null."); Entry modelEntry = this.listAllModels(false).entrySet().stream() .filter(ee -> ee.getValue().getName().equals(name)).findFirst().orElse(null); if (modelEntry != null) @@ -431,6 +435,7 @@ public ModelDescriptor selectByName(String name) { * @return the {@link ModelDescriptor} of the model */ public ModelDescriptor selectByRdfSource(String rdfURL) { + Objects.requireNonNull(rdfURL, "Argument 'rdfURL' cannot be null."); Entry modelEntry = this.listAllModels(false).entrySet().stream() .filter(ee -> ee.getValue().getRDFSource().equals(rdfURL)).findFirst().orElse(null); if (modelEntry != null) From 005333cfe185ee5c4bf390ec63ba455a6e6e7517 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 17:55:08 +0200 Subject: [PATCH 073/235] correct small errors at runtime --- .../runmode/ops/StardistFineTuneJdllOp.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index a0852428..a8e09470 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -394,7 +394,8 @@ private void downloadBioimageioStardistWeights() throws IllegalArgumentException } private void setUpConfigs() throws IOException, Exception { - if (new File(model + File.separator + Constants.RDF_FNAME).exists()) { + String rdfDir = new File(model).getParent(); + if (new File(rdfDir + File.separator + Constants.RDF_FNAME).exists()) { setUpConfigsBioimageio(); } else if (!(new File(model + File.separator + CONFIG_JSON).exists())) { throw new IOException("Missing necessary file for StarDist: " + CONFIG_JSON); @@ -414,7 +415,8 @@ private void setUpConfigs() throws IOException, Exception { @SuppressWarnings("unchecked") private void setUpConfigsBioimageio() throws IOException, Exception { - ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(this.model + File.separator + Constants.RDF_FNAME); + String rdfDir = new File(model).getParent(); + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfDir + File.separator + Constants.RDF_FNAME); Object stardistInfo = descriptor.getConfig().getSpecMap().get(StardistInferJdllOp.STARDIST_FIELD_KEY); if (stardistInfo == null || !(stardistInfo instanceof Map)) { @@ -516,7 +518,7 @@ void checkTrainingSamplesTensorDimsForStardist(Tensor trainingSamples) { String stardistAxes = STARDIST_2D_AXES; if (axes.length() == 5) stardistAxes = STARDIST_3D_AXES; - else if (axes.length() < 5) + else if (axes.length() != 5 && axes.length() != 4) throw new IllegalArgumentException("Training input tensors should have 4 dimensions (" + STARDIST_2D_AXES + ") or 5 (" + STARDIST_3D_AXES + "), but it has " + axes.length() + " (" + axes + ")."); @@ -542,10 +544,8 @@ void checkDimOrderAndTranspose(Tensor tensor, String stardistAxes, String err if (trueInd == -1) throw new IllegalArgumentException("The " + errMsgObject + " tensors provided should have dimension '" + stardistAxes.split("")[c] + "' in the axes order, but it does not (" + axes + ")."); - else if (trueInd == c) { - c ++; + else if (trueInd == c) continue; - } IntervalView wrapImg = Views.permute(tensor.getData(), trueInd, c); StringBuilder nAxes = new StringBuilder(axes); nAxes.setCharAt(c, stardistAxes.charAt(c)); From 8e1e8cf1718f43b0809e1cf6b6b06672925834f0 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 17:57:11 +0200 Subject: [PATCH 074/235] avoid unnecessary verbosity --- .../modelrunner/runmode/ops/StardistFineTuneJdllOp.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index a8e09470..4a5130ab 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -416,7 +416,7 @@ private void setUpConfigs() throws IOException, Exception { @SuppressWarnings("unchecked") private void setUpConfigsBioimageio() throws IOException, Exception { String rdfDir = new File(model).getParent(); - ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfDir + File.separator + Constants.RDF_FNAME); + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfDir + File.separator + Constants.RDF_FNAME, false); Object stardistInfo = descriptor.getConfig().getSpecMap().get(StardistInferJdllOp.STARDIST_FIELD_KEY); if (stardistInfo == null || !(stardistInfo instanceof Map)) { @@ -448,7 +448,7 @@ private void setUpConfigsBioimageio() throws IOException, Exception { private void setUpKerasWeights() throws IOException, Exception { String rdfYamlFN = this.model + File.separator + Constants.RDF_FNAME; - ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfYamlFN); + ModelDescriptor descriptor = ModelDescriptor.readFromLocalFile(rdfYamlFN, false); String stardistWeights = this.model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; stardistWeights += File.separator + STARDIST_WEIGHTS_FILE; String stardistWeightsParent = this.model + File.separator + STARDIST_WEIGHTS_FILE; From 3b9b3497a97e9806ca52305794fa282e4f195223 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 18:06:02 +0200 Subject: [PATCH 075/235] add support for more imglib2 datatypes to be sent to ptyhon appose --- .../modelrunner/tensor/ImgLib2ToArray.java | 181 +++++++++++++++++- 1 file changed, 171 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/tensor/ImgLib2ToArray.java b/src/main/java/io/bioimage/modelrunner/tensor/ImgLib2ToArray.java index 7a591625..38fd3efd 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/ImgLib2ToArray.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/ImgLib2ToArray.java @@ -21,8 +21,6 @@ package io.bioimage.modelrunner.tensor; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; import net.imglib2.Cursor; import net.imglib2.RandomAccessibleInterval; @@ -33,7 +31,10 @@ import net.imglib2.type.numeric.integer.ByteType; import net.imglib2.type.numeric.integer.IntType; import net.imglib2.type.numeric.integer.LongType; +import net.imglib2.type.numeric.integer.ShortType; import net.imglib2.type.numeric.integer.UnsignedByteType; +import net.imglib2.type.numeric.integer.UnsignedIntType; +import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.DoubleType; import net.imglib2.type.numeric.real.FloatType; import net.imglib2.util.Util; @@ -90,13 +91,23 @@ public static < T extends RealType< T > & NativeType< T > > Object build(Tensor< public static > Object build(RandomAccessibleInterval rai) { if (Util.getTypeFromInterval(rai) instanceof ByteType) { - return buildByte((RandomAccessibleInterval) rai); + return buildInt8((RandomAccessibleInterval) rai); + } else if (Util.getTypeFromInterval(rai) instanceof UnsignedByteType) { + return buildUint8((RandomAccessibleInterval) rai); + } else if (Util.getTypeFromInterval(rai) instanceof ShortType) { + return buildInt16((RandomAccessibleInterval) rai); + } else if (Util.getTypeFromInterval(rai) instanceof UnsignedShortType) { + return buildUint16((RandomAccessibleInterval) rai); } else if (Util.getTypeFromInterval(rai) instanceof IntType) { - return buildInt((RandomAccessibleInterval) rai); + return buildInt32((RandomAccessibleInterval) rai); + } else if (Util.getTypeFromInterval(rai) instanceof UnsignedIntType) { + return buildUint32((RandomAccessibleInterval) rai); + } else if (Util.getTypeFromInterval(rai) instanceof LongType) { + return buildInt64((RandomAccessibleInterval) rai); } else if (Util.getTypeFromInterval(rai) instanceof FloatType) { - return buildFloat((RandomAccessibleInterval) rai); + return buildFloat32((RandomAccessibleInterval) rai); } else if (Util.getTypeFromInterval(rai) instanceof DoubleType) { - return buildDouble((RandomAccessibleInterval) rai); + return buildFloat64((RandomAccessibleInterval) rai); } else { throw new IllegalArgumentException("The image has an unsupported type: " + Util.getTypeFromInterval(rai).getClass().toString()); } @@ -111,7 +122,7 @@ public static > Object build(RandomAccessibleInterval rai) * @param byteBuffer * target bytebuffer */ - private static byte[] buildByte(RandomAccessibleInterval imgTensor) + private static byte[] buildInt8(RandomAccessibleInterval imgTensor) { Cursor tensorCursor; if (imgTensor instanceof IntervalView) @@ -132,6 +143,96 @@ else if (imgTensor instanceof Img) return byteArr; } + /** + * Adds the ByteType {@link RandomAccessibleInterval} data to the {@link ByteBuffer} provided. + * The position of the ByteBuffer is kept in the same place as it was received. + * + * @param imgTensor + * {@link RandomAccessibleInterval} to be mapped into byte buffer + * @param byteBuffer + * target bytebuffer + */ + private static short[] buildUint8(RandomAccessibleInterval imgTensor) + { + Cursor tensorCursor; + if (imgTensor instanceof IntervalView) + tensorCursor = ((IntervalView) imgTensor).cursor(); + else if (imgTensor instanceof Img) + tensorCursor = ((Img) imgTensor).cursor(); + else + throw new IllegalArgumentException("The data of the " + Tensor.class + " has " + + "to be an instance of " + Img.class + " or " + IntervalView.class); + long flatSize = 1; + for (long ss : imgTensor.dimensionsAsLongArray()) {flatSize *= ss;} + short[] byteArr = new short[(int) flatSize]; + int cc = 0; + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + byteArr[cc ++] = tensorCursor.get().getByte(); + } + return byteArr; + } + + /** + * Adds the ByteType {@link RandomAccessibleInterval} data to the {@link ByteBuffer} provided. + * The position of the ByteBuffer is kept in the same place as it was received. + * + * @param imgTensor + * {@link RandomAccessibleInterval} to be mapped into byte buffer + * @param byteBuffer + * target bytebuffer + */ + private static short[] buildInt16(RandomAccessibleInterval imgTensor) + { + Cursor tensorCursor; + if (imgTensor instanceof IntervalView) + tensorCursor = ((IntervalView) imgTensor).cursor(); + else if (imgTensor instanceof Img) + tensorCursor = ((Img) imgTensor).cursor(); + else + throw new IllegalArgumentException("The data of the " + Tensor.class + " has " + + "to be an instance of " + Img.class + " or " + IntervalView.class); + long flatSize = 1; + for (long ss : imgTensor.dimensionsAsLongArray()) {flatSize *= ss;} + short[] byteArr = new short[(int) flatSize]; + int cc = 0; + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + byteArr[cc ++] = tensorCursor.get().get(); + } + return byteArr; + } + + /** + * Adds the ByteType {@link RandomAccessibleInterval} data to the {@link ByteBuffer} provided. + * The position of the ByteBuffer is kept in the same place as it was received. + * + * @param imgTensor + * {@link RandomAccessibleInterval} to be mapped into byte buffer + * @param byteBuffer + * target bytebuffer + */ + private static int[] buildUint16(RandomAccessibleInterval imgTensor) + { + Cursor tensorCursor; + if (imgTensor instanceof IntervalView) + tensorCursor = ((IntervalView) imgTensor).cursor(); + else if (imgTensor instanceof Img) + tensorCursor = ((Img) imgTensor).cursor(); + else + throw new IllegalArgumentException("The data of the " + Tensor.class + " has " + + "to be an instance of " + Img.class + " or " + IntervalView.class); + long flatSize = 1; + for (long ss : imgTensor.dimensionsAsLongArray()) {flatSize *= ss;} + int[] byteArr = new int[(int) flatSize]; + int cc = 0; + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + byteArr[cc ++] = tensorCursor.get().get(); + } + return byteArr; + } + /** * Adds the IntType {@link RandomAccessibleInterval} data to the {@link ByteBuffer} provided. * The position of the ByteBuffer is kept in the same place as it was received. @@ -141,7 +242,7 @@ else if (imgTensor instanceof Img) * @param byteBuffer * target bytebuffer */ - private static int[] buildInt(RandomAccessibleInterval imgTensor) + private static int[] buildInt32(RandomAccessibleInterval imgTensor) { Cursor tensorCursor; if (imgTensor instanceof IntervalView) @@ -162,6 +263,66 @@ else if (imgTensor instanceof Img) return byteArr; } + /** + * Adds the IntType {@link RandomAccessibleInterval} data to the {@link ByteBuffer} provided. + * The position of the ByteBuffer is kept in the same place as it was received. + * + * @param imgTensor + * {@link RandomAccessibleInterval} to be mapped into byte buffer + * @param byteBuffer + * target bytebuffer + */ + private static long[] buildUint32(RandomAccessibleInterval imgTensor) + { + Cursor tensorCursor; + if (imgTensor instanceof IntervalView) + tensorCursor = ((IntervalView) imgTensor).cursor(); + else if (imgTensor instanceof Img) + tensorCursor = ((Img) imgTensor).cursor(); + else + throw new IllegalArgumentException("The data of the " + Tensor.class + " has " + + "to be an instance of " + Img.class + " or " + IntervalView.class); + long flatSize = 1; + for (long ss : imgTensor.dimensionsAsLongArray()) {flatSize *= ss;} + long[] byteArr = new long[(int) flatSize]; + int cc = 0; + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + byteArr[cc ++] = tensorCursor.get().get(); + } + return byteArr; + } + + /** + * Adds the IntType {@link RandomAccessibleInterval} data to the {@link ByteBuffer} provided. + * The position of the ByteBuffer is kept in the same place as it was received. + * + * @param imgTensor + * {@link RandomAccessibleInterval} to be mapped into byte buffer + * @param byteBuffer + * target bytebuffer + */ + private static long[] buildInt64(RandomAccessibleInterval imgTensor) + { + Cursor tensorCursor; + if (imgTensor instanceof IntervalView) + tensorCursor = ((IntervalView) imgTensor).cursor(); + else if (imgTensor instanceof Img) + tensorCursor = ((Img) imgTensor).cursor(); + else + throw new IllegalArgumentException("The data of the " + Tensor.class + " has " + + "to be an instance of " + Img.class + " or " + IntervalView.class); + long flatSize = 1; + for (long ss : imgTensor.dimensionsAsLongArray()) {flatSize *= ss;} + long[] byteArr = new long[(int) flatSize]; + int cc = 0; + while (tensorCursor.hasNext()) { + tensorCursor.fwd(); + byteArr[cc ++] = tensorCursor.get().get(); + } + return byteArr; + } + /** * Adds the FloatType {@link RandomAccessibleInterval} data to the {@link ByteBuffer} provided. * The position of the ByteBuffer is kept in the same place as it was received. @@ -171,7 +332,7 @@ else if (imgTensor instanceof Img) * @param byteBuffer * target bytebuffer */ - private static float[] buildFloat(RandomAccessibleInterval imgTensor) + private static float[] buildFloat32(RandomAccessibleInterval imgTensor) { Cursor tensorCursor; if (imgTensor instanceof IntervalView) @@ -201,7 +362,7 @@ else if (imgTensor instanceof Img) * @param byteBuffer * target bytebuffer */ - private static double[] buildDouble(RandomAccessibleInterval imgTensor) + private static double[] buildFloat64(RandomAccessibleInterval imgTensor) { Cursor tensorCursor; if (imgTensor instanceof IntervalView) From 1b9de9169db5801e4b342d4735e9317ec12c5960 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 18:33:29 +0200 Subject: [PATCH 076/235] add class to handle json --- .../bioimage/modelrunner/utils/JSONUtils.java | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 src/main/java/io/bioimage/modelrunner/utils/JSONUtils.java diff --git a/src/main/java/io/bioimage/modelrunner/utils/JSONUtils.java b/src/main/java/io/bioimage/modelrunner/utils/JSONUtils.java new file mode 100644 index 00000000..492223a7 --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/utils/JSONUtils.java @@ -0,0 +1,197 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.utils; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +/** + * Utility class for JSON files and data structures. + * + * @author Carlos Garcia Lopez de Haro + */ +public class JSONUtils +{ + + /** + * Reads the provided json file and loads it into a map of string keys and object values. + * + * @param jsonFile + * The target json file. + * @return The map loaded with the json elements. + * @throws FileNotFoundException + * If the file cannot be found. + * @throws IOException + * If the file cannot be read. + */ + public static Map load(String jsonFile) throws FileNotFoundException, IOException + { + try (FileReader reader = new FileReader(jsonFile)) { + Gson gson = new Gson(); + Type mapType = new TypeToken>() {}.getType(); + Map dataMap = gson.fromJson(reader, mapType); + return dataMap; + } + } + + /** + * Reads the provided json String and loads it into a map of string keys and object values. + * + * @param jsonString + * The String json file. + * @return The map loaded with the json elements. + */ + public static Map loadFromString(String jsonString) + { + Gson gson = new Gson(); + Type mapType = new TypeToken>() {}.getType(); + Map dataMap = gson.fromJson(jsonString, mapType); + return dataMap; + } + + /** + * Converts a list of objects into an array of strings. + * + * @param list + * The target list. + * @return The array of strings. + */ + public static String[] castListToStringArray(List list) + { + String[] array = new String[list.size()]; + int c = 0; + for (Object in : list) + { + array[c++] = (String) in; + } + return array; + } + + /** + * Converts a list of objects into an array of integers. + * + * @param list + * The target list. + * @return The array of integers. + */ + public static int[] castListToIntArray(List list) + { + int[] array = new int[list.size()]; + int c = 0; + for (Object in : list) + { + array[c++] = Integer.parseInt(in.toString()); + } + return array; + } + + /** + * Converts a list of objects into an array of doubles. + * + * @param list + * The target list. + * @return The array of doubles. + */ + public static double[] castListToDoubleArray(List list) + { + try + { + double[] array = new double[list.size()]; + int c = 0; + for (Object in : list) + { + array[c++] = Double.parseDouble(in.toString()); + } + return array; + } + catch (Exception ex) + { + return null; + } + } + + /** + * Converts a list of objects into an array of floats. + * + * @param list + * The target list. + * @return The array of floats. + */ + public static float[] castListToFloatArray(List list) + { + try + { + float[] array = new float[list.size()]; + int c = 0; + for (Object in : list) + { + if (in instanceof String) { + array[c++] = Float.parseFloat((String) in); + } else if (in instanceof Integer) { + array[c++] = ((Integer) in).floatValue(); + } else if (in instanceof Double) { + array[c++] = ((Double) in).floatValue(); + } else if (in instanceof Float) { + array[c++] = ((Float) in).floatValue(); + } else if (in instanceof Long) { + array[c++] = ((Long) in).floatValue(); + } else if (in instanceof Number) { + array[c++] = ((Number) in).floatValue(); + } else if (in instanceof Byte) { + array[c++] = ((Byte) in).floatValue(); + } else { + throw new IllegalArgumentException("Unsupported type for list of Objects:" + in.getClass()); + } + } + return array; + } + catch (ClassCastException ex) + { + return null; + } + } + + /** + * Method that writes a Map into a JSON file in the path defined + * @param filePath + * path to the json file that will be created + * @param data + * data to be written into the json file + * @throws IOException if there is any problem writting the json file + */ + public static void writeJSONFile(String filePath, Map data) throws IOException { + Gson gson = new Gson(); + + try (Writer writer = new FileWriter(filePath)) { + gson.toJson(data, writer); + } catch (IOException e) { + throw e; + } + } +} From 9c4d1b7995314dbf0425964be3ff8c5c8f540686 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 18:36:06 +0200 Subject: [PATCH 077/235] correct error writting yaml instead of json --- python/ops/stardist_fine_tune/stardist_fine_tune.py | 12 ++++++------ .../runmode/ops/StardistFineTuneJdllOp.java | 10 ++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/python/ops/stardist_fine_tune/stardist_fine_tune.py b/python/ops/stardist_fine_tune/stardist_fine_tune.py index 7d0d53b2..eff23cae 100644 --- a/python/ops/stardist_fine_tune/stardist_fine_tune.py +++ b/python/ops/stardist_fine_tune/stardist_fine_tune.py @@ -19,17 +19,17 @@ def assertions(model, images, ground_truth, new_model_dir): assert isinstance(ground_truth, xr.DataArray), "the ground thruth should be a xr.DataArray" assert images.ndim == 4, "the training samples array must have 4 dimensions" - assert ground_truth.ndim == 4, "the training samples array must have 4 dimensions" + assert ground_truth.ndim == 3, "the training samples array must have 3 dimensions" - assert "".join(images.dims) == "bxyc", "the training samples axes order should be 'bxyc', not '" + "".join(images.dims) + "' as provided." - assert "".join(ground_truth.dims) == "bxy", "the ground truth samples axes order should be 'bxy', not '" + "".join(ground_truth.dims) + "' as provided." + assert "".join(images.dims) == "byxc", "the training samples axes order should be 'byxc', not '" + "".join(images.dims) + "' as provided." + assert "".join(ground_truth.dims) == "byx", "the ground truth samples axes order should be 'byx', not '" + "".join(ground_truth.dims) + "' as provided." axes_dict = {"batch size": 0, "width": 1, "height": 2} for ks, vs in axes_dict.items(): assert images.shape[vs] == ground_truth.shape[vs], "The training samples " \ - + "and the ground truth need to have the same " + ks + " : " - + images.shape[vs] + " vs " + ground_truth.shape[vs] + + "and the ground truth need to have the same " + ks + " : " \ + + str(images.shape[vs]) + " vs " + str(ground_truth.shape[vs]) def finetune_stardist(model, images, ground_truth, new_model_dir): @@ -55,4 +55,4 @@ def finetune_stardist(model, images, ground_truth, new_model_dir): model.keras_model.save(new_model_dir) model.export_TF(os.path.join(os.path.dirname(new_model_dir), "tf_weights.zip")) - return history.loss, history.rest_losses \ No newline at end of file + return history.loss, history.loss \ No newline at end of file diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 4a5130ab..535e6e8d 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -42,6 +42,7 @@ import io.bioimage.modelrunner.runmode.RunMode; import io.bioimage.modelrunner.tensor.Tensor; import io.bioimage.modelrunner.utils.Constants; +import io.bioimage.modelrunner.utils.JSONUtils; import io.bioimage.modelrunner.utils.YAMLUtils; import net.imglib2.img.Img; import net.imglib2.img.ImgFactory; @@ -161,6 +162,7 @@ public static void main(String[] args) throws IOException, InterruptedException, Tensor gtTensor = Tensor.build("gt", "byx", gt); String modelName = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models"; StardistFineTuneJdllOp op = finetuneAndCreateNew("chatty-frog", modelName); + op.installOp(); op.setBatchSize(2); op.setEpochs(2); op.setFineTuningData(inpTensor, gtTensor); @@ -402,14 +404,14 @@ private void setUpConfigs() throws IOException, Exception { } else if (!(new File(model + File.separator + THRES_JSON).exists())) { throw new IOException("Missing necessary file for StarDist: " + THRES_JSON); } else { - Map config = YAMLUtils.load(model + File.separator + CONFIG_JSON); + Map config = JSONUtils.load(model + File.separator + CONFIG_JSON); int w = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("x")]; int h = trainingSamples.getShape()[trainingSamples.getAxesOrderString().indexOf("y")]; config.put(PATCH_SIZE_KEY, new int[] {w, h}); config.put(BATCH_SIZE_KEY, this.batchSize); config.put(LR_KEY, this.lr); config.put(EPOCHS_KEY, this.epochs); - YAMLUtils.writeYamlFile(model + File.separator + CONFIG_JSON, (Map) config); + JSONUtils.writeJSONFile(model + File.separator + CONFIG_JSON, (Map) config); } } @@ -442,8 +444,8 @@ private void setUpConfigsBioimageio() throws IOException, Exception { ((Map) config).put(BATCH_SIZE_KEY, this.batchSize); ((Map) config).put(LR_KEY, this.lr); ((Map) config).put(EPOCHS_KEY, this.epochs); - YAMLUtils.writeYamlFile(model + File.separator + CONFIG_JSON, (Map) config); - YAMLUtils.writeYamlFile(model + File.separator + THRES_JSON, (Map) thres); + JSONUtils.writeJSONFile(model + File.separator + CONFIG_JSON, (Map) config); + JSONUtils.writeJSONFile(model + File.separator + THRES_JSON, (Map) thres); } private void setUpKerasWeights() throws IOException, Exception { From 93eaf8468059425d0f66c5116abb12aeee84a0a4 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 18:37:05 +0200 Subject: [PATCH 078/235] small bug --- .../modelrunner/bioimageio/download/DownloadModel.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/io/bioimage/modelrunner/bioimageio/download/DownloadModel.java b/src/main/java/io/bioimage/modelrunner/bioimageio/download/DownloadModel.java index 32b786a7..c71fb86c 100644 --- a/src/main/java/io/bioimage/modelrunner/bioimageio/download/DownloadModel.java +++ b/src/main/java/io/bioimage/modelrunner/bioimageio/download/DownloadModel.java @@ -118,6 +118,10 @@ public class DownloadModel { * Key for the map that contains the attachments of the model */ private static String ATTACH_KEY = "attachments"; + /** + * Key for the map that contains the attachment files of the model. This is a subfile of "attachments". + */ + private static String ATTACH_FILES_KEY = "files"; /** * Key for the map that contains the weights of the model */ From 0d23bb82d1cd83c7d54a75c5c8c98ffb5cbd20f8 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 18:37:53 +0200 Subject: [PATCH 079/235] small bug --- src/main/java/io/bioimage/modelrunner/runmode/RunMode.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 4b735a88..a998ebb4 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -245,7 +245,6 @@ void addCodeToRecreateTensor(String ogName, Tensor tensor) { importsCode += IMPORT_XARRAY; if (!importsCode.contains(IMPORT_NUMPY)) importsCode += IMPORT_NUMPY; - tensorRecreationCode = ""; tensorRecreationCode += "task.update('input conv')" + System.lineSeparator(); // This line wants to recreate the original numpy array. Should look like: // input0 = xr.DataArray(np.array(input0).reshape([1, 1, 512, 512]), dims=["b", "c", "y", "x"], name="input0") From 8a966d5bdf622077a4dde21bb99aa7914a46c6e9 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Tue, 3 Oct 2023 19:40:29 +0200 Subject: [PATCH 080/235] remove test code --- python/ops/stardist_fine_tune/stardist_fine_tune.py | 8 ++++---- .../java/io/bioimage/modelrunner/runmode/RunMode.java | 7 +------ .../io/bioimage/modelrunner/runmode/RunModeScripts.java | 3 --- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/python/ops/stardist_fine_tune/stardist_fine_tune.py b/python/ops/stardist_fine_tune/stardist_fine_tune.py index eff23cae..93aa3443 100644 --- a/python/ops/stardist_fine_tune/stardist_fine_tune.py +++ b/python/ops/stardist_fine_tune/stardist_fine_tune.py @@ -49,10 +49,10 @@ def finetune_stardist(model, images, ground_truth, new_model_dir): model = StarDist2D(None, model) # finetune on new data - history = model.train(X,Y, validation_data=(X,Y)) + history = model.train(images, ground_truth, validation_data=(images, ground_truth)) Path(new_model_dir).mkdir(parents=True, exist_ok=True) - model.keras_model.save(new_model_dir) - model.export_TF(os.path.join(os.path.dirname(new_model_dir), "tf_weights.zip")) + model.keras_model.save(os.path.join(new_model_dir, "stardist_weights.h5")) + model.export_TF(os.path.join(os.path.dirname(new_model_dir), "TF_SavedModel.zip")) - return history.loss, history.loss \ No newline at end of file + return history.history \ No newline at end of file diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index a998ebb4..9557e45f 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -50,17 +50,12 @@ public class RunMode { // TODO add support for list of objects private static final String OUTPUT_REFORMATING = "if isinstance(%s, xr.DataArray):" + System.lineSeparator() - + " task.update('is data array')" + System.lineSeparator() + " %s = " + RunModeScripts.XR_METHOD + "(%s)" + System.lineSeparator() + "elif isinstance(%s, np.ndarray):" + System.lineSeparator() - + " task.update('np array')" + System.lineSeparator() + " %s = " + RunModeScripts.NP_METHOD + "(%s)" + System.lineSeparator() + "elif isinstance(%s, list):" + System.lineSeparator() - + " task.update('is list')" + System.lineSeparator() + " %s = " + RunModeScripts.LIST_METHOD + "(%s)" + System.lineSeparator() + "elif isinstance(%s, dict):" + System.lineSeparator() - + " task.update('is dict')" + System.lineSeparator() - + " task.update(str(output1))" + System.lineSeparator() + " %s = " + RunModeScripts.DICT_METHOD + "(%s)" + System.lineSeparator(); private static final String DEFAULT_IMPORT = @@ -296,7 +291,7 @@ private void retrieveResultsCode() { for (String outN : this.outputNames) { String code = String.format(OUTPUT_REFORMATING, outN, outN, outN, outN, outN, outN, - outN, outN, outN, outN, outN, outN, outN); + outN, outN, outN, outN, outN, outN); retrieveResultsCode += code; taskOutputCode += String.format("task.outputs['%s'] = %s", outN, outN) + System.lineSeparator(); diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index 814ca481..8ad77561 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -53,14 +53,11 @@ public class RunModeScripts { */ protected static final String TYPE_CONVERSION_METHODS_SCRIPT = "" + "def " + NP_METHOD + "(np_arr):" + System.lineSeparator() - + " np_arr = np_arr.astype(\"uint8\")" + System.lineSeparator() + " return {\"" + DATA_KEY + "\": np_arr.flatten().tolist(), \"" + SHAPE_KEY + "\": np_arr.shape, \"" + APPOSE_DT_KEY + "\": \"" + NP_ARR_KEY + "\", \"" + DTYPE_KEY + "\": str(np_arr.dtype)}" + System.lineSeparator() + "" + System.lineSeparator() + "def " + XR_METHOD + "(xr_arr):" + System.lineSeparator() - + " xr_arr = xr_arr.astype(\"int64\")" + System.lineSeparator() - + " xr_arr[0] = 1" + System.lineSeparator() + " return {\"" + DATA_KEY + "\": xr_arr.values.flatten().tolist(), \"" + SHAPE_KEY + "\": xr_arr.shape, \"" + AXES_KEY + "\": \"\".join(xr_arr.dims),\"" + NAME_KEY + "\": xr_arr.name, \"" + APPOSE_DT_KEY + "\": \"" + TENSOR_KEY + "\", " From d048aa8ab0ebbb9f3afceaececbcc1bd5ed08289 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 00:37:04 +0200 Subject: [PATCH 081/235] improve robustness of input flushing --- .../modelrunner/runmode/RunModeScripts.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index 8ad77561..40879ed1 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -75,6 +75,19 @@ public class RunModeScripts { + " n_list.append(" + DICT_METHOD + "(value))" + System.lineSeparator() + " elif isinstance(value, list):" + System.lineSeparator() + " n_list.append(" + LIST_METHOD + "(value))" + System.lineSeparator() + + " elif str(type(value)) == \"\"" + + " || str(type(value)) == \"\"" + + " || str(type(value)) == \"\":" + System.lineSeparator() + + " n_list.append(float(value))" + System.lineSeparator() + + " elif str(type(value)) == \"\" || str(type(value)) == \"\"" + + " || str(type(value)) == \"\" || str(type(value)) == \"\"" + + " || str(type(value)) == \"\" || str(type(value)) == \"\"" + + " || str(type(value)) == \"\":" + System.lineSeparator() + + " n_list.append(int(value))" + System.lineSeparator() + + " elif str(type(value)) == \"\"" + System.lineSeparator() + + " n_list.append(str(value))" + System.lineSeparator() + + " elif str(type(value)) == \"\"" + System.lineSeparator() + + " n_list.append(bool(value))" + System.lineSeparator() + " else:" + System.lineSeparator() + " n_list.append(value)" + System.lineSeparator() + " return n_list" + System.lineSeparator() @@ -90,6 +103,19 @@ public class RunModeScripts { + " n_dic[key] = " + DICT_METHOD + "(value)" + System.lineSeparator() + " elif isinstance(value, list):" + System.lineSeparator() + " n_dic[key] = " + LIST_METHOD + "(value)" + System.lineSeparator() + + " elif str(type(value)) == \"\"" + + " || str(type(value)) == \"\"" + + " || str(type(value)) == \"\":" + System.lineSeparator() + + " n_dic[key] = float(value)" + System.lineSeparator() + + " elif str(type(value)) == \"\" || str(type(value)) == \"\"" + + " || str(type(value)) == \"\" || str(type(value)) == \"\"" + + " || str(type(value)) == \"\" || str(type(value)) == \"\"" + + " || str(type(value)) == \"\":" + System.lineSeparator() + + " n_dic[key] = int(value)" + System.lineSeparator() + + " elif str(type(value)) == \"\"" + System.lineSeparator() + + " n_dic[key] = str(value)" + System.lineSeparator() + + " elif str(type(value)) == \"\"" + System.lineSeparator() + + " n_dic[key] = bool(value)" + System.lineSeparator() + " else:" + System.lineSeparator() + " n_dic[key] = value" + System.lineSeparator() + " return n_dic" + System.lineSeparator() From 677bdf0fcad0dc3ae2bcfe6468ca63002d0f2fda Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 00:39:49 +0200 Subject: [PATCH 082/235] put pythonic or instead of || --- .../modelrunner/runmode/RunModeScripts.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index 40879ed1..4c55b67d 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -76,13 +76,13 @@ public class RunModeScripts { + " elif isinstance(value, list):" + System.lineSeparator() + " n_list.append(" + LIST_METHOD + "(value))" + System.lineSeparator() + " elif str(type(value)) == \"\"" - + " || str(type(value)) == \"\"" - + " || str(type(value)) == \"\":" + System.lineSeparator() + + " or str(type(value)) == \"\"" + + " or str(type(value)) == \"\":" + System.lineSeparator() + " n_list.append(float(value))" + System.lineSeparator() - + " elif str(type(value)) == \"\" || str(type(value)) == \"\"" - + " || str(type(value)) == \"\" || str(type(value)) == \"\"" - + " || str(type(value)) == \"\" || str(type(value)) == \"\"" - + " || str(type(value)) == \"\":" + System.lineSeparator() + + " elif str(type(value)) == \"\" or str(type(value)) == \"\"" + + " or str(type(value)) == \"\" or str(type(value)) == \"\"" + + " or str(type(value)) == \"\" or str(type(value)) == \"\"" + + " or str(type(value)) == \"\":" + System.lineSeparator() + " n_list.append(int(value))" + System.lineSeparator() + " elif str(type(value)) == \"\"" + System.lineSeparator() + " n_list.append(str(value))" + System.lineSeparator() @@ -104,13 +104,13 @@ public class RunModeScripts { + " elif isinstance(value, list):" + System.lineSeparator() + " n_dic[key] = " + LIST_METHOD + "(value)" + System.lineSeparator() + " elif str(type(value)) == \"\"" - + " || str(type(value)) == \"\"" - + " || str(type(value)) == \"\":" + System.lineSeparator() + + " or str(type(value)) == \"\"" + + " or str(type(value)) == \"\":" + System.lineSeparator() + " n_dic[key] = float(value)" + System.lineSeparator() - + " elif str(type(value)) == \"\" || str(type(value)) == \"\"" - + " || str(type(value)) == \"\" || str(type(value)) == \"\"" - + " || str(type(value)) == \"\" || str(type(value)) == \"\"" - + " || str(type(value)) == \"\":" + System.lineSeparator() + + " elif str(type(value)) == \"\" or str(type(value)) == \"\"" + + " or str(type(value)) == \"\" or str(type(value)) == \"\"" + + " or str(type(value)) == \"\" or str(type(value)) == \"\"" + + " or str(type(value)) == \"\":" + System.lineSeparator() + " n_dic[key] = int(value)" + System.lineSeparator() + " elif str(type(value)) == \"\"" + System.lineSeparator() + " n_dic[key] = str(value)" + System.lineSeparator() From 8561edd69b9625e38573209d1fd3ee2a4106182a Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 00:49:16 +0200 Subject: [PATCH 083/235] remove test code --- src/main/java/io/bioimage/modelrunner/runmode/RunMode.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 9557e45f..071cba00 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -240,7 +240,6 @@ void addCodeToRecreateTensor(String ogName, Tensor tensor) { importsCode += IMPORT_XARRAY; if (!importsCode.contains(IMPORT_NUMPY)) importsCode += IMPORT_NUMPY; - tensorRecreationCode += "task.update('input conv')" + System.lineSeparator(); // This line wants to recreate the original numpy array. Should look like: // input0 = xr.DataArray(np.array(input0).reshape([1, 1, 512, 512]), dims=["b", "c", "y", "x"], name="input0") this.tensorRecreationCode += ogName + " = xr.DataArray(np.array(" + ogName + ").reshape(["; From ed1c5ef1adf3b82bbd45d04d2f511a2b150e5aff Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 00:49:40 +0200 Subject: [PATCH 084/235] add missing colon : --- .../io/bioimage/modelrunner/runmode/RunModeScripts.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java index 4c55b67d..11c80d83 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunModeScripts.java @@ -84,9 +84,9 @@ public class RunModeScripts { + " or str(type(value)) == \"\" or str(type(value)) == \"\"" + " or str(type(value)) == \"\":" + System.lineSeparator() + " n_list.append(int(value))" + System.lineSeparator() - + " elif str(type(value)) == \"\"" + System.lineSeparator() + + " elif str(type(value)) == \"\":" + System.lineSeparator() + " n_list.append(str(value))" + System.lineSeparator() - + " elif str(type(value)) == \"\"" + System.lineSeparator() + + " elif str(type(value)) == \"\":" + System.lineSeparator() + " n_list.append(bool(value))" + System.lineSeparator() + " else:" + System.lineSeparator() + " n_list.append(value)" + System.lineSeparator() @@ -112,9 +112,9 @@ public class RunModeScripts { + " or str(type(value)) == \"\" or str(type(value)) == \"\"" + " or str(type(value)) == \"\":" + System.lineSeparator() + " n_dic[key] = int(value)" + System.lineSeparator() - + " elif str(type(value)) == \"\"" + System.lineSeparator() + + " elif str(type(value)) == \"\":" + System.lineSeparator() + " n_dic[key] = str(value)" + System.lineSeparator() - + " elif str(type(value)) == \"\"" + System.lineSeparator() + + " elif str(type(value)) == \"\":" + System.lineSeparator() + " n_dic[key] = bool(value)" + System.lineSeparator() + " else:" + System.lineSeparator() + " n_dic[key] = value" + System.lineSeparator() From ce423ae3671cb8a5014f83f7026d81efc41340a1 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 00:50:28 +0200 Subject: [PATCH 085/235] comment export stardist as h5 --- python/ops/stardist_fine_tune/stardist_fine_tune.py | 2 +- .../modelrunner/runmode/ops/StardistFineTuneJdllOp.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ops/stardist_fine_tune/stardist_fine_tune.py b/python/ops/stardist_fine_tune/stardist_fine_tune.py index 93aa3443..f1f5e7c1 100644 --- a/python/ops/stardist_fine_tune/stardist_fine_tune.py +++ b/python/ops/stardist_fine_tune/stardist_fine_tune.py @@ -52,7 +52,7 @@ def finetune_stardist(model, images, ground_truth, new_model_dir): history = model.train(images, ground_truth, validation_data=(images, ground_truth)) Path(new_model_dir).mkdir(parents=True, exist_ok=True) - model.keras_model.save(os.path.join(new_model_dir, "stardist_weights.h5")) + #model.keras_model.save(os.path.join(new_model_dir, "stardist_weights.h5")) model.export_TF(os.path.join(os.path.dirname(new_model_dir), "TF_SavedModel.zip")) return history.history \ No newline at end of file diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 535e6e8d..f606275b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -164,7 +164,7 @@ public static void main(String[] args) throws IOException, InterruptedException, StardistFineTuneJdllOp op = finetuneAndCreateNew("chatty-frog", modelName); op.installOp(); op.setBatchSize(2); - op.setEpochs(2); + op.setEpochs(1); op.setFineTuningData(inpTensor, gtTensor); op.setLearingRate((float) 1e-5); RunMode rm = RunMode.createRunMode(op); From 2aeb7a230605c8ac9ff68d31534a54dc29df33bb Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 13:31:00 +0200 Subject: [PATCH 086/235] allow selecting the weights to be finetuned --- .../ops/stardist_fine_tune/stardist_fine_tune.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/python/ops/stardist_fine_tune/stardist_fine_tune.py b/python/ops/stardist_fine_tune/stardist_fine_tune.py index f1f5e7c1..ed626f64 100644 --- a/python/ops/stardist_fine_tune/stardist_fine_tune.py +++ b/python/ops/stardist_fine_tune/stardist_fine_tune.py @@ -7,9 +7,9 @@ from pathlib import Path -def assertions(model, images, ground_truth, new_model_dir): +def assertions(model_path, images, ground_truth, new_model_dir): - assert isinstance(model, str), "The input argument 'model' must be a string, either the name" \ + assert isinstance(model_path, str), "The input argument 'model_path' must be a string, either the name" \ + " of one of the default pre-trained Stardist models or the directory to a pre-trained Stardist model" assert isinstance(new_model_dir, str), "The input argument 'new_model_dir' must be a string. It is the path" \ @@ -32,9 +32,9 @@ def assertions(model, images, ground_truth, new_model_dir): + str(images.shape[vs]) + " vs " + str(ground_truth.shape[vs]) -def finetune_stardist(model, images, ground_truth, new_model_dir): +def finetune_stardist(model_path, images, ground_truth, new_model_dir, weights_file=None): """ - model: String, path to pretrained model or pretrained model from the stardsit available + model_path: String, path to pretrained model or pretrained model from the stardsit available images: list of tensors or single tensor? If a list of tensors, it would need to be ensured taht they all have same dims, or reconstruct to have same dims. Check the number of channels and check if the channels of the images coincide Also for a path, check that it has the needed files fo a stardist model @@ -44,9 +44,11 @@ def finetune_stardist(model, images, ground_truth, new_model_dir): epochs and batch_size might have a warning for CPu if selected too large """ - assertions(model, images, ground_truth, new_model_dir) + assertions(model_path, images, ground_truth, new_model_dir) - model = StarDist2D(None, model) + model = StarDist2D(None, model_path) + if weights_file is not None: + model.load_weights("weights_last.h5") # finetune on new data history = model.train(images, ground_truth, validation_data=(images, ground_truth)) From fe78dec03eb0a2a200c01ae745838efd2bb8cfe7 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 13:55:00 +0200 Subject: [PATCH 087/235] allow setting weights of interest to fine tune --- .../runmode/ops/StardistFineTuneJdllOp.java | 81 ++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index f606275b..4f72e7d2 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -43,7 +43,6 @@ import io.bioimage.modelrunner.tensor.Tensor; import io.bioimage.modelrunner.utils.Constants; import io.bioimage.modelrunner.utils.JSONUtils; -import io.bioimage.modelrunner.utils.YAMLUtils; import net.imglib2.img.Img; import net.imglib2.img.ImgFactory; import net.imglib2.img.array.ArrayImgFactory; @@ -77,6 +76,8 @@ public class StardistFineTuneJdllOp implements OpInterface { private String nModelPath; + private String weightsToFineTune; + private int nChannelsModel; private float lr = (float) 1e-5; @@ -126,6 +127,8 @@ public class StardistFineTuneJdllOp implements OpInterface { private final static String GROUND_TRUTH_KEY = "ground_truth"; + private final static String WEIGHTS_TO_FINE_TUNE_KEY = "weights_file"; + private final static String PATCH_SIZE_KEY = "train_patch_size"; private final static String BATCH_SIZE_KEY = "train_batch_size"; @@ -179,6 +182,28 @@ public static void main(String[] args) throws IOException, InterruptedException, * can also be modified by with {@link #setBatchSize(int)} and {@link #setLearingRate(float)}. * By default the batch size is 16 and the learning rate 1e-5. * To set the number of epochs: {@link #setEpochs(int)}, default is 1. + * + * Finally in some cases, if we want to fine tune a local model, the model might have + * several weight files: + * - stardist + * - config.json + * - thresholds.json + * - stardist_weights.h5 + * - weights_best.h5 + * - weights_last.h5 + * + * If we are interested in fine tuning a stardist model starting from a certain weights file among + * the available ones, use the {@link #setWeightsToFineTune(String)} to provide the name of the + * file of interest. + * If no specific weight file is designated through the {@link #setWeightsToFineTune(String)} method, + * the system will automatically select and load a weights file containing the substring 'best', if available. + * + * If there is no weights file containing the substring 'best', the system will automatically select and + * load the file that comes first in alphabetical order from the available options. + * + * If there is only one weights file available, it is not necessary to + * use {@link #setWeightsToFineTune(String)}. + * * @param modelToFineTune * Pre-trained model that is going to be fine tuned on the user's data, it * can be either a model existing in the users machine or a model existing in the model @@ -218,6 +243,28 @@ public static StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune * can also be modified by with {@link #setBatchSize(int)} and {@link #setLearingRate(float)}. * By default the batch size is 16 and the learning rate 1e-5. * To set the number of epochs: {@link #setEpochs(int)}, default is 1. + * + * Finally in some cases, if we want to fine tune a local model, the model might have + * several weight files: + * - stardist + * - config.json + * - thresholds.json + * - stardist_weights.h5 + * - weights_best.h5 + * - weights_last.h5 + * + * If we are interested in fine tuning a stardist model starting from a certain weights file among + * the available ones, use the {@link #setWeightsToFineTune(String)} to provide the name of the + * file of interest. + * If no specific weight file is designated through the {@link #setWeightsToFineTune(String)} method, + * the system will automatically select and load a weights file containing the substring 'best', if available. + * + * If there is no weights file containing the substring 'best', the system will automatically select and + * load the file that comes first in alphabetical order from the available options. + * + * If there is only one weights file available, it is not necessary to + * use {@link #setWeightsToFineTune(String)}. + * * @param modelToFineTune * Pre-trained model that is going to be fine tuned on the user's data, it * can be either a model existing in the users machine or a model existing in the model @@ -242,6 +289,36 @@ public static StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) thr return op; } + /** + * This method should only be used when we try to fine tune models from local directories. + * + * In some cases, if we want to fine tune a local model, the model might have + * several weight files: + * - stardist + * - config.json + * - thresholds.json + * - stardist_weights.h5 + * - weights_best.h5 + * - weights_last.h5 + * + * If we are interested in fine tuning a stardist model starting from a certain weights file among + * the available ones, use the {@link #setWeightsToFineTune(String)} to provide the name of the + * file of interest. + * If no specific weight file is designated through the {@link #setWeightsToFineTune(String)} method, + * the system will automatically select and load a weights file containing the substring 'best', if available. + * + * If there is no weights file containing the substring 'best', the system will automatically select and + * load the file that comes first in alphabetical order from the available options. + * + * If there is only one weights file available, it is not necessary to + * use {@link #setWeightsToFineTune(String)}. + * @param weigthsToFineTune + * name of the weights file we want to load. It must end in .h5 and be available in the stardist model folder + */ + public void setWeightsToFineTune(String weigthsToFineTune) { + this.weightsToFineTune = weigthsToFineTune; + } + public < T extends RealType< T > & NativeType< T > > void setFineTuningData(List> trainingSamples, List> groundTruth) { @@ -307,6 +384,8 @@ public LinkedHashMap getOpInputs() throws Exception { inputsMap.put(NEW_MODEL_DIR_KEY, this.nModelPath); // TODO remove inputsMap.put(DOWNLOAD_STARDIST_KEY, this.downloadStardistPretrained); setUpConfigs(); + if (this.weightsToFineTune != null) + inputsMap.put(WEIGHTS_TO_FINE_TUNE_KEY, this.weightsToFineTune); return inputsMap; } From e8d5b69cc8cf8176658285469cd25a510389819c Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 14:12:21 +0200 Subject: [PATCH 088/235] add robustness checks to set a custom stardist weigths file --- .../runmode/ops/StardistFineTuneJdllOp.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 4f72e7d2..0d38a04a 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -385,9 +385,22 @@ public LinkedHashMap getOpInputs() throws Exception { // TODO remove inputsMap.put(DOWNLOAD_STARDIST_KEY, this.downloadStardistPretrained); setUpConfigs(); if (this.weightsToFineTune != null) - inputsMap.put(WEIGHTS_TO_FINE_TUNE_KEY, this.weightsToFineTune); + setWeigthsFile(); return inputsMap; } + + private void setWeigthsFile() { + if (!weightsToFineTune.endsWith(KERAS_SUFFIX_FILE)) + throw new IllegalArgumentException("StarDist weigths files must always end with '" + + KERAS_SUFFIX_FILE + "' and the provided file does not: " + this.weightsToFineTune); + if (new File(weightsToFineTune).isFile() && !(new File(weightsToFineTune).getParent().equals(model))) + throw new IllegalArgumentException("StarDist weigths files that can be fine tuned with this model" + + "should be in the folder: " + this.model); + if (!(new File(weightsToFineTune).isFile()) && new File(model, weightsToFineTune).isFile()) + throw new IllegalArgumentException("The StarDist weigths file provided (" + this.weightsToFineTune + + ") cannot be found in the StarDist model folder : " + this.model); + inputsMap.put(WEIGHTS_TO_FINE_TUNE_KEY, this.weightsToFineTune); + } @Override public String getCondaEnv() { From 827e20d234acf3d8a1399663c34ef94ab4f8c02f Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 14:33:26 +0200 Subject: [PATCH 089/235] increase robustness when fine tuning local models --- .../runmode/ops/StardistFineTuneJdllOp.java | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 0d38a04a..4bb1204c 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -164,7 +164,8 @@ public static void main(String[] args) throws IOException, InterruptedException, final Img< FloatType > gt = gtFactory.create( 2, 64, 64 ); Tensor gtTensor = Tensor.build("gt", "byx", gt); String modelName = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models"; - StardistFineTuneJdllOp op = finetuneAndCreateNew("chatty-frog", modelName); + String p = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models\\finetuned_StarDist H&E Nuclei Segmentation_04102023_123644"; + StardistFineTuneJdllOp op = finetuneAndCreateNew(p, modelName); op.installOp(); op.setBatchSize(2); op.setEpochs(1); @@ -204,6 +205,8 @@ public static void main(String[] args) throws IOException, InterruptedException, * If there is only one weights file available, it is not necessary to * use {@link #setWeightsToFineTune(String)}. * + * NOTE THAT weights_best.h5 AND weights_last.h5 WILL ALWAYS BE REWRITTEN AFTER EACH FINE TUNE ITERATION + * * @param modelToFineTune * Pre-trained model that is going to be fine tuned on the user's data, it * can be either a model existing in the users machine or a model existing in the model @@ -222,6 +225,9 @@ public static StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune + "or to one if the StarDist pre-trained available weigths (example: 2D_versatile_fluo)"); Objects.requireNonNull(newModelDir, "newModelDir' cannot be null. It should be a path to the directory where" + " the we want the fine tuned model to be saved."); + if (new File(newModelDir).isDirectory() == false) + throw new IllegalArgumentException("Argument 'newModelDir' should be an existing directory. In that " + + "directory the fine tuned StarDist model is going to be created."); StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); op.nModelParentPath = newModelDir; op.model = modelToFineTune; @@ -265,6 +271,8 @@ public static StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune * If there is only one weights file available, it is not necessary to * use {@link #setWeightsToFineTune(String)}. * + * NOTE THAT weights_best.h5 AND weights_last.h5 WILL ALWAYS BE REWRITTEN AFTER EACH FINE TUNE ITERATION + * * @param modelToFineTune * Pre-trained model that is going to be fine tuned on the user's data, it * can be either a model existing in the users machine or a model existing in the model @@ -310,6 +318,8 @@ public static StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) thr * If there is no weights file containing the substring 'best', the system will automatically select and * load the file that comes first in alphabetical order from the available options. * + * NOTE THAT weights_best.h5 AND weights_last.h5 WILL ALWAYS BE REWRITTEN AFTER EACH FINE TUNE ITERATION + * * If there is only one weights file available, it is not necessary to * use {@link #setWeightsToFineTune(String)}. * @param weigthsToFineTune @@ -425,13 +435,18 @@ public void setModel() throws IOException, InterruptedException, Exception { setUpStardistModelFromStardistRepo(); return; } - if (new File(model).isFile() && !StardistInferJdllOp.isModelFileStardist(model)) - throw new IllegalArgumentException("The file selected does not correspond to " - + "the rdf.yaml file of a Bioiamge.io Stardist model."); - else if (!(new File(model).isFile()) && !StardistInferJdllOp.isModelNameStardist(model)) + if (new File(model).isDirectory() && !(new File(model, Constants.RDF_FNAME).isFile())) + throw new IllegalArgumentException("The directory selected does not correspond to " + + "a valid Bioimage.io model, it does not contain the required specs file: " + Constants.RDF_FNAME); + else if (new File(model).isDirectory()&& !StardistInferJdllOp.isModelFileStardist(model + File.separator + Constants.RDF_FNAME)) + throw new IllegalArgumentException("The directory selected does not correspond to " + + "a Bioimage.io StarDist model, as per its specs file: " + Constants.RDF_FNAME); + else if (new File(model).isDirectory()) + setUpStardistModelFromLocal(); + else if (!(new File(model).isDirectory()) && !StardistInferJdllOp.isModelNameStardist(model + File.separator + Constants.RDF_FNAME)) throw new IllegalArgumentException("The model name provided does not correspond to a valid" + " Stardist model present in the Bioimage.io online reposritory."); - else if (!(new File(model).isFile())) + else if (!(new File(model).isDirectory())) setUpStardistModelFromBioimageio(); else throw new IllegalArgumentException("Cannot recognise the model provided as a StarDist model. " @@ -577,8 +592,19 @@ private static String getKerasWeigthsLink(ModelDescriptor descriptor) throws IOE + "repository for an example of a correct version."); } - private void setUpStardistModelFromLocal() { - + private void setUpStardistModelFromLocal() throws IllegalArgumentException, IOException, Exception { + if (this.nModelParentPath == null) { + File folder = new File(model); + String fineTuned = folder.getParent() + File.separator + "finetuned_" + folder.getName(); + File renamedFolder = new File(fineTuned); + if (folder.renameTo(renamedFolder)) + model = fineTuned; + this.nModelPath = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; + } else + File folder = new File(model); + String fineTuned = nModelParentPath + File.separator + "finetuned_" + folder.getName(); + } + downloadBioimageioStardistWeights(); } private < T extends RealType< T > & NativeType< T > > From e414142e0ce8bcb6a982d526c679ece4a9f7f328 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 14:48:48 +0200 Subject: [PATCH 090/235] if we want to finetune a model w/o modifying it inplace copy it to another dir --- .../runmode/ops/StardistFineTuneJdllOp.java | 12 +++- .../bioimage/modelrunner/utils/FileUtils.java | 72 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/bioimage/modelrunner/utils/FileUtils.java diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 4bb1204c..67bec13d 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -42,6 +42,7 @@ import io.bioimage.modelrunner.runmode.RunMode; import io.bioimage.modelrunner.tensor.Tensor; import io.bioimage.modelrunner.utils.Constants; +import io.bioimage.modelrunner.utils.FileUtils; import io.bioimage.modelrunner.utils.JSONUtils; import net.imglib2.img.Img; import net.imglib2.img.ImgFactory; @@ -600,9 +601,18 @@ private void setUpStardistModelFromLocal() throws IllegalArgumentException, IOEx if (folder.renameTo(renamedFolder)) model = fineTuned; this.nModelPath = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; - } else + } else { File folder = new File(model); String fineTuned = nModelParentPath + File.separator + "finetuned_" + folder.getName(); + if (!new File(fineTuned).mkdirs()) + throw new IOException("Unable to create directory for fine tuned model at: " + fineTuned); + Files.copy(Paths.get(model + Constants.RDF_FNAME), Paths.get(fineTuned + Constants.RDF_FNAME), StandardCopyOption.REPLACE_EXISTING); + if (new File(model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY).isDirectory()) { + try { + FileUtils.copyFolder(Paths.get(model, StardistInferJdllOp.STARDIST_FIELD_KEY), Paths.get(fineTuned, StardistInferJdllOp.STARDIST_FIELD_KEY)); + } catch (IOException e) { + } + } } downloadBioimageioStardistWeights(); } diff --git a/src/main/java/io/bioimage/modelrunner/utils/FileUtils.java b/src/main/java/io/bioimage/modelrunner/utils/FileUtils.java new file mode 100644 index 00000000..35666215 --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/utils/FileUtils.java @@ -0,0 +1,72 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.utils; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.function.Consumer; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipInputStream; + + +/** + * Class to unzip files and directories + * + * @author Carlos Javier Garcia Lopez de Haro + */ + +public class FileUtils { + + /** + * Copy one folder into another folder creating the necessary subfolders + * + * @param src + * folder to be copied + * @param dest + * destination folder + * @throws IOException if there is any error copying the contents of the folder + */ + public static void copyFolder(Path src, Path dest) throws IOException { + // If the directory does not exist, create it + if (!Files.exists(dest)) { + Files.createDirectories(dest); + } + try (DirectoryStream stream = Files.newDirectoryStream(src)) { + for (Path entry : stream) { + Path newDest = dest.resolve(entry.getFileName()); + + if (Files.isDirectory(entry)) { + copyFolder(entry, newDest); + } else { + Files.copy(entry, newDest, StandardCopyOption.REPLACE_EXISTING); + } + } + } + } +} From 059a0d98f8eba522afe21a8f3e795ee025478d44 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 16:02:41 +0200 Subject: [PATCH 091/235] incrase robustness finetuning local models --- .../runmode/ops/StardistFineTuneJdllOp.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 67bec13d..7d704ef1 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -166,7 +166,9 @@ public static void main(String[] args) throws IOException, InterruptedException, Tensor gtTensor = Tensor.build("gt", "byx", gt); String modelName = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models"; String p = "C:\\Users\\angel\\OneDrive\\Documentos\\pasteur\\git\\model-runner-java\\models\\finetuned_StarDist H&E Nuclei Segmentation_04102023_123644"; - StardistFineTuneJdllOp op = finetuneAndCreateNew(p, modelName); + //p = "chatty-frog"; + //StardistFineTuneJdllOp op = finetuneAndCreateNew(p, modelName); + StardistFineTuneJdllOp op = finetuneInPlace(p); op.installOp(); op.setBatchSize(2); op.setEpochs(1); @@ -220,7 +222,7 @@ public static void main(String[] args) throws IOException, InterruptedException, * @throws IOException * @throws Exception */ - public static StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune, String newModelDir) throws IOException, InterruptedException, Exception { + public static StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune, String newModelDir) throws IOException, InterruptedException, Exception { Objects.requireNonNull(modelToFineTune, "modelToFineTune' cannot be null. It should correspond to either a Bioimage.io " + "folder containing a StarDist model, the nickname of a StarDist model in the Bioimage.io (example: chatty-frog) " + "or to one if the StarDist pre-trained available weigths (example: 2D_versatile_fluo)"); @@ -285,7 +287,12 @@ public static StardistFineTuneJdllOp finetuneAndCreateNew(String modelToFineTune * @throws Exception */ public static StardistFineTuneJdllOp finetuneInPlace(String modelToFineTune) throws IOException, InterruptedException, Exception { - Objects.requireNonNull(modelToFineTune, ""); + Objects.requireNonNull(modelToFineTune, "modelToFineTune' cannot be null. It should correspond to either a Bioimage.io " + + "folder containing a StarDist model, the nickname of a StarDist model in the Bioimage.io (example: chatty-frog) " + + "or to one if the StarDist pre-trained available weigths (example: 2D_versatile_fluo)"); + if (new File(modelToFineTune).isDirectory() == false) + throw new IllegalArgumentException("Argument 'modelToFineTune' should be an existing directory. " + + "That directory should contain the model that wants to be fine-tuned and overwritten."); StardistFineTuneJdllOp op = new StardistFineTuneJdllOp(); op.model = modelToFineTune; op.setModel(); @@ -444,7 +451,7 @@ else if (new File(model).isDirectory()&& !StardistInferJdllOp.isModelFileStardis + "a Bioimage.io StarDist model, as per its specs file: " + Constants.RDF_FNAME); else if (new File(model).isDirectory()) setUpStardistModelFromLocal(); - else if (!(new File(model).isDirectory()) && !StardistInferJdllOp.isModelNameStardist(model + File.separator + Constants.RDF_FNAME)) + else if (!(new File(model).isDirectory()) && !StardistInferJdllOp.isModelNameStardist(model)) throw new IllegalArgumentException("The model name provided does not correspond to a valid" + " Stardist model present in the Bioimage.io online reposritory."); else if (!(new File(model).isDirectory())) @@ -597,22 +604,31 @@ private void setUpStardistModelFromLocal() throws IllegalArgumentException, IOEx if (this.nModelParentPath == null) { File folder = new File(model); String fineTuned = folder.getParent() + File.separator + "finetuned_" + folder.getName(); - File renamedFolder = new File(fineTuned); - if (folder.renameTo(renamedFolder)) + String fineTunedAux = "" + fineTuned; + int c = 1; + while (new File(fineTuned).exists()) + fineTuned = fineTunedAux + "-" + (c++); + if (folder.renameTo(new File(fineTuned))) model = fineTuned; this.nModelPath = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; } else { File folder = new File(model); String fineTuned = nModelParentPath + File.separator + "finetuned_" + folder.getName(); + String fineTunedAux = "" + fineTuned; + int c = 1; + while (new File(fineTuned).exists()) + fineTuned = fineTunedAux + "-" + (c++); if (!new File(fineTuned).mkdirs()) throw new IOException("Unable to create directory for fine tuned model at: " + fineTuned); - Files.copy(Paths.get(model + Constants.RDF_FNAME), Paths.get(fineTuned + Constants.RDF_FNAME), StandardCopyOption.REPLACE_EXISTING); + Files.copy(Paths.get(model, Constants.RDF_FNAME), Paths.get(fineTuned, Constants.RDF_FNAME), StandardCopyOption.REPLACE_EXISTING); if (new File(model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY).isDirectory()) { try { FileUtils.copyFolder(Paths.get(model, StardistInferJdllOp.STARDIST_FIELD_KEY), Paths.get(fineTuned, StardistInferJdllOp.STARDIST_FIELD_KEY)); } catch (IOException e) { } - } + } + model = fineTuned; + this.nModelPath = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; } downloadBioimageioStardistWeights(); } From 6cc6acda90c840653d6578db6dedd5be8641a1f4 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 16:05:47 +0200 Subject: [PATCH 092/235] remove unneeded argument for the python method --- .../stardist_fine_tune/stardist_fine_tune.py | 17 ++++++----------- .../runmode/ops/StardistFineTuneJdllOp.java | 6 ------ 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/python/ops/stardist_fine_tune/stardist_fine_tune.py b/python/ops/stardist_fine_tune/stardist_fine_tune.py index ed626f64..bfd27db9 100644 --- a/python/ops/stardist_fine_tune/stardist_fine_tune.py +++ b/python/ops/stardist_fine_tune/stardist_fine_tune.py @@ -7,14 +7,11 @@ from pathlib import Path -def assertions(model_path, images, ground_truth, new_model_dir): +def assertions(model_path, images, ground_truth, ): assert isinstance(model_path, str), "The input argument 'model_path' must be a string, either the name" \ + " of one of the default pre-trained Stardist models or the directory to a pre-trained Stardist model" - assert isinstance(new_model_dir, str), "The input argument 'new_model_dir' must be a string. It is the path" \ - + " where the fine tuned stardist model will be saved." - assert isinstance(images, xr.DataArray), "the training samples should be a xr.DataArray" assert isinstance(ground_truth, xr.DataArray), "the ground thruth should be a xr.DataArray" @@ -32,7 +29,7 @@ def assertions(model_path, images, ground_truth, new_model_dir): + str(images.shape[vs]) + " vs " + str(ground_truth.shape[vs]) -def finetune_stardist(model_path, images, ground_truth, new_model_dir, weights_file=None): +def finetune_stardist(model_path, images, ground_truth, weights_file=None): """ model_path: String, path to pretrained model or pretrained model from the stardsit available images: list of tensors or single tensor? If a list of tensors, it would need to be ensured taht they all have same dims, @@ -40,11 +37,9 @@ def finetune_stardist(model_path, images, ground_truth, new_model_dir, weights_f Also for a path, check that it has the needed files fo a stardist model ground_truth: list of tensors or single tensor? It needs to have the same type and size than images - new_model_dir: directory where the new model will be saved, save one imput and output sample - epochs and batch_size might have a warning for CPu if selected too large """ - assertions(model_path, images, ground_truth, new_model_dir) + assertions(model_path, images, ground_truth) model = StarDist2D(None, model_path) if weights_file is not None: @@ -53,8 +48,8 @@ def finetune_stardist(model_path, images, ground_truth, new_model_dir, weights_f # finetune on new data history = model.train(images, ground_truth, validation_data=(images, ground_truth)) - Path(new_model_dir).mkdir(parents=True, exist_ok=True) - #model.keras_model.save(os.path.join(new_model_dir, "stardist_weights.h5")) - model.export_TF(os.path.join(os.path.dirname(new_model_dir), "TF_SavedModel.zip")) + Path(model_path).mkdir(parents=True, exist_ok=True) + #model.keras_model.save(os.path.join(model_path, "stardist_weights.h5")) + model.export_TF(os.path.join(os.path.dirname(model_path), "TF_SavedModel.zip")) return history.history \ No newline at end of file diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java index 7d704ef1..5509116e 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/StardistFineTuneJdllOp.java @@ -75,8 +75,6 @@ public class StardistFineTuneJdllOp implements OpInterface { private String nModelParentPath; - private String nModelPath; - private String weightsToFineTune; private int nChannelsModel; @@ -399,7 +397,6 @@ public LinkedHashMap getOpInputs() throws Exception { + "setFineTuningData(Tensor trainingSamples, Tensor groundTruth)"); inputsMap.put(TRAIN_SAMPLES_KEY, this.trainingSamples); inputsMap.put(GROUND_TRUTH_KEY, this.groundTruth); - inputsMap.put(NEW_MODEL_DIR_KEY, this.nModelPath); // TODO remove inputsMap.put(DOWNLOAD_STARDIST_KEY, this.downloadStardistPretrained); setUpConfigs(); if (this.weightsToFineTune != null) @@ -494,7 +491,6 @@ private void setUpStardistModelFromBioimageio() throws IOException, InterruptedE File renamedFolder = new File(fineTuned); if (folder.renameTo(renamedFolder)) model = fineTuned; - this.nModelPath = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; downloadBioimageioStardistWeights(); } @@ -610,7 +606,6 @@ private void setUpStardistModelFromLocal() throws IllegalArgumentException, IOEx fineTuned = fineTunedAux + "-" + (c++); if (folder.renameTo(new File(fineTuned))) model = fineTuned; - this.nModelPath = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; } else { File folder = new File(model); String fineTuned = nModelParentPath + File.separator + "finetuned_" + folder.getName(); @@ -628,7 +623,6 @@ private void setUpStardistModelFromLocal() throws IllegalArgumentException, IOEx } } model = fineTuned; - this.nModelPath = model + File.separator + StardistInferJdllOp.STARDIST_FIELD_KEY; } downloadBioimageioStardistWeights(); } From c64e2540cccaaee0c6a5994b24a729274b5a8141 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 4 Oct 2023 23:34:34 +0200 Subject: [PATCH 093/235] use local appose --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 313b2060..dca9be68 100644 --- a/pom.xml +++ b/pom.xml @@ -136,11 +136,11 @@ appose 0.1.0 - + net.java.dev.jna jna From beff35fce35d5f98ec1fb6a48ec581842cbb354b Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 16 Oct 2023 14:54:22 +0200 Subject: [PATCH 094/235] unnecessary class --- .../modelrunner/runmode/RunMode2.java | 58 ------------------- .../modelrunner/runmode/ops/OpInterface.java | 3 +- 2 files changed, 1 insertion(+), 60 deletions(-) delete mode 100644 src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java deleted file mode 100644 index 4f3201f1..00000000 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode2.java +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * #%L - * Use deep learning frameworks from Java in an agnostic and isolated way. - * %% - * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ -package io.bioimage.modelrunner.runmode; - -import java.util.List; - -import io.bioimage.modelrunner.tensor.Tensor; - -/** - * Interface for run modes that contain complex Deep Learning routines. - * - * @author Carlos Garcia Lopez de Haro - * - */ -public interface RunMode2 -{ - - /** - * Applies the run mode transformation to the specified input/s tensor/s. - * - * This method will execute the corresponding run mode on the wanted inputs - * and return the result provided by the run mode. Regard that the run mode - * can be anything. For example tiling + model inference + post-processing; - * simply model inference; pre-processing + model inference - * - * - * @param inputs - * the input/s tensor/s. - * @return a list of the result tensors in their corresponding datatypes. - */ - public List> apply( Tensor< ? >... inputs ); - - /** - * Returns the name of this run mode. - * - * @return the name of this run mode. - */ - public String getName(); - - -} diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java index 18290b56..cdbe643b 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java @@ -19,12 +19,11 @@ */ package io.bioimage.modelrunner.runmode.ops; -import java.io.IOException; import java.util.LinkedHashMap; /** * Interface that every OP needs to implement to be able to be run as a RunMode - * @author Carlos Garcia Lopez de Haro + * @author Carlos Javier Garcia Lopez de Haro * */ public interface OpInterface { From 2f6f2e443f6f3bf5b7efa5dc23a264f36c2a902d Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Mon, 16 Oct 2023 21:38:58 +0200 Subject: [PATCH 095/235] start the task --- src/main/java/io/bioimage/modelrunner/runmode/RunMode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java index 071cba00..e71e0c31 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/RunMode.java @@ -131,6 +131,7 @@ public Map runOP() { break; } }); + task.start(); task.waitFor(); System.out.println("here2"); outputs = recreateOutputObjects(task.outputs); From 14eaaa4405b3839ff615ed8b2c7a30d94f1f2d71 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 1 Nov 2023 18:06:15 +0100 Subject: [PATCH 096/235] add new python transformation --- .../transformations/PythonTransformation.java | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java diff --git a/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java b/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java new file mode 100644 index 00000000..5fb6a5cc --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java @@ -0,0 +1,88 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.transformations; + +import java.util.List; + +import io.bioimage.modelrunner.tensor.Tensor; + +import net.imglib2.type.NativeType; +import net.imglib2.type.numeric.RealType; +import net.imglib2.type.numeric.real.FloatType; + +public class PythonTransformation extends AbstractTensorPixelTransformation +{ + private static String name = "python"; + + private String envYaml; + + private String script; + + private String method; + + private List args; + + public PythonTransformation() + { + super(name); + } + + public void setEnvYaml(Object envYaml) { + if (envYaml instanceof String) { + this.envYaml = String.valueOf(envYaml); + } else { + throw new IllegalArgumentException("'envYaml' parameter has to be either and instance of " + + String.class + + ". The provided argument is an instance of: " + envYaml.getClass()); + } + } + + public void setScript(Object script) { + if (script instanceof String) { + this.script = String.valueOf(script); + } else { + throw new IllegalArgumentException("'script' parameter has to be either and instance of " + + String.class + + ". The provided argument is an instance of: " + script.getClass()); + } + } + + public void setMethod(Object method) { + if (method instanceof String) { + this.method = String.valueOf(method); + } else { + throw new IllegalArgumentException("'method' parameter has to be either and instance of " + + String.class + + ". The provided argument is an instance of: " + method.getClass()); + } + } + + public < R extends RealType< R > & NativeType< R > > Tensor< FloatType > apply( final Tensor< R > input ) + { + super.setFloatUnitaryOperator( v -> ( float ) ( 1. / ( 1. + Math.exp( -v ) ) ) ); + return super.apply(input); + } + + public void applyInPlace( final Tensor< FloatType > input ) + { + super.setFloatUnitaryOperator( v -> ( float ) ( 1. / ( 1. + Math.exp( -v ) ) ) ); + super.apply(input); + } +} From d0215d5e3516290840902df630e0861a92424e6d Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 1 Nov 2023 19:21:00 +0100 Subject: [PATCH 097/235] create generic op description to run any pytohn code --- .../modelrunner/runmode/ops/GenericOp.java | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/main/java/io/bioimage/modelrunner/runmode/ops/GenericOp.java diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/GenericOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/GenericOp.java new file mode 100644 index 00000000..756c2ce5 --- /dev/null +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/GenericOp.java @@ -0,0 +1,98 @@ +/*- + * #%L + * Use deep learning frameworks from Java in an agnostic and isolated way. + * %% + * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package io.bioimage.modelrunner.runmode.ops; + +import java.util.Map; + +/** + * A generic OP that allows running Python code from JDLL if it is formatted correctly + * @author Carlos Javier Garcia Lopez de Haro + * + */ +public class GenericOp implements OpInterface { + + private String opFilePath; + + private String envPath; + + private String methodName; + + private int nOutputs; + + private Map inputsMap; + + + public static void main(String[] args) { + } + + public static GenericOp create(String envYaml, String script, String method, int nOutputs) { + GenericOp op = new GenericOp(); + op.envPath = envYaml; + op.opFilePath = script; + op.methodName = method; + op.nOutputs = nOutputs; + return op; + } + + public void setInputs(Map kwargs) { + this.inputsMap = kwargs; + } + + @Override + public String getOpPythonFilename() { + return this.opFilePath; + } + + @Override + public int getNumberOfOutputs() { + return nOutputs; + } + + @Override + public void installOp() { + // TODO + } + + @Override + public Map getOpInputs() { + return this.inputsMap; + } + + @Override + public String getCondaEnv() { + return envPath; + } + + @Override + public String getMethodName() { + return this.methodName; + } + + @Override + public String getOpDir() { + return opFilePath; + } + + @Override + public boolean isOpInstalled() { + // TODO maybe remove this method? Make the check at installOp? + return false; + } +} From 4d9a1c3ee2dff35a7a87e6a3ebd5236a659e43a1 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 1 Nov 2023 19:21:57 +0100 Subject: [PATCH 098/235] remove bad code --- .../runmode/ops/OpDescription.java | 80 ------------------- 1 file changed, 80 deletions(-) delete mode 100644 src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java deleted file mode 100644 index 2707fdc5..00000000 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpDescription.java +++ /dev/null @@ -1,80 +0,0 @@ -/*- - * #%L - * Use deep learning frameworks from Java in an agnostic and isolated way. - * %% - * Copyright (C) 2022 - 2023 Institut Pasteur and BioImage.IO developers. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ -package io.bioimage.modelrunner.runmode.ops; - -import java.util.LinkedHashMap; -import java.util.List; - -public class OpDescription { - - private boolean isDefault = false; - - private String opDir; - - private static final List defaultOps = null; - - public static OpDescription setupOP(String projectRepo, String opFileName, String opMethodName) { - - } - - public String getOpImport() { - return ""; - } - - public int getNumberOfOutputs() { - return 0; - } - - public void defineCondaEnv() { - - } - - protected void installOp() { - - } - - public void setInputsInOrder(List orderedInputList) { - - } - - public void setNumberOfOuptuts(int nOutputs) { - - } - - public String getCondaEnv() { - return ""; - } - - public String getMethodName() { - return ""; - } - - public LinkedHashMap getMethodExtraArgs() { - return null; - } - - public Object[] getOutputs() { - return null; - } - - public String getOpDir() { - return opDir; - } -} From 67cf38350ba6b9b28ca0261cf976eee412dd21e5 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 1 Nov 2023 19:26:49 +0100 Subject: [PATCH 099/235] come back to LinkedHashMap to ensure the inputs are provided correctly --- .../io/bioimage/modelrunner/runmode/ops/GenericOp.java | 8 ++++---- .../io/bioimage/modelrunner/runmode/ops/OpInterface.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/GenericOp.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/GenericOp.java index 756c2ce5..d6751726 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/GenericOp.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/GenericOp.java @@ -19,7 +19,7 @@ */ package io.bioimage.modelrunner.runmode.ops; -import java.util.Map; +import java.util.LinkedHashMap; /** * A generic OP that allows running Python code from JDLL if it is formatted correctly @@ -36,7 +36,7 @@ public class GenericOp implements OpInterface { private int nOutputs; - private Map inputsMap; + private LinkedHashMap inputsMap; public static void main(String[] args) { @@ -51,7 +51,7 @@ public static GenericOp create(String envYaml, String script, String method, int return op; } - public void setInputs(Map kwargs) { + public void setInputs(LinkedHashMap kwargs) { this.inputsMap = kwargs; } @@ -71,7 +71,7 @@ public void installOp() { } @Override - public Map getOpInputs() { + public LinkedHashMap getOpInputs() { return this.inputsMap; } diff --git a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java index cdbe643b..957f53d5 100644 --- a/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java +++ b/src/main/java/io/bioimage/modelrunner/runmode/ops/OpInterface.java @@ -48,7 +48,7 @@ public interface OpInterface { */ public void installOp(); /** - * Get a LinkedHashMap contianing the inputs defined for the OP + * Get a Map contianing the inputs defined for the OP * @return an ordered map with the inputs to the OP, where the key * is the variable name and the object is the variable * @throws Exception if there is any error handling the inputs to the Python OP From 4380005044b247a648004b4f62c713c2a4320391 Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 1 Nov 2023 19:40:39 +0100 Subject: [PATCH 100/235] add python transformation to run arbitrary python code --- .../transformations/PythonTransformation.java | 76 ++++++++++++++++--- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java b/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java index 5fb6a5cc..7651f4f9 100644 --- a/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java +++ b/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java @@ -19,15 +19,23 @@ */ package io.bioimage.modelrunner.transformations; -import java.util.List; +import java.io.File; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.stream.Collectors; +import io.bioimage.modelrunner.runmode.RunMode; +import io.bioimage.modelrunner.runmode.ops.GenericOp; import io.bioimage.modelrunner.tensor.Tensor; - +import io.bioimage.modelrunner.utils.YAMLUtils; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.real.FloatType; -public class PythonTransformation extends AbstractTensorPixelTransformation +public class PythonTransformation extends AbstractTensorTransformation { private static String name = "python"; @@ -37,7 +45,9 @@ public class PythonTransformation extends AbstractTensorPixelTransformation private String method; - private List args; + private int nOutputs; + + private LinkedHashMap kwargs; public PythonTransformation() { @@ -48,7 +58,7 @@ public void setEnvYaml(Object envYaml) { if (envYaml instanceof String) { this.envYaml = String.valueOf(envYaml); } else { - throw new IllegalArgumentException("'envYaml' parameter has to be either and instance of " + throw new IllegalArgumentException("'envYaml' parameter has to be an instance of " + String.class + ". The provided argument is an instance of: " + envYaml.getClass()); } @@ -58,7 +68,7 @@ public void setScript(Object script) { if (script instanceof String) { this.script = String.valueOf(script); } else { - throw new IllegalArgumentException("'script' parameter has to be either and instance of " + throw new IllegalArgumentException("'script' parameter has to be an instance of " + String.class + ". The provided argument is an instance of: " + script.getClass()); } @@ -68,21 +78,63 @@ public void setMethod(Object method) { if (method instanceof String) { this.method = String.valueOf(method); } else { - throw new IllegalArgumentException("'method' parameter has to be either and instance of " + throw new IllegalArgumentException("'method' parameter has to be an instance of " + String.class + ". The provided argument is an instance of: " + method.getClass()); } } + + public void setNOutputs(Object nOutputs) { + if (Number.class.isAssignableFrom(nOutputs.getClass()) + || (nOutputs.getClass().isPrimitive() && !String.class.isAssignableFrom(nOutputs.getClass())) ) { + this.nOutputs = (int) nOutputs; + } else { + throw new IllegalArgumentException("'nOutputs' parameter has to be a number" + + ". The provided argument is an instance of: " + nOutputs.getClass()); + } + } + + public void setKwargs(Object kwargs) { + if (kwargs instanceof LinkedHashMap) { + this.kwargs = (LinkedHashMap) kwargs; + } else { + throw new IllegalArgumentException("'kwargs' parameter has to be an instance of " + + LinkedHashMap.class + + ". The provided argument is an instance of: " + method.getClass()); + } + } - public < R extends RealType< R > & NativeType< R > > Tensor< FloatType > apply( final Tensor< R > input ) + public < R extends RealType< R > & NativeType< R > > Tensor apply( final Tensor< R > input ) { - super.setFloatUnitaryOperator( v -> ( float ) ( 1. / ( 1. + Math.exp( -v ) ) ) ); - return super.apply(input); + String envName = (String) YAMLUtils.loadFromString(envYaml).get("name"); + String minicondaBase = Paths.get(System.getProperty("user.home"), ".local", "share", "appose", "miniconda").toString(); + String envPath = minicondaBase + File.separator + "envs" + File.separator + envName; + if (!(new File(envPath).isDirectory())) { + // TODO install env + } + + GenericOp op = GenericOp.create(envPath, this.script, this.method, this.nOutputs); + LinkedHashMap nMap = new LinkedHashMap(); + Calendar cal = Calendar.getInstance(); + SimpleDateFormat sdf = new SimpleDateFormat("ddMMYYYY_HHmmss"); + String dateString = sdf.format(cal.getTime()); + nMap.put("input_" + dateString, input); + nMap.putAll(kwargs); + op.setInputs(nMap); + + RunMode rm; + try { + rm = RunMode.createRunMode(op); + } catch (Exception e1) { + e1.printStackTrace(); + return (Tensor) input; + } + Map resMap = rm.runOP(); + return (Tensor) resMap.entrySet().stream() + .map(e -> e.getValue()).collect(Collectors.toList()).get(0); } public void applyInPlace( final Tensor< FloatType > input ) { - super.setFloatUnitaryOperator( v -> ( float ) ( 1. / ( 1. + Math.exp( -v ) ) ) ); - super.apply(input); } } From 54afe7fb097a5705f886164a90e0237199f4ddfe Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 1 Nov 2023 20:08:12 +0100 Subject: [PATCH 101/235] install mamba if not found --- .../transformations/PythonTransformation.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java b/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java index 7651f4f9..a5e32dbe 100644 --- a/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java +++ b/src/main/java/io/bioimage/modelrunner/transformations/PythonTransformation.java @@ -20,13 +20,19 @@ package io.bioimage.modelrunner.transformations; import java.io.File; +import java.io.IOException; import java.nio.file.Paths; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.apposed.appose.Conda; + import io.bioimage.modelrunner.runmode.RunMode; import io.bioimage.modelrunner.runmode.ops.GenericOp; import io.bioimage.modelrunner.tensor.Tensor; @@ -110,7 +116,17 @@ public < R extends RealType< R > & NativeType< R > > Tensor apply( fi String minicondaBase = Paths.get(System.getProperty("user.home"), ".local", "share", "appose", "miniconda").toString(); String envPath = minicondaBase + File.separator + "envs" + File.separator + envName; if (!(new File(envPath).isDirectory())) { - // TODO install env + try { + Conda conda = new Conda(minicondaBase); + final List< String > cmd = + new ArrayList<>( Arrays.asList( "env", "create", "--prefix", + minicondaBase + File.separator + "envs", "--force", + "-n", envName, "--file", envYaml, "-y" ) ); + conda.runConda( cmd.stream().toArray( String[]::new ) ); + } catch (IOException | InterruptedException e1) { + e1.printStackTrace(); + return (Tensor) input; + } } GenericOp op = GenericOp.create(envPath, this.script, this.method, this.nOutputs); From 342e0757bce9d492a6d00aaf7f62ca1c53d8cdbd Mon Sep 17 00:00:00 2001 From: carlosuc3m <100329787@alumnos.uc3m.es> Date: Wed, 1 Nov 2023 22:56:58 +0100 Subject: [PATCH 102/235] use appose snaptshot --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dca9be68..0ae5a18a 100644 --- a/pom.xml +++ b/pom.xml @@ -134,7 +134,7 @@ org.apposed appose - 0.1.0 + 0.1.1-SNAPSHOT