embkit 0.2__tar.gz → 0.3__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 (89) hide show
  1. {embkit-0.2 → embkit-0.3}/PKG-INFO +3 -1
  2. {embkit-0.2 → embkit-0.3}/pyproject.toml +5 -3
  3. {embkit-0.2 → embkit-0.3}/src/embkit/__init__.py +23 -8
  4. {embkit-0.2 → embkit-0.3}/src/embkit/__main__.py +14 -4
  5. {embkit-0.2 → embkit-0.3}/src/embkit/align.py +0 -41
  6. {embkit-0.2 → embkit-0.3}/src/embkit/commands/__init__.py +2 -2
  7. {embkit-0.2 → embkit-0.3}/src/embkit/commands/align.py +2 -7
  8. {embkit-0.2 → embkit-0.3}/src/embkit/commands/cbio.py +1 -1
  9. {embkit-0.2 → embkit-0.3}/src/embkit/commands/model.py +98 -85
  10. {embkit-0.2 → embkit-0.3}/src/embkit/commands/protein.py +21 -6
  11. embkit-0.2/src/embkit/commands/datasets.py → embkit-0.3/src/embkit/commands/resources.py +6 -6
  12. {embkit-0.2 → embkit-0.3}/src/embkit/constraints/network_constraint.py +19 -1
  13. embkit-0.3/src/embkit/datasets/__init__.py +51 -0
  14. embkit-0.3/src/embkit/encoding/__init__.py +155 -0
  15. embkit-0.3/src/embkit/encoding/protein.py +98 -0
  16. {embkit-0.2 → embkit-0.3}/src/embkit/estimator/vae_estimator.py +2 -2
  17. embkit-0.3/src/embkit/factory/__init__.py +17 -0
  18. embkit-0.3/src/embkit/factory/core.py +46 -0
  19. embkit-0.3/src/embkit/factory/layers.py +253 -0
  20. embkit-0.3/src/embkit/factory/mapping.py +117 -0
  21. embkit-0.3/src/embkit/factory/registry.py +71 -0
  22. embkit-0.3/src/embkit/files/__init__.py +3 -0
  23. embkit-0.3/src/embkit/files/h5.py +131 -0
  24. embkit-0.3/src/embkit/files/json.py +20 -0
  25. {embkit-0.2/src/embkit/file_readers → embkit-0.3/src/embkit/files}/read_csv.py +57 -47
  26. {embkit-0.2 → embkit-0.3}/src/embkit/losses/vae_loss.py +6 -5
  27. embkit-0.3/src/embkit/models/ffnn.py +50 -0
  28. embkit-0.3/src/embkit/models/vae/base_vae.py +112 -0
  29. embkit-0.3/src/embkit/models/vae/decoder.py +84 -0
  30. {embkit-0.2 → embkit-0.3}/src/embkit/models/vae/encoder.py +57 -37
  31. embkit-0.3/src/embkit/models/vae/net_vae.py +115 -0
  32. {embkit-0.2 → embkit-0.3}/src/embkit/models/vae/rna_vae.py +5 -5
  33. embkit-0.3/src/embkit/models/vae/vae.py +102 -0
  34. embkit-0.3/src/embkit/modules/__init__.py +18 -0
  35. {embkit-0.2/src/embkit/layers → embkit-0.3/src/embkit/modules}/masked_linear.py +2 -2
  36. {embkit-0.2/src/embkit/layers → embkit-0.3/src/embkit/modules}/tsp.py +3 -3
  37. embkit-0.3/src/embkit/optimize/__init__.py +504 -0
  38. {embkit-0.2 → embkit-0.3}/src/embkit/pathway.py +50 -0
  39. {embkit-0.2 → embkit-0.3}/src/embkit/preprocessing/__init__.py +2 -2
  40. embkit-0.3/src/embkit/preprocessing/dataset.py +35 -0
  41. {embkit-0.2 → embkit-0.3}/src/embkit/preprocessing/normalize.py +35 -4
  42. {embkit-0.2/src/embkit/datasets → embkit-0.3/src/embkit/resources}/c_bio_portal.py +4 -3
  43. {embkit-0.2/src/embkit/datasets → embkit-0.3/src/embkit/resources}/gtex.py +2 -2
  44. {embkit-0.2/src/embkit/datasets → embkit-0.3/src/embkit/resources}/hugo.py +1 -1
  45. embkit-0.2/src/embkit/datasets/dataset.py → embkit-0.3/src/embkit/resources/resource.py +24 -20
  46. {embkit-0.2/src/embkit/datasets → embkit-0.3/src/embkit/resources}/sif.py +1 -1
  47. {embkit-0.2 → embkit-0.3}/src/embkit/utilities/kmeans.py +1 -1
  48. {embkit-0.2 → embkit-0.3}/src/embkit/utilities/pca.py +1 -1
  49. embkit-0.3/src/embkit/version.py +62 -0
  50. {embkit-0.2 → embkit-0.3}/src/embkit.egg-info/PKG-INFO +3 -1
  51. {embkit-0.2 → embkit-0.3}/src/embkit.egg-info/SOURCES.txt +27 -20
  52. {embkit-0.2 → embkit-0.3}/src/embkit.egg-info/requires.txt +2 -0
  53. {embkit-0.2 → embkit-0.3}/tests/test_main.py +29 -0
  54. embkit-0.2/src/embkit/file_readers/__init__.py +0 -1
  55. embkit-0.2/src/embkit/layers/__init__.py +0 -33
  56. embkit-0.2/src/embkit/layers/constraint_info.py +0 -111
  57. embkit-0.2/src/embkit/layers/layer_info.py +0 -108
  58. embkit-0.2/src/embkit/models/ffnn.py +0 -151
  59. embkit-0.2/src/embkit/models/hla2vec.py +0 -307
  60. embkit-0.2/src/embkit/models/protein.py +0 -175
  61. embkit-0.2/src/embkit/models/vae/base_vae.py +0 -327
  62. embkit-0.2/src/embkit/models/vae/decoder.py +0 -58
  63. embkit-0.2/src/embkit/models/vae/hla2vec.py +0 -307
  64. embkit-0.2/src/embkit/models/vae/net_vae.py +0 -192
  65. embkit-0.2/src/embkit/models/vae/pytorch.py +0 -150
  66. embkit-0.2/src/embkit/models/vae/vae.py +0 -218
  67. {embkit-0.2 → embkit-0.3}/README.md +0 -0
  68. {embkit-0.2 → embkit-0.3}/setup.cfg +0 -0
  69. {embkit-0.2 → embkit-0.3}/setup.py +0 -0
  70. {embkit-0.2 → embkit-0.3}/src/embkit/bmeg.py +0 -0
  71. {embkit-0.2 → embkit-0.3}/src/embkit/c_bio/__init__.py +0 -0
  72. {embkit-0.2 → embkit-0.3}/src/embkit/c_bio/api.py +0 -0
  73. {embkit-0.2 → embkit-0.3}/src/embkit/commands/matrix.py +0 -0
  74. {embkit-0.2 → embkit-0.3}/src/embkit/constraints/__init__.py +0 -0
  75. {embkit-0.2 → embkit-0.3}/src/embkit/estimator/__init__.py +0 -0
  76. {embkit-0.2/src/embkit/preprocessing → embkit-0.3/src/embkit/files}/loaders.py +0 -0
  77. {embkit-0.2 → embkit-0.3}/src/embkit/losses/__init__.py +0 -0
  78. {embkit-0.2 → embkit-0.3}/src/embkit/metrics/__init__.py +0 -0
  79. {embkit-0.2 → embkit-0.3}/src/embkit/metrics/distance/__init__.py +0 -0
  80. {embkit-0.2 → embkit-0.3}/src/embkit/metrics/distance/metrics.py +0 -0
  81. {embkit-0.2 → embkit-0.3}/src/embkit/models/__init__.py +0 -0
  82. {embkit-0.2 → embkit-0.3}/src/embkit/models/vae/__init__.py +0 -0
  83. {embkit-0.2/src/embkit/layers → embkit-0.3/src/embkit/modules}/pairwise_comparison_layer.py +0 -0
  84. {embkit-0.2/src/embkit/datasets → embkit-0.3/src/embkit/resources}/__init__.py +0 -0
  85. {embkit-0.2/src/embkit/datasets → embkit-0.3/src/embkit/resources}/util.py +0 -0
  86. {embkit-0.2 → embkit-0.3}/src/embkit/utilities/__init__.py +0 -0
  87. {embkit-0.2 → embkit-0.3}/src/embkit.egg-info/dependency_links.txt +0 -0
  88. {embkit-0.2 → embkit-0.3}/src/embkit.egg-info/entry_points.txt +0 -0
  89. {embkit-0.2 → embkit-0.3}/src/embkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: embkit
3
- Version: 0.2
3
+ Version: 0.3
4
4
  Summary: Embedding Kit for embedding models
5
5
  Author-email: Kyle Ellrott <ellrott@ohsu.edu>, Raphael Kirchgaessner <kirchgae@ohsu.edu>
6
6
  License: MIT
@@ -17,6 +17,8 @@ Requires-Dist: gripql
17
17
  Requires-Dist: tqdm
18
18
  Requires-Dist: biopython
19
19
  Requires-Dist: fair-esm
20
+ Requires-Dist: faiss-cpu
21
+ Requires-Dist: h5py
20
22
 
21
23
 
22
24
  # Embedding Kit
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "embkit"
7
- version = "0.2"
7
+ version = "0.3"
8
8
  description = "Embedding Kit for embedding models"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -24,7 +24,9 @@ dependencies = [
24
24
  "gripql",
25
25
  "tqdm",
26
26
  "biopython",
27
- "fair-esm"
27
+ "fair-esm",
28
+ "faiss-cpu",
29
+ "h5py"
28
30
  ]
29
31
 
30
32
  [tool.setuptools]
@@ -34,4 +36,4 @@ package-dir = { "" = "src" }
34
36
  where = ["src"]
35
37
 
36
38
  [project.scripts]
37
- embkit = "embkit.__main__:cli"
39
+ embkit = "embkit.__main__:cli"
@@ -24,7 +24,7 @@ def get_device() -> torch.device:
24
24
  logger.info("Using CPU")
25
25
  return torch.device("cpu")
26
26
 
27
- def dataframe_tensor(df: pd.DataFrame,device=None) -> torch.Tensor:
27
+ def dataframe_tensor(df: pd.DataFrame, device=None, dtype=torch.float32) -> torch.Tensor:
28
28
  """
29
29
  dataframe_tensor
30
30
 
@@ -32,7 +32,7 @@ def dataframe_tensor(df: pd.DataFrame,device=None) -> torch.Tensor:
32
32
  """
33
33
  if device is None:
34
34
  device = get_device()
35
- return torch.from_numpy(df.values.astype(np.float32)).to(device)
35
+ return torch.from_numpy(df.to_numpy(copy=True)).to(device=device, dtype=dtype)
36
36
 
37
37
  def tensor_dataframe(tn: torch.Tensor, index=None, columns=None) -> pd.DataFrame:
38
38
  """
@@ -40,11 +40,29 @@ def tensor_dataframe(tn: torch.Tensor, index=None, columns=None) -> pd.DataFrame
40
40
 
41
41
  take a torch tensor, create a pandas dataframe
42
42
  """
43
- return pd.DataFrame(tn.cpu().detach().numpy(), index=index, columns=columns)
43
+ return pd.DataFrame(tn.to(device="cpu", dtype=torch.float32).detach().numpy(), index=index, columns=columns)
44
+
45
+ def dataframe_dataset(df: pd.DataFrame, device=None, dtype=torch.float32) -> torch.utils.data.Dataset:
46
+ """
47
+ dataframe_dataset
48
+
49
+ take a pandas dataframe and return a pytorch dataset
50
+
51
+ :param df: Input pandas Dataframe
52
+ :type df: pd.DataFrame
53
+ :param device: Device to put torch tensors on
54
+ :return: Description
55
+ :rtype: Dataset
56
+ """
57
+ if device is None:
58
+ device = get_device()
59
+ x = torch.from_numpy(df.to_numpy(copy=True)).to(device=device, dtype=dtype)
60
+ dataset = TensorDataset(x)
61
+ return dataset
44
62
 
45
63
  def dataframe_loader(df: pd.DataFrame,
46
64
  batch_size = 256, shuffle=True,
47
- device=None) -> torch.utils.data.DataLoader:
65
+ device=None, dtype=torch.float32) -> torch.utils.data.DataLoader:
48
66
  """
49
67
  dataframe_loader
50
68
 
@@ -54,9 +72,6 @@ def dataframe_loader(df: pd.DataFrame,
54
72
  :param device: Device the where tensor should be moved. If None, use get_device
55
73
  """
56
74
 
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)
75
+ dataset = dataframe_dataset(df, device=device, dtype=dtype)
61
76
  data_loader = DataLoader(dataset, batch_size=batch_size, shuffle=shuffle)
62
77
  return data_loader
@@ -1,12 +1,15 @@
1
1
  import click
2
2
  import logging
3
3
 
4
- from .commands import model, matrix, cbio_cmd, protein, datasets, align
4
+ from embkit.version import get_version
5
+
6
+ from .commands import model, matrix, cbio_cmd, protein, resources, align
5
7
 
6
8
  @click.group(invoke_without_command=True)
7
9
  @click.option('--verbose', is_flag=True, help="Enable verbose logging")
10
+ @click.option('--version', is_flag=True, help="Show version information")
8
11
  @click.pass_context
9
- def cli(ctx, verbose):
12
+ def cli(ctx, verbose, version):
10
13
  """Embedding Kit CLI.
11
14
 
12
15
  Use 'embkit help [COMMAND]' for details on a specific command.
@@ -20,6 +23,10 @@ def cli(ctx, verbose):
20
23
  ctx.ensure_object(dict)
21
24
  ctx.obj["VERBOSE"] = verbose
22
25
 
26
+ if version:
27
+ click.echo(get_version())
28
+ ctx.exit()
29
+
23
30
  if ctx.invoked_subcommand is None:
24
31
  click.echo(ctx.get_help())
25
32
 
@@ -29,7 +36,7 @@ cli.add_command(model)
29
36
  cli.add_command(matrix)
30
37
  cli.add_command(cbio_cmd)
31
38
  cli.add_command(protein)
32
- cli.add_command(datasets)
39
+ cli.add_command(resources)
33
40
  cli.add_command(align)
34
41
 
35
42
 
@@ -62,11 +69,14 @@ def help_cmd(ctx, path):
62
69
  info_name = []
63
70
  parent = ctx.parent # start from top-level context
64
71
  for part in path:
65
- if not hasattr(cmd, "get_command"):
72
+ if not isinstance(cmd, click.Group):
66
73
  click.echo(cli.get_help(ctx)) # pragma: no cover
74
+ return
75
+
67
76
  nxt_cmd = cmd.get_command(parent, part)
68
77
  if nxt_cmd is None:
69
78
  raise click.UsageError(f"Unknown command: {' '.join(path)}")
79
+
70
80
  info_name.append(part)
71
81
  cmd = nxt_cmd
72
82
  parent = click.Context(cmd, info_name=part, parent=parent)
@@ -2,8 +2,6 @@ import numpy as np
2
2
  import pandas as pd
3
3
  from scipy.stats import spearmanr
4
4
  from scipy.optimize import linear_sum_assignment
5
- from hopcroftkarp import HopcroftKarp
6
-
7
5
 
8
6
  def calc_rmsd(array1, array2):
9
7
  """
@@ -58,45 +56,6 @@ def matrix_spearman_alignment_linear(a, b, cutoff=0.0):
58
56
  return out_a, out_b, out_score
59
57
 
60
58
 
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
59
  def procrustes(X, Y):
101
60
  """
102
61
  Computes the Procrustes transformation (optimal PURE rotation)
@@ -13,8 +13,8 @@ embkit cbio <> : cBIO methods for data querying and download
13
13
  from .model import model
14
14
  from .matrix import matrix
15
15
  from .cbio import cbio_cmd
16
- from .datasets import datasets
16
+ from .resources import resources
17
17
  from .protein import protein
18
18
  from .align import align
19
19
 
20
- __all__ = ["model", "matrix", "datasets", "protein"]
20
+ __all__ = ["model", "matrix", "resources", "protein"]
@@ -6,7 +6,7 @@ Command line tools for aligning embedding spaces
6
6
 
7
7
  import click
8
8
  import pandas as pd
9
- from ..align import matrix_spearman_alignment_linear, matrix_spearman_alignment_hopkraft
9
+ from ..align import matrix_spearman_alignment_linear
10
10
 
11
11
  align = click.Group(name="align", help="Embedding Alignment methods")
12
12
 
@@ -24,12 +24,7 @@ def pair(matrix1, matrix2, method, cutoff):
24
24
  m1 = pd.read_csv(matrix1, sep="\t", index_col=0)
25
25
  m2 = pd.read_csv(matrix2, sep="\t", index_col=0)
26
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":
27
+ if method == "linear":
33
28
  out = matrix_spearman_alignment_linear(m1, m2, cutoff)
34
29
  for k, v in out.items():
35
30
  print(f"{k}\t{v[0]}\t{v[1]}")
@@ -1,5 +1,5 @@
1
1
  import click
2
- from ..datasets import CBIOPortal
2
+ from ..resources import CBIOPortal
3
3
  from ..c_bio import CBIOAPI
4
4
  import logging
5
5
 
@@ -1,15 +1,20 @@
1
1
 
2
2
  import click
3
3
  import pandas as pd
4
- import numpy as np
5
- import torch
6
4
 
7
5
  from sklearn.preprocessing import MinMaxScaler
8
6
 
9
- from .. import dataframe_loader, dataframe_tensor, get_device
10
- from ..layers import LayerInfo, build_layers, ConstraintInfo
11
- from ..models.vae.vae import VAE, BaseVAE
12
- from ..preprocessing import ExpMinMaxScaler
7
+ import torch
8
+ from torch.utils.data import DataLoader
9
+
10
+ from .. import dataframe_loader, dataframe_tensor, get_device, dataframe_dataset
11
+ from ..files import H5Reader
12
+ from ..factory import save, load
13
+ from ..factory.layers import Layer, LayerList, ConstraintInfo
14
+ from ..optimize import fit_vae
15
+ from ..models.vae.vae import VAE
16
+ from ..preprocessing import ExpMinMaxScaler, get_dataset_nonzero_mask
17
+ from ..datasets import DatasetMask
13
18
  from ..losses import bce_with_logits, bce, mse
14
19
  from ..pathway import extract_pathway_interactions, feature_map_intersect, FeatureGroups
15
20
 
@@ -17,57 +22,95 @@ model = click.Group(name="model", help="VAE Model commands.")
17
22
 
18
23
  @model.command()
19
24
  @click.argument("input_path", type=click.Path(exists=True, dir_okay=False, readable=True, path_type=str))
25
+ @click.option("--group", "-g", default=None, help="HD5F group name")
20
26
  @click.option("--latent", "-l", type=int, default=256, show_default=True, help="Latent dimension size.")
21
27
  @click.option("--epochs", "-e", type=int, default=20, show_default=True, help="Training epochs.")
28
+ @click.option("--batch-size", "-b", type=int, default=256)
22
29
  @click.option("--encode-layers", type=str, default="400,200")
23
30
  @click.option("--decode-layers", type=str, default="200,400")
24
31
  @click.option("--normalize", "-n", type=str, default="none")
32
+ @click.option("--final-activation", default="none", type=click.Choice(["none", "sigmoid", "relu"]))
25
33
  @click.option("--learning-rate", "-r", type=float, default=0.0001)
26
34
  @click.option("--out", "-o", type=str, default=None)
27
35
  @click.option("--schedule", "-s", type=str, default=None, help="20:0,20:0.1,40:.3,40:.4")
28
36
  @click.option("--loss", type=click.Choice(["mse", "bce", "bce-logit"]), default="bce-logit")
29
37
  @click.option("--save-stats", is_flag=True)
30
- def train_vae(input_path: str, latent: int,
31
- epochs: int, out: str, normalize:str,
38
+ @click.option("--zero-mask", default=None, type=float)
39
+ @click.option("--seed", default=42, type=int)
40
+ @click.option("--bfloat16", is_flag=True)
41
+ def train_vae(input_path: str,
42
+ group: str,
43
+ latent: int,
44
+ epochs: int,
45
+ batch_size: int,
46
+ out: str, normalize:str,
32
47
  encode_layers:str, decode_layers:str,
33
48
  learning_rate: float,
49
+ final_activation: str,
34
50
  loss: str,
35
- schedule:str,
36
- save_stats: bool
51
+ schedule:str,
52
+ zero_mask: float,
53
+ save_stats: bool,
54
+ seed: int,
55
+ bfloat16: bool
37
56
  ):
38
- """Train VAE model from a TSV file."""
39
- df = pd.read_csv(input_path, sep="\t", index_col=0)
57
+ """
58
+ Train VAE model from a TSV file.
59
+ """
60
+ device = get_device()
61
+ dtype = torch.float32
62
+ if bfloat16:
63
+ dtype = torch.bfloat16
40
64
 
41
- if normalize == "expMinMax":
42
- norm = ExpMinMaxScaler()
43
- norm.fit(df)
44
- df = pd.DataFrame( norm.transform(df), index=df.index, columns=df.columns)
45
- elif normalize == "minMax":
46
- norm = MinMaxScaler()
47
- norm.fit(df)
48
- df = pd.DataFrame( norm.transform(df), index=df.index, columns=df.columns)
49
-
50
-
51
- feature_count = len(df.columns)
65
+ torch.manual_seed(seed)
66
+ df = None
67
+ if group is not None:
68
+ dataset = H5Reader(input_path, group)
69
+ #TODO add normalization here
70
+ if zero_mask is not None:
71
+ dataset_mask = get_dataset_nonzero_mask(dataset, zero_mask)
72
+ mask = dataset_mask[0].cpu().numpy()
73
+ #print(mask)
74
+ features = dataset.columns[mask]
75
+ dataset = DatasetMask(dataset, dataset_mask, device)
76
+ else:
77
+ dataset.to(device)
78
+ features = dataset.columns
79
+
80
+ else:
81
+ df = pd.read_csv(input_path, sep="\t", index_col=0)
82
+
83
+ if normalize == "expMinMax":
84
+ norm = ExpMinMaxScaler()
85
+ norm.fit(df)
86
+ df = pd.DataFrame( norm.transform(df), index=df.index, columns=df.columns)
87
+ elif normalize == "minMax":
88
+ norm = MinMaxScaler()
89
+ norm.fit(df)
90
+ df = pd.DataFrame( norm.transform(df), index=df.index, columns=df.columns)
91
+ features = df.columns
92
+ dataset = dataframe_dataset(df, device=device, dtype=dtype)
93
+
94
+ dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
95
+
52
96
 
53
97
  layer_sizes = list( int(i) for i in encode_layers.split(",") )
54
- layer_sizes.append(latent)
55
- enc_layers = build_layers( layer_sizes )
98
+ enc_layers_list = LayerList( layer_sizes )
56
99
 
57
100
  layer_sizes = list( int(i) for i in decode_layers.split(",") )
58
- layer_sizes.append(feature_count)
59
- dec_layers = build_layers( layer_sizes, end_activation="none" )
101
+ dec_layers_list = LayerList( layer_sizes, end_activation=final_activation )
60
102
 
61
103
  beta_schedule = None
62
104
  if schedule is not None:
63
- beta_schedule = [] #[(0.0, 20), (0.1, 20), (0.3, 40), (0.4, 40)]
105
+ beta_schedule = []
64
106
  for b in schedule.split(","):
65
107
  e, b = b.split(":")
66
108
  beta_schedule.append( (float(b), int(e)) )
67
- vae = VAE(features=df.columns,
109
+ vae = VAE(features=features,
68
110
  latent_dim=latent,
69
- encoder_layers=enc_layers,
70
- decoder_layers=dec_layers)
111
+ encoder_layers=enc_layers_list,
112
+ decoder_layers=dec_layers_list,
113
+ device=device, dtype=dtype)
71
114
 
72
115
  loss_func = bce_with_logits
73
116
  if loss == "mse":
@@ -75,7 +118,7 @@ def train_vae(input_path: str, latent: int,
75
118
  elif loss == "bce":
76
119
  loss_func = bce
77
120
 
78
- vae.fit(df, epochs=epochs,
121
+ fit_vae(vae, dataloader, epochs=epochs,
79
122
  beta_schedule=beta_schedule, lr=learning_rate, loss=loss_func)
80
123
  click.echo("Training complete.")
81
124
 
@@ -83,11 +126,7 @@ def train_vae(input_path: str, latent: int,
83
126
  click.echo(f"No output path provided, using default naming.")
84
127
  out = f"vae_latent{latent}_epochs{epochs}.model"
85
128
 
86
- if save_stats:
87
- vae.save(out, df)
88
- else:
89
- vae.save(out)
90
-
129
+ save(vae, out)
91
130
  click.echo(f"Model saved, to {out}")
92
131
 
93
132
 
@@ -133,15 +172,15 @@ def train_netvae(input_path: str, pathway_sif:str, out:str,
133
172
  gcounts = [5,2,1]
134
173
 
135
174
  enc_layers = [
136
- LayerInfo(group_count*gcounts[0], op="masked_linear", constraint=ConstraintInfo("features-to-group", fmap, out_group_count=gcounts[0])),
137
- LayerInfo(group_count*gcounts[1], op="masked_linear", constraint=ConstraintInfo("group-to-group", fmap, in_group_count=gcounts[0], out_group_count=gcounts[1])),
138
- LayerInfo(group_count, op="masked_linear", constraint=ConstraintInfo("group-to-group", fmap, in_group_count=gcounts[1], out_group_count=gcounts[2]))
175
+ Layer(group_count*gcounts[0], op="masked_linear", constraint=ConstraintInfo("features-to-group", fmap, out_group_count=gcounts[0])),
176
+ Layer(group_count*gcounts[1], op="masked_linear", constraint=ConstraintInfo("group-to-group", fmap, in_group_count=gcounts[0], out_group_count=gcounts[1])),
177
+ Layer(group_count, op="masked_linear", constraint=ConstraintInfo("group-to-group", fmap, in_group_count=gcounts[1], out_group_count=gcounts[2]))
139
178
  ]
140
179
 
141
180
  dec_layers = [
142
- LayerInfo(group_count*gcounts[1], op="masked_linear", constraint=ConstraintInfo("group-to-group", fmap, in_group_count=gcounts[2], out_group_count=gcounts[1])),
143
- LayerInfo(group_count*gcounts[0], op="masked_linear", constraint=ConstraintInfo("group-to-group", fmap, in_group_count=gcounts[1], out_group_count=gcounts[0])),
144
- LayerInfo(feature_count, op="masked_linear", constraint=ConstraintInfo("group-to-features", fmap, in_group_count=gcounts[0]), activation="none")
181
+ Layer(group_count*gcounts[1], op="masked_linear", constraint=ConstraintInfo("group-to-group", fmap, in_group_count=gcounts[2], out_group_count=gcounts[1])),
182
+ Layer(group_count*gcounts[0], op="masked_linear", constraint=ConstraintInfo("group-to-group", fmap, in_group_count=gcounts[1], out_group_count=gcounts[0])),
183
+ Layer(feature_count, op="masked_linear", constraint=ConstraintInfo("group-to-features", fmap, in_group_count=gcounts[0]), activation="none")
145
184
  ]
146
185
 
147
186
  loss_func = bce_with_logits
@@ -150,18 +189,24 @@ def train_netvae(input_path: str, pathway_sif:str, out:str,
150
189
  elif loss == "bce":
151
190
  loss_func = bce
152
191
 
153
-
154
- #schedule = [(0.0, 20), (0.1, 20), (0.3, 40), (0.4, 40)]
155
- schedule = [(0.0, 20)]
156
- vae = VAE(df.columns, latent_dim=group_count, encoder_layers=enc_layers, decoder_layers=dec_layers)
157
- vae.fit(X=dataloader, beta_schedule=schedule, lr=learning_rate, loss=loss_func)
192
+ schedule = [(0.0, epochs)]
193
+ vae = VAE(list(df.columns), latent_dim=group_count, encoder_layers=enc_layers, decoder_layers=dec_layers)
194
+ fit_vae(vae, X=dataloader, beta_schedule=schedule, lr=learning_rate, loss=loss_func)
158
195
 
159
196
  click.echo("Training complete.")
160
197
 
198
+ if out is None:
199
+ click.echo("No output path provided, using default naming.")
200
+ out = f"netvae_latent{group_count}_epochs{epochs}.model"
201
+
202
+ save(vae, out)
203
+ click.echo(f"Model saved, to {out}")
204
+
161
205
  if save_stats:
162
- vae.save(out, df)
163
- else:
164
- vae.save(out)
206
+ stats = pd.DataFrame({"mean": df.mean(), "std": df.std(ddof=0)})
207
+ stats_path = f"{out}.stats.tsv"
208
+ stats.to_csv(stats_path, sep="\t")
209
+ click.echo(f"Stats saved, to {stats_path}")
165
210
 
166
211
  @model.command()
167
212
  @click.argument("input_path", type=click.Path(exists=True, dir_okay=False, readable=True, path_type=str))
@@ -169,11 +214,9 @@ def train_netvae(input_path: str, pathway_sif:str, out:str,
169
214
  @click.option("--normalize", "-n", type=str, default="none")
170
215
  @click.option("--out", "-o", type=str, default="embedding.tsv")
171
216
  def encode(input_path: str, model_path:str, normalize:str, out:str):
172
- m = VAE.open_model(path=model_path)
173
- df = pd.read_csv(input_path, sep="\t", index_col=0)
174
217
 
175
- # print(m)
176
- # df = pd.read_csv(input_path, sep="\t", index_col=0)
218
+ m = load(model_path)
219
+ df = pd.read_csv(input_path, sep="\t", index_col=0)
177
220
 
178
221
  df = df[m.features]
179
222
  if normalize == "expMinMax":
@@ -188,33 +231,3 @@ def encode(input_path: str, model_path:str, normalize:str, out:str):
188
231
  martix = result[2].detach().cpu().numpy()
189
232
  out_df = pd.DataFrame(martix, index=df.index)
190
233
  out_df.to_csv(out, sep="\t")
191
-
192
- @model.command()
193
- @click.argument("h5", type=str)
194
- @click.option("--epochs", "-e", type=int, default=5, show_default=True, help="Training epochs")
195
- @click.option("--batch-size", type=int, default=1024, show_default=True, help="Batch Size")
196
- @click.option("--learning-rate", type=float, default=1e-3, show_default=True, help="Learning Rate")
197
- @click.option("--seed", type=int, default=42, show_default=True, help="Batch Size")
198
- @click.option("--embedding-dim", type=int, default=64)
199
- def train_hla2vec(h5:str, epochs:int, batch_size:int, learning_rate:float, seed:int, embedding_dim:int):
200
-
201
- #TODO: this should be put into a library function
202
- np.random.seed(seed)
203
- if torch.cuda.is_available():
204
- torch.cuda.manual_seed_all(seed)
205
- torch.manual_seed(seed)
206
-
207
- data = load_bigmhc(h5)
208
-
209
- model, history = fit_hla2vec(
210
- **data,
211
- emb_dim=embedding_dim,
212
- batch_size=batch_size,
213
- epochs=epochs,
214
- lr=learning_rate,
215
- seed=seed,
216
- )
217
-
218
- print("Final epoch:", history[-1])
219
- torch.save(model.state_dict(), "hla2vec_demo.pt")
220
- print("Saved weights -> hla2vec_demo.pt")
@@ -5,10 +5,14 @@ import re
5
5
  import sys
6
6
  from typing import List
7
7
  import click
8
+ import json
9
+ from ..files.json import StringTrimEncoder
8
10
  from Bio import SeqIO
9
11
 
12
+ import torch
13
+
10
14
  from .. import get_device
11
- from ..models.protein import ProteinEncoder
15
+ from ..encoding.protein import ProteinEncoder
12
16
 
13
17
 
14
18
  protein = click.Group(name="protein", help="Protein commands.")
@@ -37,9 +41,10 @@ def stringify(l:List[float], trim=None) -> List[str]:
37
41
  @click.option("--batch-size", type=int, default=128)
38
42
  @click.option("--trim", type=int, default=None)
39
43
  @click.option("--model", "-m", type=click.Choice(['t6', 't12', 't30', 't33', 't36', 't48']), default="t33")
40
- @click.option("--pool", "-p", type=click.Choice(["mean", "sum"]), default="mean")
44
+ @click.option("--pool", "-p", type=click.Choice(["mean", "sum", "none"]), default="mean")
41
45
  @click.option("--output", "-o", type=str, default=None)
42
- def encode(fasta: str, filter:str, batch_size:int, model:str, trim:int, pool:str, output:str):
46
+ @click.option("--fix-len", type=int, default=None)
47
+ def encode(fasta: str, filter:str, batch_size:int, model:str, trim:int, pool:str, output:str, fix_len):
43
48
  pool_map = {
44
49
  "mean" : "mean-pool",
45
50
  "sum" : "sum-pool"
@@ -50,7 +55,17 @@ def encode(fasta: str, filter:str, batch_size:int, model:str, trim:int, pool:str
50
55
 
51
56
  enc = ProteinEncoder(batch_size=batch_size, model=model)
52
57
  enc.to(get_device())
53
- for i, emb in enc.encode(fasta_reader(fasta, filter=filter), output=pool_map[pool]):
54
- out.write( f"{i}\t" + "\t".join(stringify(emb.tolist(), trim)))
55
- out.write("\n")
58
+ if pool == "none":
59
+ for i, emb in enc.encode(fasta_reader(fasta, filter=filter), output="vector", fix_len=fix_len):
60
+ out.write(f"{i}\t")
61
+ if trim:
62
+ out.write(json.dumps(emb, cls=StringTrimEncoder, trim=trim ))
63
+ else:
64
+ out.write(json.dumps(emb.tolist()))
65
+ #out.write( f"{i}\t" + "\t".join(stringify(emb.tolist(), trim)))
66
+ out.write("\n")
67
+ else:
68
+ for i, emb in enc.encode(fasta_reader(fasta, filter=filter), output=pool_map[pool]):
69
+ out.write( f"{i}\t" + "\t".join(stringify(emb.tolist(), trim)))
70
+ out.write("\n")
56
71
  out.close()
@@ -1,12 +1,12 @@
1
1
  import click
2
2
  import pandas as pd
3
- from ..preprocessing import load_raw_hugo, load_gct
4
- from ..datasets import GTEx, Hugo, SIF
3
+ from ..files import load_raw_hugo, load_gct
4
+ from ..resources import GTEx, Hugo, SIF
5
5
 
6
- datasets = click.Group(name="datasets", help="Datasets commands.")
6
+ resources = click.Group(name="resources", help="Resource commands.")
7
7
 
8
8
 
9
- @datasets.command()
9
+ @resources.command()
10
10
  @click.option("--data_type", "-t", required=False, type=str, help="Name of the dataset to download.")
11
11
  @click.option("--output_folder", "-f", required=True, type=str, help="The folder to download the dataset into.")
12
12
  def gtex(data_type: str, output_folder: str):
@@ -20,7 +20,7 @@ def gtex(data_type: str, output_folder: str):
20
20
 
21
21
 
22
22
 
23
- @datasets.command()
23
+ @resources.command()
24
24
  @click.option("--output_folder", "-f", required=True, type=str, help="The folder to download the dataset into.")
25
25
  def sif(output_folder: str):
26
26
  """Download SIF dataset."""
@@ -28,7 +28,7 @@ def sif(output_folder: str):
28
28
 
29
29
 
30
30
 
31
- @datasets.command()
31
+ @resources.command()
32
32
  @click.option("--output_folder", "-f", required=True, type=str, help="The folder to download the dataset into.")
33
33
  @click.option("--gtex_conversion", "-gtex", required=False, is_flag=True, type=bool, default=False,
34
34
  help="Whether to convert the hugo data to a gtex version.")
@@ -51,4 +51,22 @@ class NetworkConstraint:
51
51
  self._mask_np = mask
52
52
 
53
53
  def as_torch(self, device: torch.device) -> torch.Tensor:
54
- return torch.tensor(self._mask_np, device=device)
54
+ return torch.tensor(self._mask_np, device=device)
55
+
56
+ def to_dict(self) -> dict:
57
+ return {
58
+ "feature_index": self.feature_index,
59
+ "latent_index": self.latent_index,
60
+ "latent_membership": self.latent_membership,
61
+ "active": self.active,
62
+ }
63
+
64
+ @classmethod
65
+ def from_dict(cls, d: dict) -> "NetworkConstraint":
66
+ obj = cls(
67
+ feature_index=d["feature_index"],
68
+ latent_index=d["latent_index"],
69
+ latent_membership=d.get("latent_membership"),
70
+ )
71
+ obj.set_active(d.get("active", True))
72
+ return obj