BUCToolkit 1.0b0__tar.gz → 1.0b2__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 (100) hide show
  1. buctoolkit-1.0b2/BUCToolkit/BatchMD/constrained_md/README.md +4 -0
  2. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchStructures/BatchStructuresBase.py +7 -3
  3. buctoolkit-1.0b2/BUCToolkit/BatchStructures/README.md +14 -0
  4. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchStructures/__init__.py +7 -0
  5. buctoolkit-1.0b2/BUCToolkit/BatchStructures/batch.py +256 -0
  6. buctoolkit-1.0b2/BUCToolkit/BatchStructures/data.py +440 -0
  7. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/Preprocessing/preprocessing.py +5 -4
  8. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/StandardTemplate.py +1 -1
  9. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/ConstrainedMolecularDynamics.py +3 -1
  10. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/DataLoaders.py +2 -1
  11. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/NEB.py +3 -1
  12. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/StructureOptimization.py +5 -5
  13. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/_io.py +18 -12
  14. buctoolkit-1.0b2/BUCToolkit/cli/convert_data.py +56 -0
  15. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/cli/main.py +31 -13
  16. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit.egg-info/PKG-INFO +2 -2
  17. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit.egg-info/SOURCES.txt +6 -0
  18. buctoolkit-1.0b2/MANIFEST.in +1 -0
  19. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/PKG-INFO +2 -2
  20. buctoolkit-1.0b2/README.md +545 -0
  21. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/setup.py +5 -2
  22. buctoolkit-1.0b0/README.md +0 -23
  23. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchGenerate/CheckStructures.py +0 -0
  24. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchGenerate/__init__.py +0 -0
  25. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchGenerate/coords_interp.py +0 -0
  26. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchGenerate/initial_ads_structures.py +0 -0
  27. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchGenerate/random_replace.py +0 -0
  28. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMC/MetropolisMC.py +0 -0
  29. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMC/_BaseMC.py +0 -0
  30. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMC/__init__.py +0 -0
  31. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/BiasedMD.py +0 -0
  32. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/NVE.py +0 -0
  33. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/NVT.py +0 -0
  34. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/_BaseMD.py +0 -0
  35. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/__init__.py +0 -0
  36. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/constrained_md/BiasedMD.py +0 -0
  37. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/constrained_md/ConstrNVE.py +0 -0
  38. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/constrained_md/ConstrNVT.py +0 -0
  39. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/constrained_md/NVE.py +0 -0
  40. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/constrained_md/NVT.py +0 -0
  41. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/constrained_md/_BaseMD.py +0 -0
  42. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/constrained_md/_ConstrBaseMD.py +0 -0
  43. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchMD/constrained_md/__init__.py +0 -0
  44. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/TS/CI_NEB.py +0 -0
  45. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/TS/Dimer.py +0 -0
  46. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/TS/__init__.py +0 -0
  47. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/_BaseOpt.py +0 -0
  48. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/__init__.py +0 -0
  49. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/_utils/__init__.py +0 -0
  50. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/_utils/_line_search.py +0 -0
  51. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/_utils/_warnings.py +0 -0
  52. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/frequency.py +0 -0
  53. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/minimize/CG.py +0 -0
  54. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/minimize/FIRE.py +0 -0
  55. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/minimize/QN.py +0 -0
  56. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchOptim/minimize/__init__.py +0 -0
  57. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/BatchStructures/StructuresIO.py +0 -0
  58. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/Preprocessing/__init__.py +0 -0
  59. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/Preprocessing/load_files.py +0 -0
  60. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/Preprocessing/sampling.py +0 -0
  61. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/Preprocessing/supercells.py +0 -0
  62. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/Preprocessing/write_files.py +0 -0
  63. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/__init__.py +0 -0
  64. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/_version.py +0 -0
  65. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/Losses.py +0 -0
  66. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/Metrics.py +0 -0
  67. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/ModelOptims.py +0 -0
  68. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/MolecularDynamics.py +0 -0
  69. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/MonteCarlo.py +0 -0
  70. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/Predictor.py +0 -0
  71. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/Trainer.py +0 -0
  72. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/VibrationAnalysis.py +0 -0
  73. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/api/__init__.py +0 -0
  74. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/cli/__init__.py +0 -0
  75. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/cli/cli.py +0 -0
  76. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/cli/input_stub.py +0 -0
  77. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/cli/print_logo.py +0 -0
  78. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/cli/template_model.py +0 -0
  79. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/io.py +0 -0
  80. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/AtomSelector.py +0 -0
  81. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/AtomicNumber2Properties.py +0 -0
  82. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/ElemListReduce.py +0 -0
  83. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/Ewald.py +0 -0
  84. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/IrregularTensorReformat.py +0 -0
  85. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/_CheckModules.py +0 -0
  86. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/_Element_info.py +0 -0
  87. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/__init__.py +0 -0
  88. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/_para_flatt_list.py +0 -0
  89. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/_print_formatter.py +0 -0
  90. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/check_structures.py +0 -0
  91. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/function_utils.py +0 -0
  92. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/grad_functions.py +0 -0
  93. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/index_ops.py +0 -0
  94. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit/utils/setup_loggers.py +0 -0
  95. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit.egg-info/dependency_links.txt +0 -0
  96. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit.egg-info/entry_points.txt +0 -0
  97. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit.egg-info/requires.txt +0 -0
  98. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/BUCToolkit.egg-info/top_level.txt +0 -0
  99. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/LICENSE +0 -0
  100. {buctoolkit-1.0b0 → buctoolkit-1.0b2}/setup.cfg +0 -0
