embkit 0.1.0__tar.gz → 0.2__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.
Files changed (88) hide show
  1. embkit-0.2/PKG-INFO +69 -0
  2. embkit-0.2/README.md +49 -0
  3. {embkit-0.1.0 → embkit-0.2}/pyproject.toml +11 -3
  4. embkit-0.2/src/embkit/__init__.py +62 -0
  5. embkit-0.2/src/embkit/__main__.py +81 -0
  6. embkit-0.2/src/embkit/align.py +151 -0
  7. {embkit-0.1.0 → embkit-0.2}/src/embkit/bmeg.py +7 -0
  8. embkit-0.2/src/embkit/c_bio/__init__.py +1 -0
  9. embkit-0.2/src/embkit/c_bio/api.py +13 -0
  10. embkit-0.2/src/embkit/commands/__init__.py +20 -0
  11. embkit-0.2/src/embkit/commands/align.py +35 -0
  12. embkit-0.2/src/embkit/commands/cbio.py +63 -0
  13. embkit-0.2/src/embkit/commands/datasets.py +61 -0
  14. embkit-0.2/src/embkit/commands/matrix.py +36 -0
  15. embkit-0.2/src/embkit/commands/model.py +220 -0
  16. embkit-0.2/src/embkit/commands/protein.py +56 -0
  17. embkit-0.2/src/embkit/datasets/__init__.py +4 -0
  18. embkit-0.2/src/embkit/datasets/c_bio_portal.py +134 -0
  19. embkit-0.2/src/embkit/datasets/dataset.py +138 -0
  20. embkit-0.2/src/embkit/datasets/gtex.py +109 -0
  21. embkit-0.2/src/embkit/datasets/hugo.py +17 -0
  22. embkit-0.2/src/embkit/datasets/sif.py +17 -0
  23. embkit-0.2/src/embkit/datasets/util.py +49 -0
  24. {embkit-0.1.0 → embkit-0.2}/src/embkit/estimator/vae_estimator.py +14 -3
  25. embkit-0.2/src/embkit/file_readers/__init__.py +1 -0
  26. embkit-0.2/src/embkit/file_readers/read_csv.py +252 -0
  27. embkit-0.2/src/embkit/layers/__init__.py +33 -0
  28. embkit-0.2/src/embkit/layers/constraint_info.py +111 -0
  29. embkit-0.2/src/embkit/layers/layer_info.py +108 -0
  30. embkit-0.2/src/embkit/layers/masked_linear.py +88 -0
  31. embkit-0.2/src/embkit/layers/pairwise_comparison_layer.py +91 -0
  32. embkit-0.2/src/embkit/layers/tsp.py +103 -0
  33. embkit-0.2/src/embkit/losses/__init__.py +1 -0
  34. embkit-0.2/src/embkit/losses/vae_loss.py +108 -0
  35. embkit-0.2/src/embkit/metrics/distance/__init__.py +1 -0
  36. embkit-0.2/src/embkit/metrics/distance/metrics.py +36 -0
  37. embkit-0.2/src/embkit/models/__init__.py +21 -0
  38. embkit-0.2/src/embkit/models/ffnn.py +151 -0
  39. embkit-0.2/src/embkit/models/hla2vec.py +307 -0
  40. embkit-0.2/src/embkit/models/protein.py +175 -0
  41. embkit-0.2/src/embkit/models/vae/__init__.py +10 -0
  42. embkit-0.2/src/embkit/models/vae/base_vae.py +327 -0
  43. embkit-0.2/src/embkit/models/vae/decoder.py +58 -0
  44. embkit-0.2/src/embkit/models/vae/encoder.py +145 -0
  45. embkit-0.2/src/embkit/models/vae/hla2vec.py +307 -0
  46. embkit-0.2/src/embkit/models/vae/net_vae.py +192 -0
  47. embkit-0.2/src/embkit/models/vae/pytorch.py +150 -0
  48. embkit-0.2/src/embkit/models/vae/rna_vae.py +282 -0
  49. embkit-0.2/src/embkit/models/vae/vae.py +218 -0
  50. embkit-0.2/src/embkit/pathway.py +177 -0
  51. embkit-0.2/src/embkit/preprocessing/__init__.py +8 -0
  52. embkit-0.2/src/embkit/preprocessing/loaders.py +40 -0
  53. embkit-0.2/src/embkit/utilities/__init__.py +2 -0
  54. embkit-0.2/src/embkit/utilities/kmeans.py +46 -0
  55. embkit-0.2/src/embkit/utilities/pca.py +38 -0
  56. embkit-0.2/src/embkit.egg-info/PKG-INFO +69 -0
  57. embkit-0.2/src/embkit.egg-info/SOURCES.txt +67 -0
  58. embkit-0.2/src/embkit.egg-info/entry_points.txt +2 -0
  59. {embkit-0.1.0 → embkit-0.2}/src/embkit.egg-info/requires.txt +5 -0
  60. embkit-0.2/tests/test_main.py +65 -0
  61. embkit-0.1.0/PKG-INFO +0 -42
  62. embkit-0.1.0/README.md +0 -27
  63. embkit-0.1.0/src/embkit/__main__.py +0 -14
  64. embkit-0.1.0/src/embkit/align.py +0 -59
  65. embkit-0.1.0/src/embkit/commands.py +0 -27
  66. embkit-0.1.0/src/embkit/layers/__init__.py +0 -1
  67. embkit-0.1.0/src/embkit/layers/masked_linear.py +0 -28
  68. embkit-0.1.0/src/embkit/losses/__init__.py +0 -1
  69. embkit-0.1.0/src/embkit/losses/vae_loss.py +0 -16
  70. embkit-0.1.0/src/embkit/models/__init__.py +0 -1
  71. embkit-0.1.0/src/embkit/models/vae_model/__init__.py +0 -3
  72. embkit-0.1.0/src/embkit/models/vae_model/base_vae.py +0 -226
  73. embkit-0.1.0/src/embkit/models/vae_model/decoder.py +0 -17
  74. embkit-0.1.0/src/embkit/models/vae_model/encoder.py +0 -99
  75. embkit-0.1.0/src/embkit/models/vae_model/net_vae.py +0 -186
  76. embkit-0.1.0/src/embkit/pathway.py +0 -8
  77. embkit-0.1.0/src/embkit/vae.py +0 -97
  78. embkit-0.1.0/src/embkit.egg-info/PKG-INFO +0 -42
  79. embkit-0.1.0/src/embkit.egg-info/SOURCES.txt +0 -30
  80. {embkit-0.1.0 → embkit-0.2}/setup.cfg +0 -0
  81. {embkit-0.1.0 → embkit-0.2}/setup.py +0 -0
  82. {embkit-0.1.0 → embkit-0.2}/src/embkit/constraints/__init__.py +0 -0
  83. {embkit-0.1.0 → embkit-0.2}/src/embkit/constraints/network_constraint.py +0 -0
  84. {embkit-0.1.0/src/embkit → embkit-0.2/src/embkit/estimator}/__init__.py +0 -0
  85. {embkit-0.1.0/src/embkit/estimator → embkit-0.2/src/embkit/metrics}/__init__.py +0 -0
  86. {embkit-0.1.0/src/embkit → embkit-0.2/src/embkit/preprocessing}/normalize.py +0 -0
  87. {embkit-0.1.0 → embkit-0.2}/src/embkit.egg-info/dependency_links.txt +0 -0
  88. {embkit-0.1.0 → embkit-0.2}/src/embkit.egg-info/top_level.txt +0 -0
