def key_abstype(self):
    if hasattr(self.result, 'store'):
      # have a store, can look stuff up
      feat_name = 'isstructured'
      ds = self.result.metadata['dataset']
      cs = self.result.metadata['class_space']
      fm = self.result.store.get_FeatureMap(ds, feat_name)
      feat_space = self.result.store.get_Space(feat_name)

      # Extract goldstandard and overall classification matrix
      # TODO: Check that CL has full coverage w/o overlap
      gs = self.result.store.get_ClassMap(ds, cs).raw
      cl = np.zeros(gs.shape, dtype=self.result.results[0].classifications.dtype)
      for r in self.result.results:
        cl[r.instance_indices] = r.classifications

      retval = {}
      for i, cat in enumerate(feat_space):
        cat_mask = fm[:,i].nonzero()[0]
        cat_res = Result(gs[cat_mask], cl[cat_mask], cat_mask)
        cm = cat_res.confusion_matrix(self.interpreter)
        prf = CombinedMicroAverage(cm[None,:])
        retval[cat] = {'precision':prf.precision, 'recall':prf.recall, 'fscore':prf.fscore}
      return retval
    else:
      return {}
  def key_breakdown(self):
    if hasattr(self.result, 'store'):
      store = self.result.store
      # have a store, can look stuff up
      ds = self.result.metadata['dataset']
      cs = self.result.metadata['class_space']
      try:
        class_space = store.get_Space(cs)
        space = store.get_Space(self.space_name)
        space_md = store.get_SpaceMetadata(self.space_name)
      except NoData:
        # TODO: handle NoData here with an error message
        raise

      # get the actual space and check it is suitable
      if space_md['type'] == 'feature':
        fm = store.get_FeatureMap(ds, self.space_name).raw.toarray()
        if fm.min() < 0 or fm.max() > 1:
          raise TypeError('feature space has non 0/1 elements')
        mat = fm.astype(bool)
      elif space_md['type'] == 'class':
        mat = store.get_ClassMap(ds, self.space_name).raw
      else:
        raise TypeError('space {0} has unsuitable type: {1}'.format(self.space_name, space_md['type']))

      # Extract goldstandard and overall classification matrix
      # TODO: Check that CL has full coverage w/o overlap
      gs = self.result.store.get_ClassMap(ds, cs).raw
      cl = np.zeros(gs.shape, dtype=self.result.results[0].classifications.dtype)
      for r in self.result.results:
        cl[r.instance_indices] = r.classifications

      retval = {}
      for i, cat in enumerate(space):
        cat_mask = mat[:,i].nonzero()[0]
        cat_res = Result(gs[cat_mask], cl[cat_mask], cat_mask)
        cm = cat_res.confusion_matrix(self.interpreter)
        prf = self.cmm(cm.sum(0))
        breakdown = dict(zip(class_space, map(self.cmm,cm) ))
        retval[cat] = (prf, breakdown)
      return retval
    else:
      return {}