#!/usr/bin/env perl
use strict;
use lib $ENV{ 'MAIN_CONF'}  ;
use main_config ;
my %commands = () ;

if ( @ARGV <= 0 ) { push ( @{$commands{'help'}}, ' ' ) ; } 
else { (%commands) = main_config::get_commands ( @ARGV ) ; }

my $conf_file ;
if ( -f "main_config.data" )
{    $conf_file = "main_config.data" ; }
else
{    $conf_file = join ('', $ENV{"MAIN_CONF"}, "main_config.data" ) ; }

my %my_main = main_config::read_main_config_file ( $conf_file ) ; 

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

if ( !exists($my_main{"PREF_KICK_CR0"}  ) )  { push ( @{$my_main{"PREF_KICK_CR0"}} , 0 ) ; }
if ( !exists($my_main{"PREF_KICK_CR1"}  ) )  { push ( @{$my_main{"PREF_KICK_CR1"}} , 0 ) ; }
if ( !exists($my_main{"PREF_STEP_COOL"} ) )  { push ( @{$my_main{"PREF_STEP_COOL"}} , 0 ) ; }
if ( !exists($my_main{"PREF_STEP_MIN"}  ) )  { push ( @{$my_main{"PREF_STEP_MIN"}}  , 30 ) ; }
if ( !exists($my_main{"PREF_BVAL_MIN"}  ) )  { push ( @{$my_main{"PREF_BVAL_MIN"}}  , 5 ) ; }
if ( !exists($my_main{"PREF_BVAL_MAX"}  ) )  { push ( @{$my_main{"PREF_BVAL_MAX"}}  , 200 ) ; }
if ( !exists($my_main{"PREF_BACKUP"}  ) )  { push ( @{$my_main{"PREF_BACKUP"}} , "OFF" ) ; }
if ( !exists($my_main{"PREF_SCAL_XTARG"} ) )  { push ( @{$my_main{"PREF_SCAL_XTARG"}} , 1.5 ) ; }
if ( !exists($my_main{"PREF_MAP_XTARG"}  ) )  { push ( @{$my_main{"PREF_MAP_XTARG"}}  , 3 ) ; }
if ( !exists($my_main{"PREF_MAP_XDIFF"} ) )  { push ( @{$my_main{"PREF_MAP_XDIFF"}} , 3 ) ; }
if ( !exists($my_main{"PREF_MAP_DENS"}  ) )  { push ( @{$my_main{"PREF_MAP_DENS"}} , 1 ) ; }
if ( !exists($my_main{"PREF_NCS_FLAG"}  ) )  { push ( @{$my_main{"PREF_NCS_FLAG"}} , "OFF" ) ; }
if ( !exists($my_main{"PREF_NCS_FORCE"} ) )  { push ( @{$my_main{"PREF_NCS_FORCE"}} , 5.0 ) ; }
if ( !exists($my_main{"PREF_NCS_CRYST"}  ) )  { push ( @{$my_main{"PREF_NCS_CRYST"}} , "1" ) ; }
if ( !exists($my_main{"BREF_NCS_FORCE"} ) )  { push ( @{$my_main{"BREF_NCS_FORCE"}} , 0.004 ) ; }
if ( !exists($my_main{"PREF_DIST_CUTOFF"}  ) )  { push ( @{$my_main{"PREF_DIST_CUTOFF"}} , 4.5 ) ; }
if ( !exists($my_main{"PREF_TARGET"}  ) )  { push ( @{$my_main{"PREF_TARGET"}} , "FREE_KICK" ) ; }
if ( !exists($my_main{"PREF_WAY"}  ) )  { push ( @{$my_main{"PREF_WAY"}} , "FAST" ) ; }
if ( !exists($my_main{"PREF_PRECISION"}  ) )  { push ( @{$my_main{"PREF_PRECISION"}} , 3 ) ; }
if ( !exists($my_main{"PREF_ML_MISSIN"}  ) )  { push ( @{$my_main{"PREF_ML_MISSIN"}} , "100" ) ; }
if ( !exists($my_main{"PREF_ML_KICK"}  ) )  { push ( @{$my_main{"PREF_ML_KICK"}} , 0.5 ) ; }
if ( !exists($my_main{"PREF_ML_AVER"}  ) )  { push ( @{$my_main{"PREF_ML_AVER"}} , 1 ) ; }
if ( !exists( $my_main{"BULK_SOLV_METHOD"} ) ) { push ( @{$my_main{"BULK_SOLV_METHOD"}}, "NONE" ) } ; 
if ( !exists( $my_main{"DFR_RFREE"} ) ) { push ( @{$my_main{"DFR_RFREE"}}, "OFF" ) } ; 
if ( !exists($my_main{"MAP_ZONES"}  ) )  { push ( @{$my_main{"MAP_ZONES"}}  , 0 ) ; }

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

my $MACRO_FILE = "refine.cmds" ;
my $PROC_ERROR = "FALSE" ;
my $doit = "FALSE" ;

