-
Notifications
You must be signed in to change notification settings - Fork 2
Proj mat calc fix #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -102,6 +102,30 @@ def load_structure_graph(): | |||||
| df = df.set_index('acronym') | ||||||
| return df | ||||||
|
|
||||||
| def de_layer(st): | ||||||
| """de-layer cortical projection targets | ||||||
|
|
||||||
| Args: | ||||||
| st (str): e.g. ipsi_VISal2/3 | ||||||
|
|
||||||
| Returns: | ||||||
| str: e.g. ipsi_VISal | ||||||
| """ | ||||||
| CTX_STRUCTS = STRUCTURE_DESCENDANTS_ACRONYM['CTX'] | ||||||
| sub_st = st.replace("ipsi_","").replace("contra_","") | ||||||
| if sub_st in CTX_STRUCTS: | ||||||
|
|
||||||
| for l in ["1","2/3","4","5","6a","6b"]: | ||||||
| st = st.replace(l,"") | ||||||
|
|
||||||
| if "ENT" in st: | ||||||
| for l in ["2", "3", "5/6", "6"]: | ||||||
| st = st.replace(l,"") | ||||||
|
|
||||||
| return st | ||||||
| else: | ||||||
| return st | ||||||
|
|
||||||
|
|
||||||
| def process_pin_jblob( slide_specimen_id, jblob, annotation, structures, prints=False) : | ||||||
| """ | ||||||
|
|
@@ -303,6 +327,7 @@ def get_ccf_structure(voxel, name_map=None, annotation=None, coordinate_to_voxel | |||||
| return name_map[structure_id] | ||||||
|
|
||||||
| def projection_matrix_for_swc(input_swc_file, mask_method = "tip_and_branch", | ||||||
| apply_mask_at_cortical_parent_level=False, | ||||||
| count_method = "node", annotation=None, | ||||||
| annotation_path = None, volume_shape=(1320, 800, 1140), | ||||||
| resolution=10, node_type_list=[2], | ||||||
|
|
@@ -316,6 +341,9 @@ def projection_matrix_for_swc(input_swc_file, mask_method = "tip_and_branch", | |||||
| 'tip_and_branch' will return a projection matrix masking only structures with tip and branch nodes. If 'tip' | ||||||
| will only look at structures with tip nodes. And last, if 'branch' will only look at structures with | ||||||
| branch nodes. | ||||||
| apply_mask_at_cortical_parent_level (bool): If True, the `mask_method` will be applied to aggregated cortical | ||||||
| regions. E.g. if `mask_method`='tip_and_branch' and apply_mask_at_cortical_parent_level = True, then | ||||||
| the tip-and-branch mask will be enforced at the (e.g.) VISp level, instead of in VISp1, VISp2/3 etc. independantly | ||||||
| count_method (str): ['node','tip','branch']. When 'node', will measure axon length directly. | ||||||
| Otherwise will return the count of tip or branch nodes in each structure | ||||||
| annotation (array, optional): 3 dimensional ccf annotation array. Defaults to None. | ||||||
|
|
@@ -402,11 +430,21 @@ def node_ider(morph,i): | |||||
|
|
||||||
| # determine ipsi/contra projections | ||||||
| morph_df["ccf_structure_sided"] = morph_df.apply(lambda row: "ipsi_{}".format(row.ccf_structure) if row.z<z_midline else "contra_{}".format(row.ccf_structure), axis=1) | ||||||
| # mask the morphology dataframe accordinagly | ||||||
| if mask_method!=None: | ||||||
|
|
||||||
| if apply_mask_at_cortical_parent_level: | ||||||
| morph_df['ccf_structure_rollup'] = morph_df['ccf_structure'].map(de_layer) | ||||||
| morph_df["ccf_structure_sided_rollup"] = morph_df.apply(lambda row: "ipsi_{}".format(row.ccf_structure_rollup) if row.z<z_midline else "contra_{}".format(row.ccf_structure_rollup), axis=1) | ||||||
|
|
||||||
| # mask the morphology dataframe accordingly | ||||||
|
||||||
| # mask the morphology dataframe accordingly | |
| # mask the morphology dataframe accordingly |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -10,7 +10,7 @@ | |||||
| class IO_Schema(ags.ArgSchema): | ||||||
| swc_input_directory = ags.fields.InputDir(description='directory with swc files') | ||||||
| output_file = ags.fields.OutputFile(descripion='output csv with distances between files') | ||||||
|
||||||
| output_file = ags.fields.OutputFile(descripion='output csv with distances between files') | |
| output_file = ags.fields.OutputFile(description='output csv with distances between files') |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -7,16 +7,17 @@ | |||||
| class IO_Schema(ags.ArgSchema): | ||||||
| input_swc_file = ags.fields.InputFile(description='directory with micron resolution ccf registered files') | ||||||
| output_projection_csv = ags.fields.OutputFile(description="output projection csv") | ||||||
| mask_method = ags.fields.Str(description = " 'tip_and_branch', 'branch', 'tip', or 'tip_or_branch' ") | ||||||
|
||||||
| mask_method = ags.fields.Str(description = " 'tip_and_branch', 'branch', 'tip', or 'tip_or_branch' ") | |
| mask_method = ags.fields.Str(default='tip_and_branch', description = " 'tip_and_branch', 'branch', 'tip', or 'tip_or_branch' ") |
Copilot
AI
Jul 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name should be 'description' not 'descriptions'.
| apply_mask_at_cortical_parent_level = ags.fields.Bool( descriptions='If True, the `mask_method` will be applied at aggregated cortical regions') | |
| apply_mask_at_cortical_parent_level = ags.fields.Bool( description='If True, the `mask_method` will be applied at aggregated cortical regions') |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -5,16 +5,17 @@ | |||||
| import time | ||||||
| import subprocess | ||||||
| from morph_utils.ccf import projection_matrix_for_swc | ||||||
| from morph_utils.proj_mat_utils import roll_up_proj_mat | ||||||
| from morph_utils.proj_mat_utils import roll_up_proj_mat, normalize_projection_columns_per_cell | ||||||
|
|
||||||
|
|
||||||
| class IO_Schema(ags.ArgSchema): | ||||||
| ccf_swc_directory = ags.fields.InputDir(description='directory with micron resolution ccf registered files') | ||||||
| output_directory = ags.fields.OutputDir(description="output directory") | ||||||
| mask_method = ags.fields.Str(description = " 'tip_and_branch', 'branch', 'tip', or 'tip_or_branch' ") | ||||||
|
||||||
| mask_method = ags.fields.Str(description = " 'tip_and_branch', 'branch', 'tip', or 'tip_or_branch' ") | |
| mask_method = ags.fields.Str(default='tip_and_branch', description = " 'tip_and_branch', 'branch', 'tip', or 'tip_or_branch' ") |
Copilot
AI
Jul 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name should be 'description' not 'descriptions'.
| apply_mask_at_cortical_parent_level = ags.fields.Bool( descriptions='If True, the `mask_method` will be applied at aggregated cortical regions') | |
| apply_mask_at_cortical_parent_level = ags.fields.Bool( description='If True, the `mask_method` will be applied at aggregated cortical regions') |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import os | ||
| import numpy as np | ||
| import pandas as pd | ||
|
|
||
| from morph_utils.ccf import de_layer | ||
|
|
||
|
|
||
| def roll_up_proj_mat(infile, outfile): | ||
|
|
||
| df = pd.read_csv(infile, index_col=0) | ||
| df.index = df.index.map(os.path.basename) | ||
|
|
||
| non_proj_cols = [f for f in df.columns if not any([i in f for i in ["ipsi","contra"]])] | ||
| new_df = df[non_proj_cols].copy() | ||
|
|
||
| proj_cols = [f for f in df.columns if any([i in f for i in ["ipsi","contra"]])] | ||
| de_layer_dict = {p:de_layer(p) for p in proj_cols} | ||
|
|
||
| parent_names = list(de_layer_dict.values()) | ||
| unique_parent_names = np.unique(parent_names) | ||
| unique_parent_names = sorted(unique_parent_names, key=lambda x:parent_names.index(x)) | ||
|
|
||
| roll_up_records = {} | ||
| for low_res_struct in unique_parent_names: | ||
| children = [k for k,v in de_layer_dict.items() if v==low_res_struct ] | ||
| roll_up_records[low_res_struct] = children | ||
|
|
||
|
|
||
|
|
||
| # for parent, child_list in roll_up_records.items(): | ||
| # new_df[parent] = df[child_list].sum(axis=1) | ||
| new_cols = { | ||
| parent: df[child_list].sum(axis=1) | ||
| for parent, child_list in roll_up_records.items() | ||
| } | ||
| new_cols_df = pd.DataFrame(new_cols) | ||
| new_df = pd.concat([new_df, new_cols_df], axis=1) | ||
|
|
||
| # sanity check | ||
| for n_struct,old_list in roll_up_records.items(): | ||
| sum_old = df[old_list].sum(axis=1) | ||
| sum_new = new_df[n_struct] | ||
| assert sum(sum_old==sum_new) == len(df) | ||
|
|
||
|
|
||
|
|
||
| # print(outfile) | ||
| # print() | ||
| assert os.path.abspath(outfile) != os.path.abspath(infile) | ||
| new_df.to_csv(outfile) | ||
|
|
||
|
|
||
| def normalize_projection_columns_per_cell(input_df, projection_column_identifiers=['ipsi', 'contra']): | ||
| """ | ||
| :param input_df: input projection df | ||
| :param projection_column_identifiers: list of identifiers for projection columns. i.e. strings that identify projection columns from metadata columns | ||
| :return: normalized projection matrix | ||
| """ | ||
| proj_cols = [c for c in input_df.columns if any([ider in c for ider in projection_column_identifiers])] | ||
| input_df[proj_cols] = input_df[proj_cols].fillna(0) | ||
|
|
||
| res = input_df[proj_cols].T / input_df[proj_cols].sum(axis=1) | ||
| input_df[proj_cols] = res.T | ||
|
|
||
| return input_df |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -29,3 +29,4 @@ console_scripts = | |||||
| morph_utils_aggregate_single_cell_projs = morph_utils.executable_scripts.aggregate_single_cell_projection_csvs:console_script | ||||||
| morph_utils_move_somas_left_hemisphere = morph_utils.executable_scripts.move_somas_to_left_hemisphere_swc_directory:console_script | ||||||
| morph_utils_local_crop_ccf_swcs = morph_utils.executable_scripts.local_crop_ccf_swc_directory:console_script | ||||||
| morph_utils_dsit_btwn_nodes_directory = morph_utils.executable_scripts.distance_between_nodes_for_directory:console_script | ||||||
|
||||||
| morph_utils_dsit_btwn_nodes_directory = morph_utils.executable_scripts.distance_between_nodes_for_directory:console_script | |
| morph_utils_dist_btwn_nodes_directory = morph_utils.executable_scripts.distance_between_nodes_for_directory:console_script |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The word 'independantly' should be spelled 'independently'.