Repository: voxel51/fiftyone

Issue:
Need custom FloatField that supports more numeric types
In this code (taken from https://github.com/voxel51/fiftyone/blob/develop/examples/model_inference/README.md), I had to add `float(confidence)` otherwise I got an error about `confidence`, which was a numpy float32 or something similar, not being a supported value for a `mongoengine.fields.FloatField`. 

```py
for imgs, sample_ids in data_loader:
    predictions, confidences = predict(model, imgs)

    # Add predictions to your FiftyOne dataset
    for sample_id, prediction, confidence in zip(
        sample_ids, predictions, confidences
    ):
        sample = dataset[sample_id]
        sample[model_name] = fo.Classification(label=labels_map[prediction])
        sample["confidence"] = float(confidence)  # float() is required here, but shouldn't need to be...
        sample.save()
```

Kind of hard to believe that MongoEngine doesn't handle casting a `np.float32` into a float, but, alas, it seems like our wrapper around `mongoengine.fields.FloatField` will need to override the `validate()` function below to cast non-int types with `float()` as well...

https://github.com/MongoEngine/mongoengine/blob/4275c2d7b791f5910308a4815a1ba39324dee373/mongoengine/fields.py#L377-L411



Discussion:
I had to add a similar cast last night somewhere in my inference code.

On Fri, May 22, 2020, 17:51 Brian Moore <notifications@github.com> wrote:

> In this code (taken from
> https://github.com/voxel51/fiftyone/blob/develop/examples/model_inference/README.md),
> I had to add float(confidence) otherwise I got an error about confidence,
> which was a numpy float32 or something similar, not being a supported value
> for a mongoengine.fields.FloatField.
>
> for imgs, sample_ids in data_loader:
>     predictions, confidences = predict(model, imgs)
>
>     # Add predictions to your FiftyOne dataset
>     for sample_id, prediction, confidence in zip(
>         sample_ids, predictions, confidences
>     ):
>         sample = dataset[sample_id]
>         sample[model_name] = fo.Classification(label=labels_map[prediction])
>         sample["confidence"] = float(confidence)
>         sample.save()
>
> Kind of hard to believe that MongoEngine doesn't handle casting a
> np.float32 into a float, but, alas, it seems like our wrapper around
> mongoengine.fields.FloatField will need to override the validate()
> function below to cast non-int types with float() as well...
>
>
> https://github.com/MongoEngine/mongoengine/blob/4275c2d7b791f5910308a4815a1ba39324dee373/mongoengine/fields.py#L377-L411
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/voxel51/fiftyone/issues/94>, or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AEBOSJTAI46L2VPFNQGAD7TRS3XWHANCNFSM4NIEQVCQ>
> .
>


Resolving patch:
diff --git a/fiftyone/core/fields.py b/fiftyone/core/fields.py
--- a/fiftyone/core/fields.py
+++ b/fiftyone/core/fields.py
@@ -34,7 +34,19 @@ class IntField(mongoengine.IntField, Field):
 
 
 class FloatField(mongoengine.FloatField, Field):
-    pass
+    def validate(self, value):
+        try:
+            value = float(value)
+        except OverflowError:
+            self.error("The value is too large to be converted to float")
+        except (TypeError, ValueError):
+            self.error("%s could not be converted to float" % value)
+
+        if self.min_value is not None and value < self.min_value:
+            self.error("Float value is too small")
+
+        if self.max_value is not None and value > self.max_value:
+            self.error("Float value is too large")
 
 
 class StringField(mongoengine.StringField, Field):


Test patch: