cellmaps-utils 0.5.0__tar.gz → 0.6.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.
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/HISTORY.rst +13 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/PKG-INFO +22 -9
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/__init__.py +1 -1
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/apmstool.py +22 -3
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/crisprtool.py +3 -3
- cellmaps_utils-0.6.0/cellmaps_utils/hcx_utils.py +198 -0
- cellmaps_utils-0.6.0/cellmaps_utils/hierdiff.py +81 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/ifimage_readme.txt +4 -4
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/iftool.py +35 -16
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils.egg-info/PKG-INFO +22 -9
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils.egg-info/SOURCES.txt +1 -0
- cellmaps_utils-0.6.0/cellmaps_utils.egg-info/requires.txt +9 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/cellmaps_utils.rst +40 -0
- cellmaps_utils-0.6.0/docs/outputs.rst +139 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/usage.rst +311 -2
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/setup.py +8 -8
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_apmstool.py +12 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_crisprtool.py +2 -2
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_iftool.py +2 -1
- cellmaps_utils-0.5.0/cellmaps_utils/hcx_utils.py +0 -92
- cellmaps_utils-0.5.0/cellmaps_utils.egg-info/requires.txt +0 -9
- cellmaps_utils-0.5.0/docs/outputs.rst +0 -48
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/AUTHORS.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/CONTRIBUTING.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/LICENSE +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/MANIFEST.in +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/README.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/apms_readme.txt +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/basecmdtool.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/cellmaps_utilscmd.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/constants.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/crispr_readme.txt +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/ddotconverter.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/exceptions.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/hidefconverter.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/logutils.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/music_utils.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/ndexupload.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/provenance.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils/tabletool.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils.egg-info/dependency_links.txt +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils.egg-info/not-zip-safe +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/cellmaps_utils.egg-info/top_level.txt +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/Makefile +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/_build/html/_static/file.png +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/_build/html/_static/minus.png +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/_build/html/_static/plus.png +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/authors.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/conf.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/contributing.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/devbranches.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/developer.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/history.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/index.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/installation.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/integrationtesting.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/make.bat +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/modules.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/newrelease.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/pypircfile.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/docs/versioningscheme.rst +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/setup.cfg +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/.DS_Store +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/__init__.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/ddot_output.ont +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/hidef_output.edges +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/hidef_output.nodes +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/images/blue.jpg +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/images/green.jpg +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/images/red.jpg +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/images/yellow.jpg +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/parent_edgelist +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/reactome_ddot.txt +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/ro-crate-metadata.json +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/data/test_password +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_basecommandlinetool.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_ddotconverter.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_helloworldcommand.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_hidefconverter.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_integation_provenance.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_logutils.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_ndexupload.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_provenance.py +0 -0
- {cellmaps_utils-0.5.0 → cellmaps_utils-0.6.0}/tests/test_tabletool.py +0 -0
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
History
|
|
3
3
|
=======
|
|
4
4
|
|
|
5
|
+
0.6.0 (2025-02-05)
|
|
6
|
+
------------------
|
|
7
|
+
|
|
8
|
+
* Add ``HierarchyDiff`` class with ``compare_hierarchies`` method to compare two hierarchies in CX2 format, and output
|
|
9
|
+
a hierarchy with robustness score of each system.
|
|
10
|
+
|
|
11
|
+
* Add version bounds for required packages.
|
|
12
|
+
|
|
13
|
+
* Add ``convert_hierarchical_network_to_hcx`` (utility function that aids convertion of a hierarchical network in CX2 to
|
|
14
|
+
HCX) and ``add_hcx_members_annotation`` (adds 'HCX::members' attribute to nodes) to ``hcx_utils``
|
|
15
|
+
|
|
16
|
+
* Fixes in IF and APMS tools
|
|
17
|
+
|
|
5
18
|
0.5.0 (2024-09-05)
|
|
6
19
|
------------------
|
|
7
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cellmaps_utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Contains utilities needed by Cell Maps tools
|
|
5
5
|
Home-page: https://github.com/idekerlab/cellmaps_utils
|
|
6
6
|
Author: Cell Maps team
|
|
@@ -18,15 +18,15 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
18
|
Description-Content-Type: text/x-rst
|
|
19
19
|
License-File: LICENSE
|
|
20
20
|
License-File: AUTHORS.rst
|
|
21
|
-
Requires-Dist: fairscape-cli==0.2
|
|
21
|
+
Requires-Dist: fairscape-cli==1.0.2
|
|
22
22
|
Requires-Dist: ndex2<4.0.0,>=3.8.0
|
|
23
|
-
Requires-Dist: scipy
|
|
24
|
-
Requires-Dist: scikit-learn
|
|
25
|
-
Requires-Dist: pandas
|
|
26
|
-
Requires-Dist: numpy
|
|
27
|
-
Requires-Dist: dill
|
|
28
|
-
Requires-Dist: tqdm
|
|
29
|
-
Requires-Dist: requests
|
|
23
|
+
Requires-Dist: scipy<1.11,>=1.10.1
|
|
24
|
+
Requires-Dist: scikit-learn<1.4.0,>=0.19.0
|
|
25
|
+
Requires-Dist: pandas<3.0.0,>=2.0.0
|
|
26
|
+
Requires-Dist: numpy<2.0.0,>=1.24.4
|
|
27
|
+
Requires-Dist: dill<0.4.0,>=0.3.8
|
|
28
|
+
Requires-Dist: tqdm<5.0.0,>=4.66.6
|
|
29
|
+
Requires-Dist: requests<3.0.0,>=2.31.0
|
|
30
30
|
|
|
31
31
|
=============================
|
|
32
32
|
Cell Maps Pipeline Utilities
|
|
@@ -145,6 +145,19 @@ This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypack
|
|
|
145
145
|
History
|
|
146
146
|
=======
|
|
147
147
|
|
|
148
|
+
0.6.0 (2025-02-05)
|
|
149
|
+
------------------
|
|
150
|
+
|
|
151
|
+
* Add ``HierarchyDiff`` class with ``compare_hierarchies`` method to compare two hierarchies in CX2 format, and output
|
|
152
|
+
a hierarchy with robustness score of each system.
|
|
153
|
+
|
|
154
|
+
* Add version bounds for required packages.
|
|
155
|
+
|
|
156
|
+
* Add ``convert_hierarchical_network_to_hcx`` (utility function that aids convertion of a hierarchical network in CX2 to
|
|
157
|
+
HCX) and ``add_hcx_members_annotation`` (adds 'HCX::members' attribute to nodes) to ``hcx_utils``
|
|
158
|
+
|
|
159
|
+
* Fixes in IF and APMS tools
|
|
160
|
+
|
|
148
161
|
0.5.0 (2024-09-05)
|
|
149
162
|
------------------
|
|
150
163
|
|
|
@@ -22,6 +22,8 @@ class APMSDataLoader(BaseCommandLineTool):
|
|
|
22
22
|
"""
|
|
23
23
|
COMMAND = 'apmsconverter'
|
|
24
24
|
|
|
25
|
+
BAIT_COL_NAME = 'Bait'
|
|
26
|
+
|
|
25
27
|
def __init__(self, theargs,
|
|
26
28
|
provenance_utils=ProvenanceUtil()):
|
|
27
29
|
"""
|
|
@@ -43,6 +45,8 @@ class APMSDataLoader(BaseCommandLineTool):
|
|
|
43
45
|
self._tissue = theargs.tissue
|
|
44
46
|
self._author = theargs.author
|
|
45
47
|
self._gene_set = theargs.gene_set
|
|
48
|
+
self._baitcolname = theargs.baitcolname
|
|
49
|
+
self._set_name = theargs.set_name
|
|
46
50
|
self._provenance_utils = provenance_utils
|
|
47
51
|
self._softwareid = None
|
|
48
52
|
self._input_data_dict = theargs.__dict__
|
|
@@ -139,9 +143,11 @@ class APMSDataLoader(BaseCommandLineTool):
|
|
|
139
143
|
if self._gene_set is not None:
|
|
140
144
|
dir_name += self._gene_set.lower() + '_'
|
|
141
145
|
dir_name += self._cell_line.lower() + '_'
|
|
142
|
-
dir_name += self._treatment.lower()
|
|
146
|
+
dir_name += self._treatment.lower()
|
|
147
|
+
if self._set_name is not None:
|
|
148
|
+
dir_name += '_' + self._set_name
|
|
149
|
+
dir_name += '_apms_'
|
|
143
150
|
dir_name += self._release.lower()
|
|
144
|
-
|
|
145
151
|
dir_name = dir_name.replace(' ', '_')
|
|
146
152
|
self._outdir = os.path.join(self._outdir, dir_name)
|
|
147
153
|
|
|
@@ -154,7 +160,13 @@ class APMSDataLoader(BaseCommandLineTool):
|
|
|
154
160
|
"""
|
|
155
161
|
df_list = []
|
|
156
162
|
for input in self._inputs:
|
|
157
|
-
|
|
163
|
+
thesep = '\t'
|
|
164
|
+
if input.endswith('.csv'):
|
|
165
|
+
thesep = ','
|
|
166
|
+
cur_df = pd.read_csv(input, sep=thesep, na_filter=False)
|
|
167
|
+
if self._baitcolname != 'Bait':
|
|
168
|
+
if self._baitcolname in cur_df.columns:
|
|
169
|
+
cur_df.rename({self._baitcolname: 'Bait'}, axis=1, inplace=True)
|
|
158
170
|
# Handles case where HDAC2 in initial cm4ai dataset
|
|
159
171
|
# had several columns lacking .x suffix
|
|
160
172
|
# we are fixing this by checking for those columns and if
|
|
@@ -173,6 +185,7 @@ class APMSDataLoader(BaseCommandLineTool):
|
|
|
173
185
|
df = pd.concat(df_list)
|
|
174
186
|
|
|
175
187
|
apms_path = os.path.join(self._outdir, constants.APMS_TSV_FILE)
|
|
188
|
+
|
|
176
189
|
df.to_csv(apms_path, sep='\t', index=False)
|
|
177
190
|
return apms_path
|
|
178
191
|
|
|
@@ -263,11 +276,17 @@ class APMSDataLoader(BaseCommandLineTool):
|
|
|
263
276
|
parser.add_argument('--gene_set', choices=['chromatin', 'metabolic'],
|
|
264
277
|
default='chromatin',
|
|
265
278
|
help='Gene set for dataset')
|
|
279
|
+
parser.add_argument('--set_name',
|
|
280
|
+
help='If set, adds value to RO-Crate folder name before _apms_<version>. '
|
|
281
|
+
'Example values set1')
|
|
266
282
|
parser.add_argument('--tissue', choices=['undifferentiated', 'neuron',
|
|
267
283
|
'cardiomyocytes', ''],
|
|
268
284
|
default='breast; mammary gland',
|
|
269
285
|
help='Tissue for dataset. Since the default --cell_line '
|
|
270
286
|
'is MDA-MB-468, this value is set to the tissue '
|
|
271
287
|
'for that cell line')
|
|
288
|
+
parser.add_argument('--baitcolname', default='Bait',
|
|
289
|
+
help='Name of bait column in input file(s)')
|
|
290
|
+
|
|
272
291
|
return parser
|
|
273
292
|
|
|
@@ -246,7 +246,7 @@ class CRISPRDataLoader(BaseCommandLineTool):
|
|
|
246
246
|
if self._gene_set is not None:
|
|
247
247
|
dir_name += self._gene_set.lower() + '_'
|
|
248
248
|
dir_name += self._cell_line.lower() + '_'
|
|
249
|
-
dir_name += re.sub('[^a-zA-Z0-9\w\n\.]', '_', self._tissue.lower()) + '_'
|
|
249
|
+
dir_name += re.sub(r'[^a-zA-Z0-9\w\n\.]', '_', self._tissue.lower()) + '_'
|
|
250
250
|
dir_name += self._treatment.lower() + '_crispr_'
|
|
251
251
|
if self._dataset.lower() != '':
|
|
252
252
|
dir_name += self._dataset.lower() + '_'
|
|
@@ -308,8 +308,8 @@ class CRISPRDataLoader(BaseCommandLineTool):
|
|
|
308
308
|
|
|
309
309
|
Version {version}
|
|
310
310
|
|
|
311
|
-
{cmd} Loads CRISPR data into a RO-Crate by creating a
|
|
312
|
-
directory, copying over relevant and using FAIRSCAPE CLI to
|
|
311
|
+
{cmd} Loads CRISPR data into a RO-Crate by creating a
|
|
312
|
+
directory, copying over relevant and using FAIRSCAPE CLI to
|
|
313
313
|
register the data files in the directory known as an RO-Crate
|
|
314
314
|
|
|
315
315
|
""".format(version=cellmaps_utils.__version__,
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import ndex2
|
|
5
|
+
from ndex2.cx2 import CX2Network, RawCX2NetworkFactory
|
|
6
|
+
|
|
7
|
+
from cellmaps_utils.exceptions import CellMapsError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_host_and_uuid_from_network_url(network_url):
|
|
11
|
+
"""
|
|
12
|
+
Extracts the host and UUID from a given NDEx network URL.
|
|
13
|
+
|
|
14
|
+
:param network_url: The URL of the NDEx network.
|
|
15
|
+
:type network_url: str
|
|
16
|
+
:return: A tuple containing the host and the UUID of the network.
|
|
17
|
+
:rtype: tuple
|
|
18
|
+
"""
|
|
19
|
+
if network_url is None:
|
|
20
|
+
return None, None
|
|
21
|
+
parts = network_url.replace('https://', '').replace('http:/', '').split('/')
|
|
22
|
+
host, uuid = parts[0], parts[-1]
|
|
23
|
+
return host, uuid
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_interactome(host, uuid, username, password, parent_edgelist):
|
|
27
|
+
"""
|
|
28
|
+
Retrieves the interactome either from NDEx or from a local edge list.
|
|
29
|
+
|
|
30
|
+
:param host: The NDEx server host.
|
|
31
|
+
:type host: str
|
|
32
|
+
:param uuid: The UUID of the interactome network in NDEx.
|
|
33
|
+
:type uuid: str
|
|
34
|
+
:param username: The NDEx username for authentication.
|
|
35
|
+
:type username: str
|
|
36
|
+
:param password: The NDEx password for authentication.
|
|
37
|
+
:type password: str
|
|
38
|
+
:param parent_edgelist: Path to a file containing the interactome edge list.
|
|
39
|
+
:type parent_edgelist: str
|
|
40
|
+
:return: A CX2Network object representing the interactome.
|
|
41
|
+
:rtype: CX2Network
|
|
42
|
+
"""
|
|
43
|
+
interactome = CX2Network()
|
|
44
|
+
if parent_edgelist is not None:
|
|
45
|
+
with open(parent_edgelist, 'r') as f:
|
|
46
|
+
for line in f:
|
|
47
|
+
parts = line.split()
|
|
48
|
+
id_source_node = interactome.lookup_node_id_by_name(parts[0])
|
|
49
|
+
source_node = id_source_node if id_source_node is not None else interactome.add_node(
|
|
50
|
+
attributes={'name': parts[0]})
|
|
51
|
+
id_target_node = interactome.lookup_node_id_by_name(parts[1])
|
|
52
|
+
target_node = id_target_node if id_target_node is not None else interactome.add_node(
|
|
53
|
+
attributes={'name': parts[1]})
|
|
54
|
+
interactome.add_edge(source=source_node, target=target_node)
|
|
55
|
+
elif host is not None and uuid is not None:
|
|
56
|
+
client = ndex2.client.Ndex2(host=host, username=username, password=password)
|
|
57
|
+
factory = RawCX2NetworkFactory()
|
|
58
|
+
client_resp = client.get_network_as_cx2_stream(uuid)
|
|
59
|
+
interactome = factory.get_cx2network(json.loads(client_resp.content))
|
|
60
|
+
return interactome
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_root_nodes(hierarchy):
|
|
64
|
+
"""
|
|
65
|
+
Identifies the root nodes in a hierarchical network.
|
|
66
|
+
|
|
67
|
+
In CDAPS the root node has only source edges to children
|
|
68
|
+
so this function counts up number of target edges for each node
|
|
69
|
+
and the one with 0 is the root
|
|
70
|
+
|
|
71
|
+
:return: root node ids
|
|
72
|
+
:rtype: set
|
|
73
|
+
"""
|
|
74
|
+
all_nodes = set()
|
|
75
|
+
for node_id, node_obj in hierarchy.get_nodes().items():
|
|
76
|
+
all_nodes.add(node_id)
|
|
77
|
+
|
|
78
|
+
nodes_with_targets = set()
|
|
79
|
+
for edge_id, edge_obj in hierarchy.get_edges().items():
|
|
80
|
+
nodes_with_targets.add(edge_obj['t'])
|
|
81
|
+
return all_nodes.difference(nodes_with_targets)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def add_isroot_node_attribute(hierarchy, root_nodes):
|
|
85
|
+
"""
|
|
86
|
+
Using the **root_nodes** set or list, add
|
|
87
|
+
``HCX::isRoot`` to
|
|
88
|
+
every node setting value to ``True``
|
|
89
|
+
if node id is in **root_nodes**
|
|
90
|
+
otherwise set the value to ``False``
|
|
91
|
+
"""
|
|
92
|
+
attr_name = 'HCX::isRoot'
|
|
93
|
+
for node_id, node_obj in hierarchy.get_nodes().items():
|
|
94
|
+
if node_id in root_nodes:
|
|
95
|
+
hierarchy.add_node_attribute(node_id, attr_name, True)
|
|
96
|
+
else:
|
|
97
|
+
hierarchy.add_node_attribute(node_id, attr_name, False)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def add_hcx_network_annotations(hierarchy, interactome=None, output_dir='.',
|
|
101
|
+
interactome_name='hierarchy_parent.cx2', host='www.ndexbio.org', uuid=None):
|
|
102
|
+
"""
|
|
103
|
+
Adds HCX network annotations to the hierarchy.
|
|
104
|
+
|
|
105
|
+
:param hierarchy: The hierarchical network in CX2 format.
|
|
106
|
+
:type hierarchy: CX2Network
|
|
107
|
+
:param interactome: The interactome network.
|
|
108
|
+
:type interactome: CX2Network, optional
|
|
109
|
+
:param output_dir: Directory where the interactome file will be saved.
|
|
110
|
+
:type output_dir: str, optional
|
|
111
|
+
:param interactome_name: Name of the interactome file.
|
|
112
|
+
:type interactome_name: str, optional
|
|
113
|
+
:param host: NDEx host for interactome retrieval.
|
|
114
|
+
:type host: str, optional
|
|
115
|
+
:param uuid: UUID of the interactome in NDEx.
|
|
116
|
+
:type uuid: str, optional
|
|
117
|
+
:return: The updated hierarchy network with annotations.
|
|
118
|
+
:rtype: CX2Network
|
|
119
|
+
"""
|
|
120
|
+
if not isinstance(hierarchy, CX2Network):
|
|
121
|
+
raise CellMapsError("Hierarchy must be an instance of CX2Network.")
|
|
122
|
+
if uuid is None and interactome is None:
|
|
123
|
+
raise CellMapsError("UUID of interactome or interactome (instance of CX2Network) must be specified!")
|
|
124
|
+
|
|
125
|
+
hierarchy.add_network_attribute('ndexSchema', 'hierarchy_v0.1',
|
|
126
|
+
datatype='string')
|
|
127
|
+
hierarchy.add_network_attribute('HCX::modelFileCount', '2',
|
|
128
|
+
datatype='integer')
|
|
129
|
+
|
|
130
|
+
if host and uuid:
|
|
131
|
+
hierarchy.add_network_attribute('HCX::interactionNetworkHost', host)
|
|
132
|
+
hierarchy.add_network_attribute('HCX::interactionNetworkUUID', uuid)
|
|
133
|
+
else:
|
|
134
|
+
interactome_path = os.path.join(output_dir, interactome_name)
|
|
135
|
+
interactome.write_as_raw_cx2(interactome_path)
|
|
136
|
+
hierarchy.add_network_attribute('HCX::interactionNetworkName', interactome_name,
|
|
137
|
+
datatype='string')
|
|
138
|
+
return hierarchy
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def add_hcx_members_annotation(hierarchy, interactome, gene_column='CD_MemberList'):
|
|
142
|
+
"""
|
|
143
|
+
Adds the 'HCX::members' attribute to nodes in the hierarchy based on the interactome.
|
|
144
|
+
|
|
145
|
+
:param hierarchy: The hierarchical network in CX2 format.
|
|
146
|
+
:type hierarchy: CX2Network
|
|
147
|
+
:param interactome: The interactome network.
|
|
148
|
+
:type interactome: CX2Network
|
|
149
|
+
:param gene_column: Column name containing gene members.
|
|
150
|
+
:type gene_column: str, optional
|
|
151
|
+
"""
|
|
152
|
+
for node_id, node_obj in hierarchy.get_nodes().items():
|
|
153
|
+
memberlist = hierarchy.get_node(node_id).get('v', {}).get(gene_column, '').split(' ')
|
|
154
|
+
membersids = []
|
|
155
|
+
for member in memberlist:
|
|
156
|
+
id_interactome = interactome.lookup_node_id_by_name(member)
|
|
157
|
+
if id_interactome is not None:
|
|
158
|
+
membersids.append(id_interactome)
|
|
159
|
+
hierarchy.add_node_attribute(node_id, 'HCX::members', membersids, datatype='list_of_integer')
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def convert_hierarchical_network_to_hcx(hierarchy, interactome_url, ndex_username=None, ndex_password=None,
|
|
163
|
+
gene_column='CD_MemberList'):
|
|
164
|
+
"""
|
|
165
|
+
Converts a hierarchical network into HCX format by adding necessary annotations and interactome details.
|
|
166
|
+
|
|
167
|
+
:param hierarchy: The hierarchical network in CX2 format or a path to the CX2 file.
|
|
168
|
+
:type hierarchy: CX2Network or str
|
|
169
|
+
:param interactome_url: URL of the interactome network in NDEx.
|
|
170
|
+
:type interactome_url: str
|
|
171
|
+
:param ndex_username: NDEx username for authentication.
|
|
172
|
+
:type ndex_username: str, optional
|
|
173
|
+
:param ndex_password: NDEx password for authentication.
|
|
174
|
+
:type ndex_password: str, optional
|
|
175
|
+
:param gene_column: Column name containing gene members.
|
|
176
|
+
:type gene_column: str, optional
|
|
177
|
+
:return: The updated hierarchy network in CX2 format with HCX annotations.
|
|
178
|
+
:rtype: CX2Network
|
|
179
|
+
"""
|
|
180
|
+
factory = RawCX2NetworkFactory()
|
|
181
|
+
if isinstance(hierarchy, str):
|
|
182
|
+
hierarchy = factory.get_cx2network(hierarchy)
|
|
183
|
+
|
|
184
|
+
# Get the host and uuid of the interactome
|
|
185
|
+
host, uuid = get_host_and_uuid_from_network_url(interactome_url)
|
|
186
|
+
hierarchy = add_hcx_network_annotations(hierarchy, host=host, uuid=uuid)
|
|
187
|
+
|
|
188
|
+
# Create CX2Network object from interactome from NDEx
|
|
189
|
+
client = ndex2.client.Ndex2(host=host, username=ndex_username, password=ndex_password)
|
|
190
|
+
client_resp = client.get_network_as_cx2_stream(uuid)
|
|
191
|
+
interactome = factory.get_cx2network(json.loads(client_resp.content))
|
|
192
|
+
|
|
193
|
+
# Add HCX::members attribute to node attributes
|
|
194
|
+
add_hcx_members_annotation(hierarchy, interactome, gene_column)
|
|
195
|
+
|
|
196
|
+
# Add isRoot attribute to node attributes
|
|
197
|
+
add_isroot_node_attribute(hierarchy, get_root_nodes(hierarchy))
|
|
198
|
+
return hierarchy
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from ndex2.cx2 import RawCX2NetworkFactory, CX2Network
|
|
3
|
+
|
|
4
|
+
logger = logging.getLogger(__name__)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class HierarchyDiff:
|
|
8
|
+
"""
|
|
9
|
+
A class to compare two hierarchies in CX2 (HCX)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
"""
|
|
14
|
+
Constructor
|
|
15
|
+
"""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
def compare_hierarchies_from_files(self, hierarchy_a_path=None, hierarchy_b_path=None):
|
|
19
|
+
"""
|
|
20
|
+
Compare two hierarchies from file paths.
|
|
21
|
+
|
|
22
|
+
:param hierarchy_a_path: Path to hierarchy to compare
|
|
23
|
+
:type hierarchy_a_path: str
|
|
24
|
+
:param hierarchy_b_path: Path to hierarchy to compare
|
|
25
|
+
:type hierarchy_b_path: str
|
|
26
|
+
"""
|
|
27
|
+
factory = RawCX2NetworkFactory()
|
|
28
|
+
hierarchy_a = factory.get_cx2network(hierarchy_a_path)
|
|
29
|
+
hierarchy_b = factory.get_cx2network(hierarchy_b_path)
|
|
30
|
+
return self.compare_hierarchies(hierarchy_a, hierarchy_b)
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def compare_hierarchies(hierarchy_a=None, hierarchy_b=None):
|
|
34
|
+
"""
|
|
35
|
+
Compare two hierarchies in CX2 format. It looks at each system and outputs a robustness score
|
|
36
|
+
which correlates to how stable the system is in the hierarchies generated. It outputs a hierarchy with
|
|
37
|
+
the robustness score added to the systems.
|
|
38
|
+
|
|
39
|
+
:param hierarchy_a: Hierarchy to compare
|
|
40
|
+
:type hierarchy_a: ndex2.cx2.CX2Network
|
|
41
|
+
:param hierarchy_b: Hierarchy to compare
|
|
42
|
+
:type hierarchy_b: ndex2.cx2.CX2Network
|
|
43
|
+
"""
|
|
44
|
+
nodes_a = hierarchy_a.get_nodes()
|
|
45
|
+
nodes_b = hierarchy_b.get_nodes()
|
|
46
|
+
|
|
47
|
+
# Compute overlap scores for nodes based on CD_MemberList
|
|
48
|
+
all_node_ids = set(nodes_a.keys()).union(nodes_b.keys())
|
|
49
|
+
node_overlap_scores = {}
|
|
50
|
+
|
|
51
|
+
for node_id in all_node_ids:
|
|
52
|
+
members_a = set(nodes_a.get(node_id, {}).get('v', {}).get('CD_MemberList', '').split())
|
|
53
|
+
members_b = set(nodes_b.get(node_id, {}).get('v', {}).get('CD_MemberList', '').split())
|
|
54
|
+
|
|
55
|
+
if members_a and members_b:
|
|
56
|
+
# Calculate overlap score based on intersection and union
|
|
57
|
+
overlap = len(members_a.intersection(members_b))
|
|
58
|
+
union = len(members_a.union(members_b))
|
|
59
|
+
score = overlap / union if union > 0 else 0
|
|
60
|
+
else:
|
|
61
|
+
score = 0
|
|
62
|
+
|
|
63
|
+
node_overlap_scores[node_id] = score
|
|
64
|
+
|
|
65
|
+
# Create a new hierarchy to store results
|
|
66
|
+
result_hierarchy = CX2Network()
|
|
67
|
+
|
|
68
|
+
# Add nodes from hierarchy_a with robustness scores
|
|
69
|
+
for node_id, data in nodes_a.items():
|
|
70
|
+
score = node_overlap_scores.get(node_id, 0)
|
|
71
|
+
data['v']['robustness_score'] = score
|
|
72
|
+
result_hierarchy.add_node(node_id=node_id, attributes=data['v'])
|
|
73
|
+
|
|
74
|
+
# Add nodes from hierarchy_b if they don't already exist in the result hierarchy
|
|
75
|
+
for node_id, data in nodes_b.items():
|
|
76
|
+
if node_id not in nodes_a:
|
|
77
|
+
score = node_overlap_scores.get(node_id, 0)
|
|
78
|
+
data['v']['robustness_score'] = score
|
|
79
|
+
result_hierarchy.add_node(node_id=node_id, attributes=data['v'])
|
|
80
|
+
|
|
81
|
+
return result_hierarchy
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
This data set has been generated in the Emma Lundberg lab (https://ell-core.stanford.edu/)
|
|
2
|
-
|
|
2
|
+
as part of the CM4AI Research Program (https://cm4ai.org/).
|
|
3
3
|
|
|
4
|
-
This data set displays the spatial localization of
|
|
5
|
-
|
|
4
|
+
This data set displays the spatial localization of proteins in the cell line MDA-MB-468.
|
|
5
|
+
MDA-MB-468 cells were seeded into 96-well glass bottom plates
|
|
6
6
|
and treated either with the chemotherapeutic drug Paclitaxel or with the chemotherapeutic
|
|
7
7
|
drug Vorinostat (SAHA) or not treated. For drug treatment, higher cell numbers were
|
|
8
8
|
seeded than for the cells that were not treated to reach a sufficient amount of
|
|
@@ -14,7 +14,7 @@ DAPI (to label nuclei, "blue" channel),
|
|
|
14
14
|
a Calreticulin antibody (to label the endoplasmic reticulum, "yellow" channel),
|
|
15
15
|
a Tubulin antibody (to label Microtubuli, "red" channel), and an antibody against a
|
|
16
16
|
protein of interest (a different antibody / protein for each well, "green" channel).
|
|
17
|
-
In the green channel, for each well, one of
|
|
17
|
+
In the green channel, for each well, each one of the proteins was stained with an antibody
|
|
18
18
|
from the proteinatlas.org project.
|
|
19
19
|
|
|
20
20
|
The .tsv file describes each image in the data set. Each row represents one image.
|
|
@@ -138,13 +138,13 @@ class FakeImageDownloader(ImageDownloader):
|
|
|
138
138
|
raise CellMapsError('Unable to download ' +
|
|
139
139
|
str(entry))
|
|
140
140
|
fname = os.path.basename(entry[1])
|
|
141
|
-
color = re.sub('\..*$', '', re.sub('^.*_', '', fname))
|
|
141
|
+
color = re.sub(r'\..*$', '', re.sub('^.*_', '', fname))
|
|
142
142
|
src_image_dict[color] = entry[1]
|
|
143
143
|
|
|
144
144
|
for entry in download_list[5:]:
|
|
145
145
|
t.update()
|
|
146
146
|
fname = os.path.basename(entry[1])
|
|
147
|
-
color = re.sub('\..*$', '', re.sub('^.*_', '', fname))
|
|
147
|
+
color = re.sub(r'\..*$', '', re.sub('^.*_', '', fname))
|
|
148
148
|
shutil.copy(src_image_dict[color], entry[1])
|
|
149
149
|
return []
|
|
150
150
|
|
|
@@ -316,14 +316,20 @@ class IFImageDataConverter(BaseCommandLineTool):
|
|
|
316
316
|
os.path.join(self._outdir, 'readme.txt'))
|
|
317
317
|
|
|
318
318
|
# download the images
|
|
319
|
-
|
|
319
|
+
if 'Baselink' in filtered_df:
|
|
320
|
+
baselink_name = 'Baselink'
|
|
321
|
+
else:
|
|
322
|
+
baselink_name = 'base_web_link'
|
|
323
|
+
|
|
324
|
+
self._download_data(filtered_df[baselink_name].values.tolist())
|
|
320
325
|
|
|
321
326
|
# remove Baselink column
|
|
322
|
-
filtered_df.drop(
|
|
327
|
+
filtered_df.drop(baselink_name, axis=1, inplace=True)
|
|
323
328
|
|
|
324
329
|
# remove Slice column if set
|
|
325
330
|
if self._slice is not None:
|
|
326
|
-
|
|
331
|
+
if 'Slice' in filtered_df:
|
|
332
|
+
filtered_df.drop('Slice', axis=1, inplace=True)
|
|
327
333
|
|
|
328
334
|
file_path = os.path.join(self._outdir, constants.ANTIBODY_GENE_TABLE_FILE)
|
|
329
335
|
|
|
@@ -346,7 +352,8 @@ class IFImageDataConverter(BaseCommandLineTool):
|
|
|
346
352
|
gen_dsets.extend(self._register_downloaded_images(description=description,
|
|
347
353
|
keywords=keywords))
|
|
348
354
|
self._register_software(keywords=keywords, description=description)
|
|
349
|
-
|
|
355
|
+
logger.info('Registering only 1st 1000 datasets into computation due to limitations of fairscape-cli')
|
|
356
|
+
self._register_computation(generated_dataset_ids=gen_dsets[:1000],
|
|
350
357
|
description=description,
|
|
351
358
|
keywords=keywords)
|
|
352
359
|
return 0
|
|
@@ -491,15 +498,26 @@ class IFImageDataConverter(BaseCommandLineTool):
|
|
|
491
498
|
|
|
492
499
|
# keep only slice specified
|
|
493
500
|
if self._slice is not None:
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
501
|
+
if 'Slice' in df:
|
|
502
|
+
logger.info('Keeping only slice: ' + str(self._slice))
|
|
503
|
+
df = df[df['Slice'] == self._slice]
|
|
504
|
+
logger.debug(str(len(df)) + ' rows remain after slice filter')
|
|
505
|
+
else:
|
|
506
|
+
# attempt to find slice from base_web_link
|
|
507
|
+
if 'base_web_link' in df:
|
|
508
|
+
logger.info('Keeping only slice: ' + str(self._slice) + ' by parsing base_web_link')
|
|
509
|
+
df = df[df['base_web_link'].str.contains('_' + self._slice + '_', case=False)]
|
|
510
|
+
logger.debug(str(len(df)) + ' rows remain after slice filter')
|
|
497
511
|
|
|
498
512
|
# keep only treatment specified
|
|
499
513
|
logger.info('Keeping only treatment: ' + str(self._treatment))
|
|
500
514
|
df = df[df['Treatment'].str.contains(self._treatment, case=False)]
|
|
501
515
|
logger.debug(str(len(df)) + ' rows remain after treatment filter')
|
|
502
516
|
|
|
517
|
+
# remove negative-ctrl rows
|
|
518
|
+
logger.debug('Removing NEGATIVE rows')
|
|
519
|
+
df = df[df["Antibody ID"].str.contains('NEGATIVE') == False]
|
|
520
|
+
|
|
503
521
|
return df
|
|
504
522
|
|
|
505
523
|
def _register_downloaded_images(self,
|
|
@@ -601,11 +619,10 @@ class IFImageDataConverter(BaseCommandLineTool):
|
|
|
601
619
|
description=desc,
|
|
602
620
|
formatter_class=constants.ArgParseFormatter)
|
|
603
621
|
parser.add_argument('outdir',
|
|
604
|
-
help='Directory where RO-Crate will be created
|
|
605
|
-
'store results in')
|
|
622
|
+
help='Directory where RO-Crate will be created')
|
|
606
623
|
parser.add_argument('--input', required=True,
|
|
607
624
|
help='Table file with the following '
|
|
608
|
-
'fields: [Antibody ID, ENSEMBL ID, Treatment, Well, Region, Slice, Baselink] ')
|
|
625
|
+
'fields: [Antibody ID, ENSEMBL ID|ENSG, Treatment, Well, Region, Slice, Baselink|base_web_link] ')
|
|
609
626
|
parser.add_argument('--author', default='Lundberg Lab',
|
|
610
627
|
help='Author that created this data')
|
|
611
628
|
parser.add_argument('--name', default='IF images',
|
|
@@ -624,15 +641,17 @@ class IFImageDataConverter(BaseCommandLineTool):
|
|
|
624
641
|
parser.add_argument('--cell_line', default='MDA-MB-468',
|
|
625
642
|
help='Name of cell line. For example MDA-MB-468')
|
|
626
643
|
parser.add_argument('--gene_set', choices=['chromatin', 'metabolic'],
|
|
627
|
-
|
|
628
|
-
|
|
644
|
+
help='Gene set for dataset, standard names are '
|
|
645
|
+
+ 'chromatin, metabolic, or leave it unset')
|
|
629
646
|
parser.add_argument('--tissue', choices=['undifferentiated', 'neuron',
|
|
630
647
|
'cardiomyocytes', ''],
|
|
631
648
|
default='breast; mammary gland',
|
|
632
649
|
help='Tissue for dataset. Since the default --cell_line '
|
|
633
650
|
'is MDA-MB-468, this value is set to the tissue '
|
|
634
651
|
'for that cell line')
|
|
635
|
-
parser.add_argument('--slice',
|
|
636
|
-
help='Slice to keep'
|
|
652
|
+
parser.add_argument('--slice',
|
|
653
|
+
help='Slice to keep. Example names are z01, z02. If unset '
|
|
654
|
+
+ 'all slices are kept')
|
|
655
|
+
|
|
637
656
|
return parser
|
|
638
657
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cellmaps_utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Contains utilities needed by Cell Maps tools
|
|
5
5
|
Home-page: https://github.com/idekerlab/cellmaps_utils
|
|
6
6
|
Author: Cell Maps team
|
|
@@ -18,15 +18,15 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
18
|
Description-Content-Type: text/x-rst
|
|
19
19
|
License-File: LICENSE
|
|
20
20
|
License-File: AUTHORS.rst
|
|
21
|
-
Requires-Dist: fairscape-cli==0.2
|
|
21
|
+
Requires-Dist: fairscape-cli==1.0.2
|
|
22
22
|
Requires-Dist: ndex2<4.0.0,>=3.8.0
|
|
23
|
-
Requires-Dist: scipy
|
|
24
|
-
Requires-Dist: scikit-learn
|
|
25
|
-
Requires-Dist: pandas
|
|
26
|
-
Requires-Dist: numpy
|
|
27
|
-
Requires-Dist: dill
|
|
28
|
-
Requires-Dist: tqdm
|
|
29
|
-
Requires-Dist: requests
|
|
23
|
+
Requires-Dist: scipy<1.11,>=1.10.1
|
|
24
|
+
Requires-Dist: scikit-learn<1.4.0,>=0.19.0
|
|
25
|
+
Requires-Dist: pandas<3.0.0,>=2.0.0
|
|
26
|
+
Requires-Dist: numpy<2.0.0,>=1.24.4
|
|
27
|
+
Requires-Dist: dill<0.4.0,>=0.3.8
|
|
28
|
+
Requires-Dist: tqdm<5.0.0,>=4.66.6
|
|
29
|
+
Requires-Dist: requests<3.0.0,>=2.31.0
|
|
30
30
|
|
|
31
31
|
=============================
|
|
32
32
|
Cell Maps Pipeline Utilities
|
|
@@ -145,6 +145,19 @@ This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypack
|
|
|
145
145
|
History
|
|
146
146
|
=======
|
|
147
147
|
|
|
148
|
+
0.6.0 (2025-02-05)
|
|
149
|
+
------------------
|
|
150
|
+
|
|
151
|
+
* Add ``HierarchyDiff`` class with ``compare_hierarchies`` method to compare two hierarchies in CX2 format, and output
|
|
152
|
+
a hierarchy with robustness score of each system.
|
|
153
|
+
|
|
154
|
+
* Add version bounds for required packages.
|
|
155
|
+
|
|
156
|
+
* Add ``convert_hierarchical_network_to_hcx`` (utility function that aids convertion of a hierarchical network in CX2 to
|
|
157
|
+
HCX) and ``add_hcx_members_annotation`` (adds 'HCX::members' attribute to nodes) to ``hcx_utils``
|
|
158
|
+
|
|
159
|
+
* Fixes in IF and APMS tools
|
|
160
|
+
|
|
148
161
|
0.5.0 (2024-09-05)
|
|
149
162
|
------------------
|
|
150
163
|
|