openpoints 0.1.0__py3-none-any.whl
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.
- openpoints/__init__.py +3 -0
- openpoints/cpp/__init__.py +6 -0
- openpoints/cpp/chamfer_dist/__init__.py +110 -0
- openpoints/cpp/chamfer_dist/setup.py +19 -0
- openpoints/cpp/chamfer_dist/test.py +34 -0
- openpoints/cpp/emd/__init__.py +3 -0
- openpoints/cpp/emd/emd.py +88 -0
- openpoints/cpp/emd/setup.py +27 -0
- openpoints/cpp/emd/test_emd_loss.py +45 -0
- openpoints/cpp/pointnet2_batch/__init__.py +24 -0
- openpoints/cpp/pointnet2_batch/setup.py +23 -0
- openpoints/cpp/pointops/__init__.py +0 -0
- openpoints/cpp/pointops/functions/__init__.py +0 -0
- openpoints/cpp/pointops/functions/pointops.py +314 -0
- openpoints/cpp/pointops/setup.py +37 -0
- openpoints/cpp/pointops/src/__init__.py +0 -0
- openpoints/dataset/__init__.py +10 -0
- openpoints/dataset/atom3d/__init__.py +1 -0
- openpoints/dataset/atom3d/psr.py +38 -0
- openpoints/dataset/build.py +98 -0
- openpoints/dataset/data_util.py +192 -0
- openpoints/dataset/datalist.py +67 -0
- openpoints/dataset/dataset_base.py +96 -0
- openpoints/dataset/graph_dataset/__init__.py +3 -0
- openpoints/dataset/graph_dataset/graph_dataset.py +93 -0
- openpoints/dataset/graph_dataset/stack_with_pad.py +91 -0
- openpoints/dataset/graph_dataset/structural_dataset.py +73 -0
- openpoints/dataset/graph_dataset/svd_encodings_dataset.py +110 -0
- openpoints/dataset/grid_sample.py +21 -0
- openpoints/dataset/matterport3d/__init__.py +1 -0
- openpoints/dataset/matterport3d/category_mapping.tsv +1660 -0
- openpoints/dataset/matterport3d/matterport3d.py +210 -0
- openpoints/dataset/matterport3d/matterport3d_dataprocessing.py +105 -0
- openpoints/dataset/modelnet/__init__.py +3 -0
- openpoints/dataset/modelnet/modelnet40_normal_resampled_loader.py +124 -0
- openpoints/dataset/modelnet/modelnet40_ply_2048_loader.py +160 -0
- openpoints/dataset/molhiv/__init__.py +1 -0
- openpoints/dataset/molhiv/data.py +59 -0
- openpoints/dataset/molpcba/__init__.py +1 -0
- openpoints/dataset/molpcba/data.py +59 -0
- openpoints/dataset/parsers/__init__.py +1 -0
- openpoints/dataset/parsers/class_map.py +19 -0
- openpoints/dataset/parsers/constants.py +1 -0
- openpoints/dataset/parsers/parser.py +17 -0
- openpoints/dataset/parsers/parser_factory.py +29 -0
- openpoints/dataset/parsers/parser_image_folder.py +69 -0
- openpoints/dataset/parsers/parser_image_in_tar.py +222 -0
- openpoints/dataset/parsers/parser_image_tar.py +72 -0
- openpoints/dataset/parsers/parser_tfds.py +297 -0
- openpoints/dataset/pcqm4m/__init__.py +1 -0
- openpoints/dataset/pcqm4m/data.py +62 -0
- openpoints/dataset/pcqm4mv2/__init__.py +1 -0
- openpoints/dataset/pcqm4mv2/data.py +87 -0
- openpoints/dataset/s3dis/__init__.py +2 -0
- openpoints/dataset/s3dis/s3dis.py +156 -0
- openpoints/dataset/s3dis/s3dis_block.py +96 -0
- openpoints/dataset/s3dis/s3dis_sphere.py +349 -0
- openpoints/dataset/scannetv2/__init__.py +1 -0
- openpoints/dataset/scannetv2/scannet.py +176 -0
- openpoints/dataset/scanobjectnn/__init__.py +3 -0
- openpoints/dataset/scanobjectnn/scanobjectnn.py +110 -0
- openpoints/dataset/semantic_kitti/__init__.py +1 -0
- openpoints/dataset/semantic_kitti/helper_tool.py +286 -0
- openpoints/dataset/semantic_kitti/label_mapping.yaml +211 -0
- openpoints/dataset/semantic_kitti/semantickitti.py +229 -0
- openpoints/dataset/semantic_kitti/utils/meta/anno_paths.txt +272 -0
- openpoints/dataset/semantic_kitti/utils/meta/class_names.txt +13 -0
- openpoints/dataset/semantic_kitti/utils/semantic-kitti.yaml +211 -0
- openpoints/dataset/shapenet/__init__.py +1 -0
- openpoints/dataset/shapenet/shapenet55.py +76 -0
- openpoints/dataset/shapenet/shapenetpart.py +121 -0
- openpoints/dataset/shapenetpart/__init__.py +1 -0
- openpoints/dataset/shapenetpart/shapenet55.py +75 -0
- openpoints/dataset/shapenetpart/shapenetpart.py +388 -0
- openpoints/dataset/vis2d.py +17 -0
- openpoints/dataset/vis3d.py +153 -0
- openpoints/loss/__init__.py +3 -0
- openpoints/loss/build.py +281 -0
- openpoints/loss/cross_entropy.py +38 -0
- openpoints/loss/distill_loss.py +76 -0
- openpoints/models/__init__.py +10 -0
- openpoints/models/backbone/Stratified_transformer.py +558 -0
- openpoints/models/backbone/__init__.py +11 -0
- openpoints/models/backbone/baafnet.py +527 -0
- openpoints/models/backbone/ball_dgcnn.py +123 -0
- openpoints/models/backbone/curvenet.py +793 -0
- openpoints/models/backbone/debug_invvit.py +114 -0
- openpoints/models/backbone/deepgcn.py +143 -0
- openpoints/models/backbone/dgcnn.py +119 -0
- openpoints/models/backbone/graphvit3d.py +134 -0
- openpoints/models/backbone/grouppointnet.py +100 -0
- openpoints/models/backbone/pct.py +163 -0
- openpoints/models/backbone/pointmlp.py +417 -0
- openpoints/models/backbone/pointnet.py +199 -0
- openpoints/models/backbone/pointnetv2.py +511 -0
- openpoints/models/backbone/pointnext.py +663 -0
- openpoints/models/backbone/pointnextPyG.py +555 -0
- openpoints/models/backbone/pointtransformer.py +293 -0
- openpoints/models/backbone/pointvector.py +853 -0
- openpoints/models/backbone/pointvit.py +392 -0
- openpoints/models/backbone/pointvit_inv.py +942 -0
- openpoints/models/backbone/pointvit_inv_old.py +784 -0
- openpoints/models/backbone/randlenet.py +318 -0
- openpoints/models/backbone/resnet.py +342 -0
- openpoints/models/backbone/simpleview.py +153 -0
- openpoints/models/backbone/simpleview_util.py +292 -0
- openpoints/models/build.py +13 -0
- openpoints/models/classification/__init__.py +5 -0
- openpoints/models/classification/cls_base.py +136 -0
- openpoints/models/classification/point_bert.py +154 -0
- openpoints/models/layers/__init__.py +14 -0
- openpoints/models/layers/activation.py +57 -0
- openpoints/models/layers/attention.py +103 -0
- openpoints/models/layers/conv.py +167 -0
- openpoints/models/layers/drop.py +164 -0
- openpoints/models/layers/graph_conv.py +122 -0
- openpoints/models/layers/group.py +415 -0
- openpoints/models/layers/group_embed.py +286 -0
- openpoints/models/layers/helpers.py +43 -0
- openpoints/models/layers/kmeans.py +119 -0
- openpoints/models/layers/knn.py +110 -0
- openpoints/models/layers/local_aggregation.py +286 -0
- openpoints/models/layers/mlp.py +129 -0
- openpoints/models/layers/norm.py +106 -0
- openpoints/models/layers/padding.py +56 -0
- openpoints/models/layers/patch_embed.py +37 -0
- openpoints/models/layers/registry.py +168 -0
- openpoints/models/layers/subsample.py +185 -0
- openpoints/models/layers/upsampling.py +106 -0
- openpoints/models/layers/weight_init.py +89 -0
- openpoints/models/reconstruction/__init__.py +8 -0
- openpoints/models/reconstruction/base_recontruct.py +216 -0
- openpoints/models/reconstruction/maskedpoint.py +116 -0
- openpoints/models/reconstruction/maskedpointgroup.py +168 -0
- openpoints/models/reconstruction/maskedpointvit.py +253 -0
- openpoints/models/reconstruction/nodeshuffle.py +11 -0
- openpoints/models/registry.py +149 -0
- openpoints/models/segmentation/__init__.py +6 -0
- openpoints/models/segmentation/base_seg.py +278 -0
- openpoints/models/segmentation/vit_seg.py +126 -0
- openpoints/optim/__init__.py +15 -0
- openpoints/optim/adabelief.py +201 -0
- openpoints/optim/adafactor.py +167 -0
- openpoints/optim/adahessian.py +156 -0
- openpoints/optim/adamp.py +105 -0
- openpoints/optim/adamw.py +122 -0
- openpoints/optim/lamb.py +192 -0
- openpoints/optim/lars.py +135 -0
- openpoints/optim/lookahead.py +61 -0
- openpoints/optim/madgrad.py +184 -0
- openpoints/optim/nadam.py +92 -0
- openpoints/optim/nvnovograd.py +120 -0
- openpoints/optim/optim_factory.py +306 -0
- openpoints/optim/radam.py +89 -0
- openpoints/optim/rmsprop_tf.py +139 -0
- openpoints/optim/sgdp.py +70 -0
- openpoints/scheduler/__init__.py +8 -0
- openpoints/scheduler/cosine_lr.py +124 -0
- openpoints/scheduler/multistep_lr.py +65 -0
- openpoints/scheduler/plateau_lr.py +113 -0
- openpoints/scheduler/poly_lr.py +116 -0
- openpoints/scheduler/scheduler.py +110 -0
- openpoints/scheduler/scheduler_factory.py +118 -0
- openpoints/scheduler/step_lr.py +65 -0
- openpoints/scheduler/tanh_lr.py +117 -0
- openpoints/transforms/__init__.py +7 -0
- openpoints/transforms/point_transform_cpu.py +332 -0
- openpoints/transforms/point_transformer_gpu.py +764 -0
- openpoints/transforms/transforms_factory.py +60 -0
- openpoints/utils/__init__.py +8 -0
- openpoints/utils/ckpt_util.py +438 -0
- openpoints/utils/config.py +113 -0
- openpoints/utils/dist_utils.py +54 -0
- openpoints/utils/logger.py +170 -0
- openpoints/utils/metrics.py +311 -0
- openpoints/utils/random.py +16 -0
- openpoints/utils/registry.py +294 -0
- openpoints/utils/str2bool.py +11 -0
- openpoints/utils/wandb.py +88 -0
- openpoints-0.1.0.dist-info/METADATA +150 -0
- openpoints-0.1.0.dist-info/RECORD +184 -0
- openpoints-0.1.0.dist-info/WHEEL +5 -0
- openpoints-0.1.0.dist-info/licenses/LICENSE +21 -0
- openpoints-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
from typing import Tuple
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
from torch.autograd import Function
|
|
5
|
+
import torch.nn as nn
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
import pointops_cuda
|
|
9
|
+
except ImportError as exc:
|
|
10
|
+
class _MissingCudaExtension:
|
|
11
|
+
def __init__(self, module_name, error):
|
|
12
|
+
self.module_name = module_name
|
|
13
|
+
self.error = error
|
|
14
|
+
|
|
15
|
+
def __getattr__(self, name):
|
|
16
|
+
raise ImportError(
|
|
17
|
+
f"{self.module_name} is not installed. Build OpenPoints CUDA ops from "
|
|
18
|
+
"source first, e.g. `cd cpp/pointops && python setup.py install`, "
|
|
19
|
+
"or install a wheel that includes the compiled CUDA extension."
|
|
20
|
+
) from self.error
|
|
21
|
+
|
|
22
|
+
pointops_cuda = _MissingCudaExtension("pointops_cuda", exc)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FurthestSampling(Function):
|
|
26
|
+
@staticmethod
|
|
27
|
+
def forward(ctx, xyz, offset, new_offset):
|
|
28
|
+
"""
|
|
29
|
+
input: xyz: (n, 3), offset: (b), new_offset: (b)
|
|
30
|
+
output: idx: (m)
|
|
31
|
+
"""
|
|
32
|
+
assert xyz.is_contiguous()
|
|
33
|
+
n, b, n_max = xyz.shape[0], offset.shape[0], offset[0]
|
|
34
|
+
for i in range(1, b):
|
|
35
|
+
n_max = max(offset[i] - offset[i - 1], n_max)
|
|
36
|
+
idx = torch.cuda.IntTensor(new_offset[b - 1].item()).zero_()
|
|
37
|
+
tmp = torch.cuda.FloatTensor(n).fill_(1e10)
|
|
38
|
+
pointops_cuda.furthestsampling_cuda(
|
|
39
|
+
b, n_max, xyz, offset, new_offset, tmp, idx)
|
|
40
|
+
del tmp
|
|
41
|
+
return idx
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
furthestsampling = FurthestSampling.apply
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class KNNQuery(Function):
|
|
48
|
+
@staticmethod
|
|
49
|
+
def forward(ctx, nsample, xyz, new_xyz, offset, new_offset):
|
|
50
|
+
"""
|
|
51
|
+
input: xyz: (n, 3), new_xyz: (m, 3), offset: (b), new_offset: (b)
|
|
52
|
+
output: idx: (m, nsample), dist2: (m, nsample)
|
|
53
|
+
"""
|
|
54
|
+
if new_xyz is None:
|
|
55
|
+
new_xyz = xyz
|
|
56
|
+
assert xyz.is_contiguous() and new_xyz.is_contiguous()
|
|
57
|
+
m = new_xyz.shape[0]
|
|
58
|
+
idx = torch.cuda.IntTensor(m, nsample).zero_()
|
|
59
|
+
dist2 = torch.cuda.FloatTensor(m, nsample).zero_()
|
|
60
|
+
pointops_cuda.knnquery_cuda(
|
|
61
|
+
m, nsample, xyz, new_xyz, offset, new_offset, idx, dist2)
|
|
62
|
+
return idx, torch.sqrt(dist2)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
knnquery = KNNQuery.apply
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class BallQuery(Function):
|
|
69
|
+
@staticmethod
|
|
70
|
+
def forward(ctx, radius, nsample, xyz, new_xyz, offset, new_offset):
|
|
71
|
+
"""
|
|
72
|
+
input: xyz: (n, 3), new_xyz: (m, 3), offset: (b), new_offset: (b)
|
|
73
|
+
output: idx: (m, nsample), dist2: (m, nsample)
|
|
74
|
+
"""
|
|
75
|
+
if new_xyz is None:
|
|
76
|
+
new_xyz = xyz
|
|
77
|
+
assert xyz.is_contiguous() and new_xyz.is_contiguous()
|
|
78
|
+
m = new_xyz.shape[0]
|
|
79
|
+
idx = torch.cuda.IntTensor(m, nsample).zero_()
|
|
80
|
+
pointops_cuda.ballquery_cuda(
|
|
81
|
+
m, radius, nsample, xyz, new_xyz, offset, new_offset, idx)
|
|
82
|
+
return idx
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
ballquery = BallQuery.apply
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Grouping(Function):
|
|
89
|
+
@staticmethod
|
|
90
|
+
def forward(ctx, input, idx):
|
|
91
|
+
"""
|
|
92
|
+
input: input: (n, c), idx : (m, nsample)
|
|
93
|
+
output: (m, nsample, c)
|
|
94
|
+
"""
|
|
95
|
+
assert input.is_contiguous() and idx.is_contiguous()
|
|
96
|
+
m, nsample, n, c = idx.shape[0], idx.shape[1], input.shape[0], input.shape[1]
|
|
97
|
+
output = torch.cuda.FloatTensor(m, nsample, c)
|
|
98
|
+
pointops_cuda.grouping_forward_cuda(m, nsample, c, input, idx, output)
|
|
99
|
+
ctx.n = n
|
|
100
|
+
ctx.save_for_backward(idx)
|
|
101
|
+
return output
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
def backward(ctx, grad_output):
|
|
105
|
+
"""
|
|
106
|
+
input: grad_out: (m, c, nsample)
|
|
107
|
+
output: (n, c), None
|
|
108
|
+
"""
|
|
109
|
+
n = ctx.n
|
|
110
|
+
idx, = ctx.saved_tensors
|
|
111
|
+
m, nsample, c = grad_output.shape
|
|
112
|
+
grad_input = torch.cuda.FloatTensor(n, c).zero_()
|
|
113
|
+
pointops_cuda.grouping_backward_cuda(
|
|
114
|
+
m, nsample, c, grad_output, idx, grad_input)
|
|
115
|
+
return grad_input, None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
grouping = Grouping.apply
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def querygroup(nsample, xyz, new_xyz, feat, offset, new_offset,
|
|
122
|
+
radius=None, query_method='knn',
|
|
123
|
+
normalize_dp=False, idx=None
|
|
124
|
+
):
|
|
125
|
+
"""
|
|
126
|
+
the query and group function
|
|
127
|
+
support KNN and Ball Query
|
|
128
|
+
input: xyz: (n, 3), new_xyz: (m, 3), feat: (n, c), offset: (b), new_offset: (b), idx: (m, nsample)
|
|
129
|
+
output:
|
|
130
|
+
"""
|
|
131
|
+
assert xyz.is_contiguous() and new_xyz.is_contiguous() and feat.is_contiguous()
|
|
132
|
+
if new_xyz is None:
|
|
133
|
+
new_xyz = xyz
|
|
134
|
+
if idx is None:
|
|
135
|
+
if nsample is not None:
|
|
136
|
+
if query_method in ['knn', 'knnquery']:
|
|
137
|
+
idx, _ = knnquery(nsample, xyz, new_xyz,
|
|
138
|
+
offset, new_offset) # (m, nsample)
|
|
139
|
+
else:
|
|
140
|
+
idx = ballquery(radius, nsample, xyz,
|
|
141
|
+
new_xyz, offset, new_offset) # (m, nsample)
|
|
142
|
+
idx = idx.flatten().long()
|
|
143
|
+
n, m, c = xyz.shape[0], new_xyz.shape[0], feat.shape[1]
|
|
144
|
+
grouped_xyz = xyz[idx, :].view(
|
|
145
|
+
m, nsample, 3) # (m, nsample, 3)
|
|
146
|
+
grouped_xyz -= new_xyz.unsqueeze(1) # (m, nsample, 3)
|
|
147
|
+
if normalize_dp:
|
|
148
|
+
max_dist = grouped_xyz.norm(dim=-1, p=2, keepdim=True).max(dim=-1, keepdim=True)[
|
|
149
|
+
0] + 1.0e-8 if query_method == 'knn' else radius
|
|
150
|
+
grouped_xyz /= max_dist
|
|
151
|
+
|
|
152
|
+
if feat is not None:
|
|
153
|
+
grouped_feat = feat[idx, :].view(
|
|
154
|
+
m, nsample, c) # (m, nsample, c)
|
|
155
|
+
else:
|
|
156
|
+
grouped_feat = None
|
|
157
|
+
else:
|
|
158
|
+
grouped_xyz = xyz.transpose(1, 2).unsqueeze(2)
|
|
159
|
+
if feat is not None:
|
|
160
|
+
grouped_feat = feat.unsqueeze(2)
|
|
161
|
+
else:
|
|
162
|
+
grouped_feat = None
|
|
163
|
+
return grouped_xyz, grouped_feat
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def queryandgroup(nsample, xyz, new_xyz, feat, idx, offset, new_offset, use_xyz=True):
|
|
167
|
+
"""
|
|
168
|
+
input: xyz: (n, 3), new_xyz: (m, 3), feat: (n, c), idx: (m, nsample), offset: (b), new_offset: (b)
|
|
169
|
+
output: new_feat: (m, c+3, nsample), grouped_idx: (m, nsample)
|
|
170
|
+
"""
|
|
171
|
+
assert xyz.is_contiguous() and new_xyz.is_contiguous() and feat.is_contiguous()
|
|
172
|
+
if new_xyz is None:
|
|
173
|
+
new_xyz = xyz
|
|
174
|
+
if idx is None:
|
|
175
|
+
idx, _ = knnquery(nsample, xyz, new_xyz, offset,
|
|
176
|
+
new_offset) # (m, nsample)
|
|
177
|
+
|
|
178
|
+
n, m, c = xyz.shape[0], new_xyz.shape[0], feat.shape[1]
|
|
179
|
+
grouped_xyz = xyz[idx.view(-1).long(), :].view(m,
|
|
180
|
+
nsample, 3) # (m, nsample, 3)
|
|
181
|
+
grouped_xyz -= new_xyz.unsqueeze(1) # (m, nsample, 3)
|
|
182
|
+
grouped_feat = feat[idx.view(-1).long(), :].view(m, nsample, c)
|
|
183
|
+
|
|
184
|
+
if use_xyz:
|
|
185
|
+
return torch.cat((grouped_xyz, grouped_feat), -1) # (m, nsample, 3+c)
|
|
186
|
+
else:
|
|
187
|
+
return grouped_feat
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class Subtraction(Function):
|
|
191
|
+
@staticmethod
|
|
192
|
+
def forward(ctx, input1, input2, idx):
|
|
193
|
+
"""
|
|
194
|
+
input: input1: (n, c), input2: (n, c), idx: (n, nsample)
|
|
195
|
+
output: (n, nsample, c)
|
|
196
|
+
"""
|
|
197
|
+
assert input1.is_contiguous() and input2.is_contiguous()
|
|
198
|
+
n, c = input1.shape
|
|
199
|
+
nsample = idx.shape[-1]
|
|
200
|
+
output = torch.cuda.FloatTensor(n, nsample, c).zero_()
|
|
201
|
+
pointops_cuda.subtraction_forward_cuda(
|
|
202
|
+
n, nsample, c, input1, input2, idx, output)
|
|
203
|
+
ctx.save_for_backward(idx)
|
|
204
|
+
return output
|
|
205
|
+
|
|
206
|
+
@staticmethod
|
|
207
|
+
def backward(ctx, grad_output):
|
|
208
|
+
"""
|
|
209
|
+
input: grad_out: (n, nsample, c)
|
|
210
|
+
output: grad_input1: (n, c), grad_input2: (n, c)
|
|
211
|
+
"""
|
|
212
|
+
idx, = ctx.saved_tensors
|
|
213
|
+
n, nsample, c = grad_output.shape
|
|
214
|
+
grad_input1 = torch.cuda.FloatTensor(n, c).zero_()
|
|
215
|
+
grad_input2 = torch.cuda.FloatTensor(n, c).zero_()
|
|
216
|
+
pointops_cuda.subtraction_backward_cuda(
|
|
217
|
+
n, nsample, c, idx, grad_output, grad_input1, grad_input2)
|
|
218
|
+
return grad_input1, grad_input2, None
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
subtraction = Subtraction.apply
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class Aggregation(Function):
|
|
225
|
+
@staticmethod
|
|
226
|
+
def forward(ctx, input, position, weight, idx):
|
|
227
|
+
"""
|
|
228
|
+
input: input: (n, c), position: (n, nsample, c), weight : (n, nsample, c'), idx: (n, nsample)
|
|
229
|
+
output: (n, c)
|
|
230
|
+
"""
|
|
231
|
+
assert input.is_contiguous() and position.is_contiguous() and weight.is_contiguous()
|
|
232
|
+
n, nsample, c = position.shape
|
|
233
|
+
w_c = weight.shape[-1]
|
|
234
|
+
output = torch.cuda.FloatTensor(n, c).zero_()
|
|
235
|
+
pointops_cuda.aggregation_forward_cuda(
|
|
236
|
+
n, nsample, c, w_c, input, position, weight, idx, output)
|
|
237
|
+
ctx.save_for_backward(input, position, weight, idx)
|
|
238
|
+
return output
|
|
239
|
+
|
|
240
|
+
@staticmethod
|
|
241
|
+
def backward(ctx, grad_output):
|
|
242
|
+
"""
|
|
243
|
+
input: grad_out: (n, c)
|
|
244
|
+
output: grad_input: (n, c), grad_position: (n, nsample, c), grad_weight : (n, nsample, c')
|
|
245
|
+
"""
|
|
246
|
+
input, position, weight, idx = ctx.saved_tensors
|
|
247
|
+
n, nsample, c = position.shape
|
|
248
|
+
w_c = weight.shape[-1]
|
|
249
|
+
grad_input = torch.cuda.FloatTensor(n, c).zero_()
|
|
250
|
+
grad_position = torch.cuda.FloatTensor(n, nsample, c).zero_()
|
|
251
|
+
grad_weight = torch.cuda.FloatTensor(n, nsample, w_c).zero_()
|
|
252
|
+
pointops_cuda.aggregation_backward_cuda(n, nsample, c, w_c, input, position, weight, idx, grad_output,
|
|
253
|
+
grad_input, grad_position, grad_weight)
|
|
254
|
+
return grad_input, grad_position, grad_weight, None
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
aggregation = Aggregation.apply
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def interpolation(xyz, new_xyz, feat, offset, new_offset, k=3):
|
|
261
|
+
"""
|
|
262
|
+
input: xyz: (m, 3), new_xyz: (n, 3), feat: (m, c), offset: (b), new_offset: (b)
|
|
263
|
+
output: (n, c)
|
|
264
|
+
"""
|
|
265
|
+
assert xyz.is_contiguous() and new_xyz.is_contiguous() and feat.is_contiguous()
|
|
266
|
+
idx, dist = knnquery(k, xyz, new_xyz, offset, new_offset) # (n, 3), (n, 3)
|
|
267
|
+
dist_recip = 1.0 / (dist + 1e-8) # (n, 3)
|
|
268
|
+
norm = torch.sum(dist_recip, dim=1, keepdim=True)
|
|
269
|
+
weight = dist_recip / norm # (n, 3)
|
|
270
|
+
|
|
271
|
+
new_feat = torch.cuda.FloatTensor(new_xyz.shape[0], feat.shape[1]).zero_()
|
|
272
|
+
for i in range(k):
|
|
273
|
+
new_feat += feat[idx[:, i].long(), :] * weight[:, i].unsqueeze(-1)
|
|
274
|
+
return new_feat
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class Interpolation(Function):
|
|
278
|
+
@staticmethod
|
|
279
|
+
def forward(ctx, xyz, new_xyz, input, offset, new_offset, k=3):
|
|
280
|
+
"""
|
|
281
|
+
input: xyz: (m, 3), new_xyz: (n, 3), input: (m, c), offset: (b), new_offset: (b)
|
|
282
|
+
output: (n, c)
|
|
283
|
+
"""
|
|
284
|
+
assert xyz.is_contiguous() and new_xyz.is_contiguous() and input.is_contiguous()
|
|
285
|
+
idx, dist = knnquery(k, xyz, new_xyz, offset,
|
|
286
|
+
new_offset) # (n, k), (n, k)
|
|
287
|
+
dist_recip = 1.0 / (dist + 1e-8) # (n, k)
|
|
288
|
+
norm = torch.sum(dist_recip, dim=1, keepdim=True)
|
|
289
|
+
weight = dist_recip / norm # (n, k)
|
|
290
|
+
|
|
291
|
+
n, c, m = new_xyz.shape[0], input.shape[1], input.shape[0]
|
|
292
|
+
output = torch.cuda.FloatTensor(n, c).zero_()
|
|
293
|
+
pointops_cuda.interpolation_forward_cuda(
|
|
294
|
+
n, c, k, input, idx, weight, output)
|
|
295
|
+
ctx.m, ctx.k = m, k
|
|
296
|
+
ctx.save_for_backward(idx, weight)
|
|
297
|
+
return output
|
|
298
|
+
|
|
299
|
+
@staticmethod
|
|
300
|
+
def backward(ctx, grad_output):
|
|
301
|
+
"""
|
|
302
|
+
input: xyz: (m, 3), new_xyz: (n, 3), input: (m, c), offset: (b), new_offset: (b)
|
|
303
|
+
output: (n, c)
|
|
304
|
+
"""
|
|
305
|
+
m, k = ctx.m, ctx.k
|
|
306
|
+
idx, weight = ctx.saved_tensors
|
|
307
|
+
n, c = grad_output.shape
|
|
308
|
+
grad_input = torch.cuda.FloatTensor(m, c).zero_()
|
|
309
|
+
pointops_cuda.interpolation_backward_cuda(
|
|
310
|
+
n, c, k, grad_output, idx, weight, grad_input)
|
|
311
|
+
return None, None, grad_input, None, None, None
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
interpolation2 = Interpolation.apply
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#python3 setup.py install
|
|
2
|
+
from setuptools import setup
|
|
3
|
+
from torch.utils.cpp_extension import BuildExtension, CUDAExtension
|
|
4
|
+
import os
|
|
5
|
+
from distutils.sysconfig import get_config_vars
|
|
6
|
+
|
|
7
|
+
(opt,) = get_config_vars('OPT')
|
|
8
|
+
os.environ['OPT'] = " ".join(
|
|
9
|
+
flag for flag in opt.split() if flag != '-Wstrict-prototypes'
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
setup(
|
|
13
|
+
name='pointops',
|
|
14
|
+
author='Hengshuang Zhao',
|
|
15
|
+
ext_modules=[
|
|
16
|
+
CUDAExtension('pointops_cuda', [
|
|
17
|
+
'src/pointops_api.cpp',
|
|
18
|
+
'src/knnquery/knnquery_cuda.cpp',
|
|
19
|
+
'src/knnquery/knnquery_cuda_kernel.cu',
|
|
20
|
+
'src/ballquery/ballquery_cuda.cpp',
|
|
21
|
+
'src/ballquery/ballquery_cuda_kernel.cu',
|
|
22
|
+
'src/sampling/sampling_cuda.cpp',
|
|
23
|
+
'src/sampling/sampling_cuda_kernel.cu',
|
|
24
|
+
'src/grouping/grouping_cuda.cpp',
|
|
25
|
+
'src/grouping/grouping_cuda_kernel.cu',
|
|
26
|
+
'src/interpolation/interpolation_cuda.cpp',
|
|
27
|
+
'src/interpolation/interpolation_cuda_kernel.cu',
|
|
28
|
+
'src/subtraction/subtraction_cuda.cpp',
|
|
29
|
+
'src/subtraction/subtraction_cuda_kernel.cu',
|
|
30
|
+
'src/aggregation/aggregation_cuda.cpp',
|
|
31
|
+
'src/aggregation/aggregation_cuda_kernel.cu',
|
|
32
|
+
],
|
|
33
|
+
extra_compile_args={'cxx': ['-g'], 'nvcc': ['-O2']}
|
|
34
|
+
)
|
|
35
|
+
],
|
|
36
|
+
cmdclass={'build_ext': BuildExtension}
|
|
37
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from .data_util import get_features_by_keys, crop_pc, get_class_weights
|
|
2
|
+
from .build import build_dataloader_from_cfg, build_dataset_from_cfg
|
|
3
|
+
from .vis3d import vis_multi_points, vis_points
|
|
4
|
+
from .modelnet import *
|
|
5
|
+
from .s3dis import S3DIS, S3DISSphere
|
|
6
|
+
from .shapenet import *
|
|
7
|
+
from .semantic_kitti import *
|
|
8
|
+
from .scanobjectnn import *
|
|
9
|
+
from .shapenetpart import *
|
|
10
|
+
from .scannetv2 import *
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .psr import Atom2Points, AtomPSR
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
from atom3d.datasets import LMDBDataset
|
|
4
|
+
from ..build import DATASETS
|
|
5
|
+
from ...transforms import DataTransforms
|
|
6
|
+
|
|
7
|
+
prot_atoms = ['C', 'H', 'O', 'N', 'S', 'P', 'ZN', 'NA', 'FE', 'CA', 'MN', 'NI', 'CO', 'MG', 'CU', 'CL', 'SE', 'F']
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def one_of_k_encoding_unk(x, allowable_set):
|
|
11
|
+
"""Converts input to 1-hot encoding given a set of allowable values. Additionally maps inputs not in the allowable set to the last element."""
|
|
12
|
+
if x not in allowable_set:
|
|
13
|
+
x = allowable_set[-1]
|
|
14
|
+
return list(map(lambda s: x == s, allowable_set))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@DataTransforms.register_module()
|
|
18
|
+
class Atom2Points(object):
|
|
19
|
+
def __call__(self, item):
|
|
20
|
+
# Transform protein into voxel grids.
|
|
21
|
+
# Apply random rotation matrix.
|
|
22
|
+
id = eval(item['id'])
|
|
23
|
+
transformed = {
|
|
24
|
+
'pos': item['atoms'][['x', 'y', 'z']].to_numpy().astype(np.float32),
|
|
25
|
+
'features': np.array([one_of_k_encoding_unk(e, prot_atoms) for e in item['atoms']['element']]).astype(np.float32).transpose(1, 0),
|
|
26
|
+
'label': np.float32(item['scores']['gdt_ts']),
|
|
27
|
+
'target': id[0],
|
|
28
|
+
'decoy': id[1],
|
|
29
|
+
}
|
|
30
|
+
return transformed
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@DATASETS.register_module()
|
|
34
|
+
class AtomPSR(LMDBDataset):
|
|
35
|
+
def __init__(self, data_dir, split, transform=Atom2Points()):
|
|
36
|
+
assert split in ['train', 'val', 'test']
|
|
37
|
+
super().__init__(os.path.join(data_dir, split), transform)
|
|
38
|
+
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: PointNeXt
|
|
3
|
+
"""
|
|
4
|
+
import numpy as np
|
|
5
|
+
import torch
|
|
6
|
+
from easydict import EasyDict as edict
|
|
7
|
+
from openpoints.utils import registry
|
|
8
|
+
from openpoints.transforms import build_transforms_from_cfg
|
|
9
|
+
|
|
10
|
+
DATASETS = registry.Registry('dataset')
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def concat_collate_fn(datas):
|
|
14
|
+
"""collate fn for point transformer
|
|
15
|
+
"""
|
|
16
|
+
pts, feats, labels, offset, count, batches = [], [], [], [], 0, []
|
|
17
|
+
for i, data in enumerate(datas):
|
|
18
|
+
count += len(data['pos'])
|
|
19
|
+
offset.append(count)
|
|
20
|
+
pts.append(data['pos'])
|
|
21
|
+
feats.append(data['x'])
|
|
22
|
+
labels.append(data['y'])
|
|
23
|
+
batches += [i] *len(data['pos'])
|
|
24
|
+
|
|
25
|
+
data = {'pos': torch.cat(pts), 'x': torch.cat(feats), 'y': torch.cat(labels),
|
|
26
|
+
'o': torch.IntTensor(offset), 'batch': torch.LongTensor(batches)}
|
|
27
|
+
return data
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def build_dataset_from_cfg(cfg, default_args=None):
|
|
31
|
+
"""
|
|
32
|
+
Build a dataset, defined by `dataset_name`.
|
|
33
|
+
Args:
|
|
34
|
+
cfg (eDICT):
|
|
35
|
+
Returns:
|
|
36
|
+
Dataset: a constructed dataset specified by dataset_name.
|
|
37
|
+
"""
|
|
38
|
+
return DATASETS.build(cfg, default_args=default_args)
|
|
39
|
+
|
|
40
|
+
def worker_init_fn(worker_id):
|
|
41
|
+
np.random.seed(np.random.get_state()[1][0] + worker_id)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def build_dataloader_from_cfg(batch_size,
|
|
45
|
+
dataset_cfg=None,
|
|
46
|
+
dataloader_cfg=None,
|
|
47
|
+
datatransforms_cfg=None,
|
|
48
|
+
split='train',
|
|
49
|
+
distributed=True,
|
|
50
|
+
dataset=None
|
|
51
|
+
):
|
|
52
|
+
if dataset is None:
|
|
53
|
+
if datatransforms_cfg is not None:
|
|
54
|
+
# in case only val or test transforms are provided.
|
|
55
|
+
if split not in datatransforms_cfg.keys() and split in ['val', 'test']:
|
|
56
|
+
trans_split = 'val'
|
|
57
|
+
else:
|
|
58
|
+
trans_split = split
|
|
59
|
+
data_transform = build_transforms_from_cfg(trans_split, datatransforms_cfg)
|
|
60
|
+
else:
|
|
61
|
+
data_transform = None
|
|
62
|
+
|
|
63
|
+
if split not in dataset_cfg.keys() and split in ['val', 'test']:
|
|
64
|
+
dataset_split = 'test' if split == 'val' else 'val'
|
|
65
|
+
else:
|
|
66
|
+
dataset_split = split
|
|
67
|
+
split_cfg = dataset_cfg.get(dataset_split, edict())
|
|
68
|
+
if split_cfg.get('split', None) is None: # add 'split' in dataset_split_cfg
|
|
69
|
+
split_cfg.split = split
|
|
70
|
+
split_cfg.transform = data_transform
|
|
71
|
+
dataset = build_dataset_from_cfg(dataset_cfg.common, split_cfg)
|
|
72
|
+
|
|
73
|
+
collate_fn = dataset.collate_fn if hasattr(dataset, 'collate_fn') else None
|
|
74
|
+
collate_fn = dataloader_cfg.collate_fn if dataloader_cfg.get('collate_fn', None) is not None else collate_fn
|
|
75
|
+
collate_fn = eval(collate_fn) if isinstance(collate_fn, str) else collate_fn
|
|
76
|
+
|
|
77
|
+
shuffle = split == 'train'
|
|
78
|
+
if distributed:
|
|
79
|
+
sampler = torch.utils.data.distributed.DistributedSampler(dataset, shuffle=shuffle)
|
|
80
|
+
dataloader = torch.utils.data.DataLoader(dataset,
|
|
81
|
+
batch_size=batch_size,
|
|
82
|
+
num_workers=int(dataloader_cfg.num_workers),
|
|
83
|
+
worker_init_fn=worker_init_fn,
|
|
84
|
+
drop_last=split == 'train',
|
|
85
|
+
sampler=sampler,
|
|
86
|
+
collate_fn=collate_fn,
|
|
87
|
+
pin_memory=True
|
|
88
|
+
)
|
|
89
|
+
else:
|
|
90
|
+
dataloader = torch.utils.data.DataLoader(dataset,
|
|
91
|
+
batch_size=batch_size,
|
|
92
|
+
num_workers=int(dataloader_cfg.num_workers),
|
|
93
|
+
worker_init_fn=worker_init_fn,
|
|
94
|
+
drop_last=split == 'train',
|
|
95
|
+
shuffle=shuffle,
|
|
96
|
+
collate_fn=collate_fn,
|
|
97
|
+
pin_memory=True)
|
|
98
|
+
return dataloader
|