LCNE-patchseq-analysis 0.24.2__tar.gz → 0.26.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of LCNE-patchseq-analysis might be problematic. Click here for more details.

Files changed (59) hide show
  1. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/PKG-INFO +2 -2
  2. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/README.md +1 -1
  3. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/__init__.py +2 -2
  4. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/figures/fig_3a.py +1 -5
  5. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/pipeline_util/ephys.py +1 -1
  6. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/pipeline_util/metadata.py +13 -2
  7. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/pipeline_util/sequencing.py +45 -5
  8. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/population_analysis/filters.py +78 -9
  9. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis.egg-info/PKG-INFO +2 -2
  10. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.codeocean/datasets.json +0 -0
  11. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.codeocean/resources.json +0 -0
  12. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.flake8 +0 -0
  13. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.gitattributes +0 -0
  14. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  15. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  16. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.github/ISSUE_TEMPLATE/user-story.md +0 -0
  17. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.github/workflows/init.yml +0 -0
  18. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.github/workflows/tag_and_publish.yml +0 -0
  19. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.github/workflows/test_and_lint.yml +0 -0
  20. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.gitignore +0 -0
  21. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/.vscode/launch.json +0 -0
  22. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/LICENSE +0 -0
  23. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/docs/Makefile +0 -0
  24. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/docs/make.bat +0 -0
  25. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/docs/source/_static/dark-logo.svg +0 -0
  26. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/docs/source/_static/light-logo.svg +0 -0
  27. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/docs/source/conf.py +0 -0
  28. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/docs/source/index.rst +0 -0
  29. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/environment/Dockerfile +0 -0
  30. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/environment/postInstall +0 -0
  31. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/notebook/efel.ipynb +0 -0
  32. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/notebook/playground.ipynb +0 -0
  33. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/notebook/population_analysis.ipynb +0 -0
  34. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/pyproject.toml +0 -0
  35. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/setup.cfg +0 -0
  36. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/setup.py +0 -0
  37. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/data_util/__init__.py +0 -0
  38. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/data_util/mesh.py +0 -0
  39. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/data_util/metadata.py +0 -0
  40. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/data_util/nwb.py +0 -0
  41. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/efel/__init__.py +0 -0
  42. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/efel/core.py +0 -0
  43. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/efel/efel_per_spike_features.json +0 -0
  44. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/efel/io.py +0 -0
  45. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/efel/pipeline.py +0 -0
  46. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/efel/plot.py +0 -0
  47. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/efel/population.py +0 -0
  48. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/efel/util.py +0 -0
  49. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/pipeline_util/__init__.py +0 -0
  50. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/pipeline_util/lims.py +0 -0
  51. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/pipeline_util/s3.py +0 -0
  52. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/population_analysis/__init__.py +0 -0
  53. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis/population_analysis/spikes.py +0 -0
  54. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis.egg-info/SOURCES.txt +0 -0
  55. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis.egg-info/dependency_links.txt +0 -0
  56. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis.egg-info/requires.txt +0 -0
  57. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/src/LCNE_patchseq_analysis.egg-info/top_level.txt +0 -0
  58. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/tests/__init__.py +0 -0
  59. {lcne_patchseq_analysis-0.24.2 → lcne_patchseq_analysis-0.26.0}/tests/test_example.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: LCNE-patchseq-analysis
3
- Version: 0.24.2
3
+ Version: 0.26.0
4
4
  Summary: Generated from aind-library-template
5
5
  Author: Allen Institute for Neural Dynamics
6
6
  Author-email: Han Hou <han.hou@alleninstitute.org>
