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.
@@ -0,0 +1,5 @@
1
+ include README.md
2
+ include wormcat3/extdata/ORF_only_v2_nov-11-2021.csv
3
+ include wormcat3/extdata/ahringer_v2_nov-11-2021.csv
4
+ include wormcat3/extdata/orfeome_v2_nov-11-2021.csv
5
+ include wormcat3/extdata/whole_genome_v2_nov-11-2021.csv
@@ -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"/>
@@ -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"/>
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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,4 @@
1
+ __version__ = "0.0.1"
2
+
3
+ from .wormcat import Wormcat
4
+ from .statistical_analysis import PAdjustMethod
@@ -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
+