@@ -0,0 +1,4 @@
1
+ ### Here algorithms require all input batch are regular, i.e., in one batch, all structures have the same atom numbers.
2
+ * Typically, they are the same chemical systems with different configurations.
3
+ * It is useful for independent repeated MD, blue-moon ensembles, or application for Jarzynski identity.
4
+ * It is more efficiency than the irregular batch version algorithms.
@@ -423,13 +423,15 @@ class BatchStructures(object):
423
423
  _STANDARD_FILE_LIST = set(list(self._ATTR_NAMES) + ['head', ])
424
424
  if mode not in {'w', 'a'}:
425
425
  raise ValueError(f'Unknown `mode` value {mode}. It must be "w" or "a".')
426
- if not os.path.isdir(path): # path do not exist
426
+ if not os.path.exists(path): # path do not exist
427
427
  mode = 'w'
428
428
  os.makedirs(path, )
429
+ elif os.path.isfile(path):
430
+ raise OSError(f"The file `{path}` already exists.")
429
431
  elif len(os.listdir(path)) > 0:
430
432
  if mode == 'a':
431
433
  file_set = set(os.listdir(path))
432
- assert file_set == _STANDARD_FILE_LIST, 'Existing files do not match the saving data.'
434
+ if file_set != _STANDARD_FILE_LIST: raise RuntimeError('Existing files do not match the saving data.')
433
435
  else:
434
436
  for ff in os.listdir(path):
435
437
  if ff not in _STANDARD_FILE_LIST:
@@ -724,8 +726,10 @@ class BatchStructures(object):
724
726
  is_convert = True
725
727
  else:
726
728
  is_convert = False
727
- if not os.path.isdir(output_path):
729
+ if not os.path.exists(output_path):
728
730
  os.makedirs(output_path)
731
+ elif os.path.isfile(output_path):
732
+ raise OSError(f"There is already a file named '{output_path}'.")
729
733
 
730
734
  try:
731
735
  file_name_list = [f'{_}' for _ in file_name_list]
