#!/usr/bin/env python
# XDSIdxrefHelpers.py
#   Copyright (C) 2006 CCLRC, Graeme Winter
#
#   This code is distributed under the BSD license, a copy of which is
#   included in the root directory of this package.
#
# Routines which help with working with XDS IDXREF - e.g. parsing the
# output IDXREF.LP.
#

import math
import os
import sys

if not os.environ.has_key('XIA2_ROOT'):
  raise RuntimeError, 'XIA2_ROOT not defined'

if not os.environ['XIA2_ROOT'] in sys.path:
  sys.path.append(os.environ['XIA2_ROOT'])

from Experts.LatticeExpert import ApplyLattice

def _parse_idxref_lp_distance_etc(lp_file_lines):
  '''Parse the LP file for refined distance, beam centre and so on...'''

  beam = None
  diatance = None

  i = 0
  while i < len(lp_file_lines):
    line = lp_file_lines[i]
    i += 1

    if 'DETECTOR COORDINATES' in line and 'DIRECT BEAM' in line:
      beam = tuple(map(float, line.split()[-2:]))
    if 'CRYSTAL TO DETECTOR' in line:
      distance = float(line.split()[-1])
      if distance < 0:
        distance *= -1

  return beam, distance

def _parse_idxref_index_origin(lp_file_lines):
  '''Parse the LP file for the possible index origin etc.'''

  origins = { }

  i = 0
  while i < len(lp_file_lines):
    line = lp_file_lines[i]
    i += 1
    if 'INDEX_' in line and 'QUALITY' in line and 'DELTA' in line:
      while not 'SELECTED' in line:
        line = lp_file_lines[i]
        i += 1
        try:
          hkl = tuple(map(int, line.split()[:3]))
          quality, delta, xd, yd = tuple(
              map(float, line.split()[3:7]))
          origins[hkl] = quality, delta, xd, yd
        except:
          pass

      return origins


  raise RuntimeError, 'should never reach this point'

def _parse_idxref_lp(lp_file_lines):
  '''Parse the list of lines from idxref.lp.'''

  lattice_character_info = {}

  i = 0

  mosaic = 0.0

  while i < len(lp_file_lines):
    line = lp_file_lines[i]
    i += 1

    # get the mosaic information

    if 'CRYSTAL MOSAICITY' in line:
      mosaic = float(line.split()[-1])

    # get the lattice character information - coding around the
    # non-standard possibility of mI, by simply ignoring it!
    # bug # 2355

    if 'CHARACTER  LATTICE     OF FIT      a      b      c' in line:
      j = i + 1
      while lp_file_lines[j].strip() != "":
        record = lp_file_lines[j].replace('*', ' ').split()
        character = int(record[0])
        lattice = record[1]

        # FIXME need to do something properly about this...
        # bug # 2355

        if lattice == 'mI':
          j += 1
          continue

        fit = float(record[2])
        cell = tuple(map(float, record[3:9]))
        reindex_card = tuple(map(int, record[9:]))
        constrained_cell = ApplyLattice(lattice, cell)[0]

        lattice_character_info[character] = {
            'lattice':lattice,
            'fit':fit,
            'cell':constrained_cell,
            'mosaic':mosaic,
            'reidx':reindex_card}

        j += 1


  return lattice_character_info

def _parse_idxref_lp_subtree(lp_file_lines):

  subtrees = { }

  i = 0

  while i < len(lp_file_lines):
    line = lp_file_lines[i]
    i += 1

    if line.split() == ['SUBTREE', 'POPULATION']:
      j = i + 1
      line = lp_file_lines[j]
      while line.strip():
        subtree, population = tuple(map(int, line.split()))
        subtrees[subtree] = population
        j += 1
        line = lp_file_lines[j]

  return subtrees

def _parse_idxref_lp_quality(lp_file_lines):
  fraction = None
  rmsd = None
  rmsphi = None

  for record in lp_file_lines:
    if 'OUT OF' in record and 'SPOTS INDEXED' in record:
      fraction = float(record.split()[0]) / float(record.split()[3])
    if 'STANDARD DEVIATION OF SPOT    POSITION' in record:
      rmsd = float(record.split()[-1])
    if 'STANDARD DEVIATION OF SPINDLE POSITION' in record:
      rmsphi = float(record.split()[-1])

  return fraction, rmsd, rmsphi

if __name__ == '__main__':

  fraction, rmsd, rmsphi = _parse_idxref_lp_quality(
      open(sys.argv[1], 'r').readlines())

  print '%.2f %.2f %.2f' % (fraction, rmsd, rmsphi)
