code: def read(self, from_item=None, to_item=None,
               from_time=None, to_time=None):
          if to_item is None:
              to_item = self.items.data[-1] if from_item is None else from_item
          if from_item is None:
              from_item = self.items.data[0]
          if not self.items.is_valid_interval(from_item, to_item):
              raise IOError('cannot read items: not a valid interval')
          from_idx = self.items.data.index(from_item)
          to_idx = self.items.data.index(to_item)
          from_pos = self._get_item_position(from_idx)
          to_pos = self._get_item_position(to_idx)
          lower = self._get_from_time(from_time, from_pos)
          upper = self._get_to_time(to_time, to_pos) + 1
          if self.dformat == 'sparse':
              raise NotImplementedError(
                  'Reading sparse features not implemented')
          else:
              features = (self.group['features'][:, lower:upper].T
                          if self.version == '0.1'
                          else self.group['features'][lower:upper, ...])
              labels = self._labels_group[lower:upper]
          if to_idx == from_idx:
              features = [features]
              labels = [labels]
          else:
              item_ends = self._index[from_idx:to_idx] - from_pos[0] + 1
              features = np.split(features, item_ends, axis=0)
              labels = np.split(labels, item_ends, axis=0)
          items = self.items.data[from_idx:to_idx + 1]
          if self.properties is None:
              properties = None
          else:
              properties = self.properties[from_idx:to_idx + 1]
          return Data(
              items, labels, features, properties=properties, check=False)