embkit-0.2/PKG-INFO ADDED
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: embkit
3
+ Version: 0.2
4
+ Summary: Embedding Kit for embedding models
5
+ Author-email: Kyle Ellrott <ellrott@ohsu.edu>, Raphael Kirchgaessner <kirchgae@ohsu.edu>
6
+ License: MIT
7
+ Keywords: embeddings,machine learning,deep learning
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: torch>=2.0
11
+ Requires-Dist: pandas
12
+ Requires-Dist: numpy
13
+ Requires-Dist: click
14
+ Requires-Dist: scikit-learn
15
+ Requires-Dist: scipy
16
+ Requires-Dist: gripql
17
+ Requires-Dist: tqdm
18
+ Requires-Dist: biopython
19
+ Requires-Dist: fair-esm
20
+
21
+
22
+ # Embedding Kit
23
+
24
+ Methods for data normalization, embedding, synthesis and transformation
25
+
26
+
27
+ ## Installation
28
+ ```
29
+ pip install embkit
30
+ ```
31
+
32
+ # Training a model
33
+ ```
34
+ embkit model train-vae ./experiments/tcga/tumor.normalized.tsv --epochs 120
35
+ ```
36
+
37
+ ## Development
38
+
39
+ To install the library locally use:
40
+ ```pip install -e .```
41
+ ```python setup.py build```
42
+ ```python setup.py install```
43
+
44
+ ### To run tests use:
45
+ ```bash
46
+ coverage run --source=embkit -m unittest discover -s tests
47
+ ```
48
+
49
+ To generate a coverage report use:
50
+ ```bash
51
+ coverage html
52
+ ```
53
+
54
+ To open the coverage report in a browser, run:
55
+ #### MacOS:
56
+ ```bash
57
+ open htmlcov/index.html
58
+ ```
59
+
60
+ #### Linux:
61
+ ```bash
62
+ xdg-open htmlcov/index.html
63
+ ```
64
+
65
+ #### Windows:
66
+ ```bash
67
+ start htmlcov\index.html
68
+ ```
69
+
embkit-0.2/README.md ADDED
@@ -0,0 +1,49 @@
1
+
2
+ # Embedding Kit
3
+
4
+ Methods for data normalization, embedding, synthesis and transformation
5
+
6
+
7
+ ## Installation
8
+ ```
9
+ pip install embkit
10
+ ```
11
+
12
+ # Training a model
13
+ ```
14
+ embkit model train-vae ./experiments/tcga/tumor.normalized.tsv --epochs 120
15
+ ```
16
+
17
+ ## Development
18
+
19
+ To install the library locally use:
20
+ ```pip install -e .```
21
+ ```python setup.py build```
22
+ ```python setup.py install```
23
+
24
+ ### To run tests use:
25
+ ```bash
26
+ coverage run --source=embkit -m unittest discover -s tests
27
+ ```
28
+
29
+ To generate a coverage report use:
30
+ ```bash
31
+ coverage html
32
+ ```
33
+
34
+ To open the coverage report in a browser, run:
35
+ #### MacOS:
36
+ ```bash
37
+ open htmlcov/index.html
38
+ ```
39
+
40
+ #### Linux:
41
+ ```bash
42
+ xdg-open htmlcov/index.html
43
+ ```
44
+
45
+ #### Windows:
46
+ ```bash
47
+ start htmlcov\index.html
48
+ ```
49
+
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "embkit"
7
- version = "0.1.0"
7
+ version = "0.2"
8
8
  description = "Embedding Kit for embedding models"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -19,11 +19,19 @@ dependencies = [
19
19
  "pandas",
20
20
  "numpy",
21
21
  "click",
22
- "scikit-learn"
22
+ "scikit-learn",
23
+ "scipy",
24
+ "gripql",
25
+ "tqdm",
26
+ "biopython",
27
+ "fair-esm"
23
28
  ]
