#!/usr/bin/env ccp4-python

import os, sys, shutil, copy

import numpy

from libtbx import phil
from cctbx import sgtbx, maptbx
from scitbx.array_family import flex

import iotbx.ccp4_map
import iotbx.map_tools

############################################################################

master_phil_def = """
input {
    outdir = ./
        .type = str
    ref_map = None
        .type = path
    query_map = None
        .type = path
    outprefix = 'subtracted'
        .type = str
    renormalise = False
        .type = bool
}
"""
# Read in the master phil
master_phil = phil.parse(master_phil_def)
# Show defaults and exit
if '--show-defaults' in sys.argv:
    print('\n# DEFAULTS\n')
    master_phil.show()
    sys.exit()
# Copy the args so that we can remove items from the list without affecting sys.argv etc
args = copy.copy(sys.argv[1:])
# Build an interpreter from the master phil
cmd_interpr = master_phil.command_line_argument_interpreter(home_scope="input")
# Look for cmd line arguments
cmd_line_args = [a for a in args if (('=' in a) and not os.path.exists(a))]
# Remove them from the original lists
[args.remove(a) for a in cmd_line_args]
# Parse these arguments
cmd_sources = [cmd_interpr.process(arg=a) for a in cmd_line_args]
# Combine the phils
working_phil = master_phil.fetch(sources=cmd_sources)

# Pull out the python object of the arguments
params = working_phil.extract().input

############################################################################

ref_map = iotbx.ccp4_map.map_reader(params.ref_map)
query_map = iotbx.ccp4_map.map_reader(params.query_map)

assert ref_map.data.all() == query_map.data.all()
assert ref_map.data.size() == query_map.data.size()
assert ref_map.unit_cell().is_similar_to(query_map.unit_cell())

print 'ALL', ref_map.data.all() 
print 'ORIGIN', ref_map.data.origin()
print 'FOCUS', ref_map.data.focus()

for lig_occ in numpy.arange(0.0, 1.000001, 0.1):
    
    ref_occ = 1 - lig_occ
    
    print 'Subtracting {!s} * ref map'.format(ref_occ)

    diff_data = (query_map.data - ref_map.data*ref_occ).as_double()
#    diff_data.reshape(flex.grid(diff_data.all()))
    
    if params.renormalise: diff_data = diff_data/lig_occ

    outfile = params.outprefix + '-lig-occ-{!s}.ccp4'.format(lig_occ)
    outpath = os.path.join(params.outdir, outfile) 
   
    # "Un-pad" the map
    gridding_first = ref_map.data.origin()
#    gridding_last = tuple(flex.int(query_map.data.all())-2)
    gridding_last = tuple(flex.int(query_map.data.all())-1)
#    gridding_last = tuple(flex.int(query_map.data.all())-0)
    diff_data = maptbx.copy(diff_data, first=gridding_first, last=gridding_last)
 
    # Reducing the size of the grid by 1 seems to be neccessary                                
    iotbx.map_tools.write_ccp4_map( sites_cart = None, 
                                    unit_cell = query_map.unit_cell(), 
                                    map_data = diff_data, 
                                    n_real = diff_data.all(), 
                                    file_name = outpath, 
                                    buffer=0 )

#    iotbx.ccp4_map.write_ccp4_map(  file_name = outpath,
#                                    unit_cell = query_map.unit_cell(),
#                                    space_group = sgtbx.space_group_info(number=query_map.space_group_number).group(),
#                                    gridding_first = gridding_first,
#                                    gridding_last = gridding_last,
#                                    map_data = diff_data,
#                                    labels = None )