@@ -70,7 +70,7 @@ Dynamic: license-file
70
70
  [![License](https://img.shields.io/badge/license-MIT-brightgreen)](LICENSE)
71
71
  ![Code Style](https://img.shields.io/badge/code%20style-black-black)
72
72
  [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
73
- ![Interrogate](https://img.shields.io/badge/interrogate-90.5%25-brightgreen)
73
+ ![Interrogate](https://img.shields.io/badge/interrogate-90.6%25-brightgreen)
74
74
  ![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=codecov)
75
75
  ![Python](https://img.shields.io/badge/python->=3.9-blue?logo=python)
76
76
 
@@ -3,7 +3,7 @@
3
3
  [![License](https://img.shields.io/badge/license-MIT-brightgreen)](LICENSE)
4
4
  ![Code Style](https://img.shields.io/badge/code%20style-black-black)
5
5
  [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
6
- ![Interrogate](https://img.shields.io/badge/interrogate-90.5%25-brightgreen)
6
+ ![Interrogate](https://img.shields.io/badge/interrogate-90.6%25-brightgreen)
7
7
  ![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=codecov)
8
8
  ![Python](https://img.shields.io/badge/python->=3.9-blue?logo=python)
9
9
 
@@ -6,12 +6,12 @@ import os
6
6
  logger = logging.getLogger(__name__)
7
7
 
8
8
 
9
- __version__ = "0.24.2"
9
+ __version__ = "0.26.0"
10
10
 
11
11
  # Get the path of this file
12
12
  PACKAGE_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
13
13
  if os.name == "posix": # Mac/Linux
14
- RAW_DIRECTORY = os.path.join(PACKAGE_DIRECTORY, "../../data/LCNE-patchseq-ephys/raw/")
14
+ RAW_DIRECTORY = "/Users/han.hou/Scripts/LCNE-patchseq-analysis/data/LCNE-patchseq-ephys/raw"
15
15
  else: # Windows
16
16
  RAW_DIRECTORY = os.path.join(R"E:\s3\aind-patchseq-data\raw")
17
17
  RESULTS_DIRECTORY = os.path.join(PACKAGE_DIRECTORY, "../../results/")
@@ -70,7 +70,7 @@ def figure_3a_ccf_projection(if_save_fig: bool = True) -> tuple:
70
70
  ax.scatter(region_data['x'], region_data['y'],
71
71
  c=region_colors[i], alpha=0.7, s=50,
72
72
  edgecolors='black', linewidth=0.5,
73
- label=f'{region} (n={len(region_data)})')
73
+ label=f'{region} (n={len(region_data)}, {region_data["x"].isnull().sum()} missing data)')
74
74
 
75
75
  # Add labels and title
76
76
  ax.set_xlabel('X Coordinate (μm)', fontsize=12)
@@ -111,10 +111,6 @@ def figure_3a_ccf_projection(if_save_fig: bool = True) -> tuple:
111
111
  # Print summary statistics
112
112
  logger.info("\nSummary statistics:")
113
113
  logger.info(f"- Total filtered cells: {len(df_filtered)}")
114
- if len(df_filtered) > 0:
115
- logger.info(f"- X coordinate range: {df_filtered['x'].min():.1f} to {df_filtered['x'].max():.1f}")
116
- logger.info(f"- Y coordinate range: {df_filtered['y'].min():.1f} to {df_filtered['y'].max():.1f}")
117
- logger.info(f"- Injection regions: {', '.join(unique_regions)}")
118
114
 
119
115
  return fig, ax, df_filtered
120
116
 
@@ -97,5 +97,5 @@ if __name__ == "__main__":
97
97
  logging.basicConfig(level=logging.DEBUG)
98
98
 
99
99
  trigger_patchseq_upload(
100
- os.path.expanduser(R"~\Downloads\IVSCC_LC_summary.xlsx"), upload_raw_data=False
100
+ os.path.expanduser(R"~\Downloads\IVSCC_LC_summary_0709.xlsx"), upload_raw_data=False
101
101
  )
@@ -34,7 +34,7 @@ def read_brian_spreadsheet(file_path=metadata_path, add_lims=True):
34
34
  df_tab_master = pd.read_excel(file_path, sheet_name=tab_master)
35
35
 
36
36
  # Get ephys features
37
- tab_ephys_fx = "ipfx_ephys_fx_250611"
37
+ tab_ephys_fx = "ipfx_ephys_250709"
38
38
  df_tab_ephys_fx = pd.read_excel(file_path, sheet_name=tab_ephys_fx)
39
39
 
40
40
  # Add "ipfx_" prefix to ephys_fx columns except for "cell_specimen_id"
@@ -49,7 +49,7 @@ def read_brian_spreadsheet(file_path=metadata_path, add_lims=True):
49
49
  how="outer",
50
50
  suffixes=("_tab_master", "_tab_ephys_fx"),
51
51
  ).sort_values("Date", ascending=False)
52
-
52
+
53
53
  if add_lims:
54
54
  logger.info("Querying and adding LIMS data...")
55
55
  df_lims = get_lims_LCNE_patchseq()
@@ -114,6 +114,17 @@ def read_brian_spreadsheet(file_path=metadata_path, add_lims=True):
114
114
  right_on="cell_specimen_id",
115
115
  how="left",
116
116
  )
117
+
118
+ # Logging the latest cell that has a column and the total number of cells with that column
119
+ column_to_log = ["recording_date", "x", "ipfx_tau"]
120
+ for col in column_to_log:
121
+ if col in df_merged.columns:
122
+ last_date = df_merged.loc[df_merged[col].notnull(), "Date"].max()
123
+ total_cells = df_merged[col].notnull().sum()
124
+ logger.info(
125
+ f"Last date with {col}: {last_date}, "
126
+ f"Total cells with {col}: {total_cells}"
127
+ )
117
128
 
118
129
  return {
119
130
  "df_merged": df_merged,
@@ -14,16 +14,23 @@ logger = logging.getLogger(__name__)
14
14
 
15
15
  # Define the preselected columns of interest
16
16
  SEQ_COLUMNS = [
17
- # Coordinates and clusters
17
+ # --- New columns added in 0620 ---
18
+ "RNA_QC", # RNA quality control score
19
+ "imp_pscores", # Imputed pseudocluster scores
20
+
21
+ # --- Imputation to other experiments ---
18
22
  "imp_ML",
19
23
  "imp_DV",
20
24
  "imp_AP",
21
25
  "imp_pseudoclusters",
22
- # Noradrenergic markers
26
+
27
+ # --- Noradrenergic markers ---
23
28
  "Dbh", # Dopamine beta-hydroxylase
24
29
  "Th", # Tyrosine hydroxylase
25
30
  "Slc18a2", # Vesicular monoamine transporter 2 (VMAT2)
26
31
  "Slc6a2", # Norepinephrine transporter (NET)
32
+
33
+ # --- Active ion channels ---
27
34
  # Sodium channels (important for action potential initiation and upstroke)
28
35
  "Scn1a", # Nav1.1, important for AP initiation
29
36
  "Scn2a", # Nav1.2, expressed in axon initial segment
@@ -46,8 +53,41 @@ SEQ_COLUMNS = [
46
53
  # HCN channels (important for pacemaking and resonance)
47
54
  "Hcn1", # Fast-activating HCN, affects rebound spiking
48
55
  "Hcn2", # Slower-activating HCN, contributes to resonance
56
+ "Hcn3",
49
57
  "Hcn4", # Slowest-activating HCN, important in pacemaking
50
- # Other common markers
58
+
59
+ # --- Leak channels and other important channels ---
60
+ # K2P (Two-pore-domain potassium) leak channels
61
+ "Kcnk1", # TWIK-1, weak inward-rectifying K+ leak channel
62
+ "Kcnk2", # TREK-1, mechanosensitive and temperature-sensitive K2P channel
63
+ "Kcnk3", # TASK-1, pH-sensitive background K+ current
64
+ "Kcnk4", # TRAAK, mechanosensitive leak K+ channel
65
+ "Kcnk9", # TASK-3, regulates resting potential and excitability
66
+ "Kcnk10", # TREK-2, contributes to leak K+ conductance
67
+ # Sodium leak channels and associated regulators
68
+ "Nalcn", # Na+ leak channel, controls resting Na+ conductance and excitability
69
+ "Unc79", # NALCN complex component
70
+ "Unc80", # NALCN complex component
71
+ "Fam155a", # Regulatory subunit of NALCN complex
72
+ # Chloride leak channels
73
+ "Clcn2", # Voltage-gated Cl- channel, contributes to inhibitory tone
74
+
75
+ # Inward-rectifier and GPCR-modulated K+ channels (affect resting potential)
76
+ "Kcnj2", # Kir2.1, stabilizes resting membrane potential
77
+ "Kcnj10", # Kir4.1, highly expressed in glia and neurons, contributes to K+ buffering
78
+ "Kcnj3", # GIRK1, G-protein-regulated inward-rectifying K+ channel
79
+ "Kcnj6", # GIRK2, major component of GIRK channels in CNS
80
+
81
+ # --- Gap junctions and connexins ---
82
+ # Gap junction–related genes (CNS)
83
+ "Gja1", # Connexin 43, major astrocytic gap junction protein
84
+ "Gjb6", # Connexin 30, co-expressed with Gja1 in glia
85
+ "Gjd2", # Connexin 36, neuronal gap junction, key for electrical synapses
86
+ "Gjd3", # Connexin 31.9, expressed in some CNS neurons
87
+ "Panx1", # Pannexin 1, forms large-pore channels in neurons and glia
88
+ "Panx2", # Pannexin 2, CNS-specific, neuron-enriched
89
+
90
+ # --- Other common markers ---
51
91
  "Slc17a7", # Excitatory marker
52
92
  "Gad1", # Inhibitory marker
53
93
  "Sst", # Somatostatin
@@ -80,8 +120,8 @@ def extract_preselected_columns():
80
120
  src_dir = src_dir.resolve()
81
121
  dst_dir = dst_dir.resolve()
82
122
 
83
- src_file = src_dir / "log_normed_df.csv"
84
- id_mapping_file = src_dir / "exp_component_ids_for_han.csv" # Aux file for mapping ids
123
+ src_file = src_dir / "log_normed_df_more_0620.csv"
124
+ id_mapping_file = src_dir / "exp_component_ids_for_han_0620.csv" # Aux file for mapping ids
85
125
  dst_file = dst_dir / "seq_preselected.csv"
86
126
 
87
127
  logger.info(f"Reading log-normalized data from {src_file}")
@@ -33,6 +33,13 @@ q_mapmycells_dbh = 'mapmycells_subclass_name.str.contains("DBH", case=False, na=
33
33
  q_mapmycells_has_data = (
34
34
  "mapmycells_subclass_name == mapmycells_subclass_name" # True for non-NaN values
35
35
  )
36
+
37
+ q_nucleus_present = '`jem-nucleus_post_patch` == "nucleus_present"'
38
+ q_nucleus_present_has_data = '`jem-nucleus_post_patch` == `jem-nucleus_post_patch`'
39
+
40
+ q_RNA_QC = '`gene_RNA_QC (log_normed)` == True'
41
+ q_RNA_QC_has_data = '`gene_RNA_QC (log_normed)` == `gene_RNA_QC (log_normed)`'
42
+
36
43
  q_retro = '`injection region` != "Non-Retro"'
37
44
 
38
45
 
@@ -63,8 +70,10 @@ def create_filter_conditions(df_meta):
63
70
  "Fluorescence": [if_fluorescence_positive, if_fluorescence_has_data],
64
71
  "Marker Gene Any Positive": [if_marker_gene_any_positive, if_marker_gene_has_data],
65
72
  "Marker Gene All Positive": [if_marker_gene_all_positive, if_marker_gene_has_data],
66
- "Marker Gene DBH Positive": [if_marker_gene_dbh_positive, if_marker_gene_has_data],
67
- "Is DBH Subclass": [if_mapmycells_dbh, if_mapmycells_has_data],
73
+ "Marker Gene Dbh Positive": [if_marker_gene_dbh_positive, if_marker_gene_has_data],
74
+ "MapMyCells Dbh Subclass": [if_mapmycells_dbh, if_mapmycells_has_data],
75
+ "RNA QC": [df_meta.eval(q_RNA_QC), df_meta.eval(q_RNA_QC_has_data)],
76
+ "Nucleus Present": [df_meta.eval(q_nucleus_present), df_meta.eval(q_nucleus_present_has_data)],
68
77
  }
69
78
 
70
79
  return condition_mapper
@@ -109,25 +118,51 @@ def compute_confusion_matrix(condition_mapper, name1, name2):
109
118
  print(f"Any of them does not have data: {unknown.sum()}")
110
119
  return confusion_matrix
111
120
 
112
- def plot_venn_three_filters(filter1, filter2, filter3, labels=("Filter 1", "Filter 2", "Filter 3"), ax=None):
121
+
122
+ def plot_venn_three_filters(condition_mapper, to_compare: list, ax=None):
113
123
  """
114
- Plot a Venn diagram for three boolean filters or sets.
115
- Accepts either boolean arrays (same length) or sets of indices.
124
+ Plot a Venn diagram for three boolean filters from condition_mapper.
125
+
126
+ Parameters:
127
+ -----------
128
+ condition_mapper : dict
129
+ Dictionary mapping filter names to [positive_condition, has_data_condition] pairs
130
+ to_compare : list
131
+ List of 3 filter names to compare (must be keys in condition_mapper)
132
+ ax : matplotlib.axes.Axes, optional
133
+ Axes to plot on. If None, creates new figure and axes.
134
+
135
+ Returns:
136
+ --------
137
+ matplotlib.axes.Axes
138
+ The axes containing the plot
116
139
  """
117
- # Convert boolean arrays to sets of indices if needed
140
+ if len(to_compare) != 3:
141
+ raise ValueError("to_compare must contain exactly 3 filter names")
142
+
143
+ # Get the positive conditions (first element) for each filter
144
+ filter1 = condition_mapper[to_compare[0]][0] # positive condition
145
+ filter2 = condition_mapper[to_compare[1]][0] # positive condition
146
+ filter3 = condition_mapper[to_compare[2]][0] # positive condition
147
+
148
+ # Convert boolean arrays to sets of indices
118
149
  def to_set(f):
119
150
  if isinstance(f, (pd.Series, np.ndarray)) and f.dtype == bool:
120
- return set(np.where(f)[0])
151
+ return set(np.flatnonzero(f))
121
152
  elif isinstance(f, (pd.Series, np.ndarray)):
122
153
  return set(f)
123
154
  elif isinstance(f, set):
124
155
  return f
125
156
  else:
126
157
  return set(list(f))
158
+
127
159
  set1, set2, set3 = to_set(filter1), to_set(filter2), to_set(filter3)
160
+
128
161
  if ax is None:
129
162
  fig, ax = plt.subplots(figsize=(6, 6), dpi=300)
130
163
 
164
+ # Use the filter names as labels
165
+ labels = to_compare
131
166
  v = venn3([set1, set2, set3], set_labels=labels, ax=ax)
132
167
  c = venn3_circles([set1, set2, set3], ax=ax)
133
168
 
@@ -135,11 +170,45 @@ def plot_venn_three_filters(filter1, filter2, filter3, labels=("Filter 1", "Filt
135
170
  for i, color in enumerate(("black", "blue", "green")):
136
171
  c[i].set_edgecolor(color)
137
172
  v.get_label_by_id(["A", "B", "C"][i]).set_color(color)
138
-
173
+
139
174
  # Clear all patch color
140
175
  for patch in v.patches:
141
176
  if patch: # Some patches might be None
142
177
  patch.set_facecolor('none')
143
178
 
144
-
145
179
  return ax
180
+
181
+
182
+ def plot_venn_summary(
183
+ df_lists,
184
+ compare_lists=[
185
+ ["Fluorescence", "Marker Gene Dbh Positive", "MapMyCells Dbh Subclass"],
186
+ ["Fluorescence", "Marker Gene All Positive", "MapMyCells Dbh Subclass"],
187
+ ["Fluorescence", "Marker Gene Any Positive", "MapMyCells Dbh Subclass"],
188
+ ["RNA QC", "Nucleus Present", "MapMyCells Dbh Subclass"],
189
+ ],
190
+ ):
191
+ """
192
+ Plot a summary of Venn diagrams for multiple DataFrames and filter conditions.
193
+
194
+ Parameters:
195
+ -----------
196
+ df_lists : list of pd.DataFrame
197
+ List of DataFrames containing metadata for different cell populations
198
+ compare_lists : list of list of str, optional
199
+ List of filter names to compare in Venn diagrams. Default includes common filters.
200
+
201
+ Returns:
202
+ --------
203
+ matplotlib.figure.Figure
204
+ Figure containing the Venn diagrams for each comparison.
205
+ """
206
+ fig, ax = plt.subplots(len(compare_lists), 2, figsize=(12, len(compare_lists) * 4), dpi=200)
207
+
208
+ for i, df in enumerate(df_lists):
209
+ condition_mapper = create_filter_conditions(df)
210
+ for j, filters in enumerate(compare_lists):
211
+ plot_venn_three_filters(condition_mapper, filters, ax=ax[j, i])
212
+
213
+ plt.tight_layout()
214
+ return fig
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: LCNE-patchseq-analysis
3
- Version: 0.24.2
3
+ Version: 0.26.0
4
4
  Summary: Generated from aind-library-template
5
5
  Author: Allen Institute for Neural Dynamics
6
6
  Author-email: Han Hou <han.hou@alleninstitute.org>
@@ -70,7 +70,7 @@ Dynamic: license-file
70
70
  [![License](https://img.shields.io/badge/license-MIT-brightgreen)](LICENSE)
71
71
  ![Code Style](https://img.shields.io/badge/code%20style-black-black)
72
72
  [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
73
- ![Interrogate](https://img.shields.io/badge/interrogate-90.5%25-brightgreen)
73
+ ![Interrogate](https://img.shields.io/badge/interrogate-90.6%25-brightgreen)
74
74
  ![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=codecov)
75
75
  ![Python](https://img.shields.io/badge/python->=3.9-blue?logo=python)
76
76