my $keyword ; 
foreach $keyword ( sort keys (%commands) ) 
{
#    print " keyword >$keyword<\n" ;
    if ( $keyword eq 'h' || substr($keyword, 0,4) eq "help" ) { goto HELP }
    if ( $keyword eq 's' || substr($keyword, 0,4) eq "step" ) { goto STEP }
    if ( $keyword eq 'b' || substr($keyword, 0,5) eq "bramp" ) { goto BRAMP }
    if ( $keyword eq 'k' || substr($keyword, 0,4) eq "kick" ) { goto KICK }
    if ( $keyword eq 'c' || substr($keyword, 0,4) eq "cool" ) { goto COOL }

    if ( $keyword eq 't' || substr($keyword, 0,6) eq "target" ) { goto TARGET }
    if ( $keyword eq 'd' || substr($keyword, 0,8) eq "distance" ) { goto DIST_CUTOFF }
    if ( $keyword eq 'l' || substr($keyword, 0,7) eq "ml_kick" ) { goto ML_KICK }
    if ( $keyword eq 'v' || substr($keyword, 0,7) eq "ml_aver" ) { goto ML_AVER }
    if ( $keyword eq 'w' || substr($keyword, 0,3) eq "way"  ) { goto WAY }
    if ( $keyword eq 'a' || substr($keyword, 0,5) eq "atoms" ) { goto ATOMS }
    if ( $keyword eq 'r' || substr($keyword, 0,5) eq "ratio"  ) { goto RATIO }
    if ( $keyword eq 'm' || substr($keyword, 0,3) eq "map"  ) { goto MAP }
#    if ( $keyword eq 'x' || substr($keyword, 0,4) eq "xmap" ) { goto XMAP }
    if ( $keyword eq 'q' || substr($keyword, 0,4) eq "qmap" ) { goto QMAP }
    if ( $keyword eq 'p' || substr($keyword, 0,9) eq "precision" ) { goto PRECISION }

    if ( $keyword eq 'n' || substr($keyword, 0,3) eq "ncs"  ) { goto NCS }
    if ( $keyword eq 'g' || substr($keyword, 0,4) eq "gncs" ) { goto GNCS }
    if ( $keyword eq 'y' || substr($keyword, 0,9) eq "cryst_ncs" ) { goto CRYST_NCS }
    if ( $keyword eq 'x' || substr($keyword, 0,6) eq "backup" ) { goto BACKUP }

    if ( $keyword eq 'f' || substr($keyword, 0,4) eq "free" ) { goto FREE }
    if ( $keyword eq 'o' || substr($keyword, 0,6) eq "output" ) { goto OUTPUT }
    if ( substr($keyword, 0,4) eq "doit" ) { $doit = "TRUE" ; next ; }
    print "unknown option >$keyword<\n" ; $PROC_ERROR = "TRUE" ;

#-t|--target)    target function for refinement [MAP/DIFF/LSQ/ML/ML_EST/ML_APR]
#-a|--atoms)     missing atoms for estimation of ML [@{$my_main{"PREF_ML_MISSIN"}}]
#-x|--xmap)      MAP for X-DIFF refinement [@{$my_main{"PREF_MAP_XDIFF"}}]
#-c|--ml_kick)   kick for ML function  [0.05 - 0.9] [@{$my_main{"PREF_ML_KICK"}}]
  HELP:
    print << "END_OF_TEXT" ;
-h|--help)      prints this message with available options and current status 
-s|--step)      sets number of minimization steps per cycle [@{$my_main{"PREF_STEP_MIN"}}]
-k|--kick)      sets starting and final maximal xyz kick [0.0 - 0.33]
                current = [@{$my_main{"PREF_KICK_CR0"}} - @{$my_main{"PREF_KICK_CR1"}}]
-c|--cool)      sets number of cooling cycles  [@{$my_main{"PREF_STEP_COOL"}}]
-b|--bramp)     sets minimal and maximal starting atomic B-value ramp [$my_main{"PREF_BVAL_MIN"}[0] - $my_main{"PREF_BVAL_MAX"}[0]]
-t|--target)    target function for refinement [MAP/LSQ/ML/REAL_SPACE/KICK/FREE_KICK/REFMAC]
                current = [@{$my_main{"PREF_TARGET"}}]
-r|--ratio)     approximate ratio target for bond deviations  [0.005 - 0.1]
                current = [@{$my_main{"PREF_SCAL_XTARG"}}]
-l|--ml_kick)   kick ratio for ML function  [0.0 - 3.0] [@{$my_main{"PREF_ML_KICK"}}]
-v|--ml_aver)   averaging over last n AB coefifients for ML function  [@{$my_main{"PREF_ML_AVER"}}]
-m|--map)       MAP for DENSITY refinement [@{$my_main{"PREF_MAP_DENS"}}]
-d|--distance)  distance cutoff for nonbonded interactions [@{$my_main{"PREF_DIST_CUTOFF"}}]
-n|--ncs)       Non-Cryst-Similarity NCS energy flag [ON/OFF]
                current = [@{$my_main{"PREF_NCS_FLAG"}}]
-g|--gncs)      Non-Cryst-Similarity NCS geometry force = [@{$my_main{"PREF_NCS_FORCE"}}]
-y|--cryst_ncs) Refine in variety of crystal forms [1/2/BOTH]: current = [@{$my_main{"PREF_NCS_CRYST"}}]
-x|--backup)    backup after each cycle [ON/OFF]: current = [@{$my_main{"PREF_BACKUP"}}]
-f|--free)      r-free flag [ON/OFF] current [@{$my_main{"DFR_RFREE"}}]
-w|--way)       way of reciprocal space refinement [ACCURATE/FAST] [@{$my_main{"PREF_WAY"}}]
-p|--precision) precsion of x derivatives [@{$my_main{"PREF_PRECISION"}}]
-o|--output)    set file name of the created macro [$MACRO_FILE]
   --doit)      create the macro
END_OF_TEXT
#-q|--qmap)      MAP for rec. space refinement [@{$my_main{"PREF_MAP_XTARG"}}]
    exit ;
  OUTPUT: $MACRO_FILE = shift ( @{$commands{$keyword}} ) ; next ;

  STEP:  @{$my_main{"PREF_STEP_MIN"}} = shift ( @{$commands{$keyword}} ) ; next ;
  COOL:  @{$my_main{"PREF_STEP_COOL"}} = shift ( @{$commands{$keyword}} ) ; next ;
  BACKUP:  @{$my_main{"PREF_BACKUP"}} = shift ( @{$commands{$keyword}} ) ; next ;
  BRAMP: 
    @{$my_main{"PREF_BVAL_MIN"}} = shift ( @{$commands{$keyword}} ) ; 
    @{$my_main{"PREF_BVAL_MAX"}} = shift ( @{$commands{$keyword}} ) ; 
    next ;
  KICK:  
    @{$my_main{"PREF_KICK_CR0"}} = shift ( @{$commands{$keyword}} ) ; 
    @{$my_main{"PREF_KICK_CR1"}} = shift ( @{$commands{$keyword}} ) ; 
#print "kicks: {", $my_main{"PREF_KICK_CR0"}[0], $my_main{"PREF_KICK_CR1"}[0], "} \n" ;
    next ;

  TARGET: @{$my_main{"PREF_TARGET"}} = uc(shift ( @{$commands{$keyword}} )) ; next ;
  ML_KICK: @{$my_main{"PREF_ML_KICK"}} = shift ( @{$commands{$keyword}} ) ; next ;
  ML_AVER: @{$my_main{"PREF_ML_AVER"}} = shift ( @{$commands{$keyword}} ) ; next ;
  ATOMS:  @{$my_main{"PREF_ML_MISSIN"}} = shift ( @{$commands{$keyword}} ) ; next ;
  MAP:   @{$my_main{"PREF_MAP_DENS"}} = shift ( @{$commands{$keyword}} ) ; next ;
  DIST_CUTOFF:   @{$my_main{"PREF_DIST_CUTOFF"}} = shift ( @{$commands{$keyword}} ) ; next ;
  XMAP:  @{$my_main{"PREF_MAP_XDIFF"}} = shift ( @{$commands{$keyword}} ) ; next ;
#  QMAP:  @{$my_main{"PREF_MAP_XTARG"}} = shift ( @{$commands{$keyword}} ) ; next ;
  RATIO:   @{$my_main{"PREF_SCAL_XTARG"}} = shift ( @{$commands{$keyword}} ) ; next ;

  NCS:   @{$my_main{"PREF_NCS_FLAG"}} = shift ( @{$commands{$keyword}} ) ; next ;
  GNCS:    @{$my_main{"PREF_NCS_FORCE"}} = shift ( @{$commands{$keyword}} ) ; next ;
  CRYST_NCS:    @{$my_main{"PREF_NCS_CRYST"}} = uc(shift ( @{$commands{$keyword}} )) ; next ;
  WAY:    @{$my_main{"PREF_WAY"}} = uc(shift ( @{$commands{$keyword}} )) ; next ;
  FREE:  @{$my_main{"DFR_RFREE"}} = uc(shift ( @{$commands{$keyword}} )) ; next ;
  PRECISION:  @{$my_main{"PREF_PRECISION"}} = shift ( @{$commands{$keyword}} ) ; next ;
}

if ( $PROC_ERROR eq "TRUE" ) { exit ; }

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


$conf_file = "main_config.data" ; 
main_config::write_main_config_file ( $conf_file, %my_main ) ; 

###  . ${MAIN_CONF}main_config.data.save.sh

if ( $doit eq "FALSE" )  { exit ; }

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

print "creating \"$MACRO_FILE\" \n" ;
if ( -f $MACRO_FILE ) 
{ 
    my $back = join ('', $MACRO_FILE, ".old" ) ; 
    system ( "mv  $MACRO_FILE $back" ) ; 
}

my $REF_TARGET = $my_main{"PREF_TARGET"}[0] ;
print " MY REF TARGET: }", $REF_TARGET, "{\n";
if ( $REF_TARGET eq "REFMAC" ) { &create_refmac_refine  ;}

open ( MACRO,  "> $MACRO_FILE" ) || die "FILE OPEN ERROR: >$MACRO_FILE< \n" ;

my $BVAL_MAX = ${$my_main{"PREF_BVAL_MAX"}}[0] ;
my $BVAL_MIN = ${$my_main{"PREF_BVAL_MIN"}}[0] ;
my $NZONES = ${$my_main{"MAP_ZONES"}}[0] ;
my $DIST_CUTOFF = ${$my_main{"PREF_DIST_CUTOFF"}}[0] ;
print " my zones::", $NZONES, "{\n" ;
my $WAT_SEGM = ${$my_main{"WAT_SEGM"}}[0] ;
my $WAT_SEGM_D = ${$my_main{"WAT_SEGM"}}[$#{$my_main{"WAT_SEGM"}}] ;

print MACRO << "END_OF_TEXT" ;
subroutine char SEGMENTS int THE_MAP 

! renames new waters to prevent deletions of already accepted solvents
rename segm $WAT_SEGM sele segm name $WAT_SEGM_D end 
set vari II int segm sele segm name $WAT_SEGM end
if ( II .gt. 0 ) then
set vari WORK_SEGM char global - 
	segm sele segm name WORK_SEGM .o segm name $WAT_SEGM  end
! X set vari SEGMENTS char global - 
! X 	segm sele segm name SEGMENTS .o segm name WAT end
end_if

END_OF_TEXT


# multi crystals
my ( $IGR, $NCRYST, $CRYST, $GROUP );

$NCRYST = $my_main{"SG_NCRYST"}[0] ;

if ( $NCRYST > 1 )
{
    print MACRO "define init constr inter \n" ;
    for ( $CRYST = 0; $CRYST < $NCRYST ; $CRYST++ )
    {
	$GROUP = join ( '', "SG_CRYST" , $CRYST+1 ) ;
	print MACRO 
	    "set vari SEG_CRYST = \"", join(" ", @{$my_main{$GROUP}}), "\"\n",
	    "define constr inter \\\n",
	    "sele segm name SEG_CRYST end sele segm name SEG_CRYST end\n" ;
    }
    print MACRO "\n" ;

    if (  $my_main{"PREF_NCS_CRYST"}[0] ne "BOTH" ) 
    { 
	if (  $my_main{"PREF_NCS_CRYST"}[0] eq "1" ) 
	{ print MACRO "set crystal 1\n" ; }
	elsif (  $my_main{"PREF_NCS_CRYST"}[0] eq "2" ) 
	{ print MACRO "set crystal 2\n" ; }

	$NCRYST = 1 ; 
    } 
}


# composit groups - multiple confomrations ...

# 


my $CMP = "NO" ;
if ( @{$my_main{"SG_NMOL"}}[0] > @{$my_main{"SG_NGROUP"}}[0] )
{
    my ( $IGR, $GROUP, $STRATEGY );
    for ( $IGR = 1; $IGR <= @{$my_main{"SG_NGROUP"}}[0] ; $IGR++ )
    {
	$GROUP= join ( '', "SG_GROUP" , $IGR ) ;
	$STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
	if ( $my_main{$STRATEGY}[0] eq "COMPOSIT" ) { $CMP = "YES" ; }
    }
}

if ( $CMP eq "YES" ) 
{
    print MACRO "define init constr inter \n" ;

    my $MEMBER ; my $NN_GROUP=0 ;
    if ( @{$my_main{"SG_NMOL"}}[0] > @{$my_main{"SG_NGROUP"}}[0] )
    {
	my ( $IGR, $GROUP, $STRATEGY );
	for ( $IGR = 1; $IGR <= @{$my_main{"SG_NGROUP"}}[0] ; $IGR++ )
	{
	    $GROUP= join ( '', "SG_GROUP" , $IGR ) ;
	    $STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
	    if ( $my_main{$STRATEGY}[0] eq "COMPOSIT" ) 
	    { 
#	print " COMPOSIT groups: $IGR, <$GROUP> \n" ;
		
		my $LINE = join (" ", @{$my_main{$GROUP}} ) ;
		print MACRO " key outgr  sele .n segm name $LINE end\n" ;
		foreach $MEMBER ( @{$my_main{$GROUP}} )
		{
#	print " groups: $IGR, <$GROUP> $MEMBER\n" ;
		    print MACRO 
			" define constr inter \\\n",
			"sele segm name $MEMBER end sele segm name $MEMBER .o outgr end \n" ;
		}
	    }
	    else
	    { 
		my $LINE = join (" ", @{$my_main{$GROUP}} ) ;
		print MACRO 
		    " define constr inter \\\n",
		    "sele segm name $LINE end \\\n",
                    "sele segm name WORK_SEGM end \n" ;
	    }
	}
    }
    print MACRO " key outgr drop\n" ;
}

# composit group occupancies

if ( @{$my_main{"SG_NMOL"}}[0] > @{$my_main{"SG_NGROUP"}}[0] )
{
    print MACRO
	"! defining COMPOSIT GROUPS by AUTO method \n" ;

    my ( $IGR, $GROUP, $STRATEGY );
    my $NCS_START = "FALSE" ;
    for ( $IGR = 1; $IGR <= @{$my_main{"SG_NGROUP"}}[0] ; $IGR++ )
    {
	$GROUP= join ( '', "SG_GROUP" , $IGR ) ;
	$STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
	if ( $my_main{$STRATEGY}[0] ne "COMPOSIT" ) { next ; }
 #	print " groups: $IGR, <$GROUP> \n" ;
	if ( $NCS_START eq "FALSE" )
	{ 
	    print MACRO " define constr occ init\n" ;
	    $NCS_START = "TRUE" ;
	}
	print MACRO " define constr occ \(auto \\\n" ;
	my @lines = () ;
	my $MEMBER ; my $NC = 0; 
	foreach $MEMBER ( @{$my_main{$GROUP}} )
	{
	    $NC++ ;
#	print " member: $MEMBER> ", $NC, scalar(@{$my_main{$GROUP}}), "\n" ;
	    if ( $NC < @{$my_main{$GROUP}} )
	    {
		print MACRO "     sele segm name $MEMBER end \\\n" ;
	    }
	    else
	    {
		print MACRO "     sele segm name $MEMBER end \)\n\n" ;
	    }
	}
    }
}


#energy stuff and parameters

if ( $NCRYST == 1 ) 
{
print MACRO "<DEF_ALL WORK_SEGM\n" ;
}
else
{
print MACRO "set vari SEGMENTS = \"\\\n" ;
    for ( $CRYST = 0; $CRYST < $NCRYST ; $CRYST++ )
    {
	$GROUP = join ( '', "SG_CRYST" , $CRYST+1 ) ;
	print MACRO join(" ", @{$my_main{$GROUP}}), " \\\n" ;
    }
print MACRO "\"\n" ;
print MACRO "<DEF_ALL SEGMENTS\n" ;


}

print MACRO << "END_OF_TEXT" ;

ener pair off diel = 2.0 ! reduces electrostatics
ener cutoff $DIST_CUTOFF
set weight sele atom name H* end = 0.0 ! kick out Hs from calculation
set temp sele atom name H* end = 0.0 
set temp sele temp -0.1 0.1 .a .not atom name H* end = 30.0 ! sets Bs for new atoms
set temp sele temp $BVAL_MAX   1000. end = $BVAL_MAX  
set temp sele temp $BVAL_MIN  -10000 end = $BVAL_MIN

END_OF_TEXT

# MAPs

my $MAP_CREATED = "NO" ;
my $MAP = $my_main{"PREF_MAP_XTARG"}[0] ;

if ( $NCRYST == 1 ) 
{
    if ( $REF_TARGET ne "MAP" )
    {
	print MACRO << "END_OF_TEXT" ;

make map auto_grid 4.0 init cell real 
if ( MAP_LAST .lt. 0 ) return
set vari MAP_TARG int global = MAP_LAST

END_OF_TEXT

# 	if ( $my_main{"PREF_MAP_XTARG"}[0] !~ m"[0-9]" )
# 	{
# 	    print MACRO << "END_OF_TEXT" ;
#  ! nmaps + 1	
#  set vari MAP_TARG = nmaps + 1
# 		
# END_OF_TEXT
# 	}
# 	else
# 	{
# 	    if ( $my_main{"SG_NCRYST"}[0] > 1 && $MAP <= $my_main{"SG_NCRYST"}[0] * 2 ) { $MAP = $my_main{"SG_NCRYST"}[0] * 2 + 1 ; }
# print MACRO << "END_OF_TEXT" ;
# 
# ! MAP_TARG as specified
#  set vari MAP_TARG = $MAP
# 
# END_OF_TEXT
# 	}
     }

    if ( $REF_TARGET eq "MAP" ) 
    {
	print MACRO << "END_OF_TEXT" ;

 ener  dens on dens map $my_main{"PREF_MAP_DENS"}[0] \\ 
       dens poly 2

END_OF_TEXT

    }
    elsif ( $REF_TARGET eq "DIFF" ) 
    {
    $MAP_CREATED = "YES" ;
    print MACRO << "END_OF_TEXT" ;

 ener  dens on dens map @{$my_main{"PREF_MAP_XDIFF"}}[0] \\ 
       dens poly 2

END_OF_TEXT
    }
    elsif ( $REF_TARGET eq "REAL_SPACE" ) 
    {
    $MAP_CREATED = "YES" ;
    my $shell = "create_map_calc.pl --map_real 2FOFC --number_real MAP_TARG --doit" ;
    print MACRO << "END_OF_TEXT" ;

 ener  dens on dens map MAP_TARG \\ 
       dens poly 2

 shell $shell 
END_OF_TEXT
    }
    else
    {
	$MAP_CREATED = "YES" ;

	print MACRO << "END_OF_TEXT" ;

  ener x-targ ( \\
                on \\ 
                map MAP_TARG \\
              )

END_OF_TEXT
    }

#     if ( $MAP_CREATED eq "YES" ) 
#     {
# 	
# 	print MACRO << "END_OF_TEXT" ;
# 
#  make map auto_grid 4.0 init cell real 
# if ( MAP_LAST .lt. 0 ) return
# set vari MAP_TARG int = MAP_LAST
# 
# END_OF_TEXT
#     }
}
# several crystal forms
else
{
    print MACRO "define init constr map \n" ;
    for ( $CRYST = 0; $CRYST < $NCRYST ; $CRYST++ )
    {

	if ( $REF_TARGET eq "MAP" ) 
	{
	    $MAP =  $CRYST * 2 + 1 ;
	    print MACRO "make map $MAP conv real \n" ;


	}
	else {
	    $MAP =  $CRYST * 2 + 2 ;
	    print MACRO "make map $MAP conv real \n" ;
	}
	$GROUP = join ( '', "SG_CRYST" , $CRYST+1 ) ;
	print MACRO 
	    "set vari SEG_CRYST = \"", join(" ", @{$my_main{$GROUP}}), "\"\n",
	    "define constr map ", $MAP, 
	    " sele segm name SEG_CRYST end \n",
	    "energy dens ( map $MAP scale 100.0 ) \n" ;
    }
    print MACRO "\n" ;
    if ( $REF_TARGET eq "MAP" ) 
    {

print MACRO << "END_OF_TEXT" ;

 ener  dens on dens map $my_main{"PREF_MAP_DENS"}[0] \\ 
       dens poly 2

END_OF_TEXT

    }
    elsif ( $REF_TARGET eq "DIFF" ) 
    {

	print MACRO << "END_OF_TEXT" ;

 ener  dens on dens map @{$my_main{"PREF_MAP_XDIFF"}}[0] \\ 
       dens poly 2

END_OF_TEXT

    }
    else
    {

	my $macro_file = join ('', $ENV{"MAIN_CONF"}, "create_multi_deriv_maps.pl" ) ; 
	system ( "$macro_file" ) ; 
	print MACRO << "END_OF_TEXT" ;
  set vari MAP_TARG = $MAP
  ener x-targ ( \\
                on \\ 
                map MAP_TARG \\
              )

END_OF_TEXT
    }
}

my $FL_BACKGROUND = 0 ;
######## NCS region definition
if ( $my_main{"PREF_NCS_FLAG"}[0] eq "ON" ) 
{
# print " groups @{$my_main{\"SG_NMOL\"}}[0] < @{$my_main{\"SG_NGROUP\"}}[0]  \n" ;
    my $NCS_FORCE = $my_main{"PREF_NCS_FORCE"}[0] ;
    print MACRO "ener ncs scale $NCS_FORCE \n" ;
if ( @{$my_main{"SG_NMOL"}}[0] > @{$my_main{"SG_NGROUP"}}[0] )
{
    print MACRO
	"! include all the non equivalent residues here\n", 
	" key out sele .not all end\n",
	" key out_side sele .not all end\n",
	" <define_key_out.com\n\n",
	"! defining groups \n" ;

    my ( $IGR, $GROUP, $STRATEGY );
    my $NCS_START = "FALSE" ;
    for ( $IGR = 1; $IGR <= @{$my_main{"SG_NGROUP"}}[0] ; $IGR++ )
    {
	$GROUP= join ( '', "SG_GROUP" , $IGR ) ;
	$STRATEGY = join ( '', "SG_GROUP" , $IGR, "_STRATEGY" ) ;
#	print " groups: $IGR, <$GROUP> \n" ;
	if ( $my_main{$STRATEGY}[0] eq "BACKGROUND" && $FL_BACKGROUND == 0 )
	{
	    $FL_BACKGROUND++ ;
	    print MACRO "key background sele .n all end\n" ;
	}
	if ( $my_main{$STRATEGY}[0] ne "COMPOSIT" ) 
	{
	    if ( $NCS_START eq "FALSE" )
	    { 
		print MACRO " define init constr ncs \n" ;
		$NCS_START = "TRUE" ;
	    }
	    else
	    { 
		print MACRO " define constraint ncs next \n" ; 
	    }
	    
	    my $MEMBER ; my $NN_GROUP=0 ;
	    foreach $MEMBER ( @{$my_main{$GROUP}} )
	    {
		$NN_GROUP++;
#	print " member: $MEMBER> \n" ;
#		if ( $NN_GROUP ne 1 ) 
#		{
#		    print MACRO
#			" rms coor all eigen \\ \n",
#			"    sele atom name CA N C O H CB %G* %D* \\ \n",
#			"   .a ( segm name  $MEMBER .a .not out ) end sele int_ncs__1 end \n" ;
#		    print MACRO " define constr ncs sele atom name CA N C O H CB %G* %D* \\ \n",
#		    "          .a ( segm name $MEMBER .a .not out ) end  last_rms polar \n"
#		    } 
#		else
#		{
		print MACRO " define constr ncs sele atom name CA N C O H CB %G* %D* \\ \n",
		"          .a ( segm name $MEMBER .a .not out .a .n out_side ) end \n"
#		}
	    }
	    my $NCS_KEY ; my $NCS_TXT ; my $NCS_KEY_BASE ;
	    $NN_GROUP=0 ;
	    foreach $MEMBER ( @{$my_main{$GROUP}} )
	    {
		$NN_GROUP++;
		$NCS_KEY = sprintf ( "%7s%2d%3d", "int_ncs", $IGR, $NN_GROUP );
		$NCS_KEY =~ s/ /\_/g ;
		if ( $NN_GROUP == 1 ) 
		{ $NCS_KEY_BASE = $NCS_KEY ; }
		else
		{ 

		    print MACRO "make pair init sele $NCS_KEY_BASE end sele $NCS_KEY end seq name_mat \n" ;
		    print MACRO "key $NCS_KEY_BASE sele $NCS_KEY_BASE .a by pair $NCS_KEY end \n" ;
		    print MACRO "key $NCS_KEY sele $NCS_KEY .a by pair $NCS_KEY_BASE end \n\n" ;
		    print " key for NCS:", $NCS_KEY, "\n" ;
		}
	    }
	}
	if ( $my_main{$STRATEGY}[0] eq "BACKGROUND" ) 
	{
	    my $NN_GROUP= @{$my_main{$GROUP}} ;
	    my $MEMBER =  ${$my_main{$GROUP}}[$NN_GROUP-1] ;
	    print MACRO "key background sele background .o segm name $MEMBER end \n" ;
	}
	print MACRO " ener ncs @{$my_main{\"PREF_NCS_FLAG\"}}[0] \n" ;
    }
}
}
else
{
    print MACRO " define init constr ncs \n" ;
}

#    print MACRO "return \n" ;
    print MACRO " set coord save now \n" ;
    print MACRO " set coord save off \n" ;

###########  KICKS and REFINEMENT

#print MACRO "!echo NZONES= }", $NZONES, "{\n" ;

if ( $REF_TARGET ne "DIFF" && $REF_TARGET ne "MAP" && $REF_TARGET ne "REAL_SPACE"  )
{ print MACRO "< ?MAIN_CMDS_NEW:re_phase.cmds WORK_SEGM MAP_WORK $NZONES\n" ; }


my $STEP_COOL ; my $NCOOL ;

#print " pref_step_cool @{$my_main{\"PREF_STEP_COOL\"}} \n";
if ( @{$my_main{"PREF_STEP_COOL"}}[0] > 1 )
{
    $STEP_COOL = @{$my_main{"PREF_STEP_COOL"}}[0] ;
    $NCOOL = $STEP_COOL ;
# print " pref_step_cool minus 1 @{$my_main{\"PREF_STEP_COOL\"}}[0] \n";
}
else { $NCOOL = 0 ; }

print MACRO << "END_OF_TEXT" ;

mini adjust ( bond = @{$my_main{"PREF_SCAL_XTARG"}}[0] step = 100 )

END_OF_TEXT

    my $I ; my $S ;
$I=0 ; $S = 0 ;
my @cool_array = () ;
for ( $I=0 ; $I <= $NCOOL ; $I++ )
{
    $S = $S + $I ;
    push ( @cool_array, $S ) ;
    print " I $I S $S \n" ;
}

$I=0 ; 
for ( $I=0 ; $I <= $NCOOL ; $I++ )
{

## print " in III  $I cool is $NCOOL - @{$my_main{\"PREF_STEP_COOL\"}}[0] \n";
    if ( $I == 1 ) { print MACRO "mini list_gen keep\n" ; }

if ( $REF_TARGET eq "ML_EST" ) 
{
print MACRO << "END_OF_TEXT" ;

< ?MAIN_CMDS:re_phase.cmds WORK_SEGM MAP_WORK $NZONES
refl 
move fobs fsave
exit

END_OF_TEXT
}

if ( $REF_TARGET eq "REAL_SPACE" ) 
{
print MACRO << "END_OF_TEXT" ;

<map_calculate_4refine.cmds

END_OF_TEXT
}




if ( @{$my_main{"PREF_STEP_COOL"}}[0] == 1 )
{
    print MACRO
	" \n",
	" ! kick : 0.02 very small: 0.33 the largest managable by minimizer \n",
	" set coor kick @{$my_main{\"PREF_KICK_CR0\"}}[0] sele segm name SEGMENTS end \n\n";
}
elsif ( @{$my_main{"PREF_STEP_COOL"}}[0] > 1 )
{
    my $PX = ( $S - $cool_array[$STEP_COOL-$I] ) / $S ;
#    print " PARTIAL: ( $S - $I) / $STEP_COOL = $PX \n";
#    print " PARTIAL: ( $STEP_COOL - $I) / $STEP_COOL = $PX \n";
    my $KICK = ( @{$my_main{"PREF_KICK_CR0"}}[0] - @{$my_main{"PREF_KICK_CR1"}}[0] ) *
	(1. - $PX) + @{$my_main{"PREF_KICK_CR1"}}[0] ;
#    print " PARTIAL: ( $S - $I) / $STEP_COOL = $PX > $KICK \n";
#    print " PARTIAL: ( $STEP_COOL - $I) / $STEP_COOL = $PX > $KICK \n";
    printf MACRO
	"\n set coor kick %6.3f sele segm name SEGMENTS end \n", $KICK ;
}

else { print MACRO "\n ! no kick applied \n" ; }

if ( $REF_TARGET eq "ML_EST" ) 
{
print MACRO << "END_OF_TEXT" ;

< ?MAIN_CMDS:re_phase.cmds WORK_SEGM MAP_WORK $NZONES
refl 
move fobs fsave
exit

END_OF_TEXT
}

if ( $REF_TARGET eq "REAL_SPACE" ) 
{
    my $IX = int( $my_main{"PREF_STEP_MIN"}[0] / 50 ) ;
    if ( $IX < 10 ) { $IX = 10 ; }
print MACRO << "END_OF_TEXT" ;

 mini position  sele segm name SEGMENTS .a .n background end \\ 
 	 step = $my_main{"PREF_STEP_MIN"}[0] \\ 
 	 writ = $IX

END_OF_TEXT
goto FINISH 
}

if ( $REF_TARGET eq "MAP" ) 
{
    my $IX = int ( $my_main{"PREF_STEP_MIN"}[0] / 50 ) ;
    if ( $IX < 0 ) { $IX = 10 ; }
print MACRO << "END_OF_TEXT" ;

 mini position  sele segm name SEGMENTS .a .n background end \\ 
 	 step = $my_main{"PREF_STEP_MIN"}[0] \\ 
 	 writ = $IX

END_OF_TEXT
goto FINISH 
}

my $PRECISION = ${$my_main{"PREF_PRECISION"}}[0] ;
print MACRO << "END_OF_TEXT" ;

energy x-targ ( precision $PRECISION )

END_OF_TEXT

print MACRO << "END_OF_TEXT" ;

! refl key WORK_ORIG drop
! refl key TEST_ORIG drop

mini position  sele segm name SEGMENTS .a .n background end \\
     step = $my_main{"PREF_STEP_MIN"}[0] \\
END_OF_TEXT

if ( $my_main{"PREF_WAY"}[0] eq "ACCURATE" )
{    print MACRO "             each_step \\ \n" ; }

if ( $REF_TARGET eq "DIFF" ) 
{    
    print MACRO << "END_OF_TEXT" ;
             step = 15 \\
             gain = 600000.0 \\ 
END_OF_TEXT
}

if ( $my_main{"DFR_RFREE"}[0] eq "ON" )
{    
    if ( $REF_TARGET eq "FREE_KICK" ) 
    {
	print MACRO "     phase \( sele WORK_REFL end \\ \n" ; 
	print MACRO "            free sele WORK_REFL end \\ \n" ; 
	print MACRO "            test sele TEST end \\ \n" ; 
    }
    else
    {    
	print MACRO "     phase \( sele WORK_REFL end \\ \n" ; 
	print MACRO "            free sele TEST end \\ \n" ; 
    }
}
else
{ 
    print MACRO "    phase \( sele defined end \\ \n" ; 
    if ( $REF_TARGET eq "FREE_KICK" ) 
    {	
	print MACRO "            free sele defined end \\ \n" ; 
    }
}


if ( $REF_TARGET eq "MAP" )
{    print MACRO " 	     target ( map ) \\ \n" ; }
elsif ( $REF_TARGET eq "DIFF" )
{    print MACRO " 	     target ( difference ) \\ \n" ; }
elsif ( $REF_TARGET eq "LSQ" )
{    print MACRO " 	     target ( least_square ) \\ \n" ; }
elsif ( $REF_TARGET eq "ML" )
{
    my $N_AVER = $my_main{"PREF_ML_AVER"}[0] ;
    print MACRO " 	     target ( max_like $N_AVER ) \\ \n" ; 
     if ( $my_main{"DFR_RFREE"}[0] ne "ON" ) 
     { print "ML refinement - R-FREE FLAG NOT SET?\n" ; }
}
elsif ( $REF_TARGET eq "KICK" )
{
    print MACRO " 	     target ( least_square ) \\ \n" ; 
    print MACRO " 	     macro = map_kick_refine.cmds \\ \n" ; 
}
elsif ( $REF_TARGET eq "FREE_KICK" )
{    
    my $KICK = $my_main{"PREF_ML_KICK"}[0] ;
    my $N_AVER = $my_main{"PREF_ML_AVER"}[0] ;
    print MACRO " 	     target ( free_kick $KICK $N_AVER ) \\ \n" ; 
}

elsif ( $REF_TARGET eq "ML_EST" )
{    print MACRO " 	     target ( estim_ml missing @{$my_main{\"PREF_ML_MISSIN\"}}[0] ) \\ \n" ; }
elsif ( $REF_TARGET eq "ML_APR" )
{    print MACRO " 	     target ( aprox_ml ) \\ \n" ; }

# mutli crystal phasing
if ( $NCRYST > 1 ) 
{    print MACRO " 	     macro = multi_deriv_maps.com \\ \n" ; }

print MACRO "            ) \\ \n" ; 
if ( $REF_TARGET eq "DIFF" ) 
{    
    print MACRO << "END_OF_TEXT" ;
             writ = 10

END_OF_TEXT
}
if ( $REF_TARGET eq "REAL_SPACE" ) 
{    
    print MACRO << "END_OF_TEXT" ;
             writ = 10

END_OF_TEXT
}
else
{
    print MACRO << "END_OF_TEXT" ;
     writ = 1  

END_OF_TEXT
}




FINISH:

if ( ${$my_main{"PREF_BACKUP"}}[0] eq "ON" )
{
    my $my_file ; 
    if ( @{$my_main{"PREF_STEP_COOL"}}[0] > 1 )
    {
	my $PX = ( $STEP_COOL - $I ) / $STEP_COOL ;
#    print " PARTIAL: ( $STEP_COOL - $I) / $STEP_COOL = $PX \n";
	my $KICK = ( @{$my_main{"PREF_KICK_CR0"}}[0] - @{$my_main{"PREF_KICK_CR1"}}[0] ) *
	    $PX + @{$my_main{"PREF_KICK_CR1"}}[0] ;
	my $ttt = sprintf ( "%6.2f",  $KICK );
	$ttt =~ s/ //g ;
	$my_file = join ( "", "SAVE_FILE_refined_", 
			   $ttt, "-", $I, , ".PDB" ) ;
    }
    else
    {
	$my_file = join ( "", "SAVE_FILE_refined_", $I, , ".PDB" ) ;
    }

    print MACRO "write over file $my_file sele segm name SEGMENTS end coor pdb \n" ;
    
}

} 

####### return to interactive local minimizer

if ( $MAP_CREATED eq "YES" ) 
{
print MACRO << "END_OF_TEXT" ;
 delete map MAP_TARG
 delete vari MAP_TARG
END_OF_TEXT
}

if ( $NCRYST > 1 ) 
{
print MACRO << "END_OF_TEXT" ;
define init constr map
END_OF_TEXT
}

if ( $my_main{"PREF_NCS_FLAG"}[0] eq "ON" ) 
{
print MACRO << "END_OF_TEXT" ;
energy ncs off
END_OF_TEXT
}

print MACRO << "END_OF_TEXT" ;
 ! reset scale for MINIMIZE (later on ...)
 ener  dens ( on map MAP_2FOFC poly 2 ) \\ 
       ncs off
 mini position write 1 step 15 list renew
mini adjust ( bond = 0.02 step = 100 )

set coord save on

return
END_OF_TEXT

close(MACRO) ;

sub create_refmac_refine
{
    print " IN REFMAC REFINE\n" ;

    my $MTZ_FILE = $my_main{"FILE_MTZ"}[0] ;
    my $MTZ_FILE_OUT = $MTZ_FILE ;
    my $CYCLE_REF = $my_main{"PREF_STEP_MIN"}[0] ;
    $MTZ_FILE_OUT =~ s/.mtz// ;
    $MTZ_FILE_OUT = $MTZ_FILE_OUT . "_out.mtz" ;

    open ( MACRO,  "> refine_refmac.sh" ) || die "FILE OPEN ERROR: >$MACRO_FILE< \n" ;
    print MACRO << "END_OF_TEXT" ;
 
refmac5 xyzin model_refmac_in.pdb xyzout model_refmac_out.pdb hklin $MTZ_FILE hklout $MTZ_FILE_OUT \<\< eof
make hydr no
ridge dist sigma 0.02
ncycle $CYCLE_REF
end
eof
END_OF_TEXT

close ( MACRO ) ;

    system "chmod +x refine_refmac.sh" ;

    open ( MACRO,  "> $MACRO_FILE" ) || die "FILE OPEN ERROR: >$MACRO_FILE< \n" ;
    print MACRO << "END_OF_TEXT" ;

rena seq "" sele resi name HOH .o seq W* end from 1 
write over file model_refmac_in.pdb sele segm name WORK_SEGM end coor pdb standard
shell "./refine_refmac.sh > refine_refmac.log"

dele atom sele all end
 read file model_refmac_out.pdb coor pdb 
<>cmds_new/sel_active.cmds WORK
< ?MAIN_UTILS:make_bonds_from_topo.com WORK_SEGM
< ?MAIN_UTILS:fill_atoms.com WORK_SEGM
mini sele weigh -0.1 0.1 end sele all end
< re_image.cmds WORK_SEGM 
return
END_OF_TEXT

close(MACRO) ;

exit;

}
