From 6ec6344be89ab0b9c05f901c8b5cfe01d954924a Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 3 Jul 2020 16:36:09 +0800 Subject: [PATCH 01/28] test test if local change can be commit to remote github --- .../ParticleAnalysis.cpython-37.pyc | Bin 10236 -> 10214 bytes ParticleSpy/__pycache__/SegUI.cpython-37.pyc | Bin 11686 -> 11664 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 182 -> 160 bytes ParticleSpy/__pycache__/api.cpython-37.pyc | Bin 1959 -> 1937 bytes .../__pycache__/find_zoneaxis.cpython-37.pyc | Bin 3771 -> 3749 bytes .../__pycache__/particle_load.cpython-37.pyc | Bin 972 -> 950 bytes .../__pycache__/particle_save.cpython-37.pyc | Bin 802 -> 780 bytes .../__pycache__/ptcl_class.cpython-37.pyc | Bin 11361 -> 11339 bytes .../__pycache__/radial_profile.cpython-37.pyc | Bin 3513 -> 3491 bytes .../__pycache__/segptcls.cpython-37.pyc | Bin 3335 -> 3313 bytes requirements.txt | 3 ++- 11 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc b/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc index 13e52ecb30c71fe1f1badc4a79dc337786b39423..adad038501d8a70cbbd56f48ff24c92b1f199a33 100644 GIT binary patch delta 1830 zcmb`I&2Jl35WxK$e>)D%M~&l;d?7npK~q3Yn*5_%F6hjM`nLP8)P5L`J?I8;IiY5xEaf)h6os+d`)Z7>xlBIUR9X6DVz zn|ZtbYw@SWLrl@7)tDBSupL z82MmILawI1-}fZO_u{(ga?{b>rWaJyj{|T5wSOK_r^^k8gHzUcyBqMyrJur!G;EEM9z~58 zbwN?j+f6T2*Uj@%+|Me<3}v&T>5dDh?{5ogRan549JMvHsV>$8mdyeC!Q9bCUYHc`W{PaG^+jesV`cI4U~!Am!OMh)B!dbWUO>ok$F+c0 z48?{+w2mw(hK&t>6chhuvuNm~(9uUWdvvV#vGzb?78-z_llW>1KT%zS=!YhPbnZ>Q) z_fPw$q~ZBT1)Kw&eTo!x&9K2+_>dD^b1FOi`KR~ph_vfU>&D0@Y~|H^5!$i-yV{N# z9~4jJ_~&m=qn%l7kBvM}@x8F(y5RVQ`f0qdTDKf7Mf{?@SXIYQnqqK|RiUGxU43Z% zG4>hT>ahQx1!JjF6kemVyiVvyb&YhBZ;)5JaJWvI8xL{aRW(@);%xDyaT~?saDf!y zi_9mng3U5QYfDgb~6hVT=$Yyh$h!9;Ec8lcbwPoN7ax_1_?vONq$ZD`N4qnlVru+}lH35ONJB*DKL^m4-t!i!jI=eX+n$^TWe_-cIaZ(R+d-T(jq delta 1855 zcmb`IO>7%Q6vsVI?D#V%No(@`RqU|p2NI}(wt=G1q(DOgght4X*sj+TdlK)i`({lN zID`WwP}&q2zCS7FI1X6~Vvj^3Si+my%4Ycaz&pH-}Rz3>z2I$70di zs~(uvhLC2ByA{8xRUuPh`_xWmKBwc0qT*ULotDAZ^f&8VtLvE~tWS+)_hIG9tbshA z{q>RiseV$pK6j2=qKEB+L9OSZJ^&Cr%%9`bKST1{Z!$B!>xgz{( zqomGv{=}A=hwnJswzVHSLJwlzNI*L^1_?t5o#Za|1FEq^&Pl?(6loW(^}G=;W`tu^ zxQSy5E@6)1Pf(l*SfFpBZh}9I7@-tlVL!yp8L}0(DO$d0=khYOHr^SWr$!-7I+?yR2*o_fYW8lc4mcEpbVUdXJL?gmFSt9t)MN%uL2>k=B2 z(Rra^xxQEtw&e@Yg=usayTWy{J*V#B-9Z0Mt--=XOY1s)^Wxxn)svl;?>WLY>l}is z+A^6LESjUqB+!Vk9P4J|3})2BLoczp<_|;jY>*BCE@dP#3#&+@O?OCMq00s*)WMPd z>DMUX65(~iWx^H04&hdJxJu182yYVhC{f!ZA3Pl_5$$)dPSA%IE*#A|IGH%lx6v-9 zcv+eb$Ln7XPRDNc-ip*qHDUBicJ8g46~bEot+qwuu6U9Y%s<@9P^a1$A3a0$bLi=aL0(EM%uE4I}V|33wzRHFmlqq)3KXc_85 z@*Vw%vO?kTF?l|@P3j)i6dh5g^G{7&L~|BiA;)%L;>kh>*+6E9SJn6VW2fJtwjzuY z#t7qt1BAN>QNlIC2w``~z@kSM=G4i;P?}z4gUuTS_)Jv_1vad93UmR#DcI>pDJ_`s z0X05xXvw5@i7<-Lu@^XaGJO2$k%lT^iV$o$-FBc`qT^m^mD_&!6VR$feLgY$FGK6P Af&c&j diff --git a/ParticleSpy/__pycache__/SegUI.cpython-37.pyc b/ParticleSpy/__pycache__/SegUI.cpython-37.pyc index 1ec992c0aae683a55459bad2424d28d94f06ef94..084745d727c46bf2e1b83b9e6fc1188601a6884f 100644 GIT binary patch delta 2348 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 RD=Cgi&n(F(O`4c#4ghBe71IC! diff --git a/ParticleSpy/__pycache__/api.cpython-37.pyc b/ParticleSpy/__pycache__/api.cpython-37.pyc index 7a5a8483df4409e55d90c7cdf5bdca29a48ae7a8..7551fa0261e54a3adbb5b629d74bb9ff67368abb 100644 GIT binary patch delta 44 ycmZ3^Karo?iIAIJKxaCM7i|C#JY4dGjyEwX6UqHxC{F delta 66 zcmbQpznq`jiIloLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o UnpaXBlb%_UQJS>*3FBH;0J2LLaR2}S diff --git a/ParticleSpy/__pycache__/find_zoneaxis.cpython-37.pyc b/ParticleSpy/__pycache__/find_zoneaxis.cpython-37.pyc index 1e0a8364f1afde52e59cc6afcc05ade7510115d6..7265cea71f1fe55b97ec00ed565bbc08870b2ca6 100644 GIT binary patch delta 44 ycmdljyHu9jiIAIJKxaCM7i|C#JY4d9yxG4-)`3c@D<_ delta 66 zcmZ1~yIYpqiItjJY!y>loLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o UnpaXBlb%_UQJS<_lBb6W0MW%4DgXcg diff --git a/ParticleSpy/__pycache__/particle_load.cpython-37.pyc b/ParticleSpy/__pycache__/particle_load.cpython-37.pyc index fd205db7cec32cb68fa7aebe1bfad10ccdf84863..6551d95539df20926cc38c28360eef432530bd65 100644 GIT binary patch delta 92 zcmX@ZzKxyRiIMv>NpVbiW=TeA(&RHt$&8AV4VX<0Z*gQ)765e=R2B&Xjkv{{SDFiC U3jo}zQ`1m4DAioGCSOn6AL`VaWHa^HWN5QtjA)ykZt0!NSDB F1OPh59cusp delta 145 zcmeBSTg1lg#LLUY00f_k-)!W5$;fzX@>j-GU1^}muYhE$n9}0ZqT-m6jQrfhVuj+I z#FEsan3VkF(%jU%lH!>3%#w`Kq{)R$;V!a39h%Iy*yH1Y((&;{oIrjNNU#WG77`%? aAIJKxaCM7i|C#JY4d9x<#OeM}JHgDh5 s#Ju9D&8O8jGcwk1uGg$%WQ>~pPs^IIcCwZBS|Iy{wlZVYWFDPR0GnwafdBvi delta 116 zcmX>d@i2nhiIloLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o znpaXBlb%_UQJS<_n02NS=PfpG-_*ps;#-@ys&8gwY@Ez5D6zRwGmVk)*5nsj){OO& TRkYUv*_X7H8EYng(+&jyiHIv8 diff --git a/ParticleSpy/__pycache__/radial_profile.cpython-37.pyc b/ParticleSpy/__pycache__/radial_profile.cpython-37.pyc index 3e8d7acafc3abba6395f2d2e92da9b415a34abf1..1fa57ba20fb8912767665cb6cc8a9ef78aff6b14 100644 GIT binary patch delta 44 ycmdlfy;z#tiIAIJKxaCM7i|C#JY4d9w~nFDC#r3l6dX delta 66 zcmZ21y;GXoiIloLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o UnpaXBlb%_UQJS<_jHQDytH}VxZ?WYhCZ*;SuVg4v0djwt zCR@dn7N-^!$E2j@C5YlI5&%-SSc?+#(o>7%f$XTshFr3Y29y1{ zL}jCRN-~O4i!2Bl$&FkFqUg2(RTL>qKE|cas4)2*mlvbi zWJ_)xH6-VN6vzUJY9KD=01^z09E@yC0*pnnle@WX;nFW=4c`0Cfqu8O0 hBKgVBxKFC60hJVqfd~Z<0WuBA!(h8qCtv0<0RT(pRX+d# delta 389 zcmew;*)GNH#LLUY00f_k-)!Xm&BAzVGCQk1kaTCYw~+;k-(t&2OiIluUdd3T2IT(o zPPU3EElw>ejw#8=&rK{=D9%YNNiB*=$xklLP0cGQj!Dlf$tX>lyoNQLQDZX;TQ(D~ zCQxG$$QDhmBH76`93BFyAQ6yx5JG+P6%H9j?OU8_`S~RUMVWaeMIaTLj78QUinB-n zNZn#BO3X`7Em8onCrfk58XJLFEctn<#bDEmcz}FO&RaYs8AYkZ8S$C9i9qF&AVut{ zMft^<`FXb{XLA{dqT3EsQKU3^1D86Z(&QUlUW^u#mAQ2UkemlnAU8RlTa;05aw)g1 w9N1#s;^fSNO1-=kusyffp^PGh$rrd!s%U`ph=EN8>jn`B6TvL?$$NQB0G={rQ2+n{ diff --git a/requirements.txt b/requirements.txt index 1e07d7d..0bc0edc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ coverage>=4.4.0 pytest>=4.6 -pytest-cov \ No newline at end of file +pytest-cov +test \ No newline at end of file From 2929e6de5a3e387a268cd88a96cd36d438499a0d Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 3 Jul 2020 16:38:06 +0800 Subject: [PATCH 02/28] Revert "test" This reverts commit 6ec6344be89ab0b9c05f901c8b5cfe01d954924a. --- .../ParticleAnalysis.cpython-37.pyc | Bin 10214 -> 10236 bytes ParticleSpy/__pycache__/SegUI.cpython-37.pyc | Bin 11664 -> 11686 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 160 -> 182 bytes ParticleSpy/__pycache__/api.cpython-37.pyc | Bin 1937 -> 1959 bytes .../__pycache__/find_zoneaxis.cpython-37.pyc | Bin 3749 -> 3771 bytes .../__pycache__/particle_load.cpython-37.pyc | Bin 950 -> 972 bytes .../__pycache__/particle_save.cpython-37.pyc | Bin 780 -> 802 bytes .../__pycache__/ptcl_class.cpython-37.pyc | Bin 11339 -> 11361 bytes .../__pycache__/radial_profile.cpython-37.pyc | Bin 3491 -> 3513 bytes .../__pycache__/segptcls.cpython-37.pyc | Bin 3313 -> 3335 bytes requirements.txt | 3 +-- 11 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc b/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc index adad038501d8a70cbbd56f48ff24c92b1f199a33..13e52ecb30c71fe1f1badc4a79dc337786b39423 100644 GIT binary patch delta 1855 zcmb`IO>7%Q6vsVI?D#V%No(@`RqU|p2NI}(wt=G1q(DOgght4X*sj+TdlK)i`({lN zID`WwP}&q2zCS7FI1X6~Vvj^3Si+my%4Ycaz&pH-}Rz3>z2I$70di zs~(uvhLC2ByA{8xRUuPh`_xWmKBwc0qT*ULotDAZ^f&8VtLvE~tWS+)_hIG9tbshA z{q>RiseV$pK6j2=qKEB+L9OSZJ^&Cr%%9`bKST1{Z!$B!>xgz{( zqomGv{=}A=hwnJswzVHSLJwlzNI*L^1_?t5o#Za|1FEq^&Pl?(6loW(^}G=;W`tu^ zxQSy5E@6)1Pf(l*SfFpBZh}9I7@-tlVL!yp8L}0(DO$d0=khYOHr^SWr$!-7I+?yR2*o_fYW8lc4mcEpbVUdXJL?gmFSt9t)MN%uL2>k=B2 z(Rra^xxQEtw&e@Yg=usayTWy{J*V#B-9Z0Mt--=XOY1s)^Wxxn)svl;?>WLY>l}is z+A^6LESjUqB+!Vk9P4J|3})2BLoczp<_|;jY>*BCE@dP#3#&+@O?OCMq00s*)WMPd z>DMUX65(~iWx^H04&hdJxJu182yYVhC{f!ZA3Pl_5$$)dPSA%IE*#A|IGH%lx6v-9 zcv+eb$Ln7XPRDNc-ip*qHDUBicJ8g46~bEot+qwuu6U9Y%s<@9P^a1$A3a0$bLi=aL0(EM%uE4I}V|33wzRHFmlqq)3KXc_85 z@*Vw%vO?kTF?l|@P3j)i6dh5g^G{7&L~|BiA;)%L;>kh>*+6E9SJn6VW2fJtwjzuY z#t7qt1BAN>QNlIC2w``~z@kSM=G4i;P?}z4gUuTS_)Jv_1vad93UmR#DcI>pDJ_`s z0X05xXvw5@i7<-Lu@^XaGJO2$k%lT^iV$o$-FBc`qT^m^mD_&!6VR$feLgY$FGK6P Af&c&j delta 1830 zcmb`I&2Jl35WxK$e>)D%M~&l;d?7npK~q3Yn*5_%F6hjM`nLP8)P5L`J?I8;IiY5xEaf)h6os+d`)Z7>xlBIUR9X6DVz zn|ZtbYw@SWLrl@7)tDBSupL z82MmILawI1-}fZO_u{(ga?{b>rWaJyj{|T5wSOK_r^^k8gHzUcyBqMyrJur!G;EEM9z~58 zbwN?j+f6T2*Uj@%+|Me<3}v&T>5dDh?{5ogRan549JMvHsV>$8mdyeC!Q9bCUYHc`W{PaG^+jesV`cI4U~!Am!OMh)B!dbWUO>ok$F+c0 z48?{+w2mw(hK&t>6chhuvuNm~(9uUWdvvV#vGzb?78-z_llW>1KT%zS=!YhPbnZ>Q) z_fPw$q~ZBT1)Kw&eTo!x&9K2+_>dD^b1FOi`KR~ph_vfU>&D0@Y~|H^5!$i-yV{N# z9~4jJ_~&m=qn%l7kBvM}@x8F(y5RVQ`f0qdTDKf7Mf{?@SXIYQnqqK|RiUGxU43Z% zG4>hT>ahQx1!JjF6kemVyiVvyb&YhBZ;)5JaJWvI8xL{aRW(@);%xDyaT~?saDf!y zi_9mng3U5QYfDgb~6hVT=$Yyh$h!9;Ec8lcbwPoN7ax_1_?vONq$ZD`N4qnlVru+}lH35ONJB*DKL^m4-t!i!jI=eX+n$^TWe_-cIaZ(R+d-T(jq diff --git a/ParticleSpy/__pycache__/SegUI.cpython-37.pyc b/ParticleSpy/__pycache__/SegUI.cpython-37.pyc index 084745d727c46bf2e1b83b9e6fc1188601a6884f..1ec992c0aae683a55459bad2424d28d94f06ef94 100644 GIT binary patch delta 2455 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 RD=Cgi&n(F(O`4c#4ghBe71IC! delta 41 vcmdnSxPXz{iIloLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o UnpaXBlb%_UQJS>*3FBH;0J2LLaR2}S delta 44 ycmZ3^Karo?iIAIJKxaCM7i|C#JY4dGjyEwX6UqHxC{F diff --git a/ParticleSpy/__pycache__/find_zoneaxis.cpython-37.pyc b/ParticleSpy/__pycache__/find_zoneaxis.cpython-37.pyc index 7265cea71f1fe55b97ec00ed565bbc08870b2ca6..1e0a8364f1afde52e59cc6afcc05ade7510115d6 100644 GIT binary patch delta 66 zcmZ1~yIYpqiItjJY!y>loLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o UnpaXBlb%_UQJS<_lBb6W0MW%4DgXcg delta 44 ycmdljyHu9jiIAIJKxaCM7i|C#JY4d9yxG4-)`3c@D<_ diff --git a/ParticleSpy/__pycache__/particle_load.cpython-37.pyc b/ParticleSpy/__pycache__/particle_load.cpython-37.pyc index 6551d95539df20926cc38c28360eef432530bd65..fd205db7cec32cb68fa7aebe1bfad10ccdf84863 100644 GIT binary patch delta 136 zcmdnSeukafiIMv>NpVbiW=TeA(&RHt$&8AV4VX<0Z*gQ)765e=R2B&Xjkv{{SDFiC U3joj-GU1^}muYhE$n9}0ZqT-m6jQrfhVuj+I z#FEsan3VkF(%jU%lH!>3%#w`Kq{)R$;V!a39h%Iy*yH1Y((&;{oIrjNNU#WG77`%? a}zQ`1m4DAioGCSOn6AL`VaWHa^HWN5QtjA)ykZt0!NSDB F1OPh59cusp diff --git a/ParticleSpy/__pycache__/ptcl_class.cpython-37.pyc b/ParticleSpy/__pycache__/ptcl_class.cpython-37.pyc index cbe4f0ce0589eecbd8931c60aab6d49b6ad9134b..a6a8454ff13ee2f14d43019aa701a77d03e7af01 100644 GIT binary patch delta 116 zcmX>d@i2nhiIloLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o znpaXBlb%_UQJS<_n02NS=PfpG-_*ps;#-@ys&8gwY@Ez5D6zRwGmVk)*5nsj){OO& TRkYUv*_X7H8EYng(+&jyiHIv8 delta 90 zcmaDDaXNzAiIAIJKxaCM7i|C#JY4d9x<#OeM}JHgDh5 s#Ju9D&8O8jGcwk1uGg$%WQ>~pPs^IIcCwZBS|Iy{wlZVYWFDPR0GnwafdBvi diff --git a/ParticleSpy/__pycache__/radial_profile.cpython-37.pyc b/ParticleSpy/__pycache__/radial_profile.cpython-37.pyc index 1fa57ba20fb8912767665cb6cc8a9ef78aff6b14..3e8d7acafc3abba6395f2d2e92da9b415a34abf1 100644 GIT binary patch delta 66 zcmZ21y;GXoiIloLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o UnpaXBlb%_UQJS<_jHQAIJKxaCM7i|C#JY4d9w~nFDC#r3l6dX diff --git a/ParticleSpy/__pycache__/segptcls.cpython-37.pyc b/ParticleSpy/__pycache__/segptcls.cpython-37.pyc index 7fccec845df9a43ddbe01cd61cd3be70deda2da0..84d0a5bf9dcc7b6202ab90e314f80bb0c18dc713 100644 GIT binary patch delta 389 zcmew;*)GNH#LLUY00f_k-)!Xm&BAzVGCQk1kaTCYw~+;k-(t&2OiIluUdd3T2IT(o zPPU3EElw>ejw#8=&rK{=D9%YNNiB*=$xklLP0cGQj!Dlf$tX>lyoNQLQDZX;TQ(D~ zCQxG$$QDhmBH76`93BFyAQ6yx5JG+P6%H9j?OU8_`S~RUMVWaeMIaTLj78QUinB-n zNZn#BO3X`7Em8onCrfk58XJLFEctn<#bDEmcz}FO&RaYs8AYkZ8S$C9i9qF&AVut{ zMft^<`FXb{XLA{dqT3EsQKU3^1D86Z(&QUlUW^u#mAQ2UkemlnAU8RlTa;05aw)g1 w9N1#s;^fSNO1-=kusyffp^PGh$rrd!s%U`ph=EN8>jn`B6TvL?$$NQB0G={rQ2+n{ delta 367 zcmZpd`Y6fm#LLUY00h;q|83;{&B7QpnVr=hNV>DytH}VxZ?WYhCZ*;SuVg4v0djwt zCR@dn7N-^!$E2j@C5YlI5&%-SSc?+#(o>7%f$XTshFr3Y29y1{ zL}jCRN-~O4i!2Bl$&FkFqUg2(RTL>qKE|cas4)2*mlvbi zWJ_)xH6-VN6vzUJY9KD=01^z09E@yC0*pnnle@WX;nFW=4c`0Cfqu8O0 hBKgVBxKFC60hJVqfd~Z<0WuBA!(h8qCtv0<0RT(pRX+d# diff --git a/requirements.txt b/requirements.txt index 0bc0edc..1e07d7d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ coverage>=4.4.0 pytest>=4.6 -pytest-cov -test \ No newline at end of file +pytest-cov \ No newline at end of file From ac91654527f0890ae48a2d58e1a53c9b2e5175e7 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 4 Jul 2020 16:52:58 +0800 Subject: [PATCH 03/28] store segmented particles Set default store_im to ture to store segmented particles after call ps.ParticleAnalysis --- ParticleSpy/ParticleAnalysis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index 2cf8102..5821ca8 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -285,7 +285,7 @@ class parameters(object): """A parameters object.""" def generate(self,threshold='otsu',watershed=False,watershed_size=50, - watershed_erosion=5,invert=False,min_size=0,store_im=False, + watershed_erosion=5,invert=False,min_size=0,store_im=True, pad=5,rb_kernel=0,gaussian=0,local_size=101): self.segment = {} self.segment['threshold'] = threshold From 0b9c0489e582628c4d59e5be82bc2d56455c9068 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 4 Jul 2020 18:44:02 +0800 Subject: [PATCH 04/28] add function to show all segmented particle images eg. particles.show(). The displayed particles were normalize_boxing. Next step should enable option to display all particle images without normalize_boxing --- ParticleSpy/ptcl_class.py | 59 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/ParticleSpy/ptcl_class.py b/ParticleSpy/ptcl_class.py index 5951961..7be8265 100644 --- a/ParticleSpy/ptcl_class.py +++ b/ParticleSpy/ptcl_class.py @@ -101,7 +101,8 @@ def store_spectrum(self,spectrum,stype): def store_composition(self,composition): self.composition = {el.metadata.Sample.elements[0]:el.data for el in composition} - + + class Particle_list(object): """A particle list object.""" @@ -113,7 +114,7 @@ def append(self,particle): def save(self,filename): save_plist(self,filename) - + def plot_area(self,bins=20): """ Displays a plot of particle areas for analysed particles. @@ -254,6 +255,60 @@ def normalize_boxing(self,even=False): particle.image.axes_manager[0].size = particle.image.data.shape[0] particle.image.axes_manager[1].size = particle.image.data.shape[1] + def show(self, param='Image'): + """ + display all particle images or other parameters + + Parameters + ---------- + param : str or list, optional + DESCRIPTION. The default is ['Image']. + 'Image' + 'maps' + 'area' + 'circularity' + """ + self.normalize_boxing() + + if param=='Image': + num = len(self.list) + cols = int(np.ceil(np.sqrt(num))) + im_ls = [] + for index in range(num): + im_ls.append(self.list[index].image.data) + self._show_images(im_ls, cols, np.arange(num)) + + def _show_images(self, images, cols=1, titles=None): + """ + Display a list of images in a single figure with matplotlib. + + Parameters + --------- + images: List of np.arrays compatible with plt.imshow. + + cols (Default = 1): Number of columns in figure (number of rows is + set to np.ceil(n_images/float(cols))). + + titles: List of titles corresponding to each image. Must have + the same length as titles. + --------- + Origin https://gist.github.com/soply/f3eec2e79c165e39c9d540e916142ae1 + """ + assert((titles is None) or (len(images) == len(titles))) + n_images = len(images) + if titles is None: titles = ['Image (%d)' % i for i in range(1, n_images+1)] + fig = plt.figure() + for n, (image, title) in enumerate(zip(images, titles)): + a = fig.add_subplot(cols, np.ceil(n_images/float(cols)), n+1) + if image.ndim == 2: + plt.gray() + plt.axis('off') + plt.imshow(image) + a.set_title(title, fontsize=30) + fig.set_size_inches(np.array([1,1]) * n_images) + plt.show() + + def cluster_particles(self,algorithm='Kmeans',properties=None,n_clusters=2,eps=0.2,min_samples=5): """ Cluster particles in to different populations based on specified properties. From c01d4be1dae3d99c61af2ad5640cf82ead39bf74 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Wed, 8 Jul 2020 14:37:31 +0800 Subject: [PATCH 05/28] pycache --- .../Parameters/parameters_current.hdf5 | Bin 8720 -> 8720 bytes .../Parameters/parameters_previous.hdf5 | Bin 8632 -> 8720 bytes .../ParticleAnalysis.cpython-37.pyc | Bin 10236 -> 10215 bytes ParticleSpy/__pycache__/SegUI.cpython-37.pyc | Bin 11686 -> 11664 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 182 -> 160 bytes ParticleSpy/__pycache__/api.cpython-37.pyc | Bin 1959 -> 1937 bytes .../__pycache__/find_zoneaxis.cpython-37.pyc | Bin 3771 -> 3749 bytes .../__pycache__/particle_load.cpython-37.pyc | Bin 972 -> 950 bytes .../__pycache__/particle_save.cpython-37.pyc | Bin 802 -> 780 bytes .../__pycache__/ptcl_class.cpython-37.pyc | Bin 11361 -> 13316 bytes .../__pycache__/radial_profile.cpython-37.pyc | Bin 3513 -> 3491 bytes .../__pycache__/segptcls.cpython-37.pyc | Bin 3335 -> 3313 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/ParticleSpy/Parameters/parameters_current.hdf5 b/ParticleSpy/Parameters/parameters_current.hdf5 index ebb9f72f25bebdb027d1a61ab4257153ea53a4a5..9d8fb9f4e79faca8ecd7eafc4d359099bee6f4c5 100644 GIT binary patch delta 90 zcmbQ>GQnj5FC)ujMqYa!76u5&FDWkF?8B=gFgZX@XmXdV9;4CZowDwXtdkk#`k5FQ nCQp*H14>Cuej%s9$S_$@{y$JkP+>VxjAQZ#MTN}|6bu*v@1ht* delta 81 zcmbQ>GQnj5FC)`rMqYa!CI$$|$z)*I?8B=gz{ohcQr4bPWAaW}cSf$sjB@=<7uY9H glCxvdWt@CT&JHLqDF2^PWU`>baz@6@I~Bqi0oHO8XaE2J diff --git a/ParticleSpy/Parameters/parameters_previous.hdf5 b/ParticleSpy/Parameters/parameters_previous.hdf5 index ddb527b210f245a97d43df5065cc21380b53140d..ebb9f72f25bebdb027d1a61ab4257153ea53a4a5 100644 GIT binary patch delta 131 zcmdntJi%px29to&LM?Vi_Q~4pvWx|rJ=wQ2F+SML$n~Fzk!dm`uRRYF0|ew`GB9lR z;mr|X)R??e)}4`SGNW8S(*^d)ljQ7}bQvdKlCzs6$2D0>ejg*_vcq|T2Gb73g<9;BUvY{}c3|gVl-TUazMYA&V>2Vye3u)Pm;5n93Uq#`GuSYBg14t`Qtzy*W^d?dO)Ru Q3h|R8*YY+vwAIF{Du4 zVuq%QJvDj5V3NG0nNpSN6>DAO#aM;(^4-`%QVc9<6%)fNthMv~h-jBRJm{TBjP%)~Fnr^ZL_az_M#*|J9JJ6`BnDjVk z?4ZSD<$S$q`>L9LUI;r`#ZXP&l2pyK*y(%QylR;(z)B3(Rj?@*)WnQBWzY{|?Jo=C zCM>N+p)DFUW$1E~f1VsBE3MnfgJdd;4*tz`$|#$~_(jCyh(nIaT$f=MJ`Eu%dS#lOpB0_diA`R#Nc|0}af zl3dCbCd9-V479?GhOSDRnywm~rX8qJYu!-U00#Cl9WJgMV242#`PbQ8vVv0Qg@&wK zT3J(MOEYvf$$!lbOyk_$+xD()iqX3d0t{E|lr5vCDH0q6=gDiUbehlP`pGn3&OO}K ztA^Fcn?&@feQH#V@%MB6PsR^;%0%r{yFeeKfsNpe5Dnjm(CAHalc=t>TkQdBTum%_ zgnl-|f6k4QGp#^=kYw?6K#x71lk6N&=&*w(t<>-paEPB6OwU^A&_G;7Y$CQ0O~k$J z>=G_tM!bU9cNhG_!4FP59m9j*w2i?`v5%9ez#|L8+J=i5p{gnE_4=RQ`y=A6%dMTE z&&bNFcO$s5{=3??8t)g6OO?NC{R z*P~pcHYu~Vg7)>H_4~*dWV_A&e-;d-3PJWd-pd<^wp3S8H}MvFxrMW%OYd zn&amRFOJqhJjpJgf;l1qo^fP`q6?G%R5-f*8m=!R@`ypi5MmfHg76~VM&uCpQ##Tq z)Xf005ZdepAw+y$5Al#lFZ@IKv||;>f>30;U>5sc*n7b*)tmgiVv=O}C&dDMe{L0( z=rQncJ2T8DM;~2Y!u2u&>$ClrC^Jm=D}tW`wt|>II7b6t6l@w`2aL51s#s3)f7Q&t H8J+zbiqEm+ delta 1947 zcmb`IOKcoP5Qewc-uEN;k&WL^cFlm3NT3*!7>JzM1RQL@#Gs9p$#|x{JNE9(rg|3J zaPTD|2J!%!_almhI3O;dRW6)BT#*ps)@LMygpkM)aiD58j;&STge`qjT~*!vcXxH~ zud{#8rY2IUcmV%yiQmsof1TQlF(u!NU1F-%7hhu7xR^K`YQ+R4zfVl|si?^v4_w<) zEoEcb1>IP)g+{l>lLo#t>gjLDF;*SIPzFZ zL!L|heEeY=KV~}~cZBV&tDs?i5rF5>``4U#WT7fJhy}0cmJKl=N`}W_!E()N8KsDY zg6$Qni}GCh2R2{Zzvpz*#$N0QZHO5y3eD8$A@m|tj62v5XpDJsju9TDNVDx2FKOX? z(k>eXuH&3G7jTN=Pg9)PFiYQP#Q@JXOWYS&$7u>=o~Z{UYkMeh20gzuA)vMPc-!@0 z3yH$@MohOCpdQ`*%!(6GXtLBpJtZ1>if@s-T(=A(g zaQ05OptS^fsb{(pv|YE=$P1Z6tXTUdv!5O5qwzwkMGhQhDCIuFBZQ-VNE8h`nPwZ$ z2{P!>;*h84tQ_nZ@3Sc$ocrI|gY*gSeY-70?I}~lkJdqFclHb84e}!1K1rr zGI#9;H9O^%t`V%fn_ZXVzOXEMm7MPGO`SkX3*DYkR=W?3HuR;0Bnt#Y8jS!;v#9@{ z3C0vwiZ(o-Ed~+tahrMZ*PQ13%!~VR#g6)y;*6mF01L5s$V2Zq>2$Rok)L zRRLAXNT077j%P2~rs3JH0~6@Xx77E^bjuYN?*{s}wfY+qTwGO&?Tdr;s>afW=ay|# zuW<0MYQthCanKAcCW=OYWmqd4VlXL>_1^zNs};3k7g)a8YO~^20<91aFGp@fdF)1< zC$`uYvy%G)OUz1HX^bZSCA!DD2cs#gWiFt#!zuY)@4?!iz5T3*$_o!E5SW5xq}HS& zf*0r-!%;cf-!<_XCA>~}gK(K}g>aQ{r#oDu=9`4K2)ouOH~T+)&fk2hB>x1U6D>Rv z+E2gcaR=W)J0Itk(90Yj7R#@@o$TEsQZHE(17ET;Z*PxKAM3x>HfY=tPjdYA*NddC zQ?3sUOw;%(WOyD3U#LHg3YjHWa4qbMR?#IJUt6Qh6cZg@@_c%i)Lp76+AmLLpB=e~<`le2j!V9YHH!|ify_EK z<+s_xPrOTQNf;mu5{3xFgnJ1=!gWGFVP{I;qURgy^jNMpLGQiBX0#l9CX2Zo>yy`V zbhU5h%*07b^H)49het-|b!smX1`sOrG6z@Ge^%)EhazE|;2$}?BS800h26zvZhG|} Mmqsn}^O1>v0Qr{Cb^rhX diff --git a/ParticleSpy/__pycache__/SegUI.cpython-37.pyc b/ParticleSpy/__pycache__/SegUI.cpython-37.pyc index 1ec992c0aae683a55459bad2424d28d94f06ef94..084745d727c46bf2e1b83b9e6fc1188601a6884f 100644 GIT binary patch delta 2348 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 delta 66 zcmbQpznq`jiIloLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o UnpaXBlb%_UQJS>*3FBH;0J2LLaR2}S diff --git a/ParticleSpy/__pycache__/find_zoneaxis.cpython-37.pyc b/ParticleSpy/__pycache__/find_zoneaxis.cpython-37.pyc index 1e0a8364f1afde52e59cc6afcc05ade7510115d6..a3563bd503fe92c13b45b7b0631e5a04cff94111 100644 GIT binary patch delta 65 zcmdljyHu9jiIAIJKxaCM7i|C#JY4d9yyxTSkE>-s0rU Tf=a!#w333vA!lo99 delta 87 zcmZ1~yIYpqiItjJY!y>loLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o pnpaXBlb%_UQJS<_lIJa>z%Ab5 diff --git a/ParticleSpy/__pycache__/particle_load.cpython-37.pyc b/ParticleSpy/__pycache__/particle_load.cpython-37.pyc index fd205db7cec32cb68fa7aebe1bfad10ccdf84863..6551d95539df20926cc38c28360eef432530bd65 100644 GIT binary patch delta 92 zcmX@ZzKxyRiIMv>NpVbiW=TeA(&RHt$&8AV4VX<0Z*gQ)765e=R2B&Xjkv{{SDFiC U3jo}zQ`1m4DAioGCSOn6AL`VaWHa^HWN5QtjA)ykZt0!NSDB F1OPh59cusp delta 145 zcmeBSTg1lg#LLUY00f_k-)!W5$;fzX@>j-GU1^}muYhE$n9}0ZqT-m6jQrfhVuj+I z#FEsan3VkF(%jU%lH!>3%#w`Kq{)R$;V!a39h%Iy*yH1Y((&;{oIrjNNU#WG77`%? aEpm6!v)S&1Un{G)>c_4KV%9x=A+;r9eVKA`PkvG%d7JOPa8CJhQtFUVA$; zOVh}!6(k3cC_go*0wKs=xT8oMKu92Qg8V?%#~wN1VyIn&d*xG46SDQaJ0D`C=zojh-gCjzg@S zWmm~;8#^3*vC}$sgzaYiFz;l;Y=8}d*2Qvch}{QTH?!CQb`Z23Y~MxAIvV}8Q;^ir8q#*22%Q`D98>TnW_;raZwBO9yR*D7{Z4sR|s z5?_aH!R@WJ){^52r{>whRX6YMh(!qOjMXJvc#9bnlOW=h>nkyjn&EKQiw${QsMr*? zU*h61G&_J|6fHUnvK-tfxR^cJh|>@du(Hyk9e2$nAaTmCRRAmSkivc3)>fWgc;VxGPfWO*XMwr=2{P+?quLn3HTiveSn*s=|vPq zfU52GC=^bXPSMtwZgG{`2?J?Rq^9{pX zXKIxNs2PBP-CD($=+1^0Ibg`frU-7pj-*>oY+P#FOL9e3fc_vubN&Va$BJHHtDKXD z&s&z2xT0L;ae4O+tvUE01eevoXAlm=;^CC_zJ;@2nFB-0s)j(XSf~ z;0IaGCLM+54l^sMH%k}C!CY_@+pF-;>?y1-Oz;yUSd93Qw6>hzUViu1eg2deIJPIB z0A=%NQkvpvt$__CC>DRYA7CsJXNrNZq`S`c9ccFG?t#G#@M5>RWIQ`XxVULdbW&D=inX!K>SG)$6T58zSKf-O_L0d_NxaIn6G;!O}% zPjt$f>cGC9ghPB3HLRiZBFyF9sA&xv**)0@qR*{giHtrudYQ~de;<8}d>BoR>^JX# zRVBJMGDz-3%Oe%o`+4Nx!27Tor-Ow>4p+i|5yS+FI{>^VnjGD+w;!g4-U;FDgugzL M(R;4;G=PWZKL*-uLI3~& delta 473 zcmWkqyKWOv5cN2I#m_h~W({$Oi6YrVvSV8y@emSjkP_Jx6bZp3+U&j9>+Hk2cNa%W zq$nf>2vMN<04hofwBie>5Jg(FsSpJP9nhs=_Kxn+oHIwGnK>Q)*vxh^nPiCG^2N*T zUn`%oeCbt~fAL!1|-Sy_8+i4i%8dOsYY?>uc zVJptA;fH*!w8$>8BJnh0j0l413!ZE;! z_oBENfp^~7mA3$&y=U{~FnsY27P?dL9lur{C1UF)S1sA|KGqH+Fv1)44$WZJ)hQn= z%vFof#GiFu@nh@V!04x*>(0(taHeaHuxM2w0+6UT%5gs`RBOQTP2*AIJKxaCM7i|C#JY4d9w~nFDC#r3l6dX delta 66 zcmZ21y;GXoiIloLW>IQ<9ONn^>$+oRe6RS`?F#pIn-o UnpaXBlb%_UQJS<_jHQDytH}VxZ?WYhCZ*;SuVg4v0djwt zCR@dn7N-^!$E2j@C5YlI5&%-SSc?+#(o>7%f$XTshFr3Y29y1{ zL}jCRN-~O4i!2Bl$&FkFqUg2(RTL>qKE|cas4)2*mlvbi zWJ_)xH6-VN6vzUJY9KD=01^z09E@yC0*pnnle@WX;nFW=4c`0Cfqu8O0 hBKgVBxKFC60hJVqfd~Z<0WuBA!(h8qCtv0<0RT(pRX+d# delta 389 zcmew;*)GNH#LLUY00f_k-)!Xm&BAzVGCQk1kaTCYw~+;k-(t&2OiIluUdd3T2IT(o zPPU3EElw>ejw#8=&rK{=D9%YNNiB*=$xklLP0cGQj!Dlf$tX>lyoNQLQDZX;TQ(D~ zCQxG$$QDhmBH76`93BFyAQ6yx5JG+P6%H9j?OU8_`S~RUMVWaeMIaTLj78QUinB-n zNZn#BO3X`7Em8onCrfk58XJLFEctn<#bDEmcz}FO&RaYs8AYkZ8S$C9i9qF&AVut{ zMft^<`FXb{XLA{dqT3EsQKU3^1D86Z(&QUlUW^u#mAQ2UkemlnAU8RlTa;05aw)g1 w9N1#s;^fSNO1-=kusyffp^PGh$rrd!s%U`ph=EN8>jn`B6TvL?$$NQB0G={rQ2+n{ From c84517f282c493e9d819c9e8b0169c9059a7d803 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Wed, 8 Jul 2020 14:53:08 +0800 Subject: [PATCH 06/28] Set store_im to False --- ParticleSpy/ParticleAnalysis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index 5821ca8..2cf8102 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -285,7 +285,7 @@ class parameters(object): """A parameters object.""" def generate(self,threshold='otsu',watershed=False,watershed_size=50, - watershed_erosion=5,invert=False,min_size=0,store_im=True, + watershed_erosion=5,invert=False,min_size=0,store_im=False, pad=5,rb_kernel=0,gaussian=0,local_size=101): self.segment = {} self.segment['threshold'] = threshold From 67ddc5b50c1403f69c3acefc2fcfafc26cc7ff27 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Wed, 8 Jul 2020 15:00:41 +0800 Subject: [PATCH 07/28] pycache ignored --- .gitignore | 1 + .../ParticleAnalysis.cpython-37.pyc | Bin 10215 -> 10214 bytes ParticleSpy/ptcl_class.py | 6 ++++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 82f1b04..2b79115 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ ParticleSpy/__pycache__/ ParticleSpy/Parameters/ particlespy.egg-info/ ParticleSpy/__pycache__/*.pyc +*.pyc diff --git a/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc b/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc index 9c20246a3e72a171ded0f073f77771a5d3e2bf03..08c551d903c02a516ae18072896b1e4ac7aa80de 100644 GIT binary patch delta 2338 zcmb_e-EUMy6yI5PxBJ-^TGrAJ+Aen2RldZC!4O13L1-vqQy^+`y}fsKJMG>N&b>>! z_)t((REW_rMiU<(ii-FFZqSIDsQ-X5@o657(fHtlKKkT2_flFm=#y>oyJyZhbLMx> zoSE6*4*q&Dw=0)RNAPdA71zeD<~FC8k~>mI5Z_2`>{K~n``q?~-_R_5Udf+Q`Mrte;rG`Q`9 zBTTi@(q|md^m*ZFHEvh^X;cZjMJ2ao3%K5s*|j~Ylj3nBh#(9k2CIpJd@Z{_uM!iY zYU?$X@q(}BH(ajdU)hbUUk>NGF~-(h8S$yyX2e%>T?;DaYQj=+OZR47l{H08_qmC= zc(W?Ee6&U7rkuKM>OiGHYZ9{z6H8NiT9|H@w1xn~6uPC-gf}dmfj<>0Ow_}rc?pEd zkbAwR10}PAl1bgHx{B(?r3lQ({p~-qT606klo!|ko#DuLMFDF!1Sh!1?$3bupCdq!7>`cH>`X*f+d|}i$%#baBSu*4w4GofY z-IoE>{Jw%5x|$Dly&f%flH5T+^svTlhEuCswihrhM?+hu{CoA_!VtL;GnJ^jCUKph zL7NY{G3z!|tS0Q)aw_DN#JI6ugf9~iaX3qG z>n=mTJl9*o({io%Y&sxz7dk09);CZ+fKoZWv?3n#;Cy9tLtAVb)xB(>c`i3_->lX} zC{mV1B3?TR5!TLujl$dbfj~~c9+Xud_i$&i zeY7d;n<~)h)aHb3I&&VJBailDb=~$wMHsp-92>?+xiT!M;aIMN7aQsqlL{&rotjgb z#q)u$Mzuy@z{gKjd*aGsgfP~B zvu)wHM4spb`G-vs@|2Cj&=|#6aozX93y6j-5I1U$$IFS3bh0AwM%FE^SOr=LEvrNG zm%|&Wvt0skdKTUD!qf^9(b1& z7XuM{78N7|i6Oivza81Ow@Krx1i_VYCrKj&MS>DRl;9hJ0>RRffiz3HNx8E)&_Pd3 znT?l=@I6XO)`|r-EMFPGuJ`G8HXA=xXyL*I@e2?Vr#XTI;(&xWa-ym?j-6HDge`qjT~*!nRd-eQ z{(Abi(}np$AsfTL-Xk%6;j6-~4CC^-%z4C*Gt=F?V7sAk13RqijpH%GE% zh8{O_`)7J^F3%flB0vY%s0fIXfoW7ll&raS81Qr;LfrsiL~-Bd@{io$Zk{%U8-izB zyvH#vd!QR@cA!^RM>_1L7}g~6TWUcJn0z0iqG?wT{S{sVJ^W6 zFKiy|;e{oy=2`~OR-iSFS*pZ%meSK(>E=mm+F)9?;qWZseM`6Ur;TbQ8enKK1vbx- zd#!2!C9?~Yi82p%J&GIV=P@`g7dn4t3(cKfFK=n|qYLyRoYK;epuqsaAVQQ8Zp{&Z zIluxbX9%XrlCWLls+Qt;+rd-P0|B-OV2w7A98a2OfA%~vk;l7XJQ(Yu?5)eI&MIEMBtvPO>m}>EstxNvBb+kcD6|*Q+^DW|f z7&TEx2!^@h*P}$$c2~5F;>FWgce-Txgnp^=N^)8Xq&-kPx5;=-)FUYcOD&3mO8#xBYqw+}QZ8$Zx1!Uc*9uM#{WF6d-< z0fA?N&;x-b=fl%9PAwXakEgQ@2U@;G<`{WjLWmNyK2M3NnqZKAiNGYV9wQV4L>$Tl z51%rWtt#5UyNrN9FRW@)>%=W7@EKq^@fHT+bM1wT>OBNQ?L(ZJ}3e_Su7uY z3G1c;)SddO?ONVy02T7+yizmV&@S7i5!#*$&ycdGwV|fx_#R$ts9#U&5}Kp<(kjob z_aC+h-`8n`o?~N<0@SV3wqplzR*{lPqYz_7*2~5j9F%jzkDu?eGFJ9&#uHY*m9z3F zB}M9T$KABZ+|7#IJ$8>-g>A7ivpTIVwC4ZC+HLiqwP5uw#Tt&n?pU908GylGg-yLF)mehYBtb%o3 Date: Wed, 8 Jul 2020 15:01:16 +0800 Subject: [PATCH 08/28] Revert "pycache ignored" This reverts commit 67ddc5b50c1403f69c3acefc2fcfafc26cc7ff27. --- .gitignore | 1 - .../ParticleAnalysis.cpython-37.pyc | Bin 10214 -> 10215 bytes ParticleSpy/ptcl_class.py | 6 ++---- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 2b79115..82f1b04 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ ParticleSpy/__pycache__/ ParticleSpy/Parameters/ particlespy.egg-info/ ParticleSpy/__pycache__/*.pyc -*.pyc diff --git a/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc b/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc index 08c551d903c02a516ae18072896b1e4ac7aa80de..9c20246a3e72a171ded0f073f77771a5d3e2bf03 100644 GIT binary patch delta 2340 zcmb_eOK%)S5Z>PGuJ`G8HXA=xXyL*I@e2?Vr#XTI;(&xWa-ym?j-6HDge`qjT~*!nRd-eQ z{(Abi(}np$AsfTL-Xk%6;j6-~4CC^-%z4C*Gt=F?V7sAk13RqijpH%GE% zh8{O_`)7J^F3%flB0vY%s0fIXfoW7ll&raS81Qr;LfrsiL~-Bd@{io$Zk{%U8-izB zyvH#vd!QR@cA!^RM>_1L7}g~6TWUcJn0z0iqG?wT{S{sVJ^W6 zFKiy|;e{oy=2`~OR-iSFS*pZ%meSK(>E=mm+F)9?;qWZseM`6Ur;TbQ8enKK1vbx- zd#!2!C9?~Yi82p%J&GIV=P@`g7dn4t3(cKfFK=n|qYLyRoYK;epuqsaAVQQ8Zp{&Z zIluxbX9%XrlCWLls+Qt;+rd-P0|B-OV2w7A98a2OfA%~vk;l7XJQ(Yu?5)eI&MIEMBtvPO>m}>EstxNvBb+kcD6|*Q+^DW|f z7&TEx2!^@h*P}$$c2~5F;>FWgce-Txgnp^=N^)8Xq&-kPx5;=-)FUYcOD&3mO8#xBYqw+}QZ8$Zx1!Uc*9uM#{WF6d-< z0fA?N&;x-b=fl%9PAwXakEgQ@2U@;G<`{WjLWmNyK2M3NnqZKAiNGYV9wQV4L>$Tl z51%rWtt#5UyNrN9FRW@)>%=W7@EKq^@fHT+bM1wT>OBNQ?L(ZJ}3e_Su7uY z3G1c;)SddO?ONVy02T7+yizmV&@S7i5!#*$&ycdGwV|fx_#R$ts9#U&5}Kp<(kjob z_aC+h-`8n`o?~N<0@SV3wqplzR*{lPqYz_7*2~5j9F%jzkDu?eGFJ9&#uHY*m9z3F zB}M9T$KABZ+|7#IJ$8>-g>A7ivpTIVwC4ZC+HLiqwP5uw#Tt&n?pU908GylGg-yLF)mehYBtb%o3N&b>>! z_)t((REW_rMiU<(ii-FFZqSIDsQ-X5@o657(fHtlKKkT2_flFm=#y>oyJyZhbLMx> zoSE6*4*q&Dw=0)RNAPdA71zeD<~FC8k~>mI5Z_2`>{K~n``q?~-_R_5Udf+Q`Mrte;rG`Q`9 zBTTi@(q|md^m*ZFHEvh^X;cZjMJ2ao3%K5s*|j~Ylj3nBh#(9k2CIpJd@Z{_uM!iY zYU?$X@q(}BH(ajdU)hbUUk>NGF~-(h8S$yyX2e%>T?;DaYQj=+OZR47l{H08_qmC= zc(W?Ee6&U7rkuKM>OiGHYZ9{z6H8NiT9|H@w1xn~6uPC-gf}dmfj<>0Ow_}rc?pEd zkbAwR10}PAl1bgHx{B(?r3lQ({p~-qT606klo!|ko#DuLMFDF!1Sh!1?$3bupCdq!7>`cH>`X*f+d|}i$%#baBSu*4w4GofY z-IoE>{Jw%5x|$Dly&f%flH5T+^svTlhEuCswihrhM?+hu{CoA_!VtL;GnJ^jCUKph zL7NY{G3z!|tS0Q)aw_DN#JI6ugf9~iaX3qG z>n=mTJl9*o({io%Y&sxz7dk09);CZ+fKoZWv?3n#;Cy9tLtAVb)xB(>c`i3_->lX} zC{mV1B3?TR5!TLujl$dbfj~~c9+Xud_i$&i zeY7d;n<~)h)aHb3I&&VJBailDb=~$wMHsp-92>?+xiT!M;aIMN7aQsqlL{&rotjgb z#q)u$Mzuy@z{gKjd*aGsgfP~B zvu)wHM4spb`G-vs@|2Cj&=|#6aozX93y6j-5I1U$$IFS3bh0AwM%FE^SOr=LEvrNG zm%|&Wvt0skdKTUD!qf^9(b1& z7XuM{78N7|i6Oivza81Ow@Krx1i_VYCrKj&MS>DRl;9hJ0>RRffiz3HNx8E)&_Pd3 znT?l=@I6XO)`|r-EMF Date: Wed, 8 Jul 2020 15:05:45 +0800 Subject: [PATCH 09/28] Output particle image as a list of arrays Allow segmented particle images output as a list of 2D numpy arrays (without hyperspy metadata). e.g. particles = ps.ParticleAnalysis(image, params) particles.normalize_boxing() pim_ls = particles.show(output=True) --- ParticleSpy/ptcl_class.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ParticleSpy/ptcl_class.py b/ParticleSpy/ptcl_class.py index 7be8265..edef5d0 100644 --- a/ParticleSpy/ptcl_class.py +++ b/ParticleSpy/ptcl_class.py @@ -255,7 +255,7 @@ def normalize_boxing(self,even=False): particle.image.axes_manager[0].size = particle.image.data.shape[0] particle.image.axes_manager[1].size = particle.image.data.shape[1] - def show(self, param='Image'): + def show(self, param='Image', output=False): """ display all particle images or other parameters @@ -277,6 +277,8 @@ def show(self, param='Image'): for index in range(num): im_ls.append(self.list[index].image.data) self._show_images(im_ls, cols, np.arange(num)) + if output: + return im_ls def _show_images(self, images, cols=1, titles=None): """ From 19247096a93488e7c1271b68119859b8cf3523a5 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Thu, 9 Jul 2020 14:39:39 +0800 Subject: [PATCH 10/28] typo --- ParticleSpy/ptcl_class.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ParticleSpy/ptcl_class.py b/ParticleSpy/ptcl_class.py index edef5d0..42e79b0 100644 --- a/ParticleSpy/ptcl_class.py +++ b/ParticleSpy/ptcl_class.py @@ -255,13 +255,13 @@ def normalize_boxing(self,even=False): particle.image.axes_manager[0].size = particle.image.data.shape[0] particle.image.axes_manager[1].size = particle.image.data.shape[1] - def show(self, param='Image', output=False): + def show(self, params='Image', output=False): """ display all particle images or other parameters Parameters ---------- - param : str or list, optional + params : str or list, optional DESCRIPTION. The default is ['Image']. 'Image' 'maps' @@ -270,7 +270,7 @@ def show(self, param='Image', output=False): """ self.normalize_boxing() - if param=='Image': + if params == 'Image': num = len(self.list) cols = int(np.ceil(np.sqrt(num))) im_ls = [] From ed2a0937b417333f85807a531d7a09736af81e98 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 10 Jul 2020 10:50:56 +0800 Subject: [PATCH 11/28] pycache ignore --- .gitignore | 1 + .../ParticleAnalysis.cpython-37.pyc | Bin 10215 -> 10214 bytes .../__pycache__/ptcl_class.cpython-37.pyc | Bin 13316 -> 13523 bytes ParticleSpy/ptcl_class.py | 26 +++++++++++------- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 82f1b04..2b79115 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ ParticleSpy/__pycache__/ ParticleSpy/Parameters/ particlespy.egg-info/ ParticleSpy/__pycache__/*.pyc +*.pyc diff --git a/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc b/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc index 9c20246a3e72a171ded0f073f77771a5d3e2bf03..08c551d903c02a516ae18072896b1e4ac7aa80de 100644 GIT binary patch delta 2338 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 VSfzL+1T3L!DsE{RjI(GS>hA diff --git a/ParticleSpy/ptcl_class.py b/ParticleSpy/ptcl_class.py index 42e79b0..f729b48 100644 --- a/ParticleSpy/ptcl_class.py +++ b/ParticleSpy/ptcl_class.py @@ -261,7 +261,7 @@ def show(self, params='Image', output=False): Parameters ---------- - params : str or list, optional + params : str, optional DESCRIPTION. The default is ['Image']. 'Image' 'maps' @@ -270,17 +270,19 @@ def show(self, params='Image', output=False): """ self.normalize_boxing() - if params == 'Image': - num = len(self.list) - cols = int(np.ceil(np.sqrt(num))) - im_ls = [] - for index in range(num): - im_ls.append(self.list[index].image.data) - self._show_images(im_ls, cols, np.arange(num)) + num = len(self.list) + cols = int(np.ceil(np.sqrt(num))) + data_ls = [] + for index in range(num): + if params == 'Image': + data_ls.append(self.list[index].image.data) + elif params == 'mask': + data_ls.append(self.mask) + self._show_images(data_ls, params, cols, np.arange(num)) if output: - return im_ls + return data_ls - def _show_images(self, images, cols=1, titles=None): + def _show_images(self, images, main_title, cols=1, titles=None): """ Display a list of images in a single figure with matplotlib. @@ -293,6 +295,9 @@ def _show_images(self, images, cols=1, titles=None): titles: List of titles corresponding to each image. Must have the same length as titles. + + main_title: str. Name of the showing properties. + Can be 'Image', 'mask', 'area', etc. --------- Origin https://gist.github.com/soply/f3eec2e79c165e39c9d540e916142ae1 """ @@ -308,6 +313,7 @@ def _show_images(self, images, cols=1, titles=None): plt.imshow(image) a.set_title(title, fontsize=30) fig.set_size_inches(np.array([1,1]) * n_images) + plt.title(main_title) plt.show() From 935cdb0be5ff9f37d21e083bbe45f3e91143ccd3 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 10 Jul 2020 10:52:04 +0800 Subject: [PATCH 12/28] Revert "pycache ignore" This reverts commit ed2a0937b417333f85807a531d7a09736af81e98. --- .gitignore | 1 - .../ParticleAnalysis.cpython-37.pyc | Bin 10214 -> 10215 bytes .../__pycache__/ptcl_class.cpython-37.pyc | Bin 13523 -> 13316 bytes ParticleSpy/ptcl_class.py | 26 +++++++----------- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 2b79115..82f1b04 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ ParticleSpy/__pycache__/ ParticleSpy/Parameters/ particlespy.egg-info/ ParticleSpy/__pycache__/*.pyc -*.pyc diff --git a/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc b/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc index 08c551d903c02a516ae18072896b1e4ac7aa80de..9c20246a3e72a171ded0f073f77771a5d3e2bf03 100644 GIT binary patch delta 2340 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 VSfzL+1T3L!DsE{RjI(GS>hA delta 2375 zcmaJ@+iw(A7@sqj-Pvt-+tQ`9w7}8}?EqOW1(dr$0fAV;C0q<-na<2^r|gY0XX%C6 z)ClpCh+s})Koqy(K@%~G`xp3#G4a6%%~2B)pNx^noAJr-n<=3h;w1As-IljcECZYVScgWyi`O|rJ}NAe6I zTTqUlZJj15{$p$J(mr6Is}P0|)*xgMUTCzmJs@N!|9a6{va9iU(R~uxi3_`UJ++4H zYkZq(CvBbhr3JtsbRP_Y|GBt#cgTlJI>LU00|*BZUIsAKU~8dF!g8rqEtu40uH(_e zjbk0R6|$KB-t{@z&u=g7A^U<|KV14(cVI*_3zcz`64cfTFe9gj=m`J0yYtxpnig@( zthmf9xHC?;4K4JLTA}62{AQ4JD4Wg}T#wPieC39Aa=dZ2=M6Hu7;NR?h3C<3IPqB^ z7Hj}!hEAWe0}=HslQD;e4tN#C0xyK->1p^N+WuuYTP`{O{iLzU^8AKQHYS%(%Byfg zC+ShZQG*E8x@;DVh-U%5&~r1M*95ue!P zqD)WuT3ts;Khh;l#3tf%gh-b*!Kw_ao90)WGU4abXs+4UeB!HMAQ2c)iR8=l9bY>k z*~$sX95c!9_g11_dRrO-#8>y-ne||&v=?9$j!$uN0s%uI6t~2vgOqAHZb7KtCCY?G z%~IZ>yO1sP5>lu_G-ti>@?_R6nt8_)5i{U4qG6^)Dljj?=W>-*s!S-QYEd+)R=MDb zsBJQnZ|h&$e+u--ke(jahm_FeI7tzeB#BNs;B5s|d8NN2$f!|ELoRrl;Khm!y#E*o zUj;AfUJsLe@H3!#6}$>_@;c7Y_gct9M{LB2dAbuD^MuIaUyAE`s|m|lWh4s2UI(zkxd|iG4qqg^?~mQ zzp^9-UUo}a=CXnlgfo*KHH%KVoJ+HDCyjw{OZoJCX+U?##M94t_L-&hn3EnngfSaj zn;tBh-bEZu>X!fNhJ4p9yA8GT-r}*nbJwrgS|~ea&Ep#9ctl3nQ<%7#cez5RmUoYa+rLy zifdY~P&S!ROIU+yo|@A_HTk2V%&gD?A5hF3qiH_Z=2I~K%ty2q*b8_)p_iU!sRBC? zq!gwy)~z5W#TzCBOe{JDundzD4=A5w;<0M`%U}n$jMmjv$O8oIyB_a1tTtahNM~3Y!Ogz+2in$qv4GL!Z_i z@1r~T`3>KsgG|Sx!S=BKFNoJ>m|o!rH*V?=?yKOQ4(zJ1Ad({xvr~@6z`<};3jXm% zW2 Date: Fri, 10 Jul 2020 10:53:05 +0800 Subject: [PATCH 13/28] Revert "typo" This reverts commit 19247096a93488e7c1271b68119859b8cf3523a5. --- ParticleSpy/ptcl_class.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ParticleSpy/ptcl_class.py b/ParticleSpy/ptcl_class.py index 42e79b0..edef5d0 100644 --- a/ParticleSpy/ptcl_class.py +++ b/ParticleSpy/ptcl_class.py @@ -255,13 +255,13 @@ def normalize_boxing(self,even=False): particle.image.axes_manager[0].size = particle.image.data.shape[0] particle.image.axes_manager[1].size = particle.image.data.shape[1] - def show(self, params='Image', output=False): + def show(self, param='Image', output=False): """ display all particle images or other parameters Parameters ---------- - params : str or list, optional + param : str or list, optional DESCRIPTION. The default is ['Image']. 'Image' 'maps' @@ -270,7 +270,7 @@ def show(self, params='Image', output=False): """ self.normalize_boxing() - if params == 'Image': + if param=='Image': num = len(self.list) cols = int(np.ceil(np.sqrt(num))) im_ls = [] From 6befaebee3ec48fb66d5f9c4c52d506ce38179d6 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 10 Jul 2020 11:02:12 +0800 Subject: [PATCH 14/28] pycache and parameter.h5 ignored --- .gitignore | 2 ++ .../Parameters/parameters_previous.hdf5 | Bin 8720 -> 8720 bytes .../ParticleAnalysis.cpython-37.pyc | Bin 10215 -> 10214 bytes .../__pycache__/ptcl_class.cpython-37.pyc | Bin 13316 -> 13404 bytes 4 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 82f1b04..ac625f6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ ParticleSpy/__pycache__/ ParticleSpy/Parameters/ particlespy.egg-info/ ParticleSpy/__pycache__/*.pyc +*.pyc +ParticleSpy/Parameters/parameters_previous.hdf5 diff --git a/ParticleSpy/Parameters/parameters_previous.hdf5 b/ParticleSpy/Parameters/parameters_previous.hdf5 index ebb9f72f25bebdb027d1a61ab4257153ea53a4a5..9d8fb9f4e79faca8ecd7eafc4d359099bee6f4c5 100644 GIT binary patch delta 90 zcmbQ>GQnj5FC)ujMqYa!76u5&FDWkF?8B=gFgZX@XmXdV9;4CZowDwXtdkk#`k5FQ nCQp*H14>Cuej%s9$S_$@{y$JkP+>VxjAQZ#MTN}|6bu*v@1ht* delta 81 zcmbQ>GQnj5FC)`rMqYa!CI$$|$z)*I?8B=gz{ohcQr4bPWAaW}cSf$sjB@=<7uY9H glCxvdWt@CT&JHLqDF2^PWU`>baz@6@I~Bqi0oHO8XaE2J diff --git a/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc b/ParticleSpy/__pycache__/ParticleAnalysis.cpython-37.pyc index 9c20246a3e72a171ded0f073f77771a5d3e2bf03..08c551d903c02a516ae18072896b1e4ac7aa80de 100644 GIT binary patch delta 2338 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 D;HEeM delta 2095 zcmaJ?TWl0n7@jjbGdtaOx3_KSEo~_+*#S~63ksCbQi~vj0)h%dn{}9-Zl}&(ICDxb z&ZcUO#snyMG)OeM`>a0ThG)Zr4;r8JZ9)ttz8P;%`rw2AKT}L4#7WLK|C#gu=ltjU zFY{pb&Dq3wJRTF^X`d1@E9tw5mMGEr=IFylz1~=~T*oTp*sM#N_}TU(A5?FVcK%1a zm4B_S@q22LJ9Rhsg}P)d5nB^UFDxbb7Y);-AEnx0d>?5Tg3YxEt%H}&t;E|ztNoI= zKu9{+=VH^6(h5tojep-X&^CzTR)iG7c7(mP#^$?(9OU;~c94j zRy*5%Cqk0^=g!Z`IKR`?L&n0}cm35p2FAW@IHg&G65Oo`U|H->(IfmpcZc=ANBc3; zDA~+#>}4x-Lk`^Vr4lWc)}2AoqHHPS*e;{T@C*!92=yqPs$J}Pi>xF;&cT4^;V9hy zJO~@yftjY#C-~z>UDII9q9GkGpjp64=nQ=xKIqN=aU)YKSdV||WDCV7x_7#^(7PaR zMfc9r6M&N%@g?)B;b@5s{tV!`J9u)l*?9;=KbkidGg&+D6Wdo%nwio0&CP2oBCO)0 zz=*=YNV+8ePpAl0fe0SSl2=6PFyaYw;wmYNEW)IU3`6n6Dyb6q7Rd=^X>pK6J4R1P$fTa5oyTIr)N|I^WjxV`aDD!1%6mk|FLA7-Tb_{m)C}AGR zC4(AyKT?>_gH_RSb=l5yXRvGKEEtH8a4zPX5LZQL4zBtbgJa?2TmGTU^lAZdo( z+2R64{wGZd)#1Su!eR`_`w0Xu0;H*K4+HvE31DOuNQ60g17}DXP=GpgA}da1BX0^! z%u1e=l{N{h;)H;lvPea$3T1hbGMOnJflWeoU!D@n3XEu3_2de0&eTesC$Si^-z`*$ zr{F%-NV(37a(k#R9YyxNy17PA%|^58b-3)6DTsw!X#(5kES#HzSb9Pfv2c{qBBce?z^>pcGj?vC zTJ#eCE!D1Iw5Y@DwPWoR3D;s_SQI;N9ZsZJfjVAdI!-sqEIzBO>p5Fm! zL)Fj2be137X-(_O$y1h5aP|5bn`KJW%GxHQH&OjPg!d6HAz&iv3DcQ(q1-c&RhOaa zgWK!4d;q`~ZRV?HF%SE=E_BzwcXnHAxOxjAa5r+*GWGb3Wia3>V^C@=>Gh9xEzUz$ zy9^SLT4;eCOHY)rJTmJ#t{y7|nVBhA3&EA}dfeO9P4@E-c3oH*1snJjzMcgMYf2Nt z9M)ud4W^SpFQL~#q&IN6iS9%BDTJpH_9HYP1m$%YrQ-V`ns8$RzEecR1 z^kd%G+(8cT>$|ten__+R0Kd2UoBklV@J8ShcBu{V*aK6Sf3j!qV9;ZOKTU8hmYklL zfS9~!nXE{$+3WnzJ=(P1xZYLaHxst^k3iRt0llGK_7OS3SwXYE4I24>3!kW@L6k@X z>46525Gk%|WKv7g{k)v+8w!$IhCr8=!rl{iO}n%-T!6+3DNIH5jo(lA!SDXZ^p=i0 ac)n7+JO>_7Y_360(Az-9CZ67#BJw|O8v2g_ From 75757486d36fdb99ca82725e69adefe2e85f178d Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 10 Jul 2020 11:14:23 +0800 Subject: [PATCH 15/28] ignore --- .gitignore | 1 + .../__pycache__/ptcl_class.cpython-37.pyc | Bin 13404 -> 13434 bytes 2 files changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ac625f6..585b19b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ particlespy.egg-info/ ParticleSpy/__pycache__/*.pyc *.pyc ParticleSpy/Parameters/parameters_previous.hdf5 +ParticleSpy/__pycache__/ptcl_class.cpython-37.pyc diff --git a/ParticleSpy/__pycache__/ptcl_class.cpython-37.pyc b/ParticleSpy/__pycache__/ptcl_class.cpython-37.pyc index 45739a37d0eded6415f16a8dcf4a5f8c90b94306..23ebc6dcb111c8edc3718092185f34441a06893f 100644 GIT binary patch delta 280 zcmcbU@hgMZiI^}%nO8Sm=-cJG5}e^3mF(0QW%37 zG&wh4RsG5|`L0GkBkSY>O;6UM2|&%04`|vja&7*rxsZi%#^m{WPK@&=KhjHLoHp52 zzmIzkP({%K5V3IbJ^gU**&yaz5HWAEgFz%v)hvUlf-`^uentKu;h7*})?^36K*o)e z`2{65uQFW5$hdlPps}L-Vvrmo14FR@kio#n!N|kJ!pOrY!^FYJ$5ga<@vir7IKY(T_fpjqOR15GpmxL-wf From 44d9d195846745b307e317d326640de2dfcfea4e Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 10 Jul 2020 19:33:35 +0800 Subject: [PATCH 16/28] Allow show particle masks in a single frame e.g. particle_list.show('mask') or particle_list.show('Image') --- ParticleSpy/ptcl_class.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/ParticleSpy/ptcl_class.py b/ParticleSpy/ptcl_class.py index edef5d0..8ec03c4 100644 --- a/ParticleSpy/ptcl_class.py +++ b/ParticleSpy/ptcl_class.py @@ -261,7 +261,7 @@ def show(self, param='Image', output=False): Parameters ---------- - param : str or list, optional + param : str, optional DESCRIPTION. The default is ['Image']. 'Image' 'maps' @@ -270,17 +270,19 @@ def show(self, param='Image', output=False): """ self.normalize_boxing() - if param=='Image': - num = len(self.list) - cols = int(np.ceil(np.sqrt(num))) - im_ls = [] - for index in range(num): - im_ls.append(self.list[index].image.data) - self._show_images(im_ls, cols, np.arange(num)) + num = len(self.list) + cols = int(np.ceil(np.sqrt(num))) + data_ls = [] + for index in range(num): + if param == 'Image': + data_ls.append(self.list[index].image.data) + elif param == 'mask': + data_ls.append(self.list[index].mask) + self._show_images(data_ls, param, cols, np.arange(num)) if output: - return im_ls + return data_ls - def _show_images(self, images, cols=1, titles=None): + def _show_images(self, images, main_title, cols=1, titles=None): """ Display a list of images in a single figure with matplotlib. @@ -308,6 +310,7 @@ def _show_images(self, images, cols=1, titles=None): plt.imshow(image) a.set_title(title, fontsize=30) fig.set_size_inches(np.array([1,1]) * n_images) + fig.suptitle(main_title, fontsize=30, y=0.95) plt.show() From f59395de19957c871bab6a1aa4ef24b1edc94565 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 11 Jul 2020 13:00:45 +0800 Subject: [PATCH 17/28] adjust particle_list.show Allow show segmented particles in a montage with adjustable number of columns. e.g. particle_list.show(cols=1). Default montage try to display all particles into a square arrangement. --- ParticleSpy/ptcl_class.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ParticleSpy/ptcl_class.py b/ParticleSpy/ptcl_class.py index 8ec03c4..46b264c 100644 --- a/ParticleSpy/ptcl_class.py +++ b/ParticleSpy/ptcl_class.py @@ -255,7 +255,7 @@ def normalize_boxing(self,even=False): particle.image.axes_manager[0].size = particle.image.data.shape[0] particle.image.axes_manager[1].size = particle.image.data.shape[1] - def show(self, param='Image', output=False): + def show(self, param='Image', cols=None, output=False): """ display all particle images or other parameters @@ -271,7 +271,8 @@ def show(self, param='Image', output=False): self.normalize_boxing() num = len(self.list) - cols = int(np.ceil(np.sqrt(num))) + if cols==None: + cols = int(np.ceil(np.sqrt(num))) data_ls = [] for index in range(num): if param == 'Image': From cbff6f939ba0065dc8e5fe843311befd9ea20210 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 11 Jul 2020 17:23:38 +0800 Subject: [PATCH 18/28] Correct particle intensity_std calculation Plus correct particle only image 'p_im' --- ParticleSpy/ParticleAnalysis.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index 2cf8102..8c33d9f 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -65,13 +65,12 @@ def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): for region in regionprops(labeled, coordinates='rc'): #'count' start with 1, 0 is background p = Particle() - - p_im = np.zeros_like(image.data) - p_im[labeled==region.label] = image.data[labeled==region.label] - np.min(image.data[labeled==region.label]) - + maskp = np.zeros_like(image.data) maskp[labeled==region.label] = 1 + p_im = image.data*maskp + #Calculate average background around image dilated_mask = morphology.binary_dilation(maskp).astype(int) dilated_mask2 = morphology.binary_dilation(dilated_mask).astype(int) @@ -111,7 +110,7 @@ def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): intensity = ((image.data - p.background)*maskp).sum() p.set_intensity(intensity) p.set_property("intensity_max",((image.data - p.background)*maskp).max(),None) - p.set_property("intensity_std",((image.data - p.background)*maskp).std()/p.properties['intensity_max']['value'],None) + p.set_property("intensity_std",((image.data - p.background)*maskp).std(),None) #Set zoneaxis '''im_smooth = filters.gaussian(np.uint16(p_im),1) From f33e4d981d61112c6074fe327b4358194864cd2f Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 11 Jul 2020 17:25:33 +0800 Subject: [PATCH 19/28] Allow user to select whether perform background subtraction before calculating image intensity default is True, i.e. perform background subtraction --- ParticleSpy/ParticleAnalysis.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index 8c33d9f..ba9147e 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -19,7 +19,8 @@ import trackpy import os -def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): +def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1)), + bkg_sub=True): """ Perform segmentation and analysis of images of particles. @@ -72,11 +73,13 @@ def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): p_im = image.data*maskp #Calculate average background around image - dilated_mask = morphology.binary_dilation(maskp).astype(int) - dilated_mask2 = morphology.binary_dilation(dilated_mask).astype(int) - boundary_mask = dilated_mask2 - dilated_mask - p.background = np.sum(boundary_mask*image.data)/np.count_nonzero(boundary_mask) - + if bkg_sub==True: + dilated_mask = morphology.binary_dilation(maskp).astype(int) + dilated_mask2 = morphology.binary_dilation(dilated_mask).astype(int) + boundary_mask = dilated_mask2 - dilated_mask + p.background = np.sum(boundary_mask*image.data)/np.count_nonzero(boundary_mask) + else: + p.background = 0.0 #origin = ac_number #p.set_origin(origin) From e0b7666c508830b140515e817a015875faa7b20c Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 11 Jul 2020 18:20:42 +0800 Subject: [PATCH 20/28] create a new parameter "bkg_sub" and set default to True Default is perform background subtraction for intensity calculation and for stored particle image. --- ParticleSpy/ParticleAnalysis.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index ba9147e..e041a2e 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -19,8 +19,7 @@ import trackpy import os -def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1)), - bkg_sub=True): +def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): """ Perform segmentation and analysis of images of particles. @@ -73,7 +72,7 @@ def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1)), p_im = image.data*maskp #Calculate average background around image - if bkg_sub==True: + if parameters.store['bkg_sub']==True: dilated_mask = morphology.binary_dilation(maskp).astype(int) dilated_mask2 = morphology.binary_dilation(dilated_mask).astype(int) boundary_mask = dilated_mask2 - dilated_mask @@ -234,13 +233,16 @@ def store_image(particle,image,params): ii = np.where(particle.mask) box_x_min = np.min(ii[0]) - box_x_max = np.max(ii[0]) - box_y_max = np.max(ii[1]) + box_x_max = np.max(ii[0])+1 box_y_min = np.min(ii[1]) + box_y_max = np.max(ii[1])+1 pad = params.store['pad'] + if params.store['bkg_sub']==True: + image.data = (image.data - particle.background)*particle.mask + if params.store['p_only']==True: - image = image*particle.mask + image.data = image.data*particle.mask if box_y_min-pad > 0 and box_x_min-pad > 0 and box_x_max+pad < particle.mask.shape[0] and box_y_max+pad < particle.mask.shape[1]: p_boxed = image.isig[(box_y_min-pad):(box_y_max+pad),(box_x_min-pad):(box_x_max+pad)] @@ -301,6 +303,7 @@ def generate(self,threshold='otsu',watershed=False,watershed_size=50, self.segment['local_size'] = local_size self.store = {} + self.store['bkg_sub'] = True self.store['store_im'] = store_im self.store['pad'] = pad self.store['p_only'] = False @@ -332,6 +335,7 @@ def save(self,filename=os.path.dirname(inspect.getfile(process))+'/Parameters/pa segment.attrs["rb_kernel"] = self.segment['rb_kernel'] segment.attrs["gaussian"] = self.segment['gaussian'] segment.attrs["local_size"] = self.segment['local_size'] + store.attrs['bkg_sub'] = self.store['bkg_sub'] store.attrs['store_im'] = self.store['store_im'] store.attrs['pad'] = self.store['pad'] store.attrs['store_maps'] = self.store['store_maps'] From 9ce452e880fc25b5a94555a67387d052fa678023 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 11 Jul 2020 18:43:13 +0800 Subject: [PATCH 21/28] store background intensity into particle.properties --- ParticleSpy/ParticleAnalysis.py | 13 +++++++------ ParticleSpy/ptcl_class.py | 3 +++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index e041a2e..ee41afb 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -76,9 +76,10 @@ def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): dilated_mask = morphology.binary_dilation(maskp).astype(int) dilated_mask2 = morphology.binary_dilation(dilated_mask).astype(int) boundary_mask = dilated_mask2 - dilated_mask - p.background = np.sum(boundary_mask*image.data)/np.count_nonzero(boundary_mask) + background = np.sum(boundary_mask*image.data)/np.count_nonzero(boundary_mask) + p.set_background(background) else: - p.background = 0.0 + p.set_background(0.0) #origin = ac_number #p.set_origin(origin) @@ -109,10 +110,10 @@ def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): p.set_property("solidity",region.solidity,None) #Set total image intensity - intensity = ((image.data - p.background)*maskp).sum() + intensity = ((image.data - p.properties['background']['value'])*maskp).sum() p.set_intensity(intensity) - p.set_property("intensity_max",((image.data - p.background)*maskp).max(),None) - p.set_property("intensity_std",((image.data - p.background)*maskp).std(),None) + p.set_property("intensity_max",((image.data - p.properties['background']['value'])*maskp).max(),None) + p.set_property("intensity_std",((image.data - p.properties['background']['value'])*maskp).std(),None) #Set zoneaxis '''im_smooth = filters.gaussian(np.uint16(p_im),1) @@ -239,7 +240,7 @@ def store_image(particle,image,params): pad = params.store['pad'] if params.store['bkg_sub']==True: - image.data = (image.data - particle.background)*particle.mask + image.data = (image.data - particle.properties['background']['value'])*particle.mask if params.store['p_only']==True: image.data = image.data*particle.mask diff --git a/ParticleSpy/ptcl_class.py b/ParticleSpy/ptcl_class.py index 46b264c..4e9a20a 100644 --- a/ParticleSpy/ptcl_class.py +++ b/ParticleSpy/ptcl_class.py @@ -62,6 +62,9 @@ def set_eccentricity(self,eccentricity): def set_intensity(self,intensity): self.properties['intensity'] = {'value':intensity,'units':None} + def set_background(self,background): + self.properties['background'] = {'value':background,'units':None} + def set_property(self,propname,value,units): """ Give a Particle() object an arbitrary property. From df9217bbb8f072b18442a8b10b2b5cbd26e70ed8 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 11 Jul 2020 19:18:46 +0800 Subject: [PATCH 22/28] Allow save no-paded particle image With particle.store['pad']=None and particle.store['store_im']=True, the saved particle image is masked from original survey image and have save dimension as survey image and saved mask. --- ParticleSpy/ParticleAnalysis.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index ee41afb..823c063 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -240,15 +240,18 @@ def store_image(particle,image,params): pad = params.store['pad'] if params.store['bkg_sub']==True: - image.data = (image.data - particle.properties['background']['value'])*particle.mask + image.data = image.data - particle.properties['background']['value'] if params.store['p_only']==True: image.data = image.data*particle.mask - if box_y_min-pad > 0 and box_x_min-pad > 0 and box_x_max+pad < particle.mask.shape[0] and box_y_max+pad < particle.mask.shape[1]: - p_boxed = image.isig[(box_y_min-pad):(box_y_max+pad),(box_x_min-pad):(box_x_max+pad)] + if pad!=None: + if box_y_min-pad > 0 and box_x_min-pad > 0 and box_x_max+pad < particle.mask.shape[0] and box_y_max+pad < particle.mask.shape[1]: + p_boxed = image.isig[(box_y_min-pad):(box_y_max+pad),(box_x_min-pad):(box_x_max+pad)] + else: + p_boxed = image.isig[(box_y_min):(box_y_max),(box_x_min):(box_x_max)] else: - p_boxed = image.isig[(box_y_min):(box_y_max),(box_x_min):(box_x_max)] + p_boxed = image.data particle.store_im(p_boxed) def store_maps(particle,ac,params): From 01e12902b41b4fa4ef21d4c5570ef508a74ec83c Mon Sep 17 00:00:00 2001 From: YichiWang Date: Sat, 11 Jul 2020 19:23:55 +0800 Subject: [PATCH 23/28] correction --- ParticleSpy/ParticleAnalysis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index 823c063..8969e12 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -251,7 +251,7 @@ def store_image(particle,image,params): else: p_boxed = image.isig[(box_y_min):(box_y_max),(box_x_min):(box_x_max)] else: - p_boxed = image.data + p_boxed = image particle.store_im(p_boxed) def store_maps(particle,ac,params): From 5243334716f68be439f67be38bf916ce9b443727 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Wed, 15 Jul 2020 11:38:15 +0800 Subject: [PATCH 24/28] Correct image intensity calculation Main: Use np.ma.masked_array to mask particle image, so intensity std do not calculate the background area. Others: 1. all intensity are background subtracted intensity. 2. Background value are saved as property. --- .../Parameters/parameters_current.hdf5 | Bin 8720 -> 8800 bytes ParticleSpy/ParticleAnalysis.py | 12 +++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ParticleSpy/Parameters/parameters_current.hdf5 b/ParticleSpy/Parameters/parameters_current.hdf5 index 9d8fb9f4e79faca8ecd7eafc4d359099bee6f4c5..41d78b79dc446050e708eae9e4c3af495b9d6318 100644 GIT binary patch delta 78 zcmbQ>^1x++24liTO-6P`j>+2WvWy2dd$Mn5Vlq(N%*53pD(b<&!oa}5$iTs%2E<9( h>G8#-Nt5N}3>g_GJ1UA#o+0lrIY5qU^CNjZCIIi469@nR delta 46 zcmaFhGQnkn2BW}6O-6P`_Q~4pvWx|rJ=wQ2F+EV&%*53pI{B8o-{cGOT$_y)^q2rZ C7Y(!k diff --git a/ParticleSpy/ParticleAnalysis.py b/ParticleSpy/ParticleAnalysis.py index 8969e12..da7f08d 100644 --- a/ParticleSpy/ParticleAnalysis.py +++ b/ParticleSpy/ParticleAnalysis.py @@ -69,7 +69,7 @@ def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): maskp = np.zeros_like(image.data) maskp[labeled==region.label] = 1 - p_im = image.data*maskp + p_im = np.ma.masked_array(image.data, mask=1-maskp) #Calculate average background around image if parameters.store['bkg_sub']==True: @@ -110,10 +110,11 @@ def ParticleAnalysis(acquisition,parameters,particles=None,mask=np.zeros((1))): p.set_property("solidity",region.solidity,None) #Set total image intensity - intensity = ((image.data - p.properties['background']['value'])*maskp).sum() - p.set_intensity(intensity) - p.set_property("intensity_max",((image.data - p.properties['background']['value'])*maskp).max(),None) - p.set_property("intensity_std",((image.data - p.properties['background']['value'])*maskp).std(),None) + p_im_bkgsub = np.ma.masked_array(p_im.data - p.properties['background']['value'], + mask=1-maskp) + p.set_intensity(p_im_bkgsub.sum()) + p.set_property("intensity_max",p_im_bkgsub.max(),None) + p.set_property("intensity_std",p_im_bkgsub.std(),None) #Set zoneaxis '''im_smooth = filters.gaussian(np.uint16(p_im),1) @@ -370,6 +371,7 @@ def load(self,filename=os.path.dirname(inspect.getfile(process))+'/Parameters/pa self.segment['rb_kernel'] = segment.attrs["rb_kernel"] self.segment['gaussian'] = segment.attrs["gaussian"] self.segment['local_size'] = segment.attrs["local_size"] + self.store['bkg_sub'] = store.attrs['bkg_sub'] self.store['store_im'] = store.attrs['store_im'] self.store['pad'] = store.attrs['pad'] self.store['store_maps'] = store.attrs['store_maps'] From 1436108c780fcd53d4a049343476fd777b52c66a Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 31 Jul 2020 09:56:24 +0800 Subject: [PATCH 25/28] Create boundary_analysis.py Few more functions. This is a standalone script and not merged with ParticleSpy yet. -find boundary pixel in a clock-wise seqeunce -calculate boundary curvature (signed) use least squre circle fit. -average boundary curvature by given angle interval so at same direction boundary curvatures of two particle with different size (i.e. different boundary pixels) are comparable. Normalised boundary curvature by particle's equivalent diameter is not implemented yet. --- ParticleSpy/boundary_analysis.py | 394 +++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 ParticleSpy/boundary_analysis.py diff --git a/ParticleSpy/boundary_analysis.py b/ParticleSpy/boundary_analysis.py new file mode 100644 index 0000000..8ef2003 --- /dev/null +++ b/ParticleSpy/boundary_analysis.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +""" +Created on Fri Jul 17 11:04:53 2020 + +@author: dell +""" +import numpy as np +from skimage.segmentation import find_boundaries +from scipy import optimize + +# 2D image boundary analysis + +def eight_neighbour_loop(center, start,boundary_matrix): + """center is [x,y], start is [x,y] format""" + x = center[0] + y = center[1] + neighbour_dic = {0: [x-1,y], + 1: [x-1,y-1], + 2: [x,y-1], + 3: [x+1,y-1], + 4: [x+1,y], + 5: [x+1,y+1], + 6: [x,y+1], + 7: [x-1,y+1]} + key_list = [0,1,2,3,4,5,6,7] + start_index = [key for key, val in neighbour_dic.items() if val==start][0] + + #new_list, a reorder the key_list + if start_index == 0: + new_list = list(range(8))#include start point + else: + new_list = list(range(start_index,8)) + list(range(start_index)) + for i in range(8): + #find the new boundary point and break the loop + key = new_list[i] + if neighbour_dic[key] in boundary_matrix: + new_boundary = neighbour_dic[key] + new_index = i-1 + #new start is always a background pixel + new_start = neighbour_dic[new_list[new_index]] + break + return (new_boundary, new_start) + + +def boundary_follow(img, center=None): + """ + Find boundaries and clock-wise follow boundary as a sequence list. + + Parameters + ---------- + img: (N, M) ndarray + Input single objective image. Background should be 0. + center: [int, int] + The center of the image box. + + Returns + ------- + boundary_list: list + A list of boundary pixel coordinates in clock-wise sequence. + + Example + ------- + test_im = skimage.morphology.star((20)) + n = 0 + while n<3: + test_im = skimage.morphology.binary_erosion(test_im) + n += 1 + test_im = skimage.filters.gaussian(test_im, sigma=1) + test_im = skimage.transform.rotate(test_im, 25) + test_im[test_im!=0] = 1 + plt.imshow(test_im) + + #correct boundary pixel sequence + boundary_list, ang_ls = boundary_follow(test_im) + b_rr, b_cc = np.asarray(boundary_list).transpose() + plt.figure(figsize=(10,10)) + plt.scatter(b_rr[:10], np.multiply(-1, b_cc[:10]), c='r') + plt.scatter(b_rr[10:50], np.multiply(-1, b_cc[10:50]), c='g') + plt.scatter(b_rr[50:], np.multiply(-1, b_cc[50:]), c='b') + + #incorrect boundary pixel sequence + get_boundary = find_boundaries(test_im,mode='inner') + b_rr1 = np.where(get_boundary==True)[1] + b_cc1 = np.where(get_boundary==True)[0] + plt.figure(figsize=(10,10)) + plt.scatter(b_rr1[:10], np.multiply(-1, b_cc1[:10]), c='r') + plt.scatter(b_rr1[10:50], np.multiply(-1, b_cc1[10:50]), c='g') + plt.scatter(b_rr1[50:], np.multiply(-1, b_cc1[50:]), c='b') + """ + + if center == None: + center = [img.shape[0]//2, img.shape[1]//2] + + # find_boundaries only works for bindary image + img[img!=0] = 1 + get_boundary = find_boundaries(img,mode='inner') + # get boundary pixel coordinates, + # np.where results opposite x-y coordinate, [0] is y in plt and [1] is x. + peri_x = np.where(get_boundary==True)[1] #It is Y in matplotlib + peri_y = np.where(get_boundary==True)[0] #It is X in matplotlib + peri_matrix = np.column_stack((peri_x,peri_y)).tolist() + #the uppermost, leftmost point will be the start point, b0, at boundary + b0_y = np.min(peri_y) + index_= np.min(np.where(peri_y==b0_y)) + b0_x = peri_x[index_] + b0 = [b0_x, b0_y] + #c0 is always a background point next to b0 + c0_x = b0_x - 1 + c0_y = b0_y + c0 = [c0_x, c0_y] + #Do 8-neighbours clockwise loop to find the first non-background pixel b1, + #and the background pixel c1 found before b1, + #store b0, b1 for the loop-ending comparision + b1, c1 = eight_neighbour_loop(b0,c0,peri_matrix) #Do 8-neighbour loop + b = b1 + c = c1 + #loop again + bn = b + boundary_list=[b0] + while b!=b0 or bn!=b1: + b = bn + bn, c = eight_neighbour_loop(b,c,peri_matrix) #Do 8-neighbour loop + boundary_list.append(b) + del boundary_list[-1]#the last one is the same of the first + + + # get angles + v1 = np.subtract([center[0], center[1]-1], center) #12 o'clock direction + angle_list = [] + for b in boundary_list: + v2 = np.subtract(b, center) + #ang = angle_between(v1, v2) + ang = np.rad2deg(angle_between(v2, v1)) #coordinates are mess! + if ang < 0: + ang = 360 - abs(ang) + angle_list.append(ang) + + + # sort boundary pixel in angle sequence + angle_props = np.column_stack((angle_list, boundary_list)).tolist() + angle_props.sort() + angle_list, boundary_xs, boundary_ys = np.asarray(angle_props).transpose() + boundary_list = np.column_stack((boundary_xs.astype(int),boundary_ys.astype(int))).tolist() + return boundary_list, angle_list + + +def boundary_ang(boundary_list, center=None): + ''' + For each pixel on the boundary, + get its angle cooresponding to the center of boundary. + + ''' + if center == None: + center = [img.shape[0]//2, img.shape[1]//2] + + v1 = center - [center[0], center[1]+1] + + ang_ls = [] + for b in boundary_list: + v2 = center - b + ang = angle_between(v1, v2) + ang_ls.append(ang) + + return ang_ls + +def boundary_dist(boundary_list, xscale=1, yscale=1): + ''' + Calculate the distance to centre for each boundary pixel'' + ''' + distance_list = [] + for i in boundary_list: + d = np.sqrt(((i[0]-centre[0])*xscale)**2+((i[1]-centre[1])*yscale)**2) + distance_list.append(d) + return distance_list + +def boundary_curvature(im_binary, center=None, segment=5): + ''' + Get signed boundary curvature of a enclosed particle image. + The curvature of a given pixel 'p' is defined as 1/r, + where r is the radius of the least square fitted circle + by fitting a circle to a list of pixels (i.e. segment of boundary) + [p-segment, p-segment+1, ..., p, ..., p+segment-1, p+segment]. + + Negative curvature means concave while positive means convex. + + Parameters + ------- + im_binary : 2d numpy array + binary image. + center : tuple or list, optional + Center coordinates of the enclosed particle image. + If None, use whole image center. + segment: int + Unit in pix. + + Returns + ------- + cur_ls: list + list of boundary curvature values. + + Example + ------- + test_im = skimage.morphology.star((20)) + n = 0 + while n<3: + test_im = skimage.morphology.binary_erosion(test_im) + n += 1 + test_im = skimage.filters.gaussian(test_im, sigma=1) + test_im = skimage.transform.rotate(test_im, 25) + test_im[test_im!=0] = 1 + plt.imshow(test_im) + + boundary_list, _ = boundary_follow(test_im, center=None) + b_x, b_y = np.asarray(boundary_list).transpose() + cur_ls = boundary_curvature(test_im, center=None, segment=5) + plt.figure(figsize=(10,10)) + plt.xlim(0,test_im.shape[0]) + plt.ylim(0,test_im.shape[1]) + plt.scatter(b_x, np.subtract(test_im.shape[0],b_y), c=cur_ls, cmap='coolwarm') + #plt.plot(cur_ls, 'o-') + ''' + if center == None: + center = [im_binary.shape[0]//2, im_binary.shape[1]//2] + + # get boundary pixels in clock-wise sequence. + b, _ = boundary_follow(im_binary) + b_x, b_y = np.asarray(b).transpose() + + cur_ls = [] + for i in range(len(b_x)): + # get boundary segment pixels indice + index_ls = np.arange(i-segment, i+segment+1) + # correct end boundary pixel index + for n, ii in enumerate(index_ls): + if ii >= len(b_x): + index_ls[n] = ii-len(b_x) + #print(index_ls) + + points = [] + for ind in index_ls: + points.append([b_x[ind], b_y[ind]]) + + c, r, radius, _ = least_squares_circle(points) + + #sign curvature + vec_n = np.subtract(points[len(points)//2], [c, r]) + vec_t = np.subtract(points[len(points)//2], center) + ang = abs(np.rad2deg(angle_between(vec_n, vec_t))) + if ang < 90: + cur = 1/radius + else: + cur = -1/radius + + cur_ls.append(cur) + cur_ls = np.asarray(cur_ls) + return cur_ls + +def least_squares_circle(coords): + ''' + Give a list of points, least square fit a circle + ref: https://pypi.org/project/circle-fit/ + + Parameters + ---------- + coords: list or numpy array + list of 2D point coordinates, number of points > 2. + + Returns + ------- + xc: float + x-coordinate of solution center + yc: float + y-coordinate of solution center + R: float + Radius of solution + residu: float + MSE of fitting + + Example + ------- + points = [[53, 32], [54, 32], [55, 31], [56, 30], [57, 30], + [58, 30], + [59, 29], [60, 29], [61, 30], [62, 30], [63, 31]] + c, r, radius, _ = least_squares_circle(points) + p_x = [po[0] for po in points] + p_y = [po[1] for po in points] + plt.figure(figsize=(10,10)) + plt.scatter(p_x, p_y, c='pink') + plt.scatter(p_x[len(p_x)//2], p_y[len(p_x)//2], c='r') + plt.scatter(c, r, c='r') + rr, cc = skimage.draw.circle_perimeter(int(r), int(c), int(radius)) + img = np.zeros((70, 70), dtype=np.uint8) + img[rr, cc] = 1 + plt.imshow(img) + ''' + + x, y = None, None + if isinstance(coords, np.ndarray): + x = coords[:, 0] + y = coords[:, 1] + elif isinstance(coords, list): + x = np.array([point[0] for point in coords]) + y = np.array([point[1] for point in coords]) + + x_m = np.mean(x) + y_m = np.mean(y) + center_mean = x_m, y_m + center, _ = optimize.leastsq(f, center_mean, args=(x,y)) + xc, yc = center + ri = calc_R(x, y, *center) + r = ri.mean() + residu = np.sum((ri - r)**2) + return xc, yc, r, residu + +def calc_R(x,y, xc, yc): + """ + calculate the distance of each 2D points from the center (xc, yc) + ref: https://pypi.org/project/circle-fit/ + """ + return np.sqrt((x-xc)**2 + (y-yc)**2) + +def f(c, x, y): + """ + calculate the algebraic distance between the data points + and the mean circle centered at c=(xc, yc) + ref: https://pypi.org/project/circle-fit/ + """ + Ri = calc_R(x, y, *c) + return Ri - Ri.mean() + +def unit_vector(vector): + """ Returns the unit vector of the vector. """ + return vector / np.linalg.norm(vector) + +def angle_between(v1, v2): + """ + Returns signed angle in radians from vectors 'v1' to 'v2' + direction clock-wise is positive:: + + >>> angle_between((1, 0, 0), (0, 1, 0)) + 1.5707963267948966 + >>> angle_between((1, 0, 0), (1, 0, 0)) + 0.0 + >>> angle_between((1, 0, 0), (-1, 0, 0)) + 3.141592653589793 + ref: https://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python + """ + v1_u = unit_vector(v1) + v2_u = unit_vector(v2) + minor = np.linalg.det(np.stack((v1_u[-2:], v2_u[-2:]))) + if minor == 0: + sign = 1 + else: + sign = -np.sign(minor) + dot_p = np.dot(v1_u, v2_u) + dot_p = min(max(dot_p, -1.0), 1.0) + return sign * np.arccos(dot_p) + +def ave_by_deg(ang_ls, cur_ls, interval=10): + ''' + Average boundary curvature by a given angle interval. + + Returned is a boundary curvature list + but every curvature is the average of raw curvatures + within the given angle interval. + This ensures at same direction boundary curvatures + of two particle with different size (i.e. different boundary pixels) + are comparable. + + + Parameters + ------- + cur_ls: list or 1d np array + Raw boundary pixel curvature + ang_ls: list or 1d np array + Angles associated with raw boundary pixel curvature + interval: dividable by 360, unit degree + Degree interval to average boundary curvatures + This value cannot be too small. If so at certain angle there will be + no curvature value. + ''' + ang_interval_ls = np.arange(0,365,interval) + ang_ave_ls = [] + for i in range(len(ang_interval_ls)-1): + blank_ls = [] + for n, ang in enumerate(ang_ls): + if ang_interval_ls[i]<= ang Date: Fri, 31 Jul 2020 10:09:04 +0800 Subject: [PATCH 26/28] Add reference for boundary following algorithm --- ParticleSpy/boundary_analysis.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ParticleSpy/boundary_analysis.py b/ParticleSpy/boundary_analysis.py index 8ef2003..60c1f62 100644 --- a/ParticleSpy/boundary_analysis.py +++ b/ParticleSpy/boundary_analysis.py @@ -11,7 +11,11 @@ # 2D image boundary analysis def eight_neighbour_loop(center, start,boundary_matrix): - """center is [x,y], start is [x,y] format""" + """ + center is [x,y], start is [x,y] format + + ref: P796-798, Digital Image Processing (2008) Gonzalez & Woods + """ x = center[0] y = center[1] neighbour_dic = {0: [x-1,y], @@ -45,6 +49,7 @@ def eight_neighbour_loop(center, start,boundary_matrix): def boundary_follow(img, center=None): """ Find boundaries and clock-wise follow boundary as a sequence list. + ref: P796-798, Digital Image Processing (2008) Gonzalez & Woods Parameters ---------- From 7ddf2f0e0ef90813a6f17316072025d302b74506 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 31 Jul 2020 10:36:34 +0800 Subject: [PATCH 27/28] Revert "Add reference for boundary following algorithm" This reverts commit e19dbd8aaeb1b96654a53e759df67a23474c85b1. --- ParticleSpy/boundary_analysis.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ParticleSpy/boundary_analysis.py b/ParticleSpy/boundary_analysis.py index 60c1f62..8ef2003 100644 --- a/ParticleSpy/boundary_analysis.py +++ b/ParticleSpy/boundary_analysis.py @@ -11,11 +11,7 @@ # 2D image boundary analysis def eight_neighbour_loop(center, start,boundary_matrix): - """ - center is [x,y], start is [x,y] format - - ref: P796-798, Digital Image Processing (2008) Gonzalez & Woods - """ + """center is [x,y], start is [x,y] format""" x = center[0] y = center[1] neighbour_dic = {0: [x-1,y], @@ -49,7 +45,6 @@ def eight_neighbour_loop(center, start,boundary_matrix): def boundary_follow(img, center=None): """ Find boundaries and clock-wise follow boundary as a sequence list. - ref: P796-798, Digital Image Processing (2008) Gonzalez & Woods Parameters ---------- From bf264facd96ba660599c8eb5229996ae3c86cb35 Mon Sep 17 00:00:00 2001 From: YichiWang Date: Fri, 31 Jul 2020 10:36:41 +0800 Subject: [PATCH 28/28] Revert "Create boundary_analysis.py" This reverts commit 1436108c780fcd53d4a049343476fd777b52c66a. --- ParticleSpy/boundary_analysis.py | 394 ------------------------------- 1 file changed, 394 deletions(-) delete mode 100644 ParticleSpy/boundary_analysis.py diff --git a/ParticleSpy/boundary_analysis.py b/ParticleSpy/boundary_analysis.py deleted file mode 100644 index 8ef2003..0000000 --- a/ParticleSpy/boundary_analysis.py +++ /dev/null @@ -1,394 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Fri Jul 17 11:04:53 2020 - -@author: dell -""" -import numpy as np -from skimage.segmentation import find_boundaries -from scipy import optimize - -# 2D image boundary analysis - -def eight_neighbour_loop(center, start,boundary_matrix): - """center is [x,y], start is [x,y] format""" - x = center[0] - y = center[1] - neighbour_dic = {0: [x-1,y], - 1: [x-1,y-1], - 2: [x,y-1], - 3: [x+1,y-1], - 4: [x+1,y], - 5: [x+1,y+1], - 6: [x,y+1], - 7: [x-1,y+1]} - key_list = [0,1,2,3,4,5,6,7] - start_index = [key for key, val in neighbour_dic.items() if val==start][0] - - #new_list, a reorder the key_list - if start_index == 0: - new_list = list(range(8))#include start point - else: - new_list = list(range(start_index,8)) + list(range(start_index)) - for i in range(8): - #find the new boundary point and break the loop - key = new_list[i] - if neighbour_dic[key] in boundary_matrix: - new_boundary = neighbour_dic[key] - new_index = i-1 - #new start is always a background pixel - new_start = neighbour_dic[new_list[new_index]] - break - return (new_boundary, new_start) - - -def boundary_follow(img, center=None): - """ - Find boundaries and clock-wise follow boundary as a sequence list. - - Parameters - ---------- - img: (N, M) ndarray - Input single objective image. Background should be 0. - center: [int, int] - The center of the image box. - - Returns - ------- - boundary_list: list - A list of boundary pixel coordinates in clock-wise sequence. - - Example - ------- - test_im = skimage.morphology.star((20)) - n = 0 - while n<3: - test_im = skimage.morphology.binary_erosion(test_im) - n += 1 - test_im = skimage.filters.gaussian(test_im, sigma=1) - test_im = skimage.transform.rotate(test_im, 25) - test_im[test_im!=0] = 1 - plt.imshow(test_im) - - #correct boundary pixel sequence - boundary_list, ang_ls = boundary_follow(test_im) - b_rr, b_cc = np.asarray(boundary_list).transpose() - plt.figure(figsize=(10,10)) - plt.scatter(b_rr[:10], np.multiply(-1, b_cc[:10]), c='r') - plt.scatter(b_rr[10:50], np.multiply(-1, b_cc[10:50]), c='g') - plt.scatter(b_rr[50:], np.multiply(-1, b_cc[50:]), c='b') - - #incorrect boundary pixel sequence - get_boundary = find_boundaries(test_im,mode='inner') - b_rr1 = np.where(get_boundary==True)[1] - b_cc1 = np.where(get_boundary==True)[0] - plt.figure(figsize=(10,10)) - plt.scatter(b_rr1[:10], np.multiply(-1, b_cc1[:10]), c='r') - plt.scatter(b_rr1[10:50], np.multiply(-1, b_cc1[10:50]), c='g') - plt.scatter(b_rr1[50:], np.multiply(-1, b_cc1[50:]), c='b') - """ - - if center == None: - center = [img.shape[0]//2, img.shape[1]//2] - - # find_boundaries only works for bindary image - img[img!=0] = 1 - get_boundary = find_boundaries(img,mode='inner') - # get boundary pixel coordinates, - # np.where results opposite x-y coordinate, [0] is y in plt and [1] is x. - peri_x = np.where(get_boundary==True)[1] #It is Y in matplotlib - peri_y = np.where(get_boundary==True)[0] #It is X in matplotlib - peri_matrix = np.column_stack((peri_x,peri_y)).tolist() - #the uppermost, leftmost point will be the start point, b0, at boundary - b0_y = np.min(peri_y) - index_= np.min(np.where(peri_y==b0_y)) - b0_x = peri_x[index_] - b0 = [b0_x, b0_y] - #c0 is always a background point next to b0 - c0_x = b0_x - 1 - c0_y = b0_y - c0 = [c0_x, c0_y] - #Do 8-neighbours clockwise loop to find the first non-background pixel b1, - #and the background pixel c1 found before b1, - #store b0, b1 for the loop-ending comparision - b1, c1 = eight_neighbour_loop(b0,c0,peri_matrix) #Do 8-neighbour loop - b = b1 - c = c1 - #loop again - bn = b - boundary_list=[b0] - while b!=b0 or bn!=b1: - b = bn - bn, c = eight_neighbour_loop(b,c,peri_matrix) #Do 8-neighbour loop - boundary_list.append(b) - del boundary_list[-1]#the last one is the same of the first - - - # get angles - v1 = np.subtract([center[0], center[1]-1], center) #12 o'clock direction - angle_list = [] - for b in boundary_list: - v2 = np.subtract(b, center) - #ang = angle_between(v1, v2) - ang = np.rad2deg(angle_between(v2, v1)) #coordinates are mess! - if ang < 0: - ang = 360 - abs(ang) - angle_list.append(ang) - - - # sort boundary pixel in angle sequence - angle_props = np.column_stack((angle_list, boundary_list)).tolist() - angle_props.sort() - angle_list, boundary_xs, boundary_ys = np.asarray(angle_props).transpose() - boundary_list = np.column_stack((boundary_xs.astype(int),boundary_ys.astype(int))).tolist() - return boundary_list, angle_list - - -def boundary_ang(boundary_list, center=None): - ''' - For each pixel on the boundary, - get its angle cooresponding to the center of boundary. - - ''' - if center == None: - center = [img.shape[0]//2, img.shape[1]//2] - - v1 = center - [center[0], center[1]+1] - - ang_ls = [] - for b in boundary_list: - v2 = center - b - ang = angle_between(v1, v2) - ang_ls.append(ang) - - return ang_ls - -def boundary_dist(boundary_list, xscale=1, yscale=1): - ''' - Calculate the distance to centre for each boundary pixel'' - ''' - distance_list = [] - for i in boundary_list: - d = np.sqrt(((i[0]-centre[0])*xscale)**2+((i[1]-centre[1])*yscale)**2) - distance_list.append(d) - return distance_list - -def boundary_curvature(im_binary, center=None, segment=5): - ''' - Get signed boundary curvature of a enclosed particle image. - The curvature of a given pixel 'p' is defined as 1/r, - where r is the radius of the least square fitted circle - by fitting a circle to a list of pixels (i.e. segment of boundary) - [p-segment, p-segment+1, ..., p, ..., p+segment-1, p+segment]. - - Negative curvature means concave while positive means convex. - - Parameters - ------- - im_binary : 2d numpy array - binary image. - center : tuple or list, optional - Center coordinates of the enclosed particle image. - If None, use whole image center. - segment: int - Unit in pix. - - Returns - ------- - cur_ls: list - list of boundary curvature values. - - Example - ------- - test_im = skimage.morphology.star((20)) - n = 0 - while n<3: - test_im = skimage.morphology.binary_erosion(test_im) - n += 1 - test_im = skimage.filters.gaussian(test_im, sigma=1) - test_im = skimage.transform.rotate(test_im, 25) - test_im[test_im!=0] = 1 - plt.imshow(test_im) - - boundary_list, _ = boundary_follow(test_im, center=None) - b_x, b_y = np.asarray(boundary_list).transpose() - cur_ls = boundary_curvature(test_im, center=None, segment=5) - plt.figure(figsize=(10,10)) - plt.xlim(0,test_im.shape[0]) - plt.ylim(0,test_im.shape[1]) - plt.scatter(b_x, np.subtract(test_im.shape[0],b_y), c=cur_ls, cmap='coolwarm') - #plt.plot(cur_ls, 'o-') - ''' - if center == None: - center = [im_binary.shape[0]//2, im_binary.shape[1]//2] - - # get boundary pixels in clock-wise sequence. - b, _ = boundary_follow(im_binary) - b_x, b_y = np.asarray(b).transpose() - - cur_ls = [] - for i in range(len(b_x)): - # get boundary segment pixels indice - index_ls = np.arange(i-segment, i+segment+1) - # correct end boundary pixel index - for n, ii in enumerate(index_ls): - if ii >= len(b_x): - index_ls[n] = ii-len(b_x) - #print(index_ls) - - points = [] - for ind in index_ls: - points.append([b_x[ind], b_y[ind]]) - - c, r, radius, _ = least_squares_circle(points) - - #sign curvature - vec_n = np.subtract(points[len(points)//2], [c, r]) - vec_t = np.subtract(points[len(points)//2], center) - ang = abs(np.rad2deg(angle_between(vec_n, vec_t))) - if ang < 90: - cur = 1/radius - else: - cur = -1/radius - - cur_ls.append(cur) - cur_ls = np.asarray(cur_ls) - return cur_ls - -def least_squares_circle(coords): - ''' - Give a list of points, least square fit a circle - ref: https://pypi.org/project/circle-fit/ - - Parameters - ---------- - coords: list or numpy array - list of 2D point coordinates, number of points > 2. - - Returns - ------- - xc: float - x-coordinate of solution center - yc: float - y-coordinate of solution center - R: float - Radius of solution - residu: float - MSE of fitting - - Example - ------- - points = [[53, 32], [54, 32], [55, 31], [56, 30], [57, 30], - [58, 30], - [59, 29], [60, 29], [61, 30], [62, 30], [63, 31]] - c, r, radius, _ = least_squares_circle(points) - p_x = [po[0] for po in points] - p_y = [po[1] for po in points] - plt.figure(figsize=(10,10)) - plt.scatter(p_x, p_y, c='pink') - plt.scatter(p_x[len(p_x)//2], p_y[len(p_x)//2], c='r') - plt.scatter(c, r, c='r') - rr, cc = skimage.draw.circle_perimeter(int(r), int(c), int(radius)) - img = np.zeros((70, 70), dtype=np.uint8) - img[rr, cc] = 1 - plt.imshow(img) - ''' - - x, y = None, None - if isinstance(coords, np.ndarray): - x = coords[:, 0] - y = coords[:, 1] - elif isinstance(coords, list): - x = np.array([point[0] for point in coords]) - y = np.array([point[1] for point in coords]) - - x_m = np.mean(x) - y_m = np.mean(y) - center_mean = x_m, y_m - center, _ = optimize.leastsq(f, center_mean, args=(x,y)) - xc, yc = center - ri = calc_R(x, y, *center) - r = ri.mean() - residu = np.sum((ri - r)**2) - return xc, yc, r, residu - -def calc_R(x,y, xc, yc): - """ - calculate the distance of each 2D points from the center (xc, yc) - ref: https://pypi.org/project/circle-fit/ - """ - return np.sqrt((x-xc)**2 + (y-yc)**2) - -def f(c, x, y): - """ - calculate the algebraic distance between the data points - and the mean circle centered at c=(xc, yc) - ref: https://pypi.org/project/circle-fit/ - """ - Ri = calc_R(x, y, *c) - return Ri - Ri.mean() - -def unit_vector(vector): - """ Returns the unit vector of the vector. """ - return vector / np.linalg.norm(vector) - -def angle_between(v1, v2): - """ - Returns signed angle in radians from vectors 'v1' to 'v2' - direction clock-wise is positive:: - - >>> angle_between((1, 0, 0), (0, 1, 0)) - 1.5707963267948966 - >>> angle_between((1, 0, 0), (1, 0, 0)) - 0.0 - >>> angle_between((1, 0, 0), (-1, 0, 0)) - 3.141592653589793 - ref: https://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python - """ - v1_u = unit_vector(v1) - v2_u = unit_vector(v2) - minor = np.linalg.det(np.stack((v1_u[-2:], v2_u[-2:]))) - if minor == 0: - sign = 1 - else: - sign = -np.sign(minor) - dot_p = np.dot(v1_u, v2_u) - dot_p = min(max(dot_p, -1.0), 1.0) - return sign * np.arccos(dot_p) - -def ave_by_deg(ang_ls, cur_ls, interval=10): - ''' - Average boundary curvature by a given angle interval. - - Returned is a boundary curvature list - but every curvature is the average of raw curvatures - within the given angle interval. - This ensures at same direction boundary curvatures - of two particle with different size (i.e. different boundary pixels) - are comparable. - - - Parameters - ------- - cur_ls: list or 1d np array - Raw boundary pixel curvature - ang_ls: list or 1d np array - Angles associated with raw boundary pixel curvature - interval: dividable by 360, unit degree - Degree interval to average boundary curvatures - This value cannot be too small. If so at certain angle there will be - no curvature value. - ''' - ang_interval_ls = np.arange(0,365,interval) - ang_ave_ls = [] - for i in range(len(ang_interval_ls)-1): - blank_ls = [] - for n, ang in enumerate(ang_ls): - if ang_interval_ls[i]<= ang