docs: def gen_rupture_getters(dstore, slc=slice(None),
                          concurrent_tasks=1, hdf5cache=None):
      """
      :yields: RuptureGetters
      """
      if dstore.parent:
          dstore = dstore.parent
      csm_info = dstore['csm_info']
      trt_by_grp = csm_info.grp_by("trt")
      samples = csm_info.get_samples_by_grp()
      rlzs_by_gsim = csm_info.get_rlzs_by_gsim_grp()
      rup_array = dstore['ruptures'][slc]
      maxweight = numpy.ceil(len(rup_array) / (concurrent_tasks or 1))
      nr, ne = 0, 0
      for grp_id, arr in general.group_array(rup_array, 'grp_id').items():
          if not rlzs_by_gsim[grp_id]:
              # this may happen if a source model has no sources, like
              # in event_based_risk/case_3
              continue
          for block in general.block_splitter(arr, maxweight):
              rgetter = RuptureGetter(
                  hdf5cache or dstore.filename, numpy.array(block), grp_id,
                  trt_by_grp[grp_id], samples[grp_id], rlzs_by_gsim[grp_id])
              rgetter.weight = getattr(block, 'weight', len(block))
              yield rgetter
              nr += len(block)
              ne += rgetter.num_events
      logging.info('Read %d ruptures and %d events', nr, ne)