From dd980434e2bf7fa3bcd3133724a7de7640ccd0d8 Mon Sep 17 00:00:00 2001 From: ptajvar Date: Tue, 20 Aug 2024 09:51:05 +0200 Subject: [PATCH 1/4] Added abundance_colocalization_plot function --- src/pixelator/plot/__init__.py | 71 +++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/pixelator/plot/__init__.py b/src/pixelator/plot/__init__.py index ca7f048d..20516858 100644 --- a/src/pixelator/plot/__init__.py +++ b/src/pixelator/plot/__init__.py @@ -11,7 +11,7 @@ import numpy as np import pandas as pd import seaborn as sns -from matplotlib.colors import LinearSegmentedColormap +from matplotlib.colors import LinearSegmentedColormap, Normalize from matplotlib.patches import Rectangle from scipy.stats import gaussian_kde @@ -454,3 +454,72 @@ def density_scatter_plot( plot_grid.ax_joint.axhline(0, color="black", linewidth=1, linestyle="--") plot_grid.ax_joint.axvline(0, color="black", linewidth=1, linestyle="--") return plt.gcf(), plt.gca() + + +def abundance_colocalization_plot( + pixel, + markers_x: list[str], + markers_y: list[str], + layer=None, + colocalization_column="pearson_z", +): + """Plot abundance of markers x and y with colocalization as color. + + :param pixel: Pixel object containing the data. + :param markers_x: List of markers for the x-axis. + :param markers_y: List of markers for the y-axis. + :param layer: The anndata layer (e.g. transformation) to use for the marker data. + :param colocalization_column: The column in the colocalization table to use for + colocalization values. Defaults to "pearson_z". + :return: a scatter plot of marker abundance with colocalization as color. + """ + data = pixel.adata.to_df(layer) + merged_data = pd.DataFrame() + for i, mx in enumerate(markers_x): + for j, my in enumerate(markers_y): + marker_pair_rows = ( + (pixel.colocalization["marker_1"] == mx) + & (pixel.colocalization["marker_2"] == my) + ) | ( + (pixel.colocalization["marker_1"] == my) + & (pixel.colocalization["marker_2"] == mx) + ) + + coloc_data = pixel.colocalization.loc[marker_pair_rows, :].set_index( + "component" + )[colocalization_column] + data["colocalization"] = coloc_data + data["colocalization_abs"] = data["colocalization"].abs() + data["x_abundance"] = data[mx] + data["y_abundance"] = data[my] + data["marker_x"] = mx + data["marker_y"] = my + data.fillna(0) + merged_data = pd.concat((merged_data, data), axis=0) + plot_grid = sns.FacetGrid(data=merged_data, col="marker_x", row="marker_y") + plot_grid.map_dataframe( + sns.scatterplot, + x="x_abundance", + y="y_abundance", + hue="colocalization", + size="colocalization_abs", + hue_norm=Normalize( + vmin=merged_data["colocalization"].quantile(0.1), + vmax=merged_data["colocalization"].quantile(0.9), + clip=True, + ), + size_norm=Normalize( + vmin=merged_data["colocalization_abs"].quantile(0.1), + vmax=merged_data["colocalization_abs"].quantile(0.9), + clip=True, + ), + ) + # TODO: See how the legend is determined based on the merged data to be + # able to access actual marker sizes. + for i in range(1, 6): + plot_grid._legend_data[list(plot_grid._legend_data.keys())[i]].set_markersize(5) + legend_data = { + i: plot_grid._legend_data[i] for i in list(plot_grid._legend_data.keys())[:6] + } + plot_grid.add_legend(legend_data=legend_data) + return plt.gcf(), plt.gca() From 0aefc35f07f8aa1786384b745395dbd3ab30f6eb Mon Sep 17 00:00:00 2001 From: ptajvar Date: Wed, 21 Aug 2024 17:11:31 +0200 Subject: [PATCH 2/4] added test for abundance_colocalization_plot --- src/pixelator/plot/__init__.py | 2 ++ tests/plot/test_plot.py | 16 ++++++++++++++++ .../test_abundance_colocalization_plot.png | Bin 0 -> 47788 bytes 3 files changed, 18 insertions(+) create mode 100644 tests/snapshots/test_plot/test_abundance_colocalization_plot/test_abundance_colocalization_plot.png diff --git a/src/pixelator/plot/__init__.py b/src/pixelator/plot/__init__.py index 20516858..ac9fb657 100644 --- a/src/pixelator/plot/__init__.py +++ b/src/pixelator/plot/__init__.py @@ -517,6 +517,8 @@ def abundance_colocalization_plot( # TODO: See how the legend is determined based on the merged data to be # able to access actual marker sizes. for i in range(1, 6): + if i >= len(plot_grid._legend_data): + break plot_grid._legend_data[list(plot_grid._legend_data.keys())[i]].set_markersize(5) legend_data = { i: plot_grid._legend_data[i] for i in list(plot_grid._legend_data.keys())[:6] diff --git a/tests/plot/test_plot.py b/tests/plot/test_plot.py index bce774e8..a129ac14 100644 --- a/tests/plot/test_plot.py +++ b/tests/plot/test_plot.py @@ -12,6 +12,7 @@ from pixelator.graph import Graph from pixelator.plot import ( + abundance_colocalization_plot, cell_count_plot, density_scatter_plot, edge_rank_plot, @@ -814,3 +815,18 @@ def test_density_scatter_plot( show_marginal=show_marginal, ) return fig + + +@pytest.mark.mpl_image_compare( + deterministic=True, + baseline_dir="../snapshots/test_plot/test_abundance_colocalization_plot/", +) +def test_abundance_colocalization_plot(setup_basic_pixel_dataset): + pixel_data, *_ = setup_basic_pixel_dataset + fig, _ = abundance_colocalization_plot( + pixel_data, + markers_x=["CD3", "CD8"], + markers_y=["CD14", "CD19"], + colocalization_column="pearson", + ) + return fig diff --git a/tests/snapshots/test_plot/test_abundance_colocalization_plot/test_abundance_colocalization_plot.png b/tests/snapshots/test_plot/test_abundance_colocalization_plot/test_abundance_colocalization_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ddbd994078c5e4ef3b0059a20e5659cd43d8d8 GIT binary patch literal 47788 zcmdRX2{e~|yY52+QK1Z_5TeYK3YkJGRAwr(N;F7P=An!sO+o`DiodxcWXjkeN~BaW zgc6xDWIWf8_x<*_*ZIy~`|NYpI{UQtUT+)yJ%Mo0?w%b>n7ElJidwR3 zr-nX7%`>JbdQ--Q_=+|E*$n(=(aD|roGFUMn*1+alF9>nipsaxrLoP>^;XZ9v!?7_ zO$+-y_9^U?I>#!`xVlHcHD2@Bkz;Syvu5pBqG`a+EX;k6*CRrPA^e8bIyTwYN9vPU z4`|SBI#WSUzepf>&F3-XbKT97z+*#<;SP?mPJ;v_6*TJ~kF=r2|G13Xl{t?}h zMqBC|O#UR@x3%7`LH;E0a~jY7MT6Vs|LK=pbPgU|dvL=_JSt6r-F-X$y4kVWtid|z z(67&VmtGv)sjZ#Tt?R(i>DF7NxK4oPZEDIkRqQkUhvD7*-RE!KT(x+~66=Ep=d-Y| zh?{0oEPTq>DqVimE!YsV82__>|9)v18NZYiG0m_Qe(FI>BXfJtGqBk7e8@V|Tp<7L zlsxz5V@bw3ThH|P>Ik3D%5qw;n!jOfSIzCR{?@YA@821fl$1EfFfyCC|>gaSXb6@uI9ZUTAE3qVH|a@dF<|eM;dlICEz6 zx%20-aE5+6v^G7vzx!rCzF+qKJ*S{%m@1a`a%5ycSrCgYd8l2xp5Z|f2b7hSSID1Q z>(BbUy1IONYQm|#a*58(%}dl6bz(Mb=f(1-@i9D%R99_d8V&;hI6Q^Hfp-3w^!oErla>|fBks(z^1J{ zgx;5N=~CnG+FDx67A#nx#>hWD(kpiB)~%OeM=QftmNqmPEnc-*XT{2u$zF<-#*rgQ zP3mS}h3>hn5Q5VpG8`xGtl8Sf&mFfgjdRH0-H! z*HYX#<5W{WsiHCZ-8W?YVq-0mqnNR}_biLOr8jM=cyV?7a7Pww*|H_k8z1L6^3m?li5-$r?XRSY{hvPFS~T7* zcJT0FEw7Q05vH%lqB<(WSD6;NZzBKbc&~}GO&(4fxx$iWxs;=$;|gx>(vKha&w%VXU=F2b-o^`RhgkEUS-c#Yp45Fg zbf&k-`uF#@bp!Mze}=lW6`S#?>IV+2V&;+*-&ot2VaY;8%i1p+GF#9oKU5%4eRB&7 z!WhES`hjXar`V_pJp5O$(c9O$DtMLL=eK;E7=&yp@+_d(I5>n}7yHZLi5rdO z<>gDOs&+)<>VN-!#C}zKW%%-@rlz*S(dOkp8#A~z98k_k9+#`>G$_(H(&n2tt5BMVTzrT zllIv-Xekf*p{B2{*GG1r$-)vcQ#O6gg+e1KL%Yw!DSK&TSQPrRs)ccH>W=ih+Kc;+ zJ0EcG-o0pLuYA*|XVOldJTcK4fmIz9nyf_hVkSZr#AxfUUh5!oY9u-yNV84d!XrP zM#%fL1KP(U_*6J04&<<3zkc1OvpU9RYJAw{+w;pf8zH-{3h$cG8!j@bV&L;!^Ef+u zyN*s6;>ovf2d%BG`Q3ki=f7~_f?a`ERjLy#EjeejxeJv9DimB35m-wF(Ur1BW};0 zKi`>~mluM35b81dD+K>1ZZvc2j~^njif-{EMIk%A#8XA}2Be}&N>r135nM~3J=^yD z;D#Sjmso2h56DPMv)g32LN2w|I`Sa&9dU$vQuxMmuWjT0R ztyf;^;*FDk_rqf=wp; zn0=9$9@L*1?lz)RJz{SkqB1jS;GlA{#kcN^c0PL#f;zqLhkTcmdgDpI6oUtQ+VFC- z&+3AtWbNoErKqIDp&VTur(%gT5rQ)>Rz3CY>Rx{{Nv=hU7O62d^m(`_dQX}naD*Oy zeIulxK=JJpM@wrPoA~z(Ic@E_T|10OI<%lz@vL`CM~ph;sem*5>_eWV{)^~+aaBy7 z4{_O^XiUGId$N^&XmUoTHqJU$jBm$2l|vl$6>ig>&rGjBWJPDTD>7xe11rDW7S^QUKW&-U?FUgQzWz8Mqqtf7J9 z$%!xeE5xE+(W&MeCM6{?_BLg!A3K&>=e>}Hck$7qKbP4e@oUt^DmndpFQK8S8Nct* zVSP(iS2>;CyIb4a?`0~c2L&;Ng@-%+{;s!}N5Rm+u|A2-eYktLE~D)EWkEJh&OluA zcx(a{n|AS#m6b0LOvjXpJ*V}rtlJyg^7h^i z#PGnFn3XoRwlX&5i~(MVN*;9+quaTpEXud`70k1p`&PBw3tu;5TvS3lNVuoB^26HtnchbP>z=+DB8!jb(k&PV_uNcwbC&WSG< zj(^H&P01)amy(hqdl<1r&Z*7+rJ_`kXH|9eVqbT+rPsXo?LB;0*n9eq9aRD>@&<7_ zSxQ7?5u&8&qr*!s@@x%6YU9UOu>7{MDSmDiPln7QA4)zFs~Iwx@_w9?qj_`l@&48z zKC=FDXMe3mSO`4()r+gOwUr~sQDB^p)7Yq`!lwja^e)mhmN9XJfrWSdK||Wbc;f6 zdwcunEshoe756TjKY#vo+#VSN0|Pk)1<`Ce-P}=Oq=8T_Da|8C)?c}DWsU!(@z~ATRvw8|7-8 zph(sp;o5jC{=wP4=DL}UwMMqFjlGJE8cwmrFGt(c4m^32ebnUGmwcmfdfO6TI)ZIA zBY4B7CPu}+ZDliBjMcuA;5ei;5!m;~(gv8j3hNqXN>)N+Lwt;icjU(zklXHRRXRXe)L0@?T!#<%gG9p=9^X>r{n{d@>~dCwMAg< z+WG7D+)_PtY6GIVMd#;p=jan2JV?pr!>!b}w4_ctJD24-cj@ZtQn(Y@?NYBRLb>Ru znwlD^O;Q^-E@$QxFDVaMKJfjm;Ew~ZdwPyB@}KOg;Q?y8zQ6za4*QHyg}$l?<#EQl zckf0kx^1xVnR1D~af4tPTr{RFH@OUkl~*ddO6MH=cn-(FYI1CV$*bbkLIwtgD7nUp zitW8q*MwA5_%2_*O!=ZHExBi<7rt{?SsR^4 zv3m#Q%7;gG5v5NeoI9)CejH!2T8l4h4rkS=yI!QHxo{O79bI>zMSN+g zTF>Xa<$-~L4(1yM3y|>++S%EDe0az-=U9xs4^pADRS7jY)*iuKVXBAPSK6U|eSlH# z;NT!T??YNTsvrUi0ZBCwz}Y3Y9j!}Pgd$L^r#e6s5C1Gu%p}vMf(ZwI9$?g>qRGKm z8@kd=v($d{r~|Y{Ru;OxZ`qFDpZWN4IUYUh@N4dXN1r-g4B_qwh>I^qxiy9?W!U)# z7>Z8uz{m7>%cGrtW~6J6n#4wxzj(3BzM;HpB{z5cfhQ;APJLq}HEzx7qEvtX`5N1| zw-StBV>&fdtHP?bUh&`x-_r{xkr}yruLf&XmeLlAOrOzX z+wy=3hI(sT+w%kmBu}BbC{H$cz{<%fED?Et=XuAe0LL6UD@0nY;^z(gS6^gWmn}Sa z=#X`NlAiSD&DV?e4Udjiea>@sYAK;hWN8Pz;17}@K-|b{{I`9oX%_v}b$crT5-wlA z9+;>dWz*mCtbb(0SpG?ZM=JI;K|6)A!oJrXI!DWW`cx2g2I}jQjN)k~TU*-z#fXrQ zXSk`a!WL0QV{Ocg{L^+rfSIb*4 zHS+2ErzcW?R^h`x8_T|Y;lY(gDW|5Z%jykSM%BjhZ#?qm&a#X}K4bm-l@WXqg&w1* zgvoiA^Bj`~VZn?FjZ}%X3u-z>7M3bx!Iqyt4_H?zp8B?v@Cj6X zz9M7N2M?+0*RKc4SXAy1M&V2TCd9s_;CU$3W5>ixOH2F5e*$d102eXR`-zT1De^b{ zfdI64<%apF`At^%w3aTgXY;$c#ZfD29$l@n;z-|DKHQ8IawqTTd#X&23C7>Mr`?mH zg~(BsbNrK)g98(4om&bnOvN+PTd@PLvXuaak9{rTK|1m;E>^*>3p(*7-+KJ_k12cyO6!#4G}`k(2#w4tepkPvh?-qC0vqbzJU7r1_rGi z9YTd?FPIm5^ALWAl|F)3sT4I5ouWrZ+Wu@NoXEiQ=jQ=y24KAfl$Ck$*cyN>S*`;% zC}`+dcokJiWsA#eTOQ0-?JQkO*ZF5iw3}Cq`u^tbyy=OrGlU!=NhO#~@Xcd;16&FI z4I7pL96QIjc~4Ke`3D6FBF(25r7%!Ir95YSJX$I4F`kYfNa7KEtiy(EJfLH1nC}#KO{b0AnV9mf!1%| z)}k=c0Msc5nytXuEzvaO*UBP#}!*wgj)@8#1D3Y1XPVsP6=>tnLGFFxn2q8Eu_e6!r^y*LP7## zo|&YXnVD?U#rs#TUfr&%d+DT;6WjRsc``WrMiFNnp82h6Tr- zJ$sm{3_W}7YHsN@9o{8>`RY|cQUIZ*dCY#=*!cR`?{|9xP%ys%JU2Erjt7NlQ*nW# zZs_`jC~J!%Pq&z=>G(T$*6>HYszB)EXaYJHL$z1ozi4@V^K}Kc=>o19-U~yYYijnO zyjjG(ZL0N{f+Z{J$SZmf;ziWCR5A}}A6A~QbN`osyz{Ih+M9d21y1`BZBZ9sO` zU73=?7h_j!JRAlB`!abE5Eg_WFc^Ol5-fUACzz{dz#uZ@;ziAgk=`tjqd#tb!KIOP zY+emWBnPaP>>LG%yK>{~>3ddxYsVQLormtXQA@ z25VH#Cx%qwjXx~>8w|j-@>5}5&;-WI~O@3~B8Ws)R3Z~8D#ItB=X@#V0 z<9H&pZe5g|6f(r0KYtF@xVX4f09{fPD3$)-zspCz`a~eV6Vge^{dWn@dcAvWkmyz6 z-K8io3@@^&wW!SeVIcsBKyYMDVx zH1XItJP+#AGcu%xqc*en?spF5I|1UyYZCFhPV^A?Yeq)K5`;^c6QAY6FAB=ZnWh;P zk7@sEXgPlM!kL~AcL%F4Q%8(_4_2E|T7!rH`N$AgE(f6WRXF=AwZFxH!uzP=PqMR^HpGMMVD-puUcq()OHm0fUZHMvU{23@oFalcNbGrBS91#m8e|_Ru5Ppz9&vuVmL}eTbo&8|KpO6kL)7H z@uhI2&U+|*s5MHgLlyMtckWQAv@&yYBsbQexVwik)Pcv~P>N)6m{IaCnGMRrk;X>~ zhTk7BV%=R~6B}je62X!*En^%t=HPsBxn4#4shU0*DNp@2NVtC=EbU5!oo6Ve`(JPQy0cvq<#STf`hc5JsBnUD9OE6o7DaD9 z&VBmy=}d5zADWs7&a0Dy5+iO|w3?(wBr{UbuU)&=il{8@;ajAEK(v$&<1P!tH<2xT z!5OiZQc7BK4?8v09`=Ud?xYDJ9_ z%%7j1Z~E}yqWgQ}mLej~0vAq+b7qo0kwH7iiy4Y#Wzr7+9v&va3eQwfFOw)?+0)YE z+uwgOdt~Fm=d6Gq35xv7*zo5qvugxLgJ?tR;jV{d^GIucjv} zt9QGsly+k!fgWl51FXveiROlCn@DCC`Bc(RSwQB>Kht{w=L;7$^X|;-+O^9MM4`Ti(}7c`PK6BBy?b{#F3z&k3|a|AG5}F?Y#|`v(K$Gj=T^O9 zBT@>IJ@DDJrs3h?#M#K}@vDl@Ck$Bao?UG$ca_fU(<<5;rD1#5sHj*bD@jT1?Up*u zOJ#R@&rFRXv9Fc1C@|%hSx!Ed4X;&EQ?nFLq}3}TB0^Cf9uv#D_L-Wh?%lhW`+>tR zsEDmyT?`;NP>?ZD{r#=#l&X!50233F)|b6mKtZ4^L?17hKYz`dHL4wo@lC?0bU~_X z^=9+);VNZstqMtMd*RO-Pdk6d4%ho4B7vZilDRcq==M-f>-VYqAi(r&D9r%m2U`N$@L;QJe&l58ylN9s2if>HVDu}{<^RpsWdiA zOG}6rHf4cJ^bg>ytEsEME%Ne6PSV=Bvjo34vNKlRc_Ef6vI)Q~W^dpEG*M#9N#J^QN#K>Ttg ziC=npdalz4+d=qbIkjv4?)}6CoPGY{#ic|&gW9HZTfvBX3ka&jDbBdN-Cv$=Nli_) z_&6}T4GqSmE<_Tt0dyjD;f4(x-k=Qc`SO$tLEBg!3X6MiSeORtKTdH|U*PrA(A$BF z0<*JSgtqS`&uX}3fLBa^RbSy6+SEUmWY&WaEL&cBVfJr3)x}f)JAEm^yn)Uz8)+Zx z0UwsO0x_Z$F&%^gl*m%Ztf%q{XzFWcua84|O>EXOHLI7`M1X49aOVR>4DPo;bftVj zugMdBr5*q(=b_2qlDvAr&rktaGet-5a5=-r06O6QrtW*rnOUaJZmw z!1Va%Ts9nt^7!qcgda|v2K>^p%bZ&+!{kQ+MmY8gr@!ku6koo~22RB=WOnb6NQ~^5 z#a69awN_a8dK2IB<>wnMJkpj4l4ll(zd@_vG(Nv@NhuzaQ25Eag|E_4OL-N8fnm#P zYcpu2vp*Tnoq!)iv^;nOkmobGMnz%_`LcNT_^ASgFi z&eg-C9cn{eZk+e{A~5Xa=8*FXNF@ji4sQbt9$pQ9W%#2n%7=c2{ky7UmYKK|6%~XJ zEUT)06 za$>YE2q-_#cJ3K|;u(fJZ#uStW3B`v_~!oZRRKjGKA3_%xvS5|dd$wwq;2IxQXH($ z?$651^hF6IyXQ+@U*Rb4$geMXx>z zTbphBZ9}z2HXq8U;3UuP9wlSgEaW^!#EITOTtCmwEilcrq9c_iU{xz_UZk-hT`lJ; zLMtNJCFFoOgu^4A$ZmR(moAZlT=cb)bLV2vePY=-f=i%_=_&lo0YoM|=|;O6&*b>I z$ggEW4)|V1Kdk#aDm5()nU=P8sgIA(WPce8VEMVfvKlM}tCc-hAnh!qNRpXNY#9=` zt{^eD85?tgeOUfc)|8Hn3bKO~nxrEXR%?*A9>PdT@Dz zceOL3;b8KkQ9On4)n}EJ_i1G$+sb&196RLmTf&D&-XnXMB z!Ip|B#L-qH>g4$EG(PXEyA3B~z!(I-e1LSKaI%H+^ztGm13=%B&!5fgb&SlH?VL^i zo3w9Bq~70i`vURx;MyF40&f(gKKDJ-+vXho2uov76!sa;rh?0rIK&Ne)SZ#birJqt zWX833z}^yH6&4kayV*-aYb8e@h=mUseAD!BhR?IADhBw*fccngah8CK47Rh)7BhOg z$vr2wr12TVl=t@-v%?eN>2` z2)^m~@#BbTiF|WE_K-Xs;P3aw3_ftue1yWqClYet62CgR=*T)`KQp?e=hEszl2+R) zLJ60G5Ko8;O8Rj13UD~{APi|B_;7D>Fs#t~>)Cbj?1VXiriFKV^WHm0t_^f4Je;dG zmlL>zLq=PCc`gwLBN0OYQ8O{&qO1-dUI;{pShRBr#ec5X#2KT2xmdbsCpHFFBd0%u zhkn$O;vHbH|Mw3AD5};dR9$F#EFV-2Y7MfkuhWSlKJgP=9sD^Qrg{Si1$-+;U$0~V{ga;b|@?18P;2b8o5sxhp zazi!TU%ATB@b678tN*A?H@jZJqFT4*Z5xvG1fL9Xp-dBB^j|ruKL7`Ao7ADt#%B zf2 zLM8AbML}bY-gJ}`PR3AR2CBrPuP_K89S#*f@O-e7_*Cqe-9W>q^&dAHLmVgv|7~^r zcsQwnASr^XUCb$Eu^2FtfPVZyYJD^g$$!j}5)JzA;x)M!@8;UyLI>AflJv}Z7Uh!m zs)zxkQ{$G|#b9e#f_Uisx)XaZn^DzB`J2cZ_pyLXO4g_|+{&99D* z1r!3jS;){Fhq~bL(Z)T=wZM`C0|U=rzPvI*r)r;ydJMkP1n=21t#5goh$*OicR<`p zQCN)oTLL0HxiD8kUOunf4JG#T+FB{+bQpy7_4Viy zUX_>_BbS}9?y2kRU(xqKw4+Lzn~TcbI5|1rynA=GGWo_)FqwFC5O1PpOHFlkec=PS zmLJgtU){6%dc(UCYt~Ru3lG%@(RTl9Tq2PQi={7^fOwyoX(OHs2`)e1!?L#?RYyXm zFA*IQr>{UfxQo*R2$8D)6<;DwK{$5zTCc(jZ-*~0!HN6@`8#>SwHc|CIFUC+Tu2(B zz2-~*M`_;h(TI)*2F$|wnY6L-@%YS4R;ap{nh*fkaATp4mA!q-MqTQ>-86|L zpIckYg2F(A=xaSaVdOr7kRAgFOmIRareSD!P0bo+9*tut%>a5T9^1dWbMM}H_{^R` z$AU2|vU25$6;{)ee~90=rK>9lWpXS093P6jwsK0EF)}lU{)3>rgOdPP7L=esAf3R) zE9v32Bx1A-4%N18+akFe|0Nm;#WSVc!rf4U`$_<&DEK;5_4L^CPyaXvN`V*@tb35h z?&8T{5oqg*^9j6nPtZ8SA{^$h!k6l^lRI6{#;HI>h7WW&VEaSBM~sh0rl{~ z4KXjtyWna@vj27C4RPZKp^b~Cf@LQ5(OYs(^hhZ?Ao0=GE6jb^E+oio)QI{M09FxL zLhBEi){$JSb0O5Upo%sh8fPhpEM$Z*+R}izTupHrC!)-%fN=uXeD0&@Oid$k)fmVo zwzRb9Hr$>46ul+7c70jhSl^Id$oa$zrH6X~#@y(X;p}S|E^qi)N`s-?-bgh@ClJ1a zyD)T3dQXs)EunoL{o04Ey*sc19hR%a6N6|nGyN{23Tm~SM`cHso)YPm083V!L zxM#3nCcoiAzEJiWZvmBA3gIASz1rLYh;;X?OaX+}xgonNIfYeOt4 z5exow-XxbXAYcLM6T#kzh2=p|1ikwf{0kx(3p7h&gFtn2;O!jjHnam?6@@BpVPQeI zU>J=FsUmyg^9oc`P{bs$B5z@L&<2P=_=Yaxcmf`; z#BCtjH(?rpD8zu0;pkcu{^_y(^35kc2NUx+Ed9|N4lxnR&}U}i>)6!jSIdq$p`l?8 zVR!*M1JB4zPY&&6XJ;<~Re|D51A*}*JS)F{eOU$eBkeJvfk}S`l>9PC!4x6g;T0hy z3&=!6c^?!Q#LfVEvmd@@I;x(!JRz+RNiVTA+Z6rg$Ni0h&Bs`Ktp3bN;8=wZ`LHg#@+xm zj{SHLcPTC|7F9V>D;hVR!*RVkX zQKs(wdrc_p6b0HGYV|e;2U`7CWF%nNyt=lK&`@;{E|IZMI#4zcT@WVp`aJN?WKZz< z*T(UxtXy0sozpY$#F*~eSLoR?7a7hni@`Jcqgg0MXCZnQNV%#%12+$;%1rhvg0@CB zHgJ$SfvaLHKl&$2ss`k>iCg7QWC8+lKlw`X3CITR`g;@RH*tduXx!tXF%AJ+!I+%2`+$mXMMW`C($doFT~<|iNo}3Mev!KD;lqa~C&!!;Ju+rrVW$#V?zeCK(72-Z z2`y7-Q|ez<1(wCSG2Q%oLkbtR*67417+4@DI#lR+{)vU$aC+C*p$ngIVP1XKv>%cX z7r$0>n1h|&>dl>PM88djlc1Cd>Y|R z8FY=@lmzvZ6ssEqZ*kFGJU`Vpck^u%1RT$~xO;0cuw3IEw8`;8N%r z52Qy(;3nGprAw^Yp`x>~Ow=6EH8X!;c(|f?X3DW(;@4BOjcou=&$?{cIUqXJx_hmU zp<1S+&i?v*x#@7ttq`b>g!e>!gC3>L*QG2k!c*7siUaf-faz=C4KO z)}I`Ur#6R$g;{*@o2`!<)WG~N$}_u&P&Mmqf=}r(8Xs_iiTN3xkwZ0SPoD-BV!y8w zb8fHlpZQQqNmMjWH%mU5^Aoq9@&y!Xg&|JsQ=ZqvX69K2AU>+Rl*TQyWlI&R*i8F( z!jbK_J8VAq#;!z_ zz9J|@7C*k5AayuxD#*=7K>{D$LiD)Zl4C<)hvkB#8w6(E2J1Oq0f>S*#Rm4AF~kEW z#8gz1^Uy0*3T!b@v$gLIT&(2i;SQxJ=*;dft+LzGdRP&(Bs{okmX>^KjA)mbgxd%9 z!9Y-Wl9okg4Rdi_Zw!#B9Hu;~7vv~b3Wg&TDxO=;$3 zq?qf_>n-TgTnq*{Y=sOx@y^KGfd)t03{b#(Sx@pv@e0~RA+F#Pr81745uz0gs+wtfKYH~sDVQq9OOiHM{+yDt4I!t9#0jNdh|Q~o7nvD zWnOKBmy@@ur=rgRAr#P zb#`9Q4{s}a*!lCvkGrtIpmK7BuneS~ZX7oI>^ry3vBR z%}}K`Jke|N#Nk06=KuHRdPVo&j3ti_H3qPvy>KaMO$MK^q4R%FnqC7Tm<7jC{nV+4 zrSzPrQUM+qpv-F*)MrEkt&_|4nEnn(3+MqS$NH^_9v;rUNq=P(nm@J7-Ie~GwA7#? zCqR?=ONNDX?~hc4cO>rKAM(cV4Z(!F1D-aH3p9uYlq&K^LJkTiTNtp>Q0k8gl4?P2 z&-I>CICt(Gr6^W}{#AxVFP}dhQ3TY0IM6bq=ExGm_LV6Pq;S8j;8F@}vy9jHX&@+m zbTB}nkb^(~t~4ycOYaasBUg8K8wi(7+l}l==;GiAAhPV$y~=*D z#t}*kWid^hHV0mu6>YaWv~T(N4<#h`v%+jxyBvrv^VvW4!GH1F|Nnoy!Uzqbt(c+4uf|KXj5VVV2V?(ilFr!W66o9NJ z+Zzq{yYg7eJg^|dXpWO|sKyc>&a2`b2DYY!P_M|4#79HoHlW4zN)8SVYrGmEUO{gY zKA8}Rzqf-0UF=qX!TO(YnVbgN zwv*b5(0wmnY=bMMf=`ztc~Nl>%_A&quk$AU${VTq#YGKD%6G=Ao{zyZVDrBhcdt%Q zLQ0=U!IkqS-Fz#$5ud$z!>S&*cpH?{1w2d0dDi<<`X9vM)0IDw04NHiI@ U7|<( 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 literal 0 HcmV?d00001 From a4ab4dda48824361fae42f62d5a2c419eeb49070 Mon Sep 17 00:00:00 2001 From: ptajvar Date: Thu, 22 Aug 2024 10:59:18 +0200 Subject: [PATCH 3/4] added plot legend explanation for abundance_colocalization_plot --- src/pixelator/plot/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pixelator/plot/__init__.py b/src/pixelator/plot/__init__.py index ac9fb657..a73492d6 100644 --- a/src/pixelator/plot/__init__.py +++ b/src/pixelator/plot/__init__.py @@ -515,7 +515,11 @@ def abundance_colocalization_plot( ), ) # TODO: See how the legend is determined based on the merged data to be - # able to access actual marker sizes. + # able to access actual marker sizes. Right now the _legend_data includes + # many points with different sizes and and colors even though both are + # normalized to the same range. So in the code below, we are only keeping + # the first 5 points to include the color range and setting all the sizes + # to a fixed value 5. for i in range(1, 6): if i >= len(plot_grid._legend_data): break From 334d78c213ed3d9dade02eca71e4038583adbb47 Mon Sep 17 00:00:00 2001 From: ptajvar Date: Thu, 22 Aug 2024 11:02:46 +0200 Subject: [PATCH 4/4] updated CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e68ec151..eb2fc008 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved memory usage when aggregating pixel files with precomputed layouts. +### Added + +- Add `abundance_colocalization_plot` function to make scatter plots of selected marker-pairs' abundance. + ## [0.18.2] - 2024-07-16 ### Changed