computeFeatureMeta = (name, data, resolution) => {
  const uniques = Array.from(new Set(data));
  if (uniques.length == data.length && name === UUID_NAME) {
    return {
      name,
      type: FEATURE_TYPE.UUID,
      role: FIELD_ROLE.UUID,
      dataType: DATA_TYPE.STRING,
      domain: null,
    };
  }
  const isInvalid = isFeatureInvalid(data, uniques);
  if (isInvalid) {
    return {
      name,
      type: null,
      role: null,
      dataType: null,
      domain: null,
    };
  }
  const dataType = computeDataType(uniques);
  const type = computeFeatureType(name, data, uniques);
  let domain;
  switch (type) {
    case FEATURE_TYPE.NUMERICAL:
      domain = computeNumericFeatureDomain(uniques, resolution);
      break;
    case FEATURE_TYPE.CATEGORICAL:
      domain = uniques;
      break;
    default:
      domain = [];
  }
  return {
    name,
    type,
    role: FIELD_ROLE.FEATURE,
    dataType,
    domain,
  };
}
identify whether a feature is categorical from its unique values
@param {String} name feature name
@param {Array} data feature values
@param {Number} resolution granularity of bins for numerical feature domain
@return {Object} type and domain of the feature