Repository: Project-MONAI/MONAI

Issue:
ImportError: cannot import name 'ArrayDataset'
Following the [notebook tutorial on 3D UNet](https://github.com/Project-MONAI/MONAI/blob/master/examples/notebooks/unet_segmentation_3d_ignite.ipynb), the `ArrayDataset` is not found from where it was suppose to be found, while everything else seems to be available?  

![image](https://user-images.githubusercontent.com/1060514/84504376-bee4a380-acb3-11ea-8aa4-4b72ea656271.png)

 - OS: Ubuntu 18.04
 - Python version: 3.6 venv
 - MONAI version: monai 0.1.0 (installed today with `pip install monai`, `monai-0.1.0-202004191421-py3-none-any.whl`)




Discussion:
Hi @petteriTeikari ,

This `ArrayDataset` is new added in v0.2.
You can either change to pip install from source code:
`pip install git+https://github.com/Project-MONAI/MONAI#egg=MONAI`
or:
change the branch to `releases/0.1.0` and check the examples of v0.1 release.

Thanks.
Thanks @Nic-Ma for quick reply, the install from source worked and `ArrayDataset` was found 
@Nic-Ma when following the same example, I also ran into this error 

`TypeError: object of type 'ArrayDataset' has no len()`

when executing this line:

`im, seg = monai.utils.misc.first(loader)`

similar error from:

`train_loader = DataLoader(train_ds, batch_size=5, shuffle=True, num_workers=8, pin_memory=torch.cuda.is_available())`


Resolving patch:
diff --git a/monai/data/dataset.py b/monai/data/dataset.py
--- a/monai/data/dataset.py
+++ b/monai/data/dataset.py
@@ -340,7 +340,7 @@ def to_list(x):
         return data
 
 
-class ArrayDataset(Randomizable):
+class ArrayDataset(Randomizable, _TorchDataset):
     """
     Dataset for segmentation and classification tasks based on array format input data and transforms.
     It ensures the same random seeds in the randomized transforms defined for image, segmentation and label.
@@ -419,6 +419,9 @@ def __init__(
 
         self._seed = 0  # transform synchronization seed
 
+    def __len__(self):
+        return len(self.dataset)
+
     def randomize(self):
         self._seed = self.R.randint(np.iinfo(np.int32).max)
 


Test patch:
diff --git a/tests/test_arraydataset.py b/tests/test_arraydataset.py
--- a/tests/test_arraydataset.py
+++ b/tests/test_arraydataset.py
@@ -17,9 +17,10 @@
 import nibabel as nib
 import numpy as np
 from parameterized import parameterized
+from torch.utils.data import DataLoader
 
 from monai.data import ArrayDataset
-from monai.transforms import AddChannel, Compose, LoadNifti, RandAdjustContrast, Spacing, RandGaussianNoise
+from monai.transforms import AddChannel, Compose, LoadNifti, RandAdjustContrast, RandGaussianNoise, Spacing
 
 TEST_CASE_1 = [
     Compose([LoadNifti(image_only=True), AddChannel(), RandGaussianNoise(prob=1.0)]),
@@ -74,6 +75,7 @@ def test_shape(self, img_transform, label_transform, indexes, expected_shape):
         test_segs = [test_seg1, test_seg2]
         test_labels = [1, 1]
         dataset = ArrayDataset(test_images, img_transform, test_segs, label_transform, test_labels, None)
+        self.assertEqual(len(dataset), 2)
         dataset.set_random_state(1234)
         data1 = dataset[0]
         data2 = dataset[1]
@@ -102,6 +104,7 @@ def test_default_none(self, img_transform, expected_shape):
         nib.save(test_image, test_image2)
         test_images = [test_image1, test_image2]
         dataset = ArrayDataset(test_images, img_transform)
+        self.assertEqual(len(dataset), 2)
         dataset.set_random_state(1234)
         data1 = dataset[0]
         data2 = dataset[1]
@@ -115,6 +118,26 @@ def test_default_none(self, img_transform, expected_shape):
         np.testing.assert_allclose(data2, data2_new, atol=1e-3)
         shutil.rmtree(tempdir)
 
+    @parameterized.expand([TEST_CASE_4])
+    def test_dataloading(self, img_transform, expected_shape):
+        test_image = nib.Nifti1Image(np.random.randint(0, 2, size=(128, 128, 128)), np.eye(4))
+        tempdir = tempfile.mkdtemp()
+        test_image1 = os.path.join(tempdir, "test_image1.nii.gz")
+        test_image2 = os.path.join(tempdir, "test_image2.nii.gz")
+        nib.save(test_image, test_image1)
+        nib.save(test_image, test_image2)
+        test_images = [test_image1, test_image2]
+        dataset = ArrayDataset(test_images, img_transform)
+        self.assertEqual(len(dataset), 2)
+        dataset.set_random_state(1234)
+        loader = DataLoader(dataset, batch_size=10, num_workers=1)
+        imgs = next(iter(loader))  # test batching
+        np.testing.assert_allclose(imgs.shape, [2] + list(expected_shape))
+
+        dataset.set_random_state(1234)
+        new_imgs = next(iter(loader))  # test batching
+        np.testing.assert_allclose(imgs, new_imgs, atol=1e-3)
+
 
 if __name__ == "__main__":
     unittest.main()