#!/usr/bin/python
import os,sys
from program import program
import common

class bp3(program):
  name="Bp3"
  binary="bp3"
  labelout_prefix="BP3_"
  ccp4_parsing=True
  stat={}
  stat['fom'] = common.stats(name='FOM', regexp=r"The overall FOM is\s+(\S+)")
  stat['luzzati'] = common.stats(name='average Luzzati parameter', regexp=r"the average anomalous Luzzati error is\s+(\S+)")
  stat['version'] = common.stats(name='version', regexp=r"bp3;\s+version\s+(\S+)")
  stat['ccp4_version'] = common.stats(name='version', regexp=r"CP4 software suite: library version\s+(\S+)")
  references = ( "Pannu NS, Waterreus WJ,  Skubak P, Sikharulidze I, Abrahams JP & "+
                 "de Graaff RAG (2011) Recent advances in the CRANK software suite "+
                 "for experimental phasing. Acta Cryst. D67, 331-337.", )

  def Init(self):
    self.outfilename = { 'mtz': self.name+'.mtz' }

  def TreatInput(self):
    exper=self.GetKey('targ')
    obj,N=self.inp.GetTargetObjects(exper)
    if obj is None:
      common.Error('The input objects for target {0} of {1} could not be retrieved'.format(exper,self.name))
    # SAD input
    if exper=='SAD': 
      # crystal and dataset name are compulsory for Multicomb...
      self.SetKey('XTAL', str(obj['f+'].xname))
      self.SetKey('DNAME', str(obj['f+'].dname))
      self.SetArg( 'hklin', obj['f+'].GetFileName('mtz') )
      self.SetKey(  'colu', ('F+='+obj['f+'].GetLabel('f'), 'SF+='+obj['f+'].GetLabel('sigf')) )
      self.AddToKey('colu', ('F-='+obj['f-'].GetLabel('f'), 'SF-='+obj['f-'].GetLabel('sigf')) )
      self.SetKey('modl',obj['mod'].GetFileName('pdb'))
      for at,f in obj['mod'].GetAtomTypes().iteritems():
        if f[0] is not None and f[1] is not None:
          self.SetKey('FORM', '{0} FP={1} FPP={2}'.format(at,f[0],f[1]))

  def TreatParams(self):
    if self.process.GetVirtPar('cycles'):
      self.SetKey('cycl', self.process.GetVirtPar('cycles'))
    if self.process.IsNonFalseVirtPar('beta'):
      self.SetKey('beta', self.process.GetVirtPar('beta'))
    if not self.process.GetVirtPar('target') and not self.GetKey('targ'):
      common.Error('Target/experiment has to be specified for program {0}'.format(self.name))
    if not self.GetKey('targ'):
      if self.process.GetVirtPar('target')=='SAD':
        self.SetKey('targ','SAD')
    else:
      self.CapitalizeKey('targ')
    program.TreatParams(self)

  def DefineOutput(self):
    outmtz=self.outfilename['mtz']
    outpdb='heavy-1.pdb'
    atomtypes,xname={},None
    if self.inp.Get('model'):
      atomtypes=self.inp.Get('model').GetAtomTypes()
      xname=self.inp.Get('model').GetCrystalName()
    self.out.AddNew('model', 'heavy-1.pdb', filetype='pdb', typ='substr', \
                    atomtypes=atomtypes, xname=xname)
    self.outmapcc = self.out.AddNew( 'mapcoef', outmtz, typ='best', xname=xname )
    self.outmapcc.SetLabel( ['f','ph','fom','hla','hlb','hlc','hld'] )
    # ***NSP
    if self.process.GetVirtPar('target') in ('SAD','SIRAS'):
      self.outmapcad = self.out.AddNew( 'mapcoef', self.outfilename['mtz'], typ='anom-diff', xname=xname )
      self.outmapcad.SetLabel( ['f','ph'] )


  def TreatOutput(self):
    self.SetKey( 'labout', ('FB='+self.outmapcc.GetLabel('f'),'PHIB='+self.outmapcc.GetLabel('ph')) )
    self.AddToKey( 'labout', 'FOM='+self.outmapcc.GetLabel('fom') )
    self.AddToKey( 'labout', ('HLA='+self.outmapcc.GetLabel('hla'),'HLB='+self.outmapcc.GetLabel('hlb')) )
    self.AddToKey( 'labout', ('HLC='+self.outmapcc.GetLabel('hlc'),'HLD='+self.outmapcc.GetLabel('hld')) )
    if self.outmapcad:
      self.AddToKey( 'labout', ('FDIFF='+self.outmapcad.GetLabel('f'),'PDIFF='+self.outmapcad.GetLabel('ph')) )
    self.SetArg( 'hklout', self.outmapcc.GetFileName('mtz') )
    #self.SetArg( 'xyzout', self.outmodel.GetFileName('pdb') )
