#!python

"""
"""

import os
import sys
import math
import cPickle

from sloppy_oscillator import delay4_match as PD
from gmisclib import mcmc_logger as LG

from gmisclib import die
from gmisclib import fiatio
from gmisclib import mcmc
mcmc.Debug = 3
from gmisclib import mcmc_big
mcmc_big.Debug = 3
# mcmc_big = mcmc

from gmisclib import mcmc_helper as mcmcP
# from gmisclib import mcmc_m4p as mcmcP
mcmcP.Debug = 1

from newstem2 import indexclass as IC


def pd_factory(arglist, hdr={}):
	Selector = 'True'
	nselections = 0
	predict = 0.0
	Version = ''
	print "Pd_factory: %s" % str(arglist)
	while arglist and arglist[0].startswith('-'):
		arg = arglist.pop(0)
		print 'Arg=', arg
		if arg == '--':
			break
		elif arg == '-n':
			nselections = int(arglist.pop(0))
		elif arg == '-predict':
			predict = float(arglist.pop(0))
			assert predict >= 0.0
		elif arg == '-d':
			mcmcP.Debug += 1
			mcmc_big.Debug += 1
			mcmc.Debug += 1
		elif arg == '-s':
			Selector = arglist.pop(0)
		elif arg == '-v':
			Version = arglist.pop(0)
		else:
			die.die("Unrecognized argument: %s" % arg)

	if not arglist:
		die.die("No databases specified.")
	return PD.problem_definition(arglist, Selector, nselections, predict, Version)



def run(arglist):
	arglist0 = list(arglist)
	pd = pd_factory(arglist)
	guess = IC.guess(pd.GuessProbDist)
	# This is deferred initialization for problem_def:
	for tries in range(20):
		try:
			pd.logp_guts(guess)
		except mcmc_big.NotGoodPosition:
			die.warn("Initial position is not good.%s" % (('', '  Will try again.')[tries+1<6]))
			continue
		else:
			break
	pd.idxr = IC.guess_to_indexer(guess)

	# Guess some initial values to seed the iteration:
	lov = [guess.get_prms() for i in range(guess.n())]
	st = mcmcP.make_stepper_from_lov(pd, lov, mcmc_big, mcmc.position_repeatable)

	if os.path.exists(pd.log_fn()):
		die.die("Log file %s already exists.  Clear it or move it." % pd.log_fn())
	logger = LG.logger_A(fiatio.writer(open(pd.log_fn(), 'w')))
	logger.header('ARGV', ' '.join(arglist0))
	logger.header('Argv', cPickle.dumps(arglist0))
	logger.headers(pd.log_headers())
	logger.comment("Doc:")
	sh = mcmcP.stepper(st, logger=logger)
	logger.set_logstep(int(round(math.sqrt(5*sh.x.np))), None)

	# Find the bottom, roughly:
	acc = mcmcP.step_acceptor(sh.x.np, T0=100.0, T=1.0, ooze=0.4)
	sh.run_to_bottom(ns=2+int(round(math.sqrt(sh.x.np))), acceptable_step=acc)
	logger.Add(sh.x, sh.iter, reason='Initial minimization')	# Log the (hopeful) minimum.
	logger.comment('Initial minimization done')

	# Run for a while to let the temperature equilibriate:
	sh.x.set_sort_strategy(sh.x.SSNEVER)
	sh.run_to_change(2*sh.x.np, acceptable_step=mcmc.T_acceptor())
	sh.run_to_ergodic(1.0, T=1.0)	# Make sure the temperature is cold.
	logger.Add(sh.x, sh.iter, reason='Temperature=1')
	logger.set_trigger_point()
	logger.set_logstep(int(round(math.sqrt(sh.x.np))), 0.01, reason="sampling")
	Nlog = 200
	ERGSTEP = 1.0
	while logger.nlogged < Nlog:
		sh.run_to_ergodic(ERGSTEP, T=1.0)	# Collect the data.



if __name__ == '__main__':
	arglist = sys.argv[1:]
	print 'Arglist:', arglist
	run(arglist)
