from __future__ import absolute_import, division, print_function

import iotbx.gui_tools
from iotbx import file_reader
from libtbx.utils import Sorry
import os
import six
from six.moves import range

def space_group_as_str(space_group):
  from cctbx import sgtbx
  if space_group is None :
    return ""
  elif isinstance(space_group, sgtbx.space_group_info):
    return str(space_group)
  else :
    sg_info = sgtbx.space_group_info(group=space_group)
    return str(sg_info)

def unit_cell_as_str(unit_cell, separator=" "):
  assert isinstance(separator, str) and separator != ""
  if unit_cell is not None :
    format = separator.join([ "%g" for i in range(6) ])
    return format % unit_cell.parameters()
  else :
    return ""

class reflections_handler(iotbx.gui_tools.manager):
  file_type = "hkl"
  file_type_label = "Reflections"
  def __init__(self,
                allowed_param_names=None,
                allowed_multiple_params=None,
                debug=False,
                minimum_data_score=4,
                prefer_amplitudes=False):
    iotbx.gui_tools.manager.__init__(self,
      allowed_param_names=allowed_param_names,
      allowed_multiple_params=allowed_multiple_params,
      debug=debug)
    self.minimum_data_score = minimum_data_score
    self.prefer_amplitudes = prefer_amplitudes

  def get_miller_array(self, labels, file_name=None, file_param_name=None):
    hkl_file = self.get_file(file_name=file_name,
      file_param_name=file_param_name)
    if (hkl_file is None):
      return None
    for array in hkl_file.file_server.miller_arrays :
      array_label_string = array.info().label_string()
      array_labels = array.info().labels
      if ((array_label_string == labels) or
          (array_labels == labels) or
          (",".join(array_labels) == labels)):
        return array
    return None

  def get_wavelength(self, *args, **kwds):
    array = self.get_miller_array(*args, **kwds)
    if (array is not None):
      info = array.info()
      if (info is not None):
        return info.wavelength
    return None

  def check_symmetry(self, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    hkl_server = hkl_file.file_server
    ma = hkl_server.miller_arrays[0]
    if (ma.space_group() is None) or (ma.unit_cell() is None):
      raise Sorry("Incomplete symmetry for this reflections file.  Please "+
        "use a format that includes both space group and unit cell, such as "+
        "an MTZ or merged Scalepack file.")
    return True

  def get_file_type_label(self, file_name=None, input_file=None):
    if (input_file is not None):
      return input_file.file_object.file_type()

  def get_all_labels(self, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    if hkl_file is None :
      labels = []
      for (file_name, hkl_file) in self.input_files():
        miller_arrays = hkl_file.file_server.miller_arrays
        labels.extend([ a.info().label_string() for a in miller_arrays ])
    else :
      miller_arrays = hkl_file.file_server.miller_arrays
      labels = [ a.info().label_string() for a in miller_arrays ]
    return labels

  def get_rfree_labels(self, *args, **kwds):
    prefer_neutron = kwds.pop("neutron", None)
    hkl_file = self.get_file(*args, **kwds)
    labels = []
    if hkl_file is not None :
      hkl_server = hkl_file.file_server
      arrays_and_flags = hkl_server.get_r_free_flags(
        file_name                = None,
        label                    = None,
        test_flag_value          = None,
        disable_suitability_test = False,
        parameter_scope          = "",
        return_all_valid_arrays  = True,
        minimum_score            = 1)
      if (prefer_neutron is not None):
        xray_arrays = []
        neutron_arrays = []
        other_arrays = []
        for array_and_flag_value in arrays_and_flags :
          array = array_and_flag_value[0]
          label = array.info().label_string().lower()
          if ("neutron" in label):
            neutron_arrays.append(array_and_flag_value)
          elif ("xray" in label):
            xray_arrays.append(array_and_flag_value)
          else :
            other_arrays.append(array_and_flag_value)
        if (prefer_neutron) and (len(neutron_arrays) > 0):
          arrays_and_flags = neutron_arrays + other_arrays
        elif (not prefer_neutron) and (len(xray_arrays) > 0):
          arrays_and_flags = xray_arrays + other_arrays
      if len(arrays_and_flags) > 0 :
        labels = [ a.info().label_string() for a, fl in arrays_and_flags ]
    return labels

  def has_rfree(self, *args, **kwds):
    return len(self.get_rfree_labels(*args, **kwds)) > 0

  def has_neutron_rfree(self, *args, **kwds):
    kwds['neutron'] = True
    labels = self.get_rfree_labels(*args, **kwds)
    return ([ "neutron" in l.lower() for l in labels ].count(True) > 0)

  def get_rfree_flag_value(self, array_name, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    flag = None
    if hkl_file is not None :
      hkl_server = hkl_file.file_server
      arrays_and_flags = hkl_server.get_r_free_flags(
        file_name                = None,
        label                    = None,
        test_flag_value          = None,
        disable_suitability_test = False,
        parameter_scope          = "",
        return_all_valid_arrays  = True,
        minimum_score            = 1)
      for miller_array, array_flag in arrays_and_flags :
        label = miller_array.info().label_string()
        if label == array_name :
          flag = array_flag
          break
    return flag

  def get_experimental_phase_labels(self, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    labels = []
    if hkl_file is not None :
      hkl_server = hkl_file.file_server
      miller_arrays = hkl_server.get_experimental_phases(
        file_name               = hkl_file.file_name,
        labels                  = None,
        ignore_all_zeros        = True,
        parameter_scope         = "",
        return_all_valid_arrays = True,
        minimum_score           = 1)
      labels = [ array.info().label_string() for array in miller_arrays ]
    return labels

  def has_phases(self, *args, **kwds):
    return len(self.get_experimental_phase_labels(*args, **kwds)) > 0

  def get_phase_arrays(self, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    labels = []
    if hkl_file is not None :
      hkl_server = hkl_file.file_server
      miller_arrays = hkl_server.get_phases_deg(
        file_name=hkl_file.file_name,
        labels=None,
        convert_to_phases_if_necessary=False,
        original_phase_units=None,
        parameter_scope=None,
        parameter_name=None,
        return_all_valid_arrays=True,
        minimum_score=1)
      return miller_arrays
    return []

  def get_phase_deg_labels(self, *args, **kwds):
    miller_arrays = self.get_phase_arrays(*args, **kwds)
    labels = []
    for array in miller_arrays :
      labels_str = array.info().label_string()
      if labels_str.startswith("FOM") : continue
      labels.append(labels_str)
    return labels

  def get_phase_column_labels(self, *args, **kwds):
    labels = []
    miller_arrays = self.get_phase_arrays(*args, **kwds)
    for array in miller_arrays :
      for label in array.info().labels :
        if label.upper().startswith("PH"):
          labels.append(label)
          break
    return labels

  def get_data_arrays(self, *args, **kwds):
    prefer_neutron = kwds.pop("neutron", None)
    hkl_file = self.get_file(*args, **kwds)
    if hkl_file is not None :
      hkl_server = hkl_file.file_server
      miller_arrays = hkl_server.get_xray_data(
        file_name               = None,
        labels                  = None,
        ignore_all_zeros        = False,
        parameter_scope         = "",
        return_all_valid_arrays = True,
        minimum_score           = self.minimum_data_score)
      if self.prefer_amplitudes :
        f_arrays = []
        other_arrays = []
        for array in miller_arrays :
          if array.is_xray_amplitude_array():
            f_arrays.append(array)
          else :
            other_arrays.append(array)
        miller_arrays = f_arrays + other_arrays
      elif (prefer_neutron is not None):
        xray_arrays = []
        neutron_arrays = []
        other_arrays = []
        for array in miller_arrays :
          label = array.info().label_string().lower()
          if ("neutron" in label):
            neutron_arrays.append(array)
          elif ("xray" in label):
            xray_arrays.append(array)
          else :
            other_arrays.append(array)
        if (prefer_neutron) and (len(neutron_arrays) > 0):
          miller_arrays = neutron_arrays + other_arrays
        elif (not prefer_neutron) and (len(xray_arrays) > 0):
          miller_arrays = xray_arrays + other_arrays
      return miller_arrays
    return []

  def get_data_labels(self, *args, **kwds):
    return extract_labels(self.get_data_arrays(*args, **kwds))

  def get_amplitude_arrays(self, *args, **kwds):
    allow_conversion = kwds.pop('allow_conversion', False)
    hkl_file = self.get_file(*args, **kwds)
    if hkl_file is not None :
      hkl_server = hkl_file.file_server
      miller_arrays = hkl_server.get_amplitudes(
        file_name               = None,
        labels                  = None,
        convert_to_amplitudes_if_necessary = allow_conversion,
        parameter_scope         = "",
        parameter_name          = "",
        return_all_valid_arrays = True,
        minimum_score           = 1,
        strict                  = True)
      return miller_arrays
    return []

  def get_amplitude_labels(self, *args, **kwds):
    return extract_labels(self.get_amplitude_arrays(*args, **kwds))

  def get_amplitude_column_labels(self, *args, **kwds):
    miller_arrays = self.get_amplitude_arrays(*args, **kwds)
    labels = []
    for array in miller_arrays :
      # XXX what about anomalous data?
      labels.extend(array.info().labels[0])
    return labels

  def get_intensity_arrays(self, *args, **kwds):
    miller_arrays = self.get_data_arrays(*args, **kwds)
    i_arrays = []
    for array in miller_arrays :
      if array.is_xray_intensity_array():
        i_arrays.append(array)
    return i_arrays

  def get_intensity_labels(self, *args, **kwds):
    return extract_labels(self.get_intensity_arrays(*args, **kwds))

  # space-separated, column labels only
  def get_data_labels_for_wizard(self, *args, **kwds):
    miller_arrays = self.get_data_arrays(*args, **kwds)
    labels = [ " ".join(array.info().labels) for array in miller_arrays ]
    return labels

  def has_data(self, *args, **kwds):
    return len(self.get_data_labels(*args, **kwds)) > 0

  def has_neutron_data(self, *args, **kwds):
    kwds['neutron'] = True
    labels = self.get_data_labels(*args, **kwds)
    return ([ "neutron" in l.lower() for l in labels ].count(True) > 0)

  def get_anomalous_data_labels(self, *args, **kwds):
    kwds = dict(kwds) # XXX gross...
    allow_dano = kwds.pop("allow_reconstructed_amplitudes", True)
    hkl_file = self.get_file(*args, **kwds)
    labels = []
    if hkl_file is not None :
      hkl_server = hkl_file.file_server
      miller_arrays = hkl_server.get_xray_data(
        file_name               = None,
        labels                  = None,
        ignore_all_zeros        = False,
        parameter_scope         = "",
        return_all_valid_arrays = True,
        minimum_score           = self.minimum_data_score)
      for array in miller_arrays :
        if (array.anomalous_flag()):
          if ((array.is_xray_reconstructed_amplitude_array()) and
              (not allow_dano)):
            continue
          labels.append(array.info().label_string())
    return labels

  def has_anomalous_data(self, *args, **kwds):
    return (len(self.get_anomalous_data_labels(*args, **kwds)) > 0)

  def get_phaser_map_fc_labels(self, *args, **kwds):
    labels = self.get_fmodel_labels(*args, **kwds)
    first_column_only = kwds.pop('first_column_only', False)
    hkl_file = self.get_file(*args, **kwds)
    if (hkl_file is not None):
      for miller_array in hkl_file.file_server.miller_arrays :
        if (miller_array.is_complex_array()):
          labels_str = miller_array.info().label_string()
          if labels_str.startswith("FWT"):
            labels.append(miller_array.info().labels[0])
    return labels

  def get_fmodel_labels(self, *args, **kwds):
    first_column_only = kwds.pop('first_column_only', False)
    hkl_file = self.get_file(*args, **kwds)
    labels_list = []
    if (hkl_file is not None):
      for miller_array in hkl_file.file_server.miller_arrays :
        if (miller_array.is_complex_array()):
          labels = miller_array.info().label_string()
          if (labels.startswith("F-model") or
              labels.upper().startswith("FMODEL") or
              labels.upper().startswith("FC")):
            if (first_column_only):
              labels_list.append(miller_array.info().labels[0])
            else :
              labels_list.append(labels)
    return labels_list

  def get_map_coeff_labels(self, *args, **kwds):
    # FIXME this is just gross...
    kwds_basic = {}
    kwds_maps = {}
    for kwd in dict(kwds):
      if (kwd in ["file_name", "file_param_name"]):
        kwds_basic[kwd] = kwds[kwd]
      else :
        kwds_maps[kwd] = kwds[kwd]
    hkl_file = self.get_file(*args, **kwds_basic)
    if hkl_file is not None :
      return get_map_coeff_labels(hkl_file.file_server, **kwds_maps)
    return []

  def get_map_coeff_labels_for_build(self, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    if hkl_file is not None :
      return get_map_coeffs_for_build(hkl_file.file_server)
    return []

  def get_map_coeff_labels_for_fft(self, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    labels_list = []
    if hkl_file is not None :
      all_labels = get_map_coeff_labels(hkl_file.file_server,
        keep_array_labels=True)
      for labels in all_labels :
        if isinstance(labels, str):
          labels_list.append(labels)
        else :
          labels_list.append(" ".join(labels))
    return labels_list

  def get_two_fofc_map_labels(self, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    labels_list = []
    if (hkl_file is not None):
      for array in hkl_file.file_server.miller_arrays :
        labels = array.info().label_string()
        if (labels.startswith("FWT") or labels.startswith("2FOFC")):
          labels_list.append(labels)
    return labels_list

  def get_fofc_map_labels(self, *args, **kwds):
    hkl_file = self.get_file(*args, **kwds)
    labels_list = []
    if (hkl_file is not None):
      for array in hkl_file.file_server.miller_arrays :
        labels = array.info().label_string()
        if (labels.startswith("DELFWT") or labels.startswith("FOFC")):
          labels_list.append(labels)
    return labels_list

  def get_amplitude_column_labels(self, *args, **kwds):
    miller_arrays = self.get_amplitude_arrays(*args, **kwds)
    labels = []
    for array in miller_arrays :
      # XXX what about anomalous data?
      labels.extend(array.info().labels[0])
    return labels

  def d_max_min(self, file_name=None, file_param_name=None,
      array_name=None, array_names=None):
    from iotbx.reflection_file_editor import get_best_resolution
    miller_arrays = []
    if (file_name is None) and (file_param_name is None):
      for phil_name, file_name in six.iteritems(self._param_files):
        input_file = self.get_file(file_name)
        if (input_file is not None):
          miller_arrays.extend(input_file.file_server.miller_arrays)
    else :
      hkl_file = self.get_file(file_name, file_param_name)
      if (hkl_file is None):
        return (None, None)
      for miller_array in hkl_file.file_server.miller_arrays :
        label = miller_array.info().label_string()
        if (array_name is not None):
          if (label == array_name):
            miller_arrays = [miller_array]
            break
        elif (array_names is not None):
          if (label in array_names):
            miller_arrays.append(miller_array)
        else :
          miller_arrays.append(miller_array)
    (d_max, d_min) = get_best_resolution(miller_arrays)
    return (d_max, d_min)

  def get_resolution_range(self, *args, **kwds):
    (d_max, d_min) = self.d_max_min(*args, **kwds)
    if (d_max is None):
      return ""
    else :
      return "(%.3f - %.3f)" % (d_max, d_min)

  def get_resolution_limits(self, *args, **kwds):
    (d_max, d_min) = self.d_max_min(*args, **kwds)
    (d_max_str, d_min_str) = ("", "")
    if (d_max is not None):
      d_max_str = "(%.3f)" % d_max
    if (d_min is not None):
      d_min_str = "(%.3f)" % d_min
    return (d_max_str, d_min_str)

  def space_group(self, *args, **kwds):
    symm = self.crystal_symmetry(*args, **kwds)
    if symm is not None :
      return symm.space_group()
    return None

  def space_group_as_str(self, *args, **kwds):
    space_group = self.space_group(*args, **kwds)
    return space_group_as_str(space_group)

  def unit_cell(self, *args, **kwds):
    symm = self.crystal_symmetry(*args, **kwds)
    if symm is not None :
      return symm.unit_cell()
    return None

  def unit_cell_as_str(self, file_name=None, file_param_name=None,
      separator=" "):
    unit_cell = self.unit_cell(file_name, file_param_name)
    return unit_cell_as_str(unit_cell, separator)

  def crystal_symmetry(self, file_name=None, file_param_name=None):
    final_symm = None
    if file_name is None and file_param_name is None :
      for param_name, file_name in six.iteritems(self._param_files):
        input_file = self.get_file(file_name)
        miller_arrays = input_file.file_server.miller_arrays
        for array in miller_arrays :
          symm = array.crystal_symmetry()
          if symm is not None :
            final_symm = symm
            break
    else :
      hkl_file = self.get_file(file_name, file_param_name)
      if hkl_file is not None :
        miller_arrays = hkl_file.file_server.miller_arrays
        if len(miller_arrays) > 0 :
          final_symm = miller_arrays[0].crystal_symmetry()
    return final_symm

  def check_symmetry_consistency(self):
    pass

def extract_labels(miller_arrays):
  return [ array.info().label_string() for array in miller_arrays ]

def get_fp_fpp_from_sasaki(guess_ha,wavelength):
  from cctbx.eltbx import sasaki
  from decimal import Decimal, ROUND_HALF_UP
  if wavelength is None or guess_ha is None :
    return None, None
  try:
    table = sasaki.table(guess_ha)
  except Exception as e :
    return None, None
  fp_fdp = table.at_angstrom(wavelength)
  f_prime=fp_fdp.fp()
  f_double_prime=fp_fdp.fdp()
  fp = Decimal(f_prime).quantize(Decimal('0.01'), ROUND_HALF_UP)
  fpp = Decimal(f_double_prime).quantize(Decimal('0.01'), ROUND_HALF_UP)
  return fp, fpp

def get_high_resolution(server):
  d_min = None #999.99
  for miller_array in server.miller_arrays :
    try :
      array_min = miller_array.d_min()
      if d_min is None or array_min < d_min :
        d_min = array_min
    except Exception :
      pass
  return d_min

def get_miller_array_symmetry(miller_array):
  from cctbx import sgtbx
  symm = miller_array.crystal_symmetry()
  if symm is None :
    return (None, None)
  unit_cell = symm.unit_cell()
  if (unit_cell is not None):
    uc = unit_cell_as_str(unit_cell)
  else :
    uc = None
  space_group = symm.space_group()
  if (space_group is not None):
    sg = str(sgtbx.space_group_info(group=space_group))
  else :
    sg = None
  return (sg, uc)

def get_array_description(miller_array):
  from iotbx import reflection_file_utils
  info = miller_array.info()
  labels = info.label_string()
  if labels in ["PHI", "PHIB", "PHIM", "PHIC"] :
    return "Phases"
  if labels in ["FOM", "FOMM"] :
    return "Weights"
  if ((miller_array.is_integer_array() or miller_array.is_bool_array()) and
      reflection_file_utils.looks_like_r_free_flags_info(info)):
    return "R-free flag"
  methods_and_meanings = [ ("is_complex_array", "Map coeffs"),
                           ("is_xray_amplitude_array", "Amplitude"),
                           ("is_xray_intensity_array", "Intensity"),
                           ("is_hendrickson_lattman_array", "HL coeffs"),
                           ("is_bool_array", "Boolean"),
                           ("is_integer_array", "Integer"),
                           ("is_real_array", "Floating-point"), ]
  for method, desc in methods_and_meanings :
    test = getattr(miller_array, method)
    if test():
      return desc
  return "Unknown"

def get_mtz_label_prefix(input_file=None, file_name=None):
  if input_file is None :
    input_file = file_reader.any_file(file_name)
  assert (input_file.file_type == "hkl" and
          input_file.file_object.file_type() == "ccp4_mtz")
  file_content = input_file.file_object.file_content()
  last_crystal = file_content.crystals()[-1]
  crystal = last_crystal.name()
  dataset = last_crystal.datasets()[-1].name()
  return "/%s/%s" % (crystal, dataset)

def extract_map_coeffs(miller_arrays, f_lab, phi_lab, fom_lab):
  f_array = None
  phi_array = None
  fom_array = None
  #print f_lab, phi_lab, fom_lab
  for miller_array in miller_arrays :
    labels = miller_array.info().label_string()
    if (labels == f_lab):
      f_array = miller_array
    elif (labels == phi_lab):
      phi_array = miller_array
    elif (labels == fom_lab):
      fom_array = miller_array
  return (f_array, phi_array, fom_array)

def map_coeffs_from_mtz_file(mtz_file, f_label="FP", phi_label="PHIM",
    fom_label="FOMM"):
  if not os.path.isfile(mtz_file):
    raise Sorry(
      "No map coefficients are available for conversion.")
  mtz_in = file_reader.any_file(mtz_file)
  mtz_in.assert_file_type("hkl")
  miller_arrays = mtz_in.file_server.miller_arrays
  (f_array, phi_array, fom_array) = extract_map_coeffs(miller_arrays,
    f_label, phi_label, fom_label)
  if (f_array is not None) and (f_array.is_complex_array()):
    map_coeffs = f_array
  else :
    if (f_array is None) or (phi_array is None):
      raise Sorry("One or more of the columns %s and %s was not found." %
        (f_label, phi_label))
    if fom_array is not None :
      weighted_f = f_array * fom_array
    else :
      weighted_f = f_array
    map_coeffs = weighted_f.phase_transfer(phi_array, deg=True)
  return map_coeffs

def extract_phenix_refine_map_coeffs(mtz_file, limit_arrays=None):
  assert (limit_arrays is None) or (isinstance(limit_arrays, list))
  if not os.path.isfile(mtz_file):
    raise Sorry("No map coefficients are available for conversion.")
  mtz_in = file_reader.any_file(mtz_file)
  mtz_in.assert_file_type("hkl")
  miller_arrays = mtz_in.file_server.miller_arrays
  assert len(miller_arrays) > 0
  map_names = {"2FOFCWT" : "2mFo-DFc",
               "FOFCWT" : "mFo-DFc",
               "2FOFCWT_no_fill" : "2mFo-DFc_no_fill",
               "FOFCWT_no_fill" : "mFo-DFc_no_fill"}
  output_arrays = []
  for miller_array in miller_arrays :
    if miller_array.is_complex_array():
      labels = miller_array.info().label_string()
      if labels.startswith("F-model"):
        continue
      if (limit_arrays is not None) and (not labels in limit_arrays):
        continue
      f_label = miller_array.info().labels[0]
      map_name = map_names.get(f_label)
      if map_name is None :
        map_name = f_label
      output_arrays.append((miller_array, map_name))
  return output_arrays

def get_map_coeff_labels(server,
    build_only=False,
    include_fom=True,
    exclude_anomalous=False,
    exclude_fmodel=False,
    keep_array_labels=False):
  all_labels = []
  phi_labels = []
  fom_labels = []
  for miller_array in server.miller_arrays :
    label = miller_array.info().label_string()
    if label.startswith("FOM") and include_fom :
      fom_labels.append(label)
  phase_arrays = server.get_phases_deg(None, None, False, None, None, None,
                                       True, 3)
  for miller_array in phase_arrays :
    labels = miller_array.info().label_string()
    if miller_array.is_hendrickson_lattman_array():
      continue
    elif miller_array.is_complex_array():
      if ((labels.startswith("F-model") or labels.startswith("FMODEL") or
           labels.startswith("FC")) and (exclude_fmodel)):
        continue
      elif (labels.upper().startswith("ANOM")) and (exclude_anomalous):
        continue
      if build_only :
        if (not labels[0:4] in ["FOFC", "DELF", "ANOM"]):
          # list these first
          if (labels in ["FWT,PHWT", "2FOFCWT,PH2FOFCWT"]):
            all_labels.insert(0, labels)
          else :
            all_labels.append(labels)
      else :
        all_labels.append(labels)
    elif miller_array.info().labels[0].startswith("PHI"):
      phi_labels.append(labels)
  amp_arrays = server.get_amplitudes(
    file_name               = None,
    labels                  = None,
    convert_to_amplitudes_if_necessary = False,
    parameter_scope         = "",
    parameter_name          = "",
    return_all_valid_arrays = True,
    minimum_score           = 2,
    strict                  = True)
  if keep_array_labels :
    for miller_array in amp_arrays :
      data_label = miller_array.info().label_string()
      for phase_label in phi_labels :
        hybrid_label = [data_label, phase_label]
        if len(fom_labels) > 0 and include_fom :
          for fom in fom_labels :
            hybrid_label_ = hybrid_label + [ fom ]
            all_labels.append(hybrid_label_)
        else :
          all_labels.append(hybrid_label)
  else :
    for miller_array in amp_arrays :
      f_label = miller_array.info().labels[0]
      if f_label[0] == "F" and f_label != "FC" :
        for phase_label in phi_labels :
          hybrid_label = "%s,%s" % (f_label, phase_label)
          if len(fom_labels) > 0 and include_fom :
            for fom in fom_labels :
              final_label = hybrid_label + ",%s" % fom
              all_labels.append(final_label)
          else :
            all_labels.append(hybrid_label)
  return all_labels

def get_map_coeffs_for_build(server):
  return get_map_coeff_labels(server, build_only=True)

def format_map_coeffs_for_resolve(f_label, phi_label, fom_label):
  return "FP=%s PHIB=%s FOM=%s" % (f_label, phi_label, fom_label)

def decode_resolve_map_coeffs(labels):
  fields = labels.strip().split()
  f_label = None
  phi_label = None
  fom_label = None
  for field in fields :
    resolve_label, array_label = field.split("=")
    if resolve_label == "FP" :
      f_label = array_label
    elif resolve_label == "PHIB" :
      phi_label = array_label
    elif resolve_label == "FOM" :
      fom_label = array_label
  return (f_label, phi_label, fom_label)