@@ -0,0 +1,14 @@
1
+ # Here `data.py` and `batch.py` are a subset from `pytorch_geometric`
2
+
3
+ BUCToolkit uses the most basic graph data structures of
4
+ [`pytorch_geometric`](https://pytorch-geometric.readthedocs.io/en/latest/) [1, 2] framework as a
5
+ basic standard input data format.
6
+
7
+ Thus, one needs not install the whole `pytorch_geometric` with heavy dependencies to run our methods.
8
+
9
+ We follow the same approach to NequIP (https://github.com/mir-group/nequip/tree/main/nequip) and
10
+ mace (https://github.com/ACEsuit/mace), and copy their code of `data.py` and `batch.py` here.
11
+
12
+
13
+ [1] Fey, M., & Lenssen, J. E. (2019). Fast Graph Representation Learning with PyTorch Geometric (Version 2.0.1) [Computer software]. https://github.com/pyg-team/pytorch_geometric <br>
14
+ [2] https://arxiv.org/abs/1903.02428
@@ -4,7 +4,11 @@
4
4
  # File: __init__.py
5
5
  # Environment: Python 3.12
6
6
 
7
+ from BUCToolkit.BatchStructures.BatchStructuresBase import BatchStructures
7
8
  from BUCToolkit.BatchStructures.StructuresIO import read_opt_structures, read_md_traj, read_mc_traj, ArrayDumper, ArrayDumpReader
9
+ from BUCToolkit.BatchStructures.batch import Batch
10
+ from BUCToolkit.BatchStructures.data import Data
11
+
8
12
 
9
13
  __all__ = [
10
14
  "read_opt_structures",
@@ -12,4 +16,7 @@ __all__ = [
12
16
  "read_mc_traj",
13
17
  "ArrayDumper",
14
18
  "ArrayDumpReader",
19
+ 'Batch',
20
+ 'Data',
21
+ 'BatchStructures'
15
22
  ]
@@ -0,0 +1,256 @@
1
+ from collections.abc import Sequence
2
+ from typing import List
3
+
4
+ import numpy as np
5
+ import torch
6
+ from torch import Tensor
7
+
8
+ from .data import Data
9
+
10
+
11
+ class Batch(Data):
12
+ r"""A plain old python object modeling a batch of graphs as one big
13
+ (disconnected) graph. With :class:`torch_geometric.data.Data` being the
14
+ base class, all its methods can also be used here.
15
+ In addition, single graphs can be reconstructed via the assignment vector
16
+ :obj:`batch`, which maps each node to its respective graph identifier.
17
+ """
18
+
19
+ def __init__(self, batch=None, ptr=None, **kwargs):
20
+ super(Batch, self).__init__(**kwargs)
21
+
22
+ for key, item in kwargs.items():
23
+ if key == "num_nodes":
24
+ self.__num_nodes__ = item
25
+ else:
26
+ self[key] = item
27
+
28
+ self.batch = batch
29
+ self.ptr = ptr
30
+ self.__data_class__ = Data
31
+ self.__slices__ = None
32
+ self.__cumsum__ = None
33
+ self.__cat_dims__ = None
34
+ self.__num_nodes_list__ = None
35
+ self.__num_graphs__ = None
36
+
37
+ @classmethod
38
+ def from_data_list(cls, data_list, follow_batch=[], exclude_keys=[]):
39
+ r"""Constructs a batch object from a python list holding
40
+ :class:`torch_geometric.data.Data` objects.
41
+ The assignment vector :obj:`batch` is created on the fly.
42
+ Additionally, creates assignment batch vectors for each key in
43
+ :obj:`follow_batch`.
44
+ Will exclude any keys given in :obj:`exclude_keys`."""
45
+
46
+ keys = list(set(data_list[0].keys) - set(exclude_keys))
47
+ assert "batch" not in keys and "ptr" not in keys
48
+
49
+ batch = cls()
50
+ for key in data_list[0].__dict__.keys():
51
+ if key[:2] != "__" and key[-2:] != "__":
52
+ batch[key] = None
53
+
54
+ batch.__num_graphs__ = len(data_list)
55
+ batch.__data_class__ = data_list[0].__class__
56
+ for key in keys + ["batch"]:
57
+ batch[key] = []
58
+ batch["ptr"] = [0]
59
+
60
+ device = None
61
+ slices = {key: [0] for key in keys}
62
+ cumsum = {key: [0] for key in keys}
63
+ cat_dims = {}
64
+ num_nodes_list = []
65
+ for i, data in enumerate(data_list):
66
+ for key in keys:
67
+ item = data[key]
68
+
69
+ # Increase values by `cumsum` value.
70
+ cum = cumsum[key][-1]
71
+ if isinstance(item, Tensor) and item.dtype != torch.bool:
72
+ if not isinstance(cum, int) or cum != 0:
73
+ item = item + cum
74
+ elif isinstance(item, (int, float)):
75
+ item = item + cum
76
+
77
+ # Gather the size of the `cat` dimension.
78
+ size = 1
79
+ cat_dim = data.__cat_dim__(key, data[key])
80
+ # 0-dimensional tensors have no dimension along which to
81
+ # concatenate, so we set `cat_dim` to `None`.
82
+ if isinstance(item, Tensor) and item.dim() == 0:
83
+ cat_dim = None
84
+ cat_dims[key] = cat_dim
85
+
86
+ # Add a batch dimension to items whose `cat_dim` is `None`:
87
+ if isinstance(item, Tensor) and cat_dim is None:
88
+ cat_dim = 0 # Concatenate along this new batch dimension.
89
+ item = item.unsqueeze(0)
90
+ device = item.device
91
+ elif isinstance(item, Tensor):
92
+ size = item.size(cat_dim)
93
+ device = item.device
94
+
95
+ batch[key].append(item) # Append item to the attribute list.
96
+
97
+ slices[key].append(size + slices[key][-1])
98
+ inc = data.__inc__(key, item)
99
+ if isinstance(inc, (tuple, list)):
100
+ inc = torch.tensor(inc)
101
+ cumsum[key].append(inc + cumsum[key][-1])
102
+
103
+ if key in follow_batch:
104
+ if isinstance(size, Tensor):
105
+ for j, size in enumerate(size.tolist()):
106
+ tmp = f"{key}_{j}_batch"
107
+ batch[tmp] = [] if i == 0 else batch[tmp]
108
+ batch[tmp].append(
109
+ torch.full((size,), i, dtype=torch.long, device=device)
110
+ )
111
+ else:
112
+ tmp = f"{key}_batch"
113
+ batch[tmp] = [] if i == 0 else batch[tmp]
114
+ batch[tmp].append(
115
+ torch.full((size,), i, dtype=torch.long, device=device)
116
+ )
117
+
118
+ if hasattr(data, "__num_nodes__"):
119
+ num_nodes_list.append(data.__num_nodes__)
120
+ else:
121
+ num_nodes_list.append(None)
122
+
123
+ num_nodes = data.num_nodes
124
+ if num_nodes is not None:
125
+ item = torch.full((num_nodes,), i, dtype=torch.long, device=device)
126
+ batch.batch.append(item)
127
+ batch.ptr.append(batch.ptr[-1] + num_nodes)
128
+
129
+ batch.batch = None if len(batch.batch) == 0 else batch.batch
130
+ batch.ptr = None if len(batch.ptr) == 1 else batch.ptr
131
+ batch.__slices__ = slices
132
+ batch.__cumsum__ = cumsum
133
+ batch.__cat_dims__ = cat_dims
134
+ batch.__num_nodes_list__ = num_nodes_list
135
+
136
+ ref_data = data_list[0]
137
+ for key in batch.keys:
138
+ items = batch[key]
139
+ item = items[0]
140
+ cat_dim = ref_data.__cat_dim__(key, item)
141
+ cat_dim = 0 if cat_dim is None else cat_dim
142
+ if isinstance(item, Tensor):
143
+ batch[key] = torch.cat(items, cat_dim)
144
+ elif isinstance(item, (int, float)):
145
+ batch[key] = torch.tensor(items)
146
+
147
+ # if torch_geometric.is_debug_enabled():
148
+ # batch.debug()
149
+
150
+ return batch.contiguous()
151
+
152
+ def get_example(self, idx: int) -> Data:
153
+ r"""Reconstructs the :class:`torch_geometric.data.Data` object at index
154
+ :obj:`idx` from the batch object.
155
+ The batch object must have been created via :meth:`from_data_list` in
156
+ order to be able to reconstruct the initial objects."""
157
+
158
+ if self.__slices__ is None:
159
+ raise RuntimeError(
160
+ (
161
+ "Cannot reconstruct data list from batch because the batch "
162
+ "object was not created using `Batch.from_data_list()`."
163
+ )
164
+ )
165
+
166
+ data = self.__data_class__()
167
+ idx = self.num_graphs + idx if idx < 0 else idx
168
+
169
+ for key in self.__slices__.keys():
170
+ item = self[key]
171
+ if self.__cat_dims__[key] is None:
172
+ # The item was concatenated along a new batch dimension,
173
+ # so just index in that dimension:
174
+ item = item[idx]
175
+ else:
176
+ # Narrow the item based on the values in `__slices__`.
177
+ if isinstance(item, Tensor):
178
+ dim = self.__cat_dims__[key]
179
+ start = self.__slices__[key][idx]
180
+ end = self.__slices__[key][idx + 1]
181
+ item = item.narrow(dim, start, end - start)
182
+ else:
183
+ start = self.__slices__[key][idx]
184
+ end = self.__slices__[key][idx + 1]
185
+ item = item[start:end]
186
+ item = item[0] if len(item) == 1 else item
187
+
188
+ # Decrease its value by `cumsum` value:
189
+ cum = self.__cumsum__[key][idx]
190
+ if isinstance(item, Tensor):
191
+ if not isinstance(cum, int) or cum != 0:
192
+ item = item - cum
193
+ elif isinstance(item, (int, float)):
194
+ item = item - cum
195
+
196
+ data[key] = item
197
+
198
+ if self.__num_nodes_list__[idx] is not None:
199
+ data.num_nodes = self.__num_nodes_list__[idx]
200
+
201
+ return data
202
+
203
+ def index_select(self, idx: List) -> List[Data]:
204
+ if isinstance(idx, slice):
205
+ idx = list(range(self.num_graphs)[idx])
206
+
207
+ elif isinstance(idx, Tensor) and idx.dtype == torch.long:
208
+ idx = idx.flatten().tolist()
209
+
210
+ elif isinstance(idx, Tensor) and idx.dtype == torch.bool:
211
+ idx = idx.flatten().nonzero(as_tuple=False).flatten().tolist()
212
+
213
+ elif isinstance(idx, np.ndarray) and idx.dtype == np.int64:
214
+ idx = idx.flatten().tolist()
215
+
216
+ elif isinstance(idx, np.ndarray) and idx.dtype == np.bool:
217
+ idx = idx.flatten().nonzero()[0].flatten().tolist()
218
+
219
+ elif isinstance(idx, Sequence) and not isinstance(idx, str):
220
+ pass
221
+
222
+ else:
223
+ raise IndexError(
224
+ f"Only integers, slices (':'), list, tuples, torch.tensor and "
225
+ f"np.ndarray of dtype long or bool are valid indices (got "
226
+ f"'{type(idx).__name__}')"
227
+ )
228
+
229
+ return [self.get_example(i) for i in idx]
230
+
231
+ def __getitem__(self, idx):
232
+ if isinstance(idx, str):
233
+ return super(Batch, self).__getitem__(idx)
234
+ elif isinstance(idx, (int, np.integer)):
235
+ return self.get_example(idx)
236
+ else:
237
+ return self.index_select(idx)
238
+
239
+ def to_data_list(self) -> List[Data]:
240
+ r"""Reconstructs the list of :class:`torch_geometric.data.Data` objects
241
+ from the batch object.
242
+ The batch object must have been created via :meth:`from_data_list` in
243
+ order to be able to reconstruct the initial objects."""
244
+ return [self.get_example(i) for i in range(self.num_graphs)]
245
+
246
+ @property
247
+ def num_graphs(self) -> int:
248
+ """Returns the number of graphs in the batch."""
249
+ if self.__num_graphs__ is not None:
250
+ return self.__num_graphs__
251
+ elif self.ptr is not None:
252
+ return self.ptr.numel() - 1
253
+ elif self.batch is not None:
254
+ return int(self.batch.max()) + 1
255
+ else:
256
+ raise ValueError