Skip to content

Commit d10bbb3

Browse files
Update config_template.toml, config.py, display.py, and 17 more files
1 parent c13da04 commit d10bbb3

20 files changed

+214
-100
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,8 @@ mkdocs serve
5858
Head to [http://localhost:8000/](http://localhost:8000/) from a web browser.
5959
The documentation is built with [MkDocs](https://www.mkdocs.org/) using the [Material theme](https://squidfunk.github.io/mkdocs-material/). [KaTeX](https://katex.org/) CSS and fonts are embedded instead of using a CDN, and are under a [MIT license](https://opensource.org/license/MIT).
6060
61+
## Contributing
62+
63+
6164
## Credits
6265
`cuisto` has been primarly developed by [Guillaume Le Goc](https://legoc.fr) in [Julien Bouvier's lab](https://www.bouvier-lab.com/) at [NeuroPSI](https://neuropsi.cnrs.fr/). The clever name was found by Aurélie Bodeau.

configs/config_template.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@
1212
# - matplotlib colors : https://matplotlib.org/stable/gallery/color/color_demo.html
1313
#
1414
# Configuration file part of the python cuisto package.
15-
# version : 2.1
15+
# version : 2.2
1616
########################################################################################
1717

1818
object_type = "Cells" # name of QuPath base classification (eg. without the ": subclass" part)
1919
segmentation_tag = "cells" # type of segmentation, matches directory name, used only in the full pipeline
2020

2121
[atlas] # information related to the atlas used
2222
name = "allen_mouse_10um" # brainglobe-atlasapi atlas name
23-
type = "brain" # brain or cord (eg. registration done in ABBA or abba_python)
24-
midline = 5700 # midline Z coordinates (left/right limit) in microns
23+
type = "abba" # abba or brainglobe : registration done with regular ABBA (except allen_mouse_10um_java) or abba_python)
24+
midline = 5700 # midline coordinates in microns (left/right limit, Z for abba, X for brainglobe)
2525
outline_structures = ["root", "CB", "MY", "P"] # structures to show an outline of in heatmaps
2626

2727
[channels] # information related to imaging channels

cuisto/config.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ def __init__(self, config_file):
4242
else:
4343
self.bg_atlas = None
4444

45+
# name axes to handle ABBA/Brainglobe atlases differences
46+
if self.atlas["type"] in ("abba", "brain"):
47+
self.Xname = "Atlas_X" # antero-posterior (rostro-caudal)
48+
self.Yname = "Atlas_Y" # infero-superior (dorso-ventral)
49+
self.Zname = "Atlas_Z" # left-right (medio-lateral)
50+
elif self.atlas["type"] in ("brainglobe", "cord"):
51+
self.Xname = "Atlas_Z" # antero-posterior (rostro-caudal)
52+
self.Yname = "Atlas_Y" # infero-superior (dorso-ventral)
53+
self.Zname = "Atlas_X" # left-right (medio-lateral)
54+
else:
55+
raise ValueError(
56+
f"{self.atlas['type']} not supported, choose either 'abba' or 'brainglobe'."
57+
)
58+
4559
self.get_blacklist()
4660
self.get_leaves_list()
4761

@@ -125,6 +139,6 @@ def get_hue_palette(self, mode: str) -> dict:
125139
}
126140
else:
127141
palette = None
128-
warnings.warn(f"hue={self.regions["display"]["hue"]} not supported.")
142+
warnings.warn(f"hue={self.regions['display']['hue']} not supported.")
129143

130144
return palette

cuisto/display.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -796,12 +796,12 @@ def plot_2D_distributions(df: pd.DataFrame, cfg):
796796
cbar_kws = dict(label="count")
797797

798798
# determine which axes are going to be inverted
799-
if cfg.atlas["type"] == "brain":
799+
if cfg.atlas["type"] in ("abba", "brain"):
800800
cor_invertx = True
801801
cor_inverty = False
802802
top_invertx = True
803803
top_inverty = False
804-
elif cfg.atlas["type"] == "cord":
804+
elif cfg.atlas["type"] in ("brainglobe", "cord"):
805805
cor_invertx = False
806806
cor_inverty = False
807807
top_invertx = True
@@ -812,8 +812,8 @@ def plot_2D_distributions(df: pd.DataFrame, cfg):
812812
outline_kws["view"] = "sagittal"
813813
nice_joint_plot(
814814
df,
815-
x="Atlas_X",
816-
y="Atlas_Y",
815+
x=cfg.Xname,
816+
y=cfg.Yname,
817817
xlabel="Rostro-caudal (mm)",
818818
ylabel="Dorso-ventral (mm)",
819819
outline_kws=outline_kws,
@@ -825,8 +825,8 @@ def plot_2D_distributions(df: pd.DataFrame, cfg):
825825
outline_kws["view"] = "coronal"
826826
nice_joint_plot(
827827
df,
828-
x="Atlas_Z",
829-
y="Atlas_Y",
828+
x=cfg.Zname,
829+
y=cfg.Yname,
830830
xlabel="Medio-lateral (mm)",
831831
ylabel="Dorso-ventral (mm)",
832832
invertx=cor_invertx,
@@ -841,8 +841,8 @@ def plot_2D_distributions(df: pd.DataFrame, cfg):
841841
outline_kws["view"] = "top"
842842
nice_joint_plot(
843843
df,
844-
x="Atlas_X",
845-
y="Atlas_Z",
844+
x=cfg.Xname,
845+
y=cfg.Zname,
846846
xlabel="Rostro-caudal (mm)",
847847
ylabel="Medio-lateral (mm)",
848848
invertx=top_invertx,
@@ -864,8 +864,8 @@ def plot_2D_distributions(df: pd.DataFrame, cfg):
864864
_ = nice_heatmap(
865865
df,
866866
animals,
867-
x="Atlas_X",
868-
y="Atlas_Y",
867+
x=cfg.Xname,
868+
y=cfg.Yname,
869869
xlabel="Rostro-caudal (mm)",
870870
ylabel="Dorso-ventral (mm)",
871871
invertx=True,
@@ -879,8 +879,8 @@ def plot_2D_distributions(df: pd.DataFrame, cfg):
879879
_ = nice_heatmap(
880880
df,
881881
animals,
882-
x="Atlas_Z",
883-
y="Atlas_Y",
882+
x=cfg.Zname,
883+
y=cfg.Yname,
884884
xlabel="Medio-lateral (mm)",
885885
ylabel="Dorso-ventral (mm)",
886886
inverty=True,

cuisto/io.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,17 @@ def cat_csv_dir(directory, **kwargs) -> pd.DataFrame:
112112

113113

114114
def cat_json_dir(
115-
directory: str, hemisphere_names: dict, atlas: BrainGlobeAtlas
115+
directory: str,
116+
hemisphere_names: dict,
117+
atlas: BrainGlobeAtlas,
118+
xname: str = "Atlas_X",
119+
yname: str = "Atlas_Y",
120+
zname: str = "Atlas_Z",
116121
) -> pd.DataFrame:
117122
"""
118123
Scans a directory for json files and concatenate them in a single DataFrame.
119124
120-
The json files must be generated with 'pipelineImportExport.groovy" or
125+
The json files must be generated with 'pipelineImportExport.groovy" or
121126
'exportFibersAtlasCoordinates.groovy' from a QuPath project.
122127
123128
Parameters
@@ -129,6 +134,9 @@ def cat_json_dir(
129134
something else (eg. "Ipsi." and "Contra.").
130135
atlas : BrainGlobeAtlas
131136
Atlas to read regions from.
137+
xname, yname, zname : str, optional
138+
How to name x, y and z coordinates. Default is ABBA convention, eg. Atlas_X,
139+
Atlas_Y and Atlas_Z, resp. corresponding to AP, DV, ML.
132140
133141
Returns
134142
-------
@@ -160,9 +168,9 @@ def cat_json_dir(
160168
.reset_index()
161169
.rename(
162170
columns=dict(
163-
x="Atlas_X",
164-
y="Atlas_Y",
165-
z="Atlas_Z",
171+
x=xname,
172+
y=yname,
173+
z=zname,
166174
index="Object ID",
167175
classification="Classification",
168176
)
@@ -177,7 +185,9 @@ def cat_json_dir(
177185
df["Object type"] = "Detection"
178186

179187
# add brain regions
180-
df = utils.add_brain_region(df, atlas, col="Parent")
188+
df = utils.add_brain_region(
189+
df, atlas, col="Parent", xname=xname, yname=yname, zname=zname
190+
)
181191

182192
return df
183193

cuisto/process.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def process_animal(
8686
df_detections,
8787
cfg.hemispheres["names"],
8888
cfg.atlas["midline"],
89-
col="Atlas_Z",
89+
col=cfg.Zname,
9090
atlas_type=cfg.atlas["type"],
9191
)
9292
# add detection channel
@@ -104,19 +104,19 @@ def process_animal(
104104
df_detections["Atlas_DV"],
105105
df_detections["Atlas_ML"],
106106
) = utils.ccf_to_stereo(
107-
df_detections["Atlas_X"],
108-
df_detections["Atlas_Y"],
109-
df_detections["Atlas_Z"],
107+
df_detections[cfg.Xname],
108+
df_detections[cfg.Yname],
109+
df_detections[cfg.Zname],
110110
)
111111
else:
112112
(
113113
df_detections["Atlas_AP"],
114114
df_detections["Atlas_DV"],
115115
df_detections["Atlas_ML"],
116116
) = (
117-
df_detections["Atlas_X"],
118-
df_detections["Atlas_Y"],
119-
df_detections["Atlas_Z"],
117+
df_detections[cfg.Xname],
118+
df_detections[cfg.Yname],
119+
df_detections[cfg.Zname],
120120
)
121121

122122
# - Computations
@@ -270,7 +270,7 @@ def process_animals(
270270
# -- Saving
271271
if out_fmt:
272272
outdir = os.path.join(wdir, "quantification")
273-
outfile = f"{cfg.object_type.lower()}_{cfg.atlas["type"]}_{'-'.join(animals)}.{out_fmt}"
273+
outfile = f"{cfg.object_type.lower()}_{cfg.atlas['type']}_{'-'.join(animals)}.{out_fmt}"
274274
dfs = dict(
275275
df_regions=df_regions,
276276
df_coordinates=df_coordinates,

cuisto/utils.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ def add_hemisphere(
299299
hemisphere_names: dict,
300300
midline: float = 5700,
301301
col: str = "Atlas_Z",
302-
atlas_type: str = "brain",
302+
atlas_type: str = "abba",
303303
) -> pd.DataFrame:
304304
"""
305305
Add hemisphere (left/right) as a measurement for detections or annotations.
@@ -321,9 +321,10 @@ def add_hemisphere(
321321
col : str, optional
322322
Name of the column containing the Z coordinate (medio-lateral) in microns.
323323
Default is "Atlas_Z".
324-
atlas_type : {"brain", "cord"}, optional
325-
Type of atlas used for registration. Required because the brain atlas is swapped
326-
between left and right while the spinal cord atlas is not. Default is "brain".
324+
atlas_type : {"abba", "brainglobe"}, optional
325+
Type of atlas used for registration. Required because the brain atlas provided
326+
by ABBA is swapped between left and right while the brainglobe atlases are not.
327+
Default is "abba".
327328
328329
Returns
329330
-------
@@ -340,12 +341,12 @@ def add_hemisphere(
340341

341342
if kind == "detection":
342343
# use midline
343-
if atlas_type == "brain":
344-
# brain atlas : beyond midline, it's left
344+
if atlas_type in ("abba", "brain"):
345+
# regular ABBA atlas : beyond midline, it's left
345346
df.loc[df[col] >= midline, "hemisphere"] = hemisphere_names["Left"]
346347
df.loc[df[col] < midline, "hemisphere"] = hemisphere_names["Right"]
347-
elif atlas_type == "cord":
348-
# cord atlas : below midline, it's left
348+
elif atlas_type in ("brainglibe", "cord"):
349+
# brainglobe atlas : below midline, it's left
349350
df.loc[df[col] <= midline, "hemisphere"] = hemisphere_names["Left"]
350351
df.loc[df[col] > midline, "hemisphere"] = hemisphere_names["Right"]
351352

@@ -399,7 +400,12 @@ def add_channel(
399400

400401

401402
def add_brain_region(
402-
df: pd.DataFrame, atlas: BrainGlobeAtlas | None, col="Parent"
403+
df: pd.DataFrame,
404+
atlas: BrainGlobeAtlas | None,
405+
col: str = "Parent",
406+
xname: str = "Atlas_X",
407+
yname: str = "Atlas_Z",
408+
zname: str = "Altas_Z",
403409
) -> pd.DataFrame:
404410
"""
405411
Add brain region to a DataFrame with `Atlas_X`, `Atlas_Y` and `Atlas_Z` columns.
@@ -417,6 +423,9 @@ def add_brain_region(
417423
atlas : BrainGlobeAtlas or None
418424
col : str, optional
419425
Column in which to put the regions acronyms. Default is "Parent".
426+
xname, yname, zname : str, optional
427+
Name of the x, y, z coordinates columns in `df`. They should correspond to what
428+
is expected by brainglobe-atlasapi : x is AP, y is DV and Z is ML.
420429
421430
Returns
422431
-------
@@ -435,15 +444,15 @@ def add_brain_region(
435444
lims = atlas.shape_um # out of brain
436445

437446
# set out-of-brain objects at 0 so we get "root" as their parent
438-
df_in.loc[(df_in["Atlas_X"] >= lims[0]) | (df_in["Atlas_X"] < 0), "Atlas_X"] = 0
439-
df_in.loc[(df_in["Atlas_Y"] >= lims[1]) | (df_in["Atlas_Y"] < 0), "Atlas_Y"] = 0
440-
df_in.loc[(df_in["Atlas_Z"] >= lims[2]) | (df_in["Atlas_Z"] < 0), "Atlas_Z"] = 0
447+
df_in.loc[(df_in[xname] >= lims[0]) | (df_in[xname] < 0), xname] = 0
448+
df_in.loc[(df_in[yname] >= lims[1]) | (df_in[yname] < 0), yname] = 0
449+
df_in.loc[(df_in[zname] >= lims[2]) | (df_in[zname] < 0), zname] = 0
441450

442451
# build the multi index, in pixels and integers
443452
ixyz = (
444-
df_in["Atlas_X"].divide(res[0]).astype(int),
445-
df_in["Atlas_Y"].divide(res[1]).astype(int),
446-
df_in["Atlas_Z"].divide(res[2]).astype(int),
453+
df_in[xname].divide(res[0]).astype(int),
454+
df_in[yname].divide(res[1]).astype(int),
455+
df_in[zname].divide(res[2]).astype(int),
447456
)
448457
# convert i, j, k indices in raveled indices
449458
linear_indices = np.ravel_multi_index(ixyz, dims=atlas.annotation.shape)
@@ -556,7 +565,7 @@ def get_data_coverage(df: pd.DataFrame, col="Atlas_AP", by="animal") -> pd.DataF
556565
df : pd.DataFrame
557566
_description_
558567
col : str, optional
559-
Key in `df`, default is "Atlas_X".
568+
Key in `df`, default is "Atlas_AP".
560569
by : str, optional
561570
Key in `df` , default is "animal".
562571

docs/demo_notebooks/cells_distributions.ipynb

Lines changed: 4 additions & 4 deletions
Large diffs are not rendered by default.

docs/demo_notebooks/fibers_length_multi.ipynb

Lines changed: 5 additions & 5 deletions
Large diffs are not rendered by default.

docs/guide-install-abba.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ You can head to [the ABBA documentation](https://abba-documentation.readthedocs.
33

44
You will find below installation instructions for the regular [ABBA Fiji plugin](#abba-fiji), which proposes only the mouse and rat brain atlases. To be able to use the [Brainglobe atlases](https://brainglobe.info/documentation/brainglobe-atlasapi/usage/atlas-details.html#available-atlases), you will need the [Python version](#abba-python). The two can be installed alongside each other.
55

6+
!!! danger "Important"
7+
Please have a look at this [few considerations](tips-abba.md#abba-and-brainglobe-atlases) related to coordinates systems in ABBA and Brainglobe atlases and their consequences on downstream analysis.
8+
69
## ABBA Fiji
710
### Install Fiji
811
Install the "batteries-included" distribution of ImageJ, Fiji, from the [official website](https://fiji.sc/).

0 commit comments

Comments
 (0)