docs: def serialize(self, data, fmt='%10.7E'):
          """
          Serialize a collection of ground motion fields to XML.
  
          :param data:
              An iterable of "GMF set" objects.
              Each "GMF set" object should:
  
              * have an `investigation_time` attribute
              * have an `stochastic_event_set_id` attribute
              * be iterable, yielding a sequence of "GMF" objects
  
              Each "GMF" object should:
  
              * have an `imt` attribute
              * have an `sa_period` attribute (only if `imt` is 'SA')
              * have an `sa_damping` attribute (only if `imt` is 'SA')
              * have a `event_id` attribute (to indicate which rupture
                contributed to this gmf)
              * be iterable, yielding a sequence of "GMF node" objects
  
              Each "GMF node" object should have:
  
              * a `gmv` attribute (to indicate the ground motion value
              * `lon` and `lat` attributes (to indicate the geographical location
                of the ground motion field)
          """
          gmf_set_nodes = []
          for gmf_set in data:
              gmf_set_node = Node('gmfSet')
              if gmf_set.investigation_time:
                  gmf_set_node['investigationTime'] = str(
                      gmf_set.investigation_time)
              gmf_set_node['stochasticEventSetId'] = str(
                  gmf_set.stochastic_event_set_id)
              gmf_set_node.nodes = gen_gmfs(gmf_set)
              gmf_set_nodes.append(gmf_set_node)
  
          gmf_container = Node('gmfCollection')
          gmf_container[SM_TREE_PATH] = self.sm_lt_path
          gmf_container[GSIM_TREE_PATH] = self.gsim_lt_path
          gmf_container.nodes = gmf_set_nodes
  
          with open(self.dest, 'wb') as dest:
              nrml.write([gmf_container], dest, fmt)