docs: def get_vulnerability_functions_04(node, fname):
      """
      :param node:
          a vulnerabilityModel node
      :param fname:
          path to the vulnerability file
      :returns:
          a dictionary imt, vf_id -> vulnerability function
      """
      logging.warning('Please upgrade %s to NRML 0.5', fname)
      # NB: the IMTs can be duplicated and with different levels, each
      # vulnerability function in a set will get its own levels
      imts = set()
      vf_ids = set()
      # imt, vf_id -> vulnerability function
      vmodel = scientific.VulnerabilityModel(**node.attrib)
      for vset in node:
          imt_str = vset.IML['IMT']
          imls = ~vset.IML
          imts.add(imt_str)
          for vfun in vset.getnodes('discreteVulnerability'):
              vf_id = vfun['vulnerabilityFunctionID']
              if vf_id in vf_ids:
                  raise InvalidFile(
                      'Duplicated vulnerabilityFunctionID: %s: %s, line %d' %
                      (vf_id, fname, vfun.lineno))
              vf_ids.add(vf_id)
              with context(fname, vfun):
                  loss_ratios = ~vfun.lossRatio
                  coefficients = ~vfun.coefficientsVariation
              if len(loss_ratios) != len(imls):
                  raise InvalidFile(
                      'There are %d loss ratios, but %d imls: %s, line %d' %
                      (len(loss_ratios), len(imls), fname,
                       vfun.lossRatio.lineno))
              if len(coefficients) != len(imls):
                  raise InvalidFile(
                      'There are %d coefficients, but %d imls: %s, line %d' %
                      (len(coefficients), len(imls), fname,
                       vfun.coefficientsVariation.lineno))
              with context(fname, vfun):
                  vmodel[imt_str, vf_id] = scientific.VulnerabilityFunction(
                      vf_id, imt_str, imls, loss_ratios, coefficients,
                      vfun['probabilisticDistribution'])
      return vmodel