internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: open-mmlab/mmdetection3d

Issue:
Question about 3d NMS
As I can see [iou3d_utils](https://github.com/open-mmlab/mmdetection3d/blob/master/mmdet3d/ops/iou3d/iou3d_utils.py) is based on [iou3d_nms_utils](https://github.com/open-mmlab/OpenPCDet/blob/master/pcdet/ops/iou3d_nms/iou3d_nms_utils.py) of `OpenPCDet`. The implementation in `OpenPCDet` supports fair `iou` and `nms` with full 3d parametrization: `[x, y, z, dx, dy, dz, heading]`. However the implementation in `mmdetection3d` supports only `[x1, y1, x2, y2, ry]`. This design choice brings a couple of disadvantages. For example, for `VoteNet` on `SUNRGBD` we first predict boxes with angles and then [apply](https://github.com/open-mmlab/mmdetection3d/blob/master/mmdet3d/models/dense_heads/vote_head.py#L627) `nms` to the aligned boxes without angle.

So, my question is, why not to use `nms` from `OpenPCDet` instead of applying lifehacks with `aligned_nms` or `bev_nms`?
Thanks in advance.


Discussion:
Also looks like doc string of [box3d_milticlass_nms](https://github.com/open-mmlab/mmdetection3d/blob/master/mmdet3d/core/post_processing/box3d_nms.py#L8) is incorrect. `mlvl_bboxes_for_nms` real shape is `(N, 5)`, not `(N, 4)`. `mlvl_scores` real shape is `(N, n_classes + 1)`, not `(N,)`.

Also this `+ 1` for background looks like a legacy thing, leading to hacks [here](https://github.com/open-mmlab/mmdetection3d/blob/440e44a0e03d575bf682d35ab2771e88f774f4dc/mmdet3d/models/dense_heads/shape_aware_head.py#L466) and [here](https://github.com/open-mmlab/mmdetection3d/blob/440e44a0e03d575bf682d35ab2771e88f774f4dc/mmdet3d/models/dense_heads/anchor3d_head.py#L494). Can make a PR to fix it, if you think it is needed.
For VoteNet we simply follow the official implementation.
The settings of the coordinates system are a legacy issue, we are working on that to provide a more natural and simpler system in the codebases.
For docstring issues, would you like to create a PR to fix that? Thanks in advance for your kind contribution.

Resolving patch:
diff --git a/mmdet3d/core/post_processing/box3d_nms.py b/mmdet3d/core/post_processing/box3d_nms.py
--- a/mmdet3d/core/post_processing/box3d_nms.py
+++ b/mmdet3d/core/post_processing/box3d_nms.py
@@ -18,9 +18,9 @@ def box3d_multiclass_nms(mlvl_bboxes,
         mlvl_bboxes (torch.Tensor): Multi-level boxes with shape (N, M).
             M is the dimensions of boxes.
         mlvl_bboxes_for_nms (torch.Tensor): Multi-level boxes with shape
-            (N, 4). N is the number of boxes.
+            (N, 5) ([x1, y1, x2, y2, ry]). N is the number of boxes.
         mlvl_scores (torch.Tensor): Multi-level boxes with shape
-            (N, ). N is the number of boxes.
+            (N, C + 1). N is the number of boxes. C is the number of classes.
         score_thr (float): Score thredhold to filter boxes with low
             confidence.
         max_num (int): Maximum number of boxes will be kept.


Test patch:
Repository: open-mmlab/mmdetection3d

Issue:
votenet pre-trained scannet model doesn't work!  KeyError: 'ann_info'
raceback (most recent call last):
  File "demo/pcd_demo.py", line 41, in <module>
    main()
  File "demo/pcd_demo.py", line 28, in main
    result, data = inference_detector(model, args.pcd)
  File "/home/user/deeplearning/mmdetection3d/mmdet3d/apis/inference.py", line 102, in inference_detector
    data = test_pipeline(data)
  File "/home/user/deeplearning/mmdetection/mmdet/datasets/pipelines/compose.py", line 40, in __call__
    data = t(data)
  File "/home/user/deeplearning/mmdetection3d/mmdet3d/datasets/pipelines/transforms_3d.py", line 406, in __call__
    assert 'axis_align_matrix' in input_dict['ann_info'].keys(), \
KeyError: 'ann_info'



Discussion:
Thank you for pointing out the bug. I will raise a PR to fix it.
This bug is because we only support VoteNet demo on SUN RGB-D dataset, and ScanNet is slightly different from SUN RGB-D. Maybe you can try playing with the SUN RGB-D VoteNet weight first?

Resolving patch:
diff --git a/mmdet3d/apis/inference.py b/mmdet3d/apis/inference.py
--- a/mmdet3d/apis/inference.py
+++ b/mmdet3d/apis/inference.py
@@ -89,6 +89,8 @@ def inference_detector(model, pcd):
         pts_filename=pcd,
         box_type_3d=box_type_3d,
         box_mode_3d=box_mode_3d,
+        # for ScanNet demo we need axis_align_matrix
+        ann_info=dict(axis_align_matrix=np.eye(4)),
         sweeps=[],
         # set timestamp = 0
         timestamp=[0],


Test patch:
Repository: open-mmlab/mmdetection3d

Issue:
Bug in indoor_converter
If `pkl_prefix=='sunrgbd'` we go to this [else](https://github.com/open-mmlab/mmdetection3d/blob/master/tools/data_converter/indoor_converter.py#L89) for `s3dis` and get `FileNotFoundError`.


Discussion:

Resolving patch:
diff --git a/tools/data_converter/indoor_converter.py b/tools/data_converter/indoor_converter.py
--- a/tools/data_converter/indoor_converter.py
+++ b/tools/data_converter/indoor_converter.py
@@ -86,7 +86,7 @@ def create_indoor_info_file(data_path,
         # no need to generate for test set
         train_dataset.get_seg_infos()
         val_dataset.get_seg_infos()
-    else:
+    elif pkl_prefix == 's3dis':
         # S3DIS doesn't have a fixed train-val split
         # it has 6 areas instead, so we generate info file for each of them
         # in training, we will use dataset to wrap different areas


Test patch:
Repository: open-mmlab/mmdetection3d

Issue:
An error occurred while creating Scannetv2 data
@Wuziyi616  I am trying to create the Scannet dataset as required, but an error occurred when I operate ```python tools/create_data.py scannet --root-path ./data/scannet --out-dir ./data/scannet --extra-tag scannet```. Here is the error message:
```
scannet info test file is saved to ./data/scannet/scannet_infos_test.pkl
Traceback (most recent call last):
  File "tools/create_data.py", line 300, in <module>
    workers=args.workers)
  File "tools/create_data.py", line 134, in scannet_data_prep
    root_path, info_prefix, out_dir, workers=workers)
  File "/scratch1/du014/Auxiliary_Code/mmdetection3d/tools/data_converter/indoor_converter.py", line 87, in create_indoor_info_file
    train_dataset.get_seg_infos()
  File "/scratch1/du014/Auxiliary_Code/mmdetection3d/tools/data_converter/scannet_data_utils.py", line 204, in get_seg_infos
    scene_idxs, label_weight = self.get_scene_idxs_and_label_weight()
  File "/scratch1/du014/Auxiliary_Code/mmdetection3d/tools/data_converter/scannet_data_utils.py", line 247, in get_scene_idxs_and_label_weight
    scene_idxs.extend([idx] * round(sample_prob[idx] * num_iter))
TypeError: can't multiply sequence by non-int of type 'numpy.float64'
```

My environment:
- cuda 10.2
- python 3.6
- mmcv-full 1.3.7
- mmdet 2.11.0
- mmdet3d 0.14.0
- mmsegmentation 0.14.0
- numpy 1.18.0

Can anyone help me????


Discussion:
It's very strange because `round()` should convert the value to `int`. Maybe you can change it to `scene_idxs.extend([idx] * int(round(sample_prob[idx] * num_iter)))` and have a try?
Hi @Wuziyi616,
I'm also meeting this bug. The thing is `type(round(np.float64)) == np.float64`. Should we reopen this and fix?
BTW, your solution is fine.
Yes of course! Can you kindly fix it in a one line PR? Thanks!

Resolving patch:
diff --git a/tools/data_converter/scannet_data_utils.py b/tools/data_converter/scannet_data_utils.py
--- a/tools/data_converter/scannet_data_utils.py
+++ b/tools/data_converter/scannet_data_utils.py
@@ -244,7 +244,7 @@ def get_scene_idxs_and_label_weight(self):
         num_iter = int(np.sum(num_point_all) / float(self.num_points))
         scene_idxs = []
         for idx in range(len(self.data_infos)):
-            scene_idxs.extend([idx] * round(sample_prob[idx] * num_iter))
+            scene_idxs.extend([idx] * int(round(sample_prob[idx] * num_iter)))
         scene_idxs = np.array(scene_idxs).astype(np.int32)
 
         # calculate label weight, adopted from PointNet++


Test patch:
Repository: open-mmlab/mmdetection3d

Issue:
Possible bug with 'rt_mat (np.ndarray)' in coord_3d_mode
https://github.com/open-mmlab/mmdetection3d/blob/a1e04538295b02d42fc59bb7ed58c59c98220174/mmdet3d/core/bbox/structures/coord_3d_mode.py#L246

Should it be `if rt_mat.shape[1] == 4:` to take into account both (np.ndarray | torch.Tensor) types of `rt_mat` as input 
or
convert `rt_mat` from np.ndarray to torch.Tensor before using `if rt_mat.size(1) == 4` ?


Discussion:
I agree. Can you kindly make an one-line PR to change it to `rt_mat.shape[1]`? Thanks!
I found that instead of changing to `rt_mat.shape[1]`, the second choice of converting `rt_mat` from np.ndarray to torch.Tensor helps because in further code torch.Tensor type methods are being used! I would make a PR 

Resolving patch:
diff --git a/mmdet3d/core/bbox/structures/coord_3d_mode.py b/mmdet3d/core/bbox/structures/coord_3d_mode.py
--- a/mmdet3d/core/bbox/structures/coord_3d_mode.py
+++ b/mmdet3d/core/bbox/structures/coord_3d_mode.py
@@ -243,6 +243,8 @@ def convert_point(point, src, dst, rt_mat=None):
                 f'Conversion from Coord3DMode {src} to {dst} '
                 'is not supported yet')
 
+        if not isinstance(rt_mat, torch.Tensor):
+            rt_mat = arr.new_tensor(rt_mat)
         if rt_mat.size(1) == 4:
             extended_xyz = torch.cat(
                 [arr[:, :3], arr.new_ones(arr.size(0), 1)], dim=-1)


Test patch:
Repository: open-mmlab/mmdetection3d

Issue:
Possible bug in 'bev_range' of ObjectRangeFilter
https://github.com/open-mmlab/mmdetection3d/blob/ea846013ed0b1e561887ec1789fcaae2a0c037e8/mmdet3d/datasets/pipelines/transforms_3d.py#L702

Here, I think it is assumed that the points coordinate system is LIDAR (KITTI: Z-up) by default, but isn't this should be made consistent to points type (like LIDAR or CAMERA), because if points are loaded in CAMERA coordinate system (KITTI: Y-down), then the respective code should be `self.bev_range = self.pcd_range[[0, 2, 3, 5]]`. Did I understood correctly ?

If yes, I suggest to move the respective line to `__call__ ` so that we can check the instance of `input_dict['points']` and then initialize `self.bev_range` accordingly!


Discussion:
Yes, this really makes sense. Currently, we only use this transform in LiDAR point cloud loading so it won't cause any problems, but it's your concern is reasonable. Can you kindly raise a PR to fix it? I think your solution of checking the type of points is great!

Resolving patch:
diff --git a/mmdet3d/datasets/pipelines/transforms_3d.py b/mmdet3d/datasets/pipelines/transforms_3d.py
--- a/mmdet3d/datasets/pipelines/transforms_3d.py
+++ b/mmdet3d/datasets/pipelines/transforms_3d.py
@@ -4,7 +4,8 @@
 from mmcv.utils import build_from_cfg
 
 from mmdet3d.core import VoxelGenerator
-from mmdet3d.core.bbox import box_np_ops
+from mmdet3d.core.bbox import (CameraInstance3DBoxes, DepthInstance3DBoxes,
+                               LiDARInstance3DBoxes, box_np_ops)
 from mmdet.datasets.builder import PIPELINES
 from mmdet.datasets.pipelines import RandomFlip
 from ..builder import OBJECTSAMPLERS
@@ -699,7 +700,6 @@ class ObjectRangeFilter(object):
 
     def __init__(self, point_cloud_range):
         self.pcd_range = np.array(point_cloud_range, dtype=np.float32)
-        self.bev_range = self.pcd_range[[0, 1, 3, 4]]
 
     def __call__(self, input_dict):
         """Call function to filter objects by the range.
@@ -711,9 +711,16 @@ def __call__(self, input_dict):
             dict: Results after filtering, 'gt_bboxes_3d', 'gt_labels_3d' \
                 keys are updated in the result dict.
         """
+        # Check points instance type and initialise bev_range
+        if isinstance(input_dict['gt_bboxes_3d'],
+                      (LiDARInstance3DBoxes, DepthInstance3DBoxes)):
+            bev_range = self.pcd_range[[0, 1, 3, 4]]
+        elif isinstance(input_dict['gt_bboxes_3d'], CameraInstance3DBoxes):
+            bev_range = self.pcd_range[[0, 2, 3, 5]]
+
         gt_bboxes_3d = input_dict['gt_bboxes_3d']
         gt_labels_3d = input_dict['gt_labels_3d']
-        mask = gt_bboxes_3d.in_range_bev(self.bev_range)
+        mask = gt_bboxes_3d.in_range_bev(bev_range)
         gt_bboxes_3d = gt_bboxes_3d[mask]
         # mask is a torch tensor but gt_labels_3d is still numpy array
         # using mask to index gt_labels_3d will cause bug when


Test patch:
Repository: open-mmlab/mmdetection3d

Issue:
Possible bug with 'with_distance = True' in DynamicVFE
https://github.com/open-mmlab/mmdetection3d/blob/d0d3d944ee7874e53eeea4ce9801a8e2c289e6ea/mmdet3d/models/voxel_encoders/voxel_encoder.py#L334
Should it be `in_channels += 1`?


Discussion:
Yes I guess it's a typo. Have you encountered any bugs because of it? If you have checked the results, could you please create a PR to fix it?

Resolving patch:
diff --git a/mmdet3d/models/voxel_encoders/voxel_encoder.py b/mmdet3d/models/voxel_encoders/voxel_encoder.py
--- a/mmdet3d/models/voxel_encoders/voxel_encoder.py
+++ b/mmdet3d/models/voxel_encoders/voxel_encoder.py
@@ -133,7 +133,7 @@ def __init__(self,
         if with_voxel_center:
             in_channels += 3
         if with_distance:
-            in_channels += 3
+            in_channels += 1
         self.in_channels = in_channels
         self._with_distance = with_distance
         self._with_cluster_center = with_cluster_center
@@ -331,7 +331,7 @@ def __init__(self,
         if with_voxel_center:
             in_channels += 3
         if with_distance:
-            in_channels += 3
+            in_channels += 1
         self.in_channels = in_channels
         self._with_distance = with_distance
         self._with_cluster_center = with_cluster_center


Test patch:
Repository: MongoEngine/mongoengine

Issue:
DecimalField validation raises InvalidOperation instead of ValidationError
When you create a Document instance with DecimalField in it and fill it with a string that isn't a number and then you call validate(), decimal.InvalidOperation exception is raised instead of mongoengine.ValidationError. FloatField works as expected when supplied the same string and raises ValidationError.

I think DecimalField should follow FloatField's behavior and raise ValidationError.

This is my test case:

``` python
import mongoengine
import unittest


class Test(mongoengine.Document):
    float = mongoengine.FloatField()
    decimal = mongoengine.DecimalField()


class ValidateTestCase(unittest.TestCase):
    def test_float(self):
        doc = Test(float='something invalid')
        self.assertRaises(mongoengine.ValidationError, doc.validate)

    def test_decimal(self):
        doc = Test(decimal='something invalid')
        self.assertRaises(mongoengine.ValidationError, doc.validate)


if __name__ == '__main__':
    unittest.main()
```



Discussion:

Resolving patch:
diff --git a/mongoengine/fields.py b/mongoengine/fields.py
--- a/mongoengine/fields.py
+++ b/mongoengine/fields.py
@@ -304,7 +304,10 @@ def to_python(self, value):
             return value
 
         # Convert to string for python 2.6 before casting to Decimal
-        value = decimal.Decimal("%s" % value)
+        try:
+            value = decimal.Decimal("%s" % value)
+        except decimal.InvalidOperation:
+            return value
         return value.quantize(self.precision, rounding=self.rounding)
 
     def to_mongo(self, value):


Test patch:
diff --git a/tests/fields/fields.py b/tests/fields/fields.py
--- a/tests/fields/fields.py
+++ b/tests/fields/fields.py
@@ -384,6 +384,9 @@ class Person(Document):
         person.height = 4.0
         self.assertRaises(ValidationError, person.validate)
 
+        person_2 = Person(height='something invalid')
+        self.assertRaises(ValidationError, person_2.validate)
+
     def test_decimal_validation(self):
         """Ensure that invalid values cannot be assigned to decimal fields.
         """
@@ -405,6 +408,11 @@ class Person(Document):
         self.assertRaises(ValidationError, person.validate)
         person.height = Decimal('4.0')
         self.assertRaises(ValidationError, person.validate)
+        person.height = 'something invalid'
+        self.assertRaises(ValidationError, person.validate)
+
+        person_2 = Person(height='something invalid')
+        self.assertRaises(ValidationError, person_2.validate)
 
         Person.drop_collection()
Repository: MongoEngine/mongoengine

Issue:
The need of set__ in update method
Hi, right now in the latest MongoEngine to perform an update we need to do

``` python
MyDocument.objects(id=x).update(set__name="Bruno")
```

I guess (and documentation points it) that it should be

``` python
MyDocument.objects(id=x).update(name="Bruno")
```

The internals of pymongo' s set__ should be abstracted, why the set__ is needed, is it a bug in code or in docs?



Discussion:
We could default to `$set` but we are explicit about the operation you want to perform - so currently you have to say `set__` and that helps remove ambiguities around `update(name=None)` is that a `$set` or `$unset` operation?

I got it, but I think it should default to $set and only $unset should be explicit ``update(unset__field=None)``

The reason:

Having a data source in JSON or dict I can do this:

``` python
data = dict(x=1, y=2)
Model.objects.create(**data)
```

But I cant do

``` python
data = dict(x=1, y=2)
Model.objects(group="foo").update(**data)
```

I could do this using a dict comprehensions but it is a bit ugly.

``` python
data = dict(x=1, y=2)
Model.objects(group="foo").update(
    **{"set__%s" % k: v for k, v in data.items()}
)
```

Happy to take a pr with it included ;)  Please document that its default as well.

@rochacbruno Dict comprehensions are not supported in Python 2.6.

The following code is equivalent and supported in Python 2.6:

```
data = dict(x=1, y=2)
Model.objects(group="foo").update(
    **dict(("set__%s" % k, v) for k, v in data.items())
)
```


Resolving patch:
diff --git a/mongoengine/queryset/transform.py b/mongoengine/queryset/transform.py
--- a/mongoengine/queryset/transform.py
+++ b/mongoengine/queryset/transform.py
@@ -164,6 +164,9 @@ def update(_doc_cls=None, **update):
             mongo_update.update(value)
             continue
         parts = key.split('__')
+        # if there is no operator, default to "set"
+        if len(parts) < 3 and parts[0] not in UPDATE_OPERATORS:
+            parts.insert(0, 'set')
         # Check for an operator and transform to mongo-style if there is
         op = None
         if parts[0] in UPDATE_OPERATORS:


Test patch:
diff --git a/tests/document/instance.py b/tests/document/instance.py
--- a/tests/document/instance.py
+++ b/tests/document/instance.py
@@ -1074,11 +1074,13 @@ def update_no_value_raises():
 
         self.assertRaises(OperationError, update_no_value_raises)
 
-        def update_no_op_raises():
+        def update_no_op_should_default_to_set():
             person = self.Person.objects.first()
             person.update(name="Dan")
+            person.reload()
+            return person.name
 
-        self.assertRaises(InvalidQueryError, update_no_op_raises)
+        self.assertEqual("Dan", update_no_op_should_default_to_set())
 
     def test_update_unique_field(self):
         class Doc(Document):
Repository: MongoEngine/mongoengine

Issue:
TypeError exception if model returns None from __str__()



Discussion:

Resolving patch:
diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py
--- a/mongoengine/base/document.py
+++ b/mongoengine/base/document.py
@@ -229,7 +229,7 @@ def __repr__(self):
             u = self.__str__()
         except (UnicodeEncodeError, UnicodeDecodeError):
             u = '[Bad Unicode data]'
-        repr_type = type(u)
+        repr_type = str if u is None else type(u)
         return repr_type('<%s: %s>' % (self.__class__.__name__, u))
 
     def __str__(self):


Test patch:
diff --git a/tests/document/instance.py b/tests/document/instance.py
--- a/tests/document/instance.py
+++ b/tests/document/instance.py
@@ -103,6 +103,19 @@ def __unicode__(self):
 
         self.assertEqual('<Article: привет мир>', repr(doc))
 
+    def test_repr_none(self):
+        """Ensure None values handled correctly
+        """
+        class Article(Document):
+            title = StringField()
+
+            def __str__(self):
+                return None
+
+        doc = Article(title=u'привет мир')
+
+        self.assertEqual('<Article: None>', repr(doc))
+
     def test_queryset_resurrects_dropped_collection(self):
         self.Person.drop_collection()
Repository: MongoEngine/mongoengine

Issue:
Fix storing value of precision attribute in DecimalField.
There's an indeterminacy between docs (hence comments) and the actual format of the value stored.
Docs:

```
precision – Number of decimal places to store.
```

But in the code:

``` python
self.precision = decimal.Decimal(".%s" % ("0" * precision))
```

Yes, documentation refers to the parameter of the constructor. But it turns out to be unexpected behaviour, since if I try to run `field.precision`, I will not get the same value and there's nothing in the docs about it.



Discussion:

Resolving patch:
diff --git a/mongoengine/fields.py b/mongoengine/fields.py
--- a/mongoengine/fields.py
+++ b/mongoengine/fields.py
@@ -308,7 +308,7 @@ def __init__(self, min_value=None, max_value=None, force_string=False,
         self.min_value = min_value
         self.max_value = max_value
         self.force_string = force_string
-        self.precision = decimal.Decimal(".%s" % ("0" * precision))
+        self.precision = precision
         self.rounding = rounding
 
         super(DecimalField, self).__init__(**kwargs)
@@ -322,7 +322,7 @@ def to_python(self, value):
             value = decimal.Decimal("%s" % value)
         except decimal.InvalidOperation:
             return value
-        return value.quantize(self.precision, rounding=self.rounding)
+        return value.quantize(decimal.Decimal(".%s" % ("0" * self.precision)), rounding=self.rounding)
 
     def to_mongo(self, value, use_db_field=True):
         if value is None:


Test patch:
Repository: MongoEngine/mongoengine

Issue:
write_concern not in params of Collection#remove
fixes #801 



Discussion:

Resolving patch:
diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py
--- a/mongoengine/queryset/base.py
+++ b/mongoengine/queryset/base.py
@@ -459,7 +459,7 @@ def delete(self, write_concern=None, _from_doc_delete=False):
                     write_concern=write_concern,
                     **{'pull_all__%s' % field_name: self})
 
-        result = queryset._collection.remove(queryset._query, write_concern=write_concern)
+        result = queryset._collection.remove(queryset._query, **write_concern)
         return result["n"]
 
     def update(self, upsert=False, multi=True, write_concern=None,


Test patch: