import pickle


def distance_histogram_dict(f):
  """Parses distance histogram dict pickle.

  Distance histograms are stored as pickles of dicts.

  Write one of these with contacts/write_rr_file.write_pickle_file()

  Args:
    f: File-like handle to distance histogram dict pickle.

  Returns:
    Dict with fields:
      probs: (an L x L x num_bins) histogram.
      num_bins: number of bins for each residue pair
      min_range: left hand edge of the distance histogram
      max_range: the extent of the histogram NOT the right hand edge.
  """
  contact_dict = pickle.load(f, encoding='latin1')

  num_res = len(contact_dict['sequence'])

  if not all(key in contact_dict.keys()
             for key in ['probs', 'num_bins', 'min_range', 'max_range']):
    raise ValueError('The pickled contact dict doesn\'t contain all required '
                     'keys: probs, num_bins, min_range, max_range but %s.' %
                     contact_dict.keys())
  if contact_dict['probs'].ndim != 3:
    raise ValueError(
        'Probs is not rank 3 but %d' % contact_dict['probs'].ndim)
  if contact_dict['num_bins'] != contact_dict['probs'].shape[2]:
    raise ValueError(
        'The probs shape doesn\'t match num_bins in the third dimension. '
        'Expected %d got %d.' % (contact_dict['num_bins'],
                                 contact_dict['probs'].shape[2]))
  if contact_dict['probs'].shape[:2] != (num_res, num_res):
    raise ValueError(
        'The first two probs dims (%i, %i) aren\'t equal to len(sequence) %i'
        % (contact_dict['probs'].shape[0], contact_dict['probs'].shape[1],
           num_res))
  return contact_dict