24
29
 
25
30
  [tool.setuptools]
26
31
  package-dir = { "" = "src" }
27
32
 
28
33
  [tool.setuptools.packages.find]
29
- where = ["src"]
34
+ where = ["src"]
35
+
36
+ [project.scripts]
37
+ embkit = "embkit.__main__:cli"
@@ -0,0 +1,62 @@
1
+ """
2
+ Embedding Kit
3
+
4
+ The base module contains frequently used methods and functions
5
+ """
6
+ import logging
7
+ import torch
8
+ import pandas as pd
9
+ import numpy as np
10
+ from torch.utils.data import TensorDataset, DataLoader
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ def get_device() -> torch.device:
15
+ """
16
+ get_device - scan system and return default device
17
+ """
18
+ if torch.cuda.is_available():
19
+ logger.info("Using CUDA GPU")
20
+ return torch.device("cuda")
21
+ if torch.backends.mps.is_available():
22
+ logger.info("Using Metal GPU")
23
+ return torch.device("mps")
24
+ logger.info("Using CPU")
25
+ return torch.device("cpu")
26
+
27
+ def dataframe_tensor(df: pd.DataFrame,device=None) -> torch.Tensor:
28
+ """
29
+ dataframe_tensor
30
+
31
+ take a pandas dataframe, create a tensor
32
+ """
33
+ if device is None:
34
+ device = get_device()
35
+ return torch.from_numpy(df.values.astype(np.float32)).to(device)
36
+
37
+ def tensor_dataframe(tn: torch.Tensor, index=None, columns=None) -> pd.DataFrame:
38
+ """
39
+ dataframe_tensor
40
+
41
+ take a torch tensor, create a pandas dataframe
42
+ """
43
+ return pd.DataFrame(tn.cpu().detach().numpy(), index=index, columns=columns)
44
+
45
+ def dataframe_loader(df: pd.DataFrame,
46
+ batch_size = 256, shuffle=True,
47
+ device=None) -> torch.utils.data.DataLoader:
48
+ """
49
+ dataframe_loader
50
+
51
+ :param df: Pandas Dataframe to be converted into passed to DataLoader
52
+ :param batch_size: value to be passed to DataLoader batch_size
53
+ :param shuffle: value to be passed to DataLoader shuffle
54
+ :param device: Device the where tensor should be moved. If None, use get_device
55
+ """
56
+
57
+ if device is None:
58
+ device = get_device()
59
+ x = torch.from_numpy(df.values.astype(np.float32)).to(device)
60
+ dataset = TensorDataset(x)
61
+ data_loader = DataLoader(dataset, batch_size=batch_size, shuffle=shuffle)
62
+ return data_loader
@@ -0,0 +1,81 @@
1
+ import click
2
+ import logging
3
+
4
+ from .commands import model, matrix, cbio_cmd, protein, datasets, align
5
+
6
+ @click.group(invoke_without_command=True)
7
+ @click.option('--verbose', is_flag=True, help="Enable verbose logging")
8
+ @click.pass_context
9
+ def cli(ctx, verbose):
10
+ """Embedding Kit CLI.
11
+
12
+ Use 'embkit help [COMMAND]' for details on a specific command.
13
+ """
14
+ # Set up logging based on the verbose flag
15
+ logging.basicConfig(
16
+ level=logging.DEBUG if verbose else logging.INFO,
17
+ format="%(asctime)s [%(levelname)s] %(message)s"
18
+ )
19
+
20
+ ctx.ensure_object(dict)
21
+ ctx.obj["VERBOSE"] = verbose
22
+
23
+ if ctx.invoked_subcommand is None:
24
+ click.echo(ctx.get_help())
25
+
26
+
27
+ # Register our commands here
28
+ cli.add_command(model)
29
+ cli.add_command(matrix)
30
+ cli.add_command(cbio_cmd)
31
+ cli.add_command(protein)
32
+ cli.add_command(datasets)
33
+ cli.add_command(align)
34
+
35
+
36
+ # ---- 'help' command ----
37
+ @cli.command("help", context_settings=dict(ignore_unknown_options=True))
38
+ @click.argument("path", nargs=-1)
39
+ @click.pass_context
40
+ def help_cmd(ctx, path):
41
+ """
42
+ Show help for the CLI or a specific command.
43
+
44
+ Examples:
45
+ embkit help
46
+ embkit help model
47
+ embkit help model train
48
+ """
49
+ # No args -> show top-level help plus a neat command list summary
50
+ if not path:
51
+ click.echo(ctx.parent.get_help())
52
+ click.echo("\nCommands:")
53
+ # Sorted, with 1-line summaries
54
+ for name in sorted(cli.commands):
55
+ cmd = cli.commands[name]
56
+ summary = (cmd.help or cmd.short_help or "").strip().splitlines()[0]
57
+ click.echo(f" {name:15s} {summary}")
58
+ return
59
+
60
+ # Resolve dotted/space-separated path to a nested command
61
+ cmd = cli
62
+ info_name = []
63
+ parent = ctx.parent # start from top-level context
64
+ for part in path:
65
+ if not hasattr(cmd, "get_command"):
66
+ click.echo(cli.get_help(ctx)) # pragma: no cover
67
+ nxt_cmd = cmd.get_command(parent, part)
68
+ if nxt_cmd is None:
69
+ raise click.UsageError(f"Unknown command: {' '.join(path)}")
70
+ info_name.append(part)
71
+ cmd = nxt_cmd
72
+ parent = click.Context(cmd, info_name=part, parent=parent)
73
+
74
+ # Print help for the resolved command
75
+ click.echo(cmd.get_help(parent))
76
+
77
+
78
+ cli_main = cli
79
+
80
+ if __name__ == "__main__": # pragma: no cover
81
+ cli()
@@ -0,0 +1,151 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ from scipy.stats import spearmanr
4
+ from scipy.optimize import linear_sum_assignment
5
+ from hopcroftkarp import HopcroftKarp
6
+
7
+
8
+ def calc_rmsd(array1, array2):
9
+ """
10
+ Calculates the Root Mean Square Deviation (RMSD) between two arrays.
11
+ Parameters:
12
+ array1 (numpy.ndarray): The first array.
13
+ array2 (numpy.ndarray): The second array, must be of the same length as array1.
14
+
15
+ Returns:
16
+ float: The RMSD between the two arrays.
17
+ """
18
+ if len(array1) != len(array2):
19
+ raise ValueError("Arrays must be of the same length")
20
+ diff = array1 - array2
21
+ squared_diff = diff ** 2
22
+ mean_squared_diff = np.mean(squared_diff)
23
+ rmsd = np.sqrt(mean_squared_diff)
24
+
25
+ return rmsd
26
+
27
+
28
+ def matrix_spearman_alignment_linear(a, b, cutoff=0.0):
29
+ """
30
+ matrix_spearman_alignment_linear
31
+
32
+ Uses the linear_sum_assignment algorithm to create an optimal
33
+ mapping between two matrices by maximizing the total Spearman
34
+ correlation score.
35
+ """
36
+ # Identify overlapping columns
37
+ isect = a.columns.intersection(b.columns)
38
+
39
+ combined_df = pd.concat([a[isect], b[isect]], axis=0)
40
+ o = spearmanr(combined_df, axis=1)
41
+
42
+ a_count = a.shape[0]
43
+ sdf = pd.DataFrame(o.correlation[a_count:, :a_count], index=b.index, columns=a.index)
44
+
45
+ rows, cols = linear_sum_assignment(-sdf)
46
+
47
+ out_a = []
48
+ out_b = []
49
+ out_score = []
50
+
51
+ for r, c in zip(rows, cols):
52
+ score = sdf.iloc[r, c]
53
+ if score >= cutoff:
54
+ out_a.append(a.index[c])
55
+ out_b.append(b.index[r])
56
+ out_score.append(score)
57
+
58
+ return out_a, out_b, out_score
59
+
60
+
61
+ def matrix_spearman_alignment_hopkraft(a, b, cutoff=0.0):
62
+ """
63
+ matrix_spearman_alignment_hopkraft
64
+
65
+ Uses the HopcroftKarp maximum *cardinality* matching algorithm.
66
+ It finds the LARGEST NUMBER of matches, not the BEST (highest score)
67
+ match.
68
+
69
+ Note: This is fundamentally different from linear_sum_assignment.
70
+ """
71
+ isect = a.columns.intersection(b.columns)
72
+
73
+ combined_df = pd.concat([a[isect], b[isect]], axis=0)
74
+ o = spearmanr(combined_df, axis=1)
75
+
76
+ a_count = a.shape[0]
77
+ sdf = pd.DataFrame(o.correlation[a_count:, :a_count], index=b.index, columns=a.index)
78
+
79
+ m = {}
80
+ s_result = sdf.apply(lambda x: x.nlargest(10).index, axis=0)
81
+ for k, row in s_result.items():
82
+ m[k] = row.tolist()
83
+
84
+ id_map = HopcroftKarp(m).maximum_matching(keys_only=True)
85
+
86
+ out_a = []
87
+ out_b = []
88
+ out_score = []
89
+
90
+ for k, v in id_map.items():
91
+ c = sdf.loc[v, k]
92
+ if c >= cutoff:
93
+ out_a.append(k)
94
+ out_b.append(v)
95
+ out_score.append(c)
96
+
97
+ return out_a, out_b, out_score
98
+
99
+
100
+ def procrustes(X, Y):
101
+ """
102
+ Computes the Procrustes transformation (optimal PURE rotation)
103
+ to align X to Y, correcting for reflections.
104
+
105
+ Args:
106
+ X: The first matrix (N_points, N_dims).
107
+ Y: The second matrix (N_points, N_dims).
108
+
109
+ Returns:
110
+ R: The optimal rotation matrix (guaranteed det(R) = +1).
111
+ """
112
+ assert X.shape == Y.shape
113
+
114
+ M = np.dot(X.T, Y)
115
+
116
+ U, S, Vt = np.linalg.svd(M)
117
+
118
+ R = np.dot(U, Vt)
119
+
120
+ if np.linalg.det(R) < 0:
121
+ Vt_corrected = Vt.copy()
122
+ Vt_corrected[-1, :] *= -1
123
+ R = np.dot(U, Vt_corrected)
124
+
125
+ return R
126
+
127
+
128
+ def procrustes_scale(X, Y):
129
+ """
130
+ Compute the procrustes transformation (R), then compute a factor (k) to rescale the src matrix.
131
+
132
+ To apply transformtion:
133
+ src.dot(R) * k
134
+
135
+
136
+ Args:
137
+ X: The first matrix (N_points, N_dims).
138
+ Y: The second matrix (N_points, N_dims).
139
+
140
+ Returns:
141
+ R: The optimal rotation matrix (guaranteed det(R) = +1).
142
+ k: Scaling factor
143
+
144
+ """
145
+ R = procrustes(X,Y)
146
+ A = np.array(X.dot(R))
147
+ B = np.array(Y)
148
+ numerators = np.sum(A * B, axis=0)
149
+ denominators = np.sum(A * A, axis=0)
150
+ k = np.divide(numerators, denominators, out=np.zeros_like(numerators), where=denominators!=0)
151
+ return R, k
@@ -1,3 +1,10 @@
1
+
2
+ """
3
+ BMEG
4
+
5
+ Data retrieval from BMEG instance
6
+ """
7
+
1
8
  import gripql
2
9
 
3
10
  def connect(url="https://bmeg.io/grip", graph="rc6", cred_file="./bmeg_credentials.json"):
@@ -0,0 +1 @@
1
+ from .api import CBIOAPI
@@ -0,0 +1,13 @@
1
+ import requests
2
+
3
+
4
+ class CBIOAPI:
5
+
6
+ @staticmethod
7
+ def list_studies():
8
+ try:
9
+ studies = requests.get("https://www.cbioportal.org/api/studies").json()
10
+ return studies
11
+ except requests.RequestException as e:
12
+ print(f"Error fetching studies: {e}")
13
+ return None
@@ -0,0 +1,20 @@
1
+
2
+ """
3
+ Command Line Methods
4
+
5
+ embkit matrix <> : Matrix methods for normalization and transformation
6
+
7
+ embkit model <> : Methods of model training and application
8
+
9
+ embkit cbio <> : cBIO methods for data querying and download
10
+
11
+ """
12
+
13
+ from .model import model
14
+ from .matrix import matrix
15
+ from .cbio import cbio_cmd
16
+ from .datasets import datasets
17
+ from .protein import protein
18
+ from .align import align
19
+
20
+ __all__ = ["model", "matrix", "datasets", "protein"]
@@ -0,0 +1,35 @@
1
+ """
2
+
3
+ Command line tools for aligning embedding spaces
4
+
5
+ """
6
+
7
+ import click
8
+ import pandas as pd
9
+ from ..align import matrix_spearman_alignment_linear, matrix_spearman_alignment_hopkraft
10
+
11
+ align = click.Group(name="align", help="Embedding Alignment methods")
12
+
13
+ @align.command(name="pair")
14
+ @click.argument("matrix1")
15
+ @click.argument("matrix2")
16
+ @click.option("--method", "-m", required=False, type=str, default="linear")
17
+ @click.option("--cutoff", "-c", required=False, type=float, default=0.5)
18
+ def pair(matrix1, matrix2, method, cutoff):
19
+ """
20
+ Given two matrices, use feature rank correlation to
21
+ create list of pairs
22
+ """
23
+
24
+ m1 = pd.read_csv(matrix1, sep="\t", index_col=0)
25
+ m2 = pd.read_csv(matrix2, sep="\t", index_col=0)
26
+
27
+ if method == "hopkraft":
28
+ out = matrix_spearman_alignment_hopkraft(m1, m2)
29
+ for k, v in out.items():
30
+ print(f"{k}\t{v[0]}\t{v[1]}")
31
+
32
+ elif method == "linear":
33
+ out = matrix_spearman_alignment_linear(m1, m2, cutoff)
34
+ for k, v in out.items():
35
+ print(f"{k}\t{v[0]}\t{v[1]}")
@@ -0,0 +1,63 @@
1
+ import click
2
+ from ..datasets import CBIOPortal
3
+ from ..c_bio import CBIOAPI
4
+ import logging
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ cbio_cmd = click.Group(name="cbio", help="cBIO commands.")
9
+
10
+
11
+ @cbio_cmd.command(name="studies", help="List cbio studies.")
12
+ @click.pass_context
13
+ def list_studies(ctx):
14
+ """
15
+ Command to list available cBIO studies.
16
+
17
+ Parameters:
18
+ ctx: Click context object.
19
+
20
+ Returns:
21
+ None
22
+ """
23
+ api = CBIOAPI()
24
+ studies = api.list_studies()
25
+
26
+ if studies:
27
+ for study in studies:
28
+ click.echo(f"Study ID: {study['studyId']}, Name: {study['name']}")
29
+ else:
30
+ click.echo("No studies found or an error occurred while fetching studies.")
31
+
32
+
33
+ @cbio_cmd.command(name="download", help="Download cbio dataset.")
34
+ @click.option("--save_path", "-s", type=click.Path(exists=False, writable=True, path_type=str),
35
+ help="Path to save the dataset.")
36
+ @click.option("--study_id", "-si", type=str, show_default=True, help="Id of the study to download.")
37
+ @click.pass_context
38
+ def download_tmp(ctx, save_path: str | None, study_id: str):
39
+ """
40
+ Command to download a cBIO dataset by specifying the study ID.
41
+
42
+
43
+ Parameters:
44
+ ctx: Click context object.
45
+ save_path: Path to save the dataset.
46
+ study_id: ID of the study to download.
47
+
48
+ Returns:
49
+ None
50
+ """
51
+
52
+ if study_id is None:
53
+ click.echo("Study Id not specified. Please use -si option to specify the study id.")
54
+ return
55
+
56
+ cbio_portal: CBIOPortal = CBIOPortal(save_path=save_path, study_id=study_id, download=True)
57
+ cbio_portal.download()
58
+ cbio_portal.unpack()
59
+
60
+
61
+ # needed for testing
62
+ if __name__ == "__main__":
63
+ cbio_cmd() # pragma: no cover
@@ -0,0 +1,61 @@
1
+ import click
2
+ import pandas as pd
3
+ from ..preprocessing import load_raw_hugo, load_gct
4
+ from ..datasets import GTEx, Hugo, SIF
5
+
6
+ datasets = click.Group(name="datasets", help="Datasets commands.")
7
+
8
+
9
+ @datasets.command()
10
+ @click.option("--data_type", "-t", required=False, type=str, help="Name of the dataset to download.")
11
+ @click.option("--output_folder", "-f", required=True, type=str, help="The folder to download the dataset into.")
12
+ def gtex(data_type: str, output_folder: str):
13
+ """Download GTEx dataset."""
14
+
15
+ if data_type not in GTEx.NAMES:
16
+ click.echo(f"Dataset name '{data_type}' is not recognized. Available options are: {list(GTEx.NAMES.keys())}")
17
+ return
18
+
19
+ GTEx(data_type=data_type, save_path=output_folder)
20
+
21
+
22
+
23
+ @datasets.command()
24
+ @click.option("--output_folder", "-f", required=True, type=str, help="The folder to download the dataset into.")
25
+ def sif(output_folder: str):
26
+ """Download SIF dataset."""
27
+ SIF(save_path=output_folder)
28
+
29
+
30
+
31
+ @datasets.command()
32
+ @click.option("--output_folder", "-f", required=True, type=str, help="The folder to download the dataset into.")
33
+ @click.option("--gtex_conversion", "-gtex", required=False, is_flag=True, type=bool, default=False,
34
+ help="Whether to convert the hugo data to a gtex version.")
35
+ def hugo(gtex_conversion: bool, output_folder: str):
36
+ """Download Hugo dataset."""
37
+
38
+ click.echo(f"Downloading hugo dataset into '{output_folder}'")
39
+ hugo_data: Hugo = Hugo(save_path=output_folder)
40
+
41
+ if gtex_conversion:
42
+ click.echo("Converting hugo dataset using GTEx dataset...")
43
+ click.echo("Downloading required dataset (GTEx)...")
44
+ gtex_data: GTEx = GTEx(save_path=output_folder)
45
+ click.echo("Loading GTEx dataset...")
46
+ gtex_df: pd.DataFrame = load_gct(gtex_data)
47
+ click.echo("Loading Hugo dataset...")
48
+ hugo_df: pd.DataFrame = load_raw_hugo(hugo_data)
49
+
50
+ # select protein coding genes and build a dict that translates from ensembl gene id to Hugo name
51
+ gene_names = hugo_df[hugo_df["locus_group"] == "protein-coding gene"][["symbol", "ensembl_gene_id"]].set_index(
52
+ "ensembl_gene_id")["symbol"].to_dict()
53
+
54
+ # rename columns using HUGO names
55
+ df_select = gtex_df.rename(columns=lambda x: gene_names.get(x.split(".")[0], x))
56
+ # remove columns that aren't renamed (including all non-protein coding columns)
57
+ df_select = df_select.loc[:, df_select.columns.map(lambda x: not x.startswith("ENSG0"))]
58
+ output_path = f"{hugo_data.save_path}/gtex.hugo.tsv"
59
+ click.echo(f"Saving converted dataset to '{output_path}...'")
60
+ df_select.to_csv(output_path, sep="\t")
61
+ click.echo("Done.")
@@ -0,0 +1,36 @@
1
+ import click
2
+ import pandas as pd
3
+
4
+ matrix = click.Group(name="matrix", help="Model commands.")
5
+
6
+ @matrix.command()
7
+ @click.argument("srcs", nargs=-1)
8
+ @click.option("--out", "-o", required=True)
9
+ @click.option("--features", default=None, type=click.Path(exists=True, dir_okay=False, readable=True, path_type=str))
10
+ @click.option("--col-quantile", "col_quantile", default=False, is_flag=True)
11
+ @click.option("--quantile-max", "quantile_max", default=0.9, type=float)
12
+ @click.option("--precision", "-p", type=int, default=5)
13
+ def normalize(srcs, out, features, col_quantile, quantile_max, precision):
14
+
15
+ features_list = None
16
+ if features is not None:
17
+ features = []
18
+ with open(features, encoding="ascii") as handle:
19
+ features_list = list(line.rstrip() for line in handle)
20
+
21
+ dfs = []
22
+ for i in srcs:
23
+ df = pd.read_csv(i, sep="\t", index_col=0)
24
+ if features is not None:
25
+ df = df[features]
26
+ dfs.append(df)
27
+ if len(dfs) == 0:
28
+ click.echo("No matrices defined")
29
+ return
30
+ df = pd.concat( dfs )
31
+
32
+ if not col_quantile:
33
+ normDF = (df.transpose() / df.quantile(quantile_max, axis=1)).transpose().clip(upper=1.0, lower=0.0).fillna(0.0)
34
+ else:
35
+ normDF = (df / df.quantile(quantile_max)).clip(upper=1.0, lower=0.0).fillna(0.0)
36
+ normDF.round(decimals=precision).to_csv(out, sep="\t")