wormcat3 0.0.1__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.
- wormcat3-0.0.1/MANIFEST.in +5 -0
- wormcat3-0.0.1/PKG-INFO +46 -0
- wormcat3-0.0.1/README.md +22 -0
- wormcat3-0.0.1/setup.cfg +4 -0
- wormcat3-0.0.1/setup.py +38 -0
- wormcat3-0.0.1/wormcat3/__init__.py +4 -0
- wormcat3-0.0.1/wormcat3/annotations_manger.py +86 -0
- wormcat3-0.0.1/wormcat3/bubble_chart.py +234 -0
- wormcat3-0.0.1/wormcat3/extdata/ORF_only_v2_nov-11-2021.csv +19898 -0
- wormcat3-0.0.1/wormcat3/extdata/ahringer_v2_nov-11-2021.csv +16211 -0
- wormcat3-0.0.1/wormcat3/extdata/orfeome_v2_nov-11-2021.csv +11525 -0
- wormcat3-0.0.1/wormcat3/extdata/whole_genome_v2_nov-11-2021.csv +31390 -0
- wormcat3-0.0.1/wormcat3/file_util.py +87 -0
- wormcat3-0.0.1/wormcat3/gsea_analyzer.py +357 -0
- wormcat3-0.0.1/wormcat3/statistical_analysis.py +157 -0
- wormcat3-0.0.1/wormcat3/sunburst.py +104 -0
- wormcat3-0.0.1/wormcat3/sunburst_template.py +182 -0
- wormcat3-0.0.1/wormcat3/wormcat.py +99 -0
- wormcat3-0.0.1/wormcat3.egg-info/PKG-INFO +46 -0
- wormcat3-0.0.1/wormcat3.egg-info/SOURCES.txt +22 -0
- wormcat3-0.0.1/wormcat3.egg-info/dependency_links.txt +1 -0
- wormcat3-0.0.1/wormcat3.egg-info/not-zip-safe +1 -0
- wormcat3-0.0.1/wormcat3.egg-info/requires.txt +6 -0
- wormcat3-0.0.1/wormcat3.egg-info/top_level.txt +1 -0
wormcat3-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: wormcat3
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: WormCat is a tool for annotating and visualizing gene set enrichment data from C. elegans microarray, RNA seq or RNAi screen data.
|
|
5
|
+
Home-page: https://github.com/DanHUMassMed/wormcat3.git
|
|
6
|
+
Author: Dan Higgins
|
|
7
|
+
Author-email: daniel.higgins@gatech.edu
|
|
8
|
+
License: MIT
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: ipykernel==6.29.5
|
|
11
|
+
Requires-Dist: scipy==1.15.2
|
|
12
|
+
Requires-Dist: pandas==2.2.3
|
|
13
|
+
Requires-Dist: gseapy==1.1.8
|
|
14
|
+
Requires-Dist: plotnine==0.14.5
|
|
15
|
+
Requires-Dist: statsmodels==0.14.4
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: author-email
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: license
|
|
22
|
+
Dynamic: requires-dist
|
|
23
|
+
Dynamic: summary
|
|
24
|
+
|
|
25
|
+
# Analysis of genome-scale data with WormCat identifies novel enriched gene categories in studies from metabolic, tissue-specific, and lifespan-drug data
|
|
26
|
+
|
|
27
|
+
#### Authors: Amy Holdorf, Daniel Higgins, Anne Hart, Peter Boag, Gregory Pazour, Marian Walhout,and Amy Walker
|
|
28
|
+
|
|
29
|
+
[GENETICS February 1, 2020 vol. 214 no. 2 279-294;](https://academic.oup.com/genetics/article/214/2/279/5930455)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## Abstract
|
|
33
|
+
The emergence of large sets of gene regulation data has revealed the need for improved tools to 1) identify enriched functional gene categories and 2) visualize enrichment patterns across comparative datasets. Gene ontogeny enrichment (GO) has several limitations for C. elegans analysis. First, around 30% of C. elegans genes are not represented in commonly used search engines. Second, it is difficult to compare multiple GO analyses. To allow visualization and categorization of C. elegans gene sets, we have developed a web-based tool, WormCat. This tool uses a near complete annotation of C. elegans genes to determine category enrichment and define potential co-regulated or co-functioning gene sets. Then WormCat provides a scaled heat map for visualization along with enrichment statistics and annotation of each input gene. We have developed an annotation strategy based on a nested category approach where each gene is annotated at three levels. Enrichment scores are generated at each level, allowing both broad (Cat1) and more detailed analysis (Cat2, Cat3). Using WormCat on published RNA seq datasets from metabolic, tissue-specific or after treatment with lifespan-increasing drugs, we show that WormCat finds major categories appearing in GO searches and also identifies additional enriched categories that are informative for interpreting phenotypes or predicting biological function. Thus, WormCat is a powerful tool that will allow a sophisticated analysis of gene enrichment in different types of C. elegans datasets.
|
|
34
|
+
|
|
35
|
+
## Overview Wormcat
|
|
36
|
+
Wormcat is also available as an online tool at [www.wormcat.com](http://www.wormcat.com); the online version greatly simplifies the use of Wormcat and is maintained by the [Walker Lab at UMASS Medical School](https://amywalkerlab.com/).
|
|
37
|
+
|
|
38
|
+
###### The diagram below shows the flow of the Wormcat process:
|
|
39
|
+
<img src="http://wormcat.com/static/images/WormCat-Flow.png" alt="Flow" width="700"/>
|
|
40
|
+
|
|
41
|
+
###### The diagrams below shows sample output from a Wormcat.com run:
|
|
42
|
+
<img src="http://wormcat.com/static/images/results_screen.png" alt="Results" width="700"/>
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
##### Starburst view of categorical data
|
|
46
|
+
<img src="http://wormcat.com/static/images/sunburst.png" alt="starburst" width="400"/>
|
wormcat3-0.0.1/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Analysis of genome-scale data with WormCat identifies novel enriched gene categories in studies from metabolic, tissue-specific, and lifespan-drug data
|
|
2
|
+
|
|
3
|
+
#### Authors: Amy Holdorf, Daniel Higgins, Anne Hart, Peter Boag, Gregory Pazour, Marian Walhout,and Amy Walker
|
|
4
|
+
|
|
5
|
+
[GENETICS February 1, 2020 vol. 214 no. 2 279-294;](https://academic.oup.com/genetics/article/214/2/279/5930455)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Abstract
|
|
9
|
+
The emergence of large sets of gene regulation data has revealed the need for improved tools to 1) identify enriched functional gene categories and 2) visualize enrichment patterns across comparative datasets. Gene ontogeny enrichment (GO) has several limitations for C. elegans analysis. First, around 30% of C. elegans genes are not represented in commonly used search engines. Second, it is difficult to compare multiple GO analyses. To allow visualization and categorization of C. elegans gene sets, we have developed a web-based tool, WormCat. This tool uses a near complete annotation of C. elegans genes to determine category enrichment and define potential co-regulated or co-functioning gene sets. Then WormCat provides a scaled heat map for visualization along with enrichment statistics and annotation of each input gene. We have developed an annotation strategy based on a nested category approach where each gene is annotated at three levels. Enrichment scores are generated at each level, allowing both broad (Cat1) and more detailed analysis (Cat2, Cat3). Using WormCat on published RNA seq datasets from metabolic, tissue-specific or after treatment with lifespan-increasing drugs, we show that WormCat finds major categories appearing in GO searches and also identifies additional enriched categories that are informative for interpreting phenotypes or predicting biological function. Thus, WormCat is a powerful tool that will allow a sophisticated analysis of gene enrichment in different types of C. elegans datasets.
|
|
10
|
+
|
|
11
|
+
## Overview Wormcat
|
|
12
|
+
Wormcat is also available as an online tool at [www.wormcat.com](http://www.wormcat.com); the online version greatly simplifies the use of Wormcat and is maintained by the [Walker Lab at UMASS Medical School](https://amywalkerlab.com/).
|
|
13
|
+
|
|
14
|
+
###### The diagram below shows the flow of the Wormcat process:
|
|
15
|
+
<img src="http://wormcat.com/static/images/WormCat-Flow.png" alt="Flow" width="700"/>
|
|
16
|
+
|
|
17
|
+
###### The diagrams below shows sample output from a Wormcat.com run:
|
|
18
|
+
<img src="http://wormcat.com/static/images/results_screen.png" alt="Results" width="700"/>
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
##### Starburst view of categorical data
|
|
22
|
+
<img src="http://wormcat.com/static/images/sunburst.png" alt="starburst" width="400"/>
|
wormcat3-0.0.1/setup.cfg
ADDED
wormcat3-0.0.1/setup.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Setup for pypi releases of wormcat3
|
|
3
|
+
"""
|
|
4
|
+
from wormcat3 import __version__
|
|
5
|
+
from setuptools import setup, find_packages
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
# rm -rf dist
|
|
9
|
+
# python setup.py sdist
|
|
10
|
+
# pip install dist/wormcat3-1.0.1.tar.gz
|
|
11
|
+
# twine check dist/*
|
|
12
|
+
# twine upload --repository pypi dist/*
|
|
13
|
+
|
|
14
|
+
this_directory = Path(__file__).parent
|
|
15
|
+
long_description = (this_directory / "README.md").read_text()
|
|
16
|
+
|
|
17
|
+
setup(name='wormcat3',
|
|
18
|
+
version=__version__,
|
|
19
|
+
description='WormCat is a tool for annotating and visualizing gene set enrichment data from C. elegans microarray, RNA seq or RNAi screen data.',
|
|
20
|
+
long_description_content_type="text/markdown",
|
|
21
|
+
long_description=long_description,
|
|
22
|
+
|
|
23
|
+
url='https://github.com/DanHUMassMed/wormcat3.git',
|
|
24
|
+
author='Dan Higgins',
|
|
25
|
+
author_email='daniel.higgins@gatech.edu',
|
|
26
|
+
license='MIT',
|
|
27
|
+
|
|
28
|
+
packages=find_packages(),
|
|
29
|
+
install_requires=[
|
|
30
|
+
'ipykernel==6.29.5',
|
|
31
|
+
'scipy==1.15.2',
|
|
32
|
+
'pandas==2.2.3',
|
|
33
|
+
'gseapy==1.1.8',
|
|
34
|
+
'plotnine==0.14.5',
|
|
35
|
+
'statsmodels==0.14.4'
|
|
36
|
+
],
|
|
37
|
+
include_package_data=True,
|
|
38
|
+
zip_safe=False)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from wormcat3 import file_util
|
|
3
|
+
|
|
4
|
+
class AnnotationsManager:
|
|
5
|
+
"""Manages gene annotations and preprocessing."""
|
|
6
|
+
|
|
7
|
+
def __init__(self, annotation_file):
|
|
8
|
+
"""Initialize with the path to the annotation file."""
|
|
9
|
+
if file_util.is_file_path(annotation_file):
|
|
10
|
+
self.annotation_file_path = annotation_file
|
|
11
|
+
else:
|
|
12
|
+
self.annotation_file_path = file_util.find_file_path(annotation_file)
|
|
13
|
+
if not self.annotation_file_path:
|
|
14
|
+
raise FileNotFoundError(f"Annotation file not found: {annotation_file}")
|
|
15
|
+
|
|
16
|
+
self.annotations_df = self._load_annotations()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _load_annotations(self):
|
|
21
|
+
"""Load annotations from file."""
|
|
22
|
+
try:
|
|
23
|
+
df = pd.read_csv(self.annotation_file_path)
|
|
24
|
+
df.columns = df.columns.str.replace(' ', '.')
|
|
25
|
+
if df.empty:
|
|
26
|
+
raise ValueError(f"Annotation file '{self.annotation_file_path}' is empty.")
|
|
27
|
+
return df
|
|
28
|
+
except Exception as e:
|
|
29
|
+
raise ValueError(f"Failed to load annotation file: {e}")
|
|
30
|
+
|
|
31
|
+
def get_gene_id_type(self, gene_set):
|
|
32
|
+
"""Determine the gene ID type from the gene set."""
|
|
33
|
+
if len(gene_set) < 2:
|
|
34
|
+
raise ValueError("At least two genes are required for comparison.")
|
|
35
|
+
|
|
36
|
+
# Check if the first two genes start with "WBGene"
|
|
37
|
+
if gene_set[0].startswith("WBGene") and gene_set[1].startswith("WBGene"):
|
|
38
|
+
return "Wormbase.ID"
|
|
39
|
+
elif not gene_set[0].startswith("WBGene") and not gene_set[1].startswith("WBGene"):
|
|
40
|
+
return "Sequence.ID"
|
|
41
|
+
else:
|
|
42
|
+
raise ValueError("Invalid gene data: One gene starts with 'WBGene', but the other does not.")
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def dedup_list(input_list):
|
|
46
|
+
"""Deduplicate a list while preserving order."""
|
|
47
|
+
seen = set()
|
|
48
|
+
deduped_list = []
|
|
49
|
+
for item in input_list:
|
|
50
|
+
if item not in seen:
|
|
51
|
+
deduped_list.append(item)
|
|
52
|
+
seen.add(item)
|
|
53
|
+
return deduped_list
|
|
54
|
+
|
|
55
|
+
def add_annotations(self, gene_set_list, gene_type):
|
|
56
|
+
"""Add annotations to the gene set."""
|
|
57
|
+
gene_set_df = pd.DataFrame(gene_set_list, columns=[gene_type])
|
|
58
|
+
|
|
59
|
+
# Verify if 'gene_type' is a column in the DataFrame
|
|
60
|
+
if gene_type not in self.annotations_df.columns:
|
|
61
|
+
raise ValueError(f"Column '{gene_type}' not found in the DataFrame.")
|
|
62
|
+
|
|
63
|
+
return pd.merge(gene_set_df, self.annotations_df, on=gene_type, how='left')
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def split_background_on_annotation_match(self, background_list, gene_type):
|
|
67
|
+
"""Split background genes into those with and without annotations."""
|
|
68
|
+
background_df = pd.DataFrame(background_list, columns=[gene_type])
|
|
69
|
+
|
|
70
|
+
# Check if gene_type is in both dataframes
|
|
71
|
+
if gene_type not in background_df.columns:
|
|
72
|
+
raise ValueError(f"'{gene_type}' not found in background_df.")
|
|
73
|
+
if gene_type not in self.annotations_df.columns:
|
|
74
|
+
raise ValueError(f"'{gene_type}' not found in annotations_df.")
|
|
75
|
+
|
|
76
|
+
# Perform the left merge
|
|
77
|
+
merged_df = pd.merge(background_df, self.annotations_df, on=gene_type, how='left')
|
|
78
|
+
|
|
79
|
+
# Split based on presence of annotation (assuming at least one non-key column in annotations_df)
|
|
80
|
+
annotation_columns = [col for col in self.annotations_df.columns if col != gene_type]
|
|
81
|
+
|
|
82
|
+
background_available_df = merged_df.dropna(subset=annotation_columns)
|
|
83
|
+
background_not_matched_df = merged_df[merged_df[annotation_columns].isnull().all(axis=1)]
|
|
84
|
+
background_not_matched_df = background_not_matched_df[[gene_type]]
|
|
85
|
+
|
|
86
|
+
return background_available_df, background_not_matched_df
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import numpy as np
|
|
3
|
+
from plotnine import *
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
# Suppress UserWarnings and DeprecationWarnings from plotnine
|
|
8
|
+
warnings.filterwarnings('ignore', category=UserWarning, module='plotnine')
|
|
9
|
+
warnings.filterwarnings('ignore', category=DeprecationWarning, module='plotnine')
|
|
10
|
+
|
|
11
|
+
def preprocess_bubble_data(data_file_path):
|
|
12
|
+
"""
|
|
13
|
+
Preprocess CSV data for bubble plot visualization.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
csv_file_name (str): Path to the CSV file containing the data.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
pd.DataFrame: Processed DataFrame ready for plotting.
|
|
20
|
+
"""
|
|
21
|
+
try:
|
|
22
|
+
# Read the CSV file
|
|
23
|
+
bubbles_data = pd.read_csv(data_file_path)
|
|
24
|
+
column_names = bubbles_data.columns.tolist()
|
|
25
|
+
correction_method = 'Bonferroni' if 'Bonferroni' in column_names else 'FDR'
|
|
26
|
+
|
|
27
|
+
# Remove rows with missing values
|
|
28
|
+
bubbles_data = bubbles_data.dropna()
|
|
29
|
+
|
|
30
|
+
# # Add calibration points
|
|
31
|
+
# calibration_points = pd.DataFrame({
|
|
32
|
+
# "Category": ["calibration high", "calibration low"],
|
|
33
|
+
# "RGS": [250, 1],
|
|
34
|
+
# "AC": [0, 0],
|
|
35
|
+
# "PValue": [1.00E-50, 1],
|
|
36
|
+
# correction_method: [1.00E-50, 1]
|
|
37
|
+
# })
|
|
38
|
+
|
|
39
|
+
# bubbles_data = pd.concat([bubbles_data, calibration_points], ignore_index=True)
|
|
40
|
+
|
|
41
|
+
# Compute normalized value as a placeholder
|
|
42
|
+
bubbles_data['bubbles_z'] = round(0.001 * (bubbles_data['PValue'] - bubbles_data['PValue'].mean()) / bubbles_data['PValue'].std(), 2)
|
|
43
|
+
|
|
44
|
+
# Create color coding based on Bonferroni-corrected p-values
|
|
45
|
+
conditions = [
|
|
46
|
+
(bubbles_data[correction_method] < 1e-40),
|
|
47
|
+
(bubbles_data[correction_method] < 1e-20),
|
|
48
|
+
(bubbles_data[correction_method] < 1e-10),
|
|
49
|
+
(bubbles_data[correction_method] < 1e-5),
|
|
50
|
+
(bubbles_data[correction_method] < 1e-2),
|
|
51
|
+
(bubbles_data[correction_method] < 5e-2),
|
|
52
|
+
(bubbles_data[correction_method] >= 5e-2)
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
values = ["Col1", "Col2", "Col3", "Col4", "Col5", "Col6", "NS"]
|
|
56
|
+
bubbles_data['p_value_type'] = np.select(conditions, values, default='')
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# Create size coding based on RGS values
|
|
60
|
+
size_conditions = [
|
|
61
|
+
(bubbles_data['RGS'] > 150),
|
|
62
|
+
(bubbles_data['RGS'] > 100),
|
|
63
|
+
(bubbles_data['RGS'] > 75),
|
|
64
|
+
(bubbles_data['RGS'] > 50),
|
|
65
|
+
(bubbles_data['RGS'] > 25),
|
|
66
|
+
(bubbles_data['RGS'] > 10),
|
|
67
|
+
(bubbles_data['RGS'] > 5),
|
|
68
|
+
(bubbles_data['RGS'] > 2),
|
|
69
|
+
(bubbles_data['RGS'] <= 2)
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
size_values = ["Size1", "Size2", "Size3", "Size4", "Size5", "Size6", "Size7", "Size8", "Size9"]
|
|
73
|
+
bubbles_data['RGS_size'] = np.select(size_conditions, size_values, default='')
|
|
74
|
+
|
|
75
|
+
bubbles_data = order_categories_by_column(
|
|
76
|
+
bubbles_data,
|
|
77
|
+
category_column = 'Category',
|
|
78
|
+
order_by_column = correction_method,
|
|
79
|
+
ascending=False
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return bubbles_data
|
|
83
|
+
|
|
84
|
+
except FileNotFoundError:
|
|
85
|
+
raise FileNotFoundError(f"CSV file not found: {data_file_path}")
|
|
86
|
+
except pd.errors.EmptyDataError:
|
|
87
|
+
raise ValueError(f"The CSV file is empty: {data_file_path}")
|
|
88
|
+
except pd.errors.ParserError:
|
|
89
|
+
raise ValueError(f"Error parsing CSV file: {data_file_path}")
|
|
90
|
+
except KeyError as e:
|
|
91
|
+
raise KeyError(f"Required column missing in CSV file: {e}")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def order_categories_by_column(df, category_column='Category', order_by_column='PValue', ascending=True):
|
|
95
|
+
"""
|
|
96
|
+
Convert a column to a categorical type ordered by another column.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
df (pd.DataFrame): DataFrame with category and ordering columns.
|
|
100
|
+
category_column (str): Name of the column to be converted to categorical.
|
|
101
|
+
order_by_column (str): Name of the column to order by.
|
|
102
|
+
ascending (bool): Sort order - True for ascending, False for descending.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
pd.DataFrame: DataFrame with category column converted to categorical type.
|
|
106
|
+
"""
|
|
107
|
+
if df is None or df.empty:
|
|
108
|
+
raise ValueError("DataFrame is empty or None")
|
|
109
|
+
|
|
110
|
+
if category_column not in df.columns:
|
|
111
|
+
raise KeyError(f"Category column '{category_column}' not found in DataFrame")
|
|
112
|
+
|
|
113
|
+
if order_by_column not in df.columns:
|
|
114
|
+
raise KeyError(f"Order column '{order_by_column}' not found in DataFrame")
|
|
115
|
+
|
|
116
|
+
# Sort the dataframe by the specified column
|
|
117
|
+
sorted_df = df.sort_values(by=order_by_column, ascending=ascending)
|
|
118
|
+
|
|
119
|
+
# Get the categories in the order determined by the sorting column
|
|
120
|
+
category_order = sorted_df[category_column].unique()
|
|
121
|
+
|
|
122
|
+
# Convert category column to categorical type with the specified order
|
|
123
|
+
df[category_column] = pd.Categorical(
|
|
124
|
+
df[category_column],
|
|
125
|
+
categories=category_order,
|
|
126
|
+
ordered=True
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
return df
|
|
130
|
+
|
|
131
|
+
def generate_bubble_plot(df, svg_file_path, plot_title="RGS"):
|
|
132
|
+
"""
|
|
133
|
+
Generate and save a bubble plot as an SVG using plotnine.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
df (pd.DataFrame): Input dataframe with columns 'Category', 'bubbles_z',
|
|
137
|
+
'RGS_size' (size labels), and 'p_value_type' (color labels).
|
|
138
|
+
output_file_name (str): Name for the output SVG file.
|
|
139
|
+
plot_title (str): Title of the plot.
|
|
140
|
+
"""
|
|
141
|
+
if df is None or df.empty:
|
|
142
|
+
raise ValueError("DataFrame is empty or None")
|
|
143
|
+
|
|
144
|
+
required_columns = ['Category', 'bubbles_z', 'RGS_size', 'p_value_type']
|
|
145
|
+
missing_columns = [col for col in required_columns if col not in df.columns]
|
|
146
|
+
if missing_columns:
|
|
147
|
+
raise KeyError(f"Required columns missing in DataFrame: {missing_columns}")
|
|
148
|
+
|
|
149
|
+
# Define color and size mapping dictionaries
|
|
150
|
+
color_mapping = {
|
|
151
|
+
"Col1": "darkred",
|
|
152
|
+
"Col2": "orangered",
|
|
153
|
+
"Col3": "tomato",
|
|
154
|
+
"Col4": "orange",
|
|
155
|
+
"Col5": "gold",
|
|
156
|
+
"Col6": "yellow",
|
|
157
|
+
"NS": "dimgray"
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
size_mapping = {
|
|
161
|
+
"Size1": 10,
|
|
162
|
+
"Size2": 9,
|
|
163
|
+
"Size3": 8,
|
|
164
|
+
"Size4": 7,
|
|
165
|
+
"Size5": 6,
|
|
166
|
+
"Size6": 5,
|
|
167
|
+
"Size7": 2.5,
|
|
168
|
+
"Size8": 1,
|
|
169
|
+
"Size9": 0.1
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
# Manual color and size scales
|
|
173
|
+
color_scale = scale_color_manual(
|
|
174
|
+
name="P value",
|
|
175
|
+
labels=["10-40", "10-20", "10-10", "10-5", "0.001", "0.05", "NS"],
|
|
176
|
+
values=color_mapping,
|
|
177
|
+
limits=list(color_mapping.keys())
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
size_scale = scale_size_manual(
|
|
181
|
+
name="Count",
|
|
182
|
+
labels=["150", "100", "75", "50", "25", "10", "5", "2", "Zero"],
|
|
183
|
+
values=size_mapping,
|
|
184
|
+
limits=list(size_mapping.keys())
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Build the plot
|
|
188
|
+
p = (
|
|
189
|
+
ggplot(df, aes(x='Category', y='bubbles_z', size='RGS_size', color='p_value_type')) +
|
|
190
|
+
ggtitle(title=plot_title) +
|
|
191
|
+
geom_point(stat='identity') +
|
|
192
|
+
color_scale +
|
|
193
|
+
size_scale +
|
|
194
|
+
labs(y=' ') +
|
|
195
|
+
ylim(-1.0, 1.0) +
|
|
196
|
+
coord_flip() +
|
|
197
|
+
theme(
|
|
198
|
+
panel_grid=element_blank(),
|
|
199
|
+
panel_background=element_blank(),
|
|
200
|
+
legend_key=element_rect(fill="white", color="white"),
|
|
201
|
+
text=element_text(family="Arial", size=14),
|
|
202
|
+
axis_text_x=element_blank(), # Remove x-axis tick labels
|
|
203
|
+
axis_ticks_x=element_blank(), # Remove x-axis tick marks
|
|
204
|
+
plot_title=element_text(margin={"b": 3, "units": "lines"})
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
try:
|
|
209
|
+
# Save plot
|
|
210
|
+
p.save(filename=svg_file_path, format="svg", width=6, height=5.5)
|
|
211
|
+
print(f"Saved plot to: {svg_file_path}")
|
|
212
|
+
except Exception as e:
|
|
213
|
+
raise IOError(f"Failed to save plot: {e}")
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def create_bubble_chart(dir_path: str, data_file_nm: str, plot_title="RGS") -> None:
|
|
217
|
+
try:
|
|
218
|
+
data_file_path = Path(dir_path) / data_file_nm
|
|
219
|
+
svg_file_nm = data_file_nm[:-3] + 'svg'
|
|
220
|
+
svg_file_path = Path(dir_path) / svg_file_nm
|
|
221
|
+
|
|
222
|
+
bubbles_data = preprocess_bubble_data(data_file_path)
|
|
223
|
+
|
|
224
|
+
generate_bubble_plot(bubbles_data, svg_file_path, plot_title = plot_title)
|
|
225
|
+
except Exception as e:
|
|
226
|
+
print(f"Error: {e}")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
if __name__ == "__main__":
|
|
230
|
+
dir_path="/Users/dan/Code/Python/wormcat3/notebooks/wormcat_out/run_49048"
|
|
231
|
+
data_file_nm= "category_2_padj_bon_run_49048.csv"
|
|
232
|
+
|
|
233
|
+
create_bubble_chart(dir_path, data_file_nm, plot_title="Category 2 Up")
|
|
234
|
+
|