docs: def convert_sourceGroup(self, node):
          """
          Convert the given node into a SourceGroup object.
  
          :param node:
              a node with tag sourceGroup
          :returns:
              a :class:`SourceGroup` instance
          """
          trt = node['tectonicRegion']
          srcs_weights = node.attrib.get('srcs_weights')
          grp_attrs = {k: v for k, v in node.attrib.items()
                       if k not in ('name', 'src_interdep', 'rup_interdep',
                                    'srcs_weights')}
          sg = SourceGroup(trt, min_mag=self.minimum_magnitude)
          sg.temporal_occurrence_model = self.get_tom(node)
          sg.name = node.attrib.get('name')
          # Set attributes related to occurrence
          sg.src_interdep = node.attrib.get('src_interdep', 'indep')
          sg.rup_interdep = node.attrib.get('rup_interdep', 'indep')
          sg.grp_probability = node.attrib.get('grp_probability')
          # Set the cluster attribute
          sg.cluster = node.attrib.get('cluster') == 'true'
          # Filter admitted cases
          # 1. The source group is a cluster. In this case the cluster must have
          #    the attributes required to define its occurrence in time.
          if sg.cluster:
              msg = 'A cluster group requires the definition of a temporal'
              msg += ' occurrence model'
              assert 'tom' in node.attrib, msg
              if isinstance(tom, PoissonTOM):
                  assert hasattr(sg, 'occurrence_rate')
          #
          for src_node in node:
              if self.source_id and self.source_id != src_node['id']:
                  continue  # filter by source_id
              src = self.convert_node(src_node)
              # transmit the group attributes to the underlying source
              for attr, value in grp_attrs.items():
                  if attr == 'tectonicRegion':
                      src_trt = src_node.get('tectonicRegion')
                      if src_trt and src_trt != trt:
                          with context(self.fname, src_node):
                              raise ValueError('Found %s, expected %s' %
                                               (src_node['tectonicRegion'], trt))
                      src.tectonic_region_type = trt
                  elif attr == 'grp_probability':
                      pass  # do not transmit
                  else:  # transmit as it is
                      setattr(src, attr, node[attr])
              sg.update(src)
          if srcs_weights is not None:
              if len(node) and len(srcs_weights) != len(node):
                  raise ValueError(
                      'There are %d srcs_weights but %d source(s) in %s'
                      % (len(srcs_weights), len(node), self.fname))
              for src, sw in zip(sg, srcs_weights):
                  src.mutex_weight = sw
          # check that, when the cluster option is set, the group has a temporal
          # occurrence model properly defined
          if sg.cluster and not hasattr(sg, 'temporal_occurrence_model'):
              msg = 'The Source Group is a cluster but does not have a '
              msg += 'temporal occurrence model'
              raise ValueError(msg)
          return sg