Repository: napari/napari

Issue:
Error when using pandas dataframe for properties on Tracks layer
## 🐛 Bug

Error when using pandas dataframe for properties on Tracks layer.

## To Reproduce

The `Tracks` layer throws an error when passing a dataframe for the properties kwarg:

```
Traceback (most recent call last):
  File "/home/quantumjot/napari/napari/_qt/event_loop.py", line 79, in gui_qt
    yield app
  File "<ipython-input-15-fdca00748db9>", line 4, in <module>
    viewer.add_tracks(data, properties=properties)
  File "/home/quantumjot/napari/napari/components/add_layers_mixin.py", line 854, in add_tracks
    layer = layers.Tracks(
  File "/home/quantumjot/napari/napari/layers/tracks/tracks.py", line 144, in __init__
    self.properties = properties or {}
  File "/home/quantumjot/anaconda3/envs/trackpy/lib/python3.8/site-packages/pandas/core/generic.py", line 1326, in __nonzero__
    raise ValueError(
ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
```

## Expected behavior

Tracks layer should accept the dataframe.

## Environment

```
napari: 0.3.9.dev31+g647d918
Platform: Linux-4.15.0-1097-oem-x86_64-with-glibc2.10
Python: 3.8.5 (default, Sep 4 2020, 07:30:14) [GCC 7.3.0]
Qt: 5.14.2
PyQt5: 5.14.2
NumPy: 1.19.1
SciPy: 1.5.2
Dask: 2.29.0
VisPy: 0.6.5
GL version: 4.6.0 NVIDIA 450.80.02
MAX_TEXTURE_SIZE: 32768
```
## Additional context



Discussion:
Thanks flagging this, @quantumjot ! I can take a look over the next couple of days.

edit: if you want to make a PR that's great too!
Notes from @quantumjot in [this comment](https://github.com/napari/napari/pull/1705#issuecomment-704930599):

> This is the offending line:
https://github.com/napari/napari/blob/647d9182a6dc3542521cbc99b8b59beb4f2ba901/napari/layers/tracks/tracks.py#L144

Resolving patch:
diff --git a/napari/layers/tracks/tracks.py b/napari/layers/tracks/tracks.py
--- a/napari/layers/tracks/tracks.py
+++ b/napari/layers/tracks/tracks.py
@@ -97,6 +97,10 @@ def __init__(
             # convert data to a numpy array if it is not already one
             data = np.asarray(data)
 
+        # in absence of properties make the default an empty dict
+        if properties is None:
+            properties = {}
+
         # set the track data dimensions (remove ID from data)
         ndim = data.shape[1] - 1
 
@@ -144,7 +148,7 @@ def __init__(
 
         # set the data, properties and graph
         self.data = data
-        self.properties = properties or {}
+        self.properties = properties
         self.graph = graph or {}
 
         self.color_by = color_by


Test patch:
diff --git a/napari/layers/tracks/_tests/test_tracks.py b/napari/layers/tracks/_tests/test_tracks.py
--- a/napari/layers/tracks/_tests/test_tracks.py
+++ b/napari/layers/tracks/_tests/test_tracks.py
@@ -57,13 +57,18 @@ def test_track_layer_data():
     assert np.all(layer.data == data)
 
 
-def test_track_layer_properties():
+properties_dict = {'time': np.arange(100)}
+properties_df = pd.DataFrame(properties_dict)
+
+
+@pytest.mark.parametrize("properties", [{}, properties_dict, properties_df])
+def test_track_layer_properties(properties):
     """Test properties."""
     data = np.zeros((100, 4))
     data[:, 1] = np.arange(100)
-    properties = {'time': data[:, 1]}
     layer = Tracks(data, properties=properties)
-    assert layer.properties == properties
+    for k, v in properties.items():
+        np.testing.assert_equal(layer.properties[k], v)
 
 
 def test_track_layer_graph():