aspect-data 0.0.3__tar.gz → 0.0.4__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.
- {aspect_data-0.0.3 → aspect_data-0.0.4}/PKG-INFO +17 -3
- {aspect_data-0.0.3 → aspect_data-0.0.4}/README.md +11 -0
- aspect_data-0.0.4/aspect/collate/__init__.py +7 -0
- aspect_data-0.0.4/aspect/collate/base.py +42 -0
- aspect_data-0.0.4/aspect/collate/chemprop.py +115 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/data.py +11 -10
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/typing.py +7 -3
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect_data.egg-info/PKG-INFO +17 -3
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect_data.egg-info/SOURCES.txt +6 -1
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect_data.egg-info/requires.txt +6 -2
- {aspect_data-0.0.3 → aspect_data-0.0.4}/pyproject.toml +5 -4
- aspect_data-0.0.4/test/test_collate.py +78 -0
- aspect_data-0.0.4/test/test_collate_chemprop.py +104 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/LICENSE +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/__init__.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/checkpoint_utils.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/cli_module/__init__.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/cli_module/cli.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/cli_module/featurize.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/cli_module/io.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/io.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/package_data.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/transform/__init__.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/transform/base.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/transform/deep_functions.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/transform/functions.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect/transform/registry.py +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect_data.egg-info/dependency_links.txt +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect_data.egg-info/entry_points.txt +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/aspect_data.egg-info/top_level.txt +0 -0
- {aspect_data-0.0.3 → aspect_data-0.0.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aspect-data
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: General purpose, chemistry, and taxonomic featurization of tabular data with caching.
|
|
5
5
|
Author-email: Eachan Johnson <eachan.johnson@crick.ac.uk>
|
|
6
6
|
License: MIT License
|
|
@@ -48,14 +48,17 @@ Requires-Dist: platformdirs>=4.4.0
|
|
|
48
48
|
Requires-Dist: tqdm
|
|
49
49
|
Provides-Extra: chem
|
|
50
50
|
Requires-Dist: schemist>=0.0.6; extra == "chem"
|
|
51
|
+
Provides-Extra: torch
|
|
52
|
+
Requires-Dist: torch>=2.4; extra == "torch"
|
|
51
53
|
Provides-Extra: chemprop
|
|
54
|
+
Requires-Dist: aspect-data[chem,torch]; extra == "chemprop"
|
|
52
55
|
Requires-Dist: chemprop>=2.1.0; extra == "chemprop"
|
|
53
56
|
Provides-Extra: deep
|
|
54
57
|
Requires-Dist: transformers; extra == "deep"
|
|
55
58
|
Provides-Extra: bio
|
|
56
|
-
Requires-Dist: vectome>=0.0.
|
|
59
|
+
Requires-Dist: vectome>=0.0.8; extra == "bio"
|
|
57
60
|
Provides-Extra: dev
|
|
58
|
-
Requires-Dist: aspect-data[bio,
|
|
61
|
+
Requires-Dist: aspect-data[bio,chemprop]; extra == "dev"
|
|
59
62
|
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
60
63
|
Requires-Dist: flake8; extra == "dev"
|
|
61
64
|
Dynamic: license-file
|
|
@@ -66,6 +69,8 @@ Dynamic: license-file
|
|
|
66
69
|

|
|
67
70
|

|
|
68
71
|
|
|
72
|
+
<img src="docs/source/_static/logo.svg" width="200">
|
|
73
|
+
|
|
69
74
|
**aspect** is a lightweight featurisation layer for tabular machine-learning data.
|
|
70
75
|
|
|
71
76
|
It lets you define independent feature pipelines for different input columns, then apply them to dictionaries, Pandas data frames, local files, Hugging Face datasets, or saved dataset checkpoints.
|
|
@@ -83,6 +88,15 @@ input table
|
|
|
83
88
|
output dataset with named feature columns
|
|
84
89
|
```
|
|
85
90
|
|
|
91
|
+
Aspect datasets store Arrow-compatible feature representations.
|
|
92
|
+
|
|
93
|
+
Before model execution, an optional collator converts stored examples into
|
|
94
|
+
runtime representations. A runtime batch is always a mapping from feature
|
|
95
|
+
column names to batched values. Values may be tensors or structured mappings.
|
|
96
|
+
|
|
97
|
+
Downstream model libraries should treat runtime batch values as opaque and
|
|
98
|
+
should not perform dataset preprocessing or deserialization.
|
|
99
|
+
|
|
86
100
|
---
|
|
87
101
|
|
|
88
102
|
## Contents
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|

|
|
5
5
|

|
|
6
6
|
|
|
7
|
+
<img src="docs/source/_static/logo.svg" width="200">
|
|
8
|
+
|
|
7
9
|
**aspect** is a lightweight featurisation layer for tabular machine-learning data.
|
|
8
10
|
|
|
9
11
|
It lets you define independent feature pipelines for different input columns, then apply them to dictionaries, Pandas data frames, local files, Hugging Face datasets, or saved dataset checkpoints.
|
|
@@ -21,6 +23,15 @@ input table
|
|
|
21
23
|
output dataset with named feature columns
|
|
22
24
|
```
|
|
23
25
|
|
|
26
|
+
Aspect datasets store Arrow-compatible feature representations.
|
|
27
|
+
|
|
28
|
+
Before model execution, an optional collator converts stored examples into
|
|
29
|
+
runtime representations. A runtime batch is always a mapping from feature
|
|
30
|
+
column names to batched values. Values may be tensors or structured mappings.
|
|
31
|
+
|
|
32
|
+
Downstream model libraries should treat runtime batch values as opaque and
|
|
33
|
+
should not perform dataset preprocessing or deserialization.
|
|
34
|
+
|
|
24
35
|
---
|
|
25
36
|
|
|
26
37
|
## Contents
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Specialised column collation."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable, Mapping, Iterable
|
|
4
|
+
from typing import Any, TypeAlias
|
|
5
|
+
|
|
6
|
+
from ..typing import Batch
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
CollateFn: TypeAlias = Callable[[Iterable[Any]], Any]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ColumnCollator:
|
|
13
|
+
"""Override collation for selected dataset columns."""
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
collators: Mapping[str, CollateFn] | None = None,
|
|
18
|
+
):
|
|
19
|
+
self.collators = collators or {}
|
|
20
|
+
|
|
21
|
+
def __call__(
|
|
22
|
+
self,
|
|
23
|
+
rows: Batch,
|
|
24
|
+
) -> dict[str, ...]:
|
|
25
|
+
from torch.utils.data import default_collate
|
|
26
|
+
|
|
27
|
+
out = {}
|
|
28
|
+
if not rows:
|
|
29
|
+
return out
|
|
30
|
+
|
|
31
|
+
for column in rows[0]:
|
|
32
|
+
values = [
|
|
33
|
+
row[column]
|
|
34
|
+
for row in rows
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
if column in self.collators:
|
|
38
|
+
out[column] = self.collators[column](values)
|
|
39
|
+
else:
|
|
40
|
+
out[column] = default_collate(values)
|
|
41
|
+
|
|
42
|
+
return out
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Chemprop collation helpers."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping, Iterable
|
|
4
|
+
|
|
5
|
+
from chemprop.data import MolGraph
|
|
6
|
+
from chemprop.data.collate import BatchMolGraph
|
|
7
|
+
import numpy as np
|
|
8
|
+
import torch
|
|
9
|
+
from torch import Tensor
|
|
10
|
+
|
|
11
|
+
from ..typing import Datum
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _as_tensor(x) -> Tensor:
|
|
15
|
+
"""Convert an value to a tensor."""
|
|
16
|
+
if x is None:
|
|
17
|
+
return None
|
|
18
|
+
if torch.is_tensor(x):
|
|
19
|
+
return x
|
|
20
|
+
return torch.as_tensor(x)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _as_numpy(x) -> np.ndarray:
|
|
24
|
+
"""Convert an value to a tensor."""
|
|
25
|
+
if x is None:
|
|
26
|
+
return None
|
|
27
|
+
if isinstance(x, np.ndarray):
|
|
28
|
+
return x
|
|
29
|
+
return np.asarray(x)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _molgraph_from_mapping(
|
|
33
|
+
x: Mapping[str, ...]
|
|
34
|
+
) -> MolGraph:
|
|
35
|
+
"""Reconstruct a Chemprop MolGraph from a cached mapping."""
|
|
36
|
+
return MolGraph(
|
|
37
|
+
V=_as_numpy(x["V"]),
|
|
38
|
+
E=_as_numpy(x["E"]),
|
|
39
|
+
edge_index=_as_numpy(x["edge_index"]).astype(np.int32),
|
|
40
|
+
rev_edge_index=_as_numpy(x["rev_edge_index"]).astype(np.int32),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _collate_optional(
|
|
45
|
+
values: Iterable[...],
|
|
46
|
+
*,
|
|
47
|
+
stack: bool,
|
|
48
|
+
):
|
|
49
|
+
"""Collate an optional Chemprop feature."""
|
|
50
|
+
if all(value is None for value in values):
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
if any(value is None for value in values):
|
|
54
|
+
raise ValueError(
|
|
55
|
+
"Cannot collate Chemprop feature containing a mixture "
|
|
56
|
+
"of None and non-None values."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
tensors = [
|
|
60
|
+
_as_tensor(value)
|
|
61
|
+
for value in values
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
if stack:
|
|
65
|
+
return torch.stack(tensors, dim=0)
|
|
66
|
+
|
|
67
|
+
return torch.cat(tensors, dim=0)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def chemprop_collate(
|
|
71
|
+
values: Iterable[Datum],
|
|
72
|
+
) -> dict[str, ...]:
|
|
73
|
+
"""Collate cached Chemprop features into a runtime model input.
|
|
74
|
+
|
|
75
|
+
Each input value is expected to have the form::
|
|
76
|
+
|
|
77
|
+
{
|
|
78
|
+
"bmg": {
|
|
79
|
+
"V": ...,
|
|
80
|
+
"E": ...,
|
|
81
|
+
"edge_index": ...,
|
|
82
|
+
"rev_edge_index": ...,
|
|
83
|
+
},
|
|
84
|
+
"V_d": ...,
|
|
85
|
+
"X_d": ...,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
=======
|
|
90
|
+
dict
|
|
91
|
+
Runtime representation suitable for ``ChempropEncoder(**batch)``.
|
|
92
|
+
|
|
93
|
+
"""
|
|
94
|
+
if len(values) == 0:
|
|
95
|
+
raise ValueError("Cannot collate an empty Chemprop batch.")
|
|
96
|
+
|
|
97
|
+
molgraphs = [
|
|
98
|
+
_molgraph_from_mapping(value["bmg"])
|
|
99
|
+
for value in values
|
|
100
|
+
]
|
|
101
|
+
bmg = BatchMolGraph(molgraphs)
|
|
102
|
+
|
|
103
|
+
V_d = _collate_optional(
|
|
104
|
+
[value.get("V_d") for value in values],
|
|
105
|
+
stack=False,
|
|
106
|
+
)
|
|
107
|
+
X_d = _collate_optional(
|
|
108
|
+
[value.get("X_d") for value in values],
|
|
109
|
+
stack=True,
|
|
110
|
+
)
|
|
111
|
+
return {
|
|
112
|
+
"bmg": bmg,
|
|
113
|
+
"V_d": V_d,
|
|
114
|
+
"X_d": X_d,
|
|
115
|
+
}
|
|
@@ -399,17 +399,17 @@ class DataPipeline:
|
|
|
399
399
|
|
|
400
400
|
@staticmethod
|
|
401
401
|
def _unsqueeze(
|
|
402
|
-
x: Mapping[str, ArrayLike]
|
|
402
|
+
x: Mapping[str, ArrayLike],
|
|
403
|
+
columns: Optional[Iterable[str]] = None
|
|
403
404
|
) -> Dict[str, np.ndarray]:
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
return x
|
|
405
|
+
columns = columns or x.keys()
|
|
406
|
+
for key in columns:
|
|
407
|
+
vals = x[key]
|
|
408
|
+
if not isinstance(vals, dict):
|
|
409
|
+
vals = np.asarray(x[key])
|
|
410
|
+
if vals.ndim == 1 and np.issubdtype(vals.dtype, np.number):
|
|
411
|
+
x[key] = vals[:, None]
|
|
412
|
+
return x
|
|
413
413
|
|
|
414
414
|
def __call__(
|
|
415
415
|
self,
|
|
@@ -477,6 +477,7 @@ class DataPipeline:
|
|
|
477
477
|
.select_columns(all_output_columns)
|
|
478
478
|
.map(
|
|
479
479
|
self._unsqueeze,
|
|
480
|
+
fn_kwargs={"columns": output_columns},
|
|
480
481
|
batched=True,
|
|
481
482
|
batch_size=batch_size,
|
|
482
483
|
desc="Unsqueezing",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Custom types."""
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any,
|
|
3
|
+
from typing import TYPE_CHECKING, Any, TypeAlias, Union
|
|
4
|
+
from collections.abc import Iterable, Mapping
|
|
4
5
|
|
|
5
6
|
from datasets import Dataset, IterableDataset
|
|
6
7
|
from pandas import DataFrame
|
|
@@ -11,14 +12,14 @@ if TYPE_CHECKING:
|
|
|
11
12
|
else:
|
|
12
13
|
ColumnTransform = Any
|
|
13
14
|
|
|
14
|
-
DataLike = Union[
|
|
15
|
+
DataLike: TypeAlias = Union[
|
|
15
16
|
str,
|
|
16
17
|
DataFrame,
|
|
17
18
|
Mapping[str, ArrayLike],
|
|
18
19
|
Dataset,
|
|
19
20
|
IterableDataset
|
|
20
21
|
]
|
|
21
|
-
FeatureLike = Union[
|
|
22
|
+
FeatureLike: TypeAlias = Union[
|
|
22
23
|
str,
|
|
23
24
|
Mapping[str, ColumnTransform],
|
|
24
25
|
Mapping[str, Mapping[str, Any]],
|
|
@@ -29,3 +30,6 @@ FeatureLike = Union[
|
|
|
29
30
|
]]
|
|
30
31
|
]
|
|
31
32
|
StrOrIterableOfStr = Union[str, Iterable[str]]
|
|
33
|
+
|
|
34
|
+
Datum: TypeAlias = Mapping[str, Any]
|
|
35
|
+
Batch: TypeAlias = Iterable[Mapping[str, Any]]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aspect-data
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: General purpose, chemistry, and taxonomic featurization of tabular data with caching.
|
|
5
5
|
Author-email: Eachan Johnson <eachan.johnson@crick.ac.uk>
|
|
6
6
|
License: MIT License
|
|
@@ -48,14 +48,17 @@ Requires-Dist: platformdirs>=4.4.0
|
|
|
48
48
|
Requires-Dist: tqdm
|
|
49
49
|
Provides-Extra: chem
|
|
50
50
|
Requires-Dist: schemist>=0.0.6; extra == "chem"
|
|
51
|
+
Provides-Extra: torch
|
|
52
|
+
Requires-Dist: torch>=2.4; extra == "torch"
|
|
51
53
|
Provides-Extra: chemprop
|
|
54
|
+
Requires-Dist: aspect-data[chem,torch]; extra == "chemprop"
|
|
52
55
|
Requires-Dist: chemprop>=2.1.0; extra == "chemprop"
|
|
53
56
|
Provides-Extra: deep
|
|
54
57
|
Requires-Dist: transformers; extra == "deep"
|
|
55
58
|
Provides-Extra: bio
|
|
56
|
-
Requires-Dist: vectome>=0.0.
|
|
59
|
+
Requires-Dist: vectome>=0.0.8; extra == "bio"
|
|
57
60
|
Provides-Extra: dev
|
|
58
|
-
Requires-Dist: aspect-data[bio,
|
|
61
|
+
Requires-Dist: aspect-data[bio,chemprop]; extra == "dev"
|
|
59
62
|
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
60
63
|
Requires-Dist: flake8; extra == "dev"
|
|
61
64
|
Dynamic: license-file
|
|
@@ -66,6 +69,8 @@ Dynamic: license-file
|
|
|
66
69
|

|
|
67
70
|

|
|
68
71
|
|
|
72
|
+
<img src="docs/source/_static/logo.svg" width="200">
|
|
73
|
+
|
|
69
74
|
**aspect** is a lightweight featurisation layer for tabular machine-learning data.
|
|
70
75
|
|
|
71
76
|
It lets you define independent feature pipelines for different input columns, then apply them to dictionaries, Pandas data frames, local files, Hugging Face datasets, or saved dataset checkpoints.
|
|
@@ -83,6 +88,15 @@ input table
|
|
|
83
88
|
output dataset with named feature columns
|
|
84
89
|
```
|
|
85
90
|
|
|
91
|
+
Aspect datasets store Arrow-compatible feature representations.
|
|
92
|
+
|
|
93
|
+
Before model execution, an optional collator converts stored examples into
|
|
94
|
+
runtime representations. A runtime batch is always a mapping from feature
|
|
95
|
+
column names to batched values. Values may be tensors or structured mappings.
|
|
96
|
+
|
|
97
|
+
Downstream model libraries should treat runtime batch values as opaque and
|
|
98
|
+
should not perform dataset preprocessing or deserialization.
|
|
99
|
+
|
|
86
100
|
---
|
|
87
101
|
|
|
88
102
|
## Contents
|
|
@@ -11,6 +11,9 @@ aspect/cli_module/__init__.py
|
|
|
11
11
|
aspect/cli_module/cli.py
|
|
12
12
|
aspect/cli_module/featurize.py
|
|
13
13
|
aspect/cli_module/io.py
|
|
14
|
+
aspect/collate/__init__.py
|
|
15
|
+
aspect/collate/base.py
|
|
16
|
+
aspect/collate/chemprop.py
|
|
14
17
|
aspect/transform/__init__.py
|
|
15
18
|
aspect/transform/base.py
|
|
16
19
|
aspect/transform/deep_functions.py
|
|
@@ -21,4 +24,6 @@ aspect_data.egg-info/SOURCES.txt
|
|
|
21
24
|
aspect_data.egg-info/dependency_links.txt
|
|
22
25
|
aspect_data.egg-info/entry_points.txt
|
|
23
26
|
aspect_data.egg-info/requires.txt
|
|
24
|
-
aspect_data.egg-info/top_level.txt
|
|
27
|
+
aspect_data.egg-info/top_level.txt
|
|
28
|
+
test/test_collate.py
|
|
29
|
+
test/test_collate_chemprop.py
|
|
@@ -7,18 +7,22 @@ platformdirs>=4.4.0
|
|
|
7
7
|
tqdm
|
|
8
8
|
|
|
9
9
|
[bio]
|
|
10
|
-
vectome>=0.0.
|
|
10
|
+
vectome>=0.0.8
|
|
11
11
|
|
|
12
12
|
[chem]
|
|
13
13
|
schemist>=0.0.6
|
|
14
14
|
|
|
15
15
|
[chemprop]
|
|
16
|
+
aspect-data[chem,torch]
|
|
16
17
|
chemprop>=2.1.0
|
|
17
18
|
|
|
18
19
|
[deep]
|
|
19
20
|
transformers
|
|
20
21
|
|
|
21
22
|
[dev]
|
|
22
|
-
aspect-data[bio,
|
|
23
|
+
aspect-data[bio,chemprop]
|
|
23
24
|
pytest>=7.4
|
|
24
25
|
flake8
|
|
26
|
+
|
|
27
|
+
[torch]
|
|
28
|
+
torch>=2.4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "aspect-data"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.4"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Eachan Johnson", email="eachan.johnson@crick.ac.uk" },
|
|
6
6
|
]
|
|
@@ -44,10 +44,11 @@ dependencies = [
|
|
|
44
44
|
|
|
45
45
|
[project.optional-dependencies]
|
|
46
46
|
chem = ["schemist>=0.0.6"]
|
|
47
|
-
|
|
47
|
+
torch = ["torch>=2.4"]
|
|
48
|
+
chemprop = ["aspect-data[torch,chem]", "chemprop>=2.1.0"]
|
|
48
49
|
deep = ["transformers"]
|
|
49
|
-
bio = ["vectome>=0.0.
|
|
50
|
-
dev = ["aspect-data[
|
|
50
|
+
bio = ["vectome>=0.0.8"]
|
|
51
|
+
dev = ["aspect-data[chemprop,bio]", "pytest>=7.4", "flake8"]
|
|
51
52
|
|
|
52
53
|
[project.urls]
|
|
53
54
|
"Homepage" = "https://github.com/scbirlab/aspect"
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
|
|
2
|
+
from aspect.collate import ColumnCollator
|
|
3
|
+
|
|
4
|
+
def test_column_collator_default():
|
|
5
|
+
import torch
|
|
6
|
+
|
|
7
|
+
collator = ColumnCollator()
|
|
8
|
+
|
|
9
|
+
batch = collator([
|
|
10
|
+
{
|
|
11
|
+
"x": torch.tensor([1., 2.]),
|
|
12
|
+
"y": torch.tensor(1.),
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"x": torch.tensor([3., 4.]),
|
|
16
|
+
"y": torch.tensor(2.),
|
|
17
|
+
},
|
|
18
|
+
])
|
|
19
|
+
|
|
20
|
+
assert batch["x"].shape == (2, 2)
|
|
21
|
+
assert batch["y"].shape == (2,)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_column_collator_override():
|
|
25
|
+
collator = ColumnCollator(
|
|
26
|
+
collators={
|
|
27
|
+
"special": lambda values: {
|
|
28
|
+
"values": values,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
batch = collator([
|
|
34
|
+
{
|
|
35
|
+
"x": 1,
|
|
36
|
+
"special": "a",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"x": 2,
|
|
40
|
+
"special": "b",
|
|
41
|
+
},
|
|
42
|
+
])
|
|
43
|
+
|
|
44
|
+
assert batch["special"] == {
|
|
45
|
+
"values": ["a", "b"],
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_column_collator_mixed():
|
|
50
|
+
import torch
|
|
51
|
+
|
|
52
|
+
collator = ColumnCollator(
|
|
53
|
+
collators={
|
|
54
|
+
"graph": lambda values: {
|
|
55
|
+
"graph_batch": values,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
batch = collator([
|
|
61
|
+
{
|
|
62
|
+
"fp": torch.tensor([1., 2.]),
|
|
63
|
+
"graph": {"id": 1},
|
|
64
|
+
"target": torch.tensor(0.),
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"fp": torch.tensor([3., 4.]),
|
|
68
|
+
"graph": {"id": 2},
|
|
69
|
+
"target": torch.tensor(1.),
|
|
70
|
+
},
|
|
71
|
+
])
|
|
72
|
+
|
|
73
|
+
assert batch["fp"].shape == (2, 2)
|
|
74
|
+
assert batch["target"].shape == (2,)
|
|
75
|
+
assert batch["graph"]["graph_batch"] == [
|
|
76
|
+
{"id": 1},
|
|
77
|
+
{"id": 2},
|
|
78
|
+
]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Tests for Chemprop collation."""
|
|
2
|
+
|
|
3
|
+
from chemprop.data.collate import BatchMolGraph
|
|
4
|
+
from chemprop.featurizers import SimpleMoleculeMolGraphFeaturizer
|
|
5
|
+
import pytest
|
|
6
|
+
from rdkit import Chem
|
|
7
|
+
import torch
|
|
8
|
+
|
|
9
|
+
from aspect.collate.chemprop import chemprop_collate
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _cached_molgraph(smiles: str) -> dict:
|
|
13
|
+
"""Create an HF-like serialized MolGraph."""
|
|
14
|
+
featurizer = SimpleMoleculeMolGraphFeaturizer()
|
|
15
|
+
molgraph = featurizer(
|
|
16
|
+
Chem.MolFromSmiles(smiles)
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
"V": molgraph.V.tolist(),
|
|
21
|
+
"E": molgraph.E.tolist(),
|
|
22
|
+
"edge_index": molgraph.edge_index.tolist(),
|
|
23
|
+
"rev_edge_index": molgraph.rev_edge_index.tolist(),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_chemprop_collate_graphs():
|
|
28
|
+
smiles = ["CCO", "CCN", "CCC"]
|
|
29
|
+
values = [
|
|
30
|
+
{
|
|
31
|
+
"bmg": _cached_molgraph(s),
|
|
32
|
+
"V_d": None,
|
|
33
|
+
"X_d": None,
|
|
34
|
+
}
|
|
35
|
+
for s in smiles
|
|
36
|
+
]
|
|
37
|
+
batch = chemprop_collate(values)
|
|
38
|
+
|
|
39
|
+
assert set(batch) == {
|
|
40
|
+
"bmg",
|
|
41
|
+
"V_d",
|
|
42
|
+
"X_d",
|
|
43
|
+
}
|
|
44
|
+
assert isinstance(
|
|
45
|
+
batch["bmg"],
|
|
46
|
+
BatchMolGraph,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
assert batch["V_d"] is None
|
|
50
|
+
assert batch["X_d"] is None
|
|
51
|
+
|
|
52
|
+
assert batch["bmg"].V.ndim == 2
|
|
53
|
+
assert batch["bmg"].edge_index.ndim == 2
|
|
54
|
+
|
|
55
|
+
assert torch.unique(
|
|
56
|
+
batch["bmg"].batch
|
|
57
|
+
).numel() == 3
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_chemprop_collate_X_d():
|
|
61
|
+
values = [
|
|
62
|
+
{
|
|
63
|
+
"bmg": _cached_molgraph("CCO"),
|
|
64
|
+
"V_d": None,
|
|
65
|
+
"X_d": [1.0, 2.0],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"bmg": _cached_molgraph("CCN"),
|
|
69
|
+
"V_d": None,
|
|
70
|
+
"X_d": [3.0, 4.0],
|
|
71
|
+
},
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
batch = chemprop_collate(values)
|
|
75
|
+
|
|
76
|
+
assert batch["X_d"].shape == (2, 2)
|
|
77
|
+
assert torch.equal(
|
|
78
|
+
batch["X_d"],
|
|
79
|
+
torch.tensor([
|
|
80
|
+
[1., 2.],
|
|
81
|
+
[3., 4.],
|
|
82
|
+
]),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_chemprop_collate_rejects_mixed_optional_values():
|
|
87
|
+
values = [
|
|
88
|
+
{
|
|
89
|
+
"bmg": _cached_molgraph("CCO"),
|
|
90
|
+
"V_d": None,
|
|
91
|
+
"X_d": [1.0, 2.0],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"bmg": _cached_molgraph("CCN"),
|
|
95
|
+
"V_d": None,
|
|
96
|
+
"X_d": None,
|
|
97
|
+
},
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
with pytest.raises(
|
|
101
|
+
ValueError,
|
|
102
|
+
match="mixture of None and non-None",
|
|
103
|
+
):
|
|
104
|
+
chemprop_collate(values)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|