#!/bin/sh
# If running in a UNIX shell, restart wish on the next line \
exec wish "$0" ${1+"$@"}


####  EasySDE.tcl  ####

# Copyright (c) 2003, 2009, 2012 Oscar Garcia

# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# 
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.



global globinfo nextFlag
# globinfo is array of:
#   title binaries dataFile model nglobals nlocals nplots g1 ... g6 l1 l2 ext
#   ageScale htScale saved

package require Tk  ;#  for tclkit

set progID {EasySDE 2.1}


###  Help  ###

set helptext(model) {MODEL SPECIFICATION

Title:  Run description.
Binary files:  Use pre-processed data file, and final local values
	from the last run.  Local parameter(s) must be the same.
File:  Name of input data file with plot numbers, ages and heights.
Scaling:  Data in the input file are divided by these values.
	Convergence may be faster and more reliable if the mean age
	and height are closer to one.  Initial estimates and report
	output are for the scaled model.
Model:  Click to select a (sub)model.  G are global, and L local
	parameters.
Initial estimates:  Starting values for iterations.  Must correspond
	to the specified scaling, if any.
Next:  Procede with the data pre-processing (generate binary files).
Quit:  Abort.
}

set helptext(data) {DATA PRE-PROCESSING

Log is displayed, no input necessary.
Input file ages and heights are scaled, if necessary, and stored in
   a binary file DATA.tmp.
Data is checked for non-decreasing age sequences.
Initial local estimate(s) is (are) stored in binary direct-access
   file PARS.tmp.  Same value for all plots.
A text file CTRL.tmp with control info is generated.
Next:  Procede with the parameter estimation run.
Quit:  Abort.
Save:  Save data pre-processing report.
}

set helptext(run) {RUN MONITORING LOG

Log of parameter estimation run.
Next:  Display the final results report.
Quit:  Abort.
Save:  Save log.
}

set helptext(report) {RESULTS REPORT

Results.  Values reflect the scaling used, if any.
For each plot, the contribution to the minimized FUNCTION (-2 times
   the log-likelihood), local parameter estimate(s) and its (their)
   estimated standard error(s) are shown.  Unusually high FUNCTION
   values indicate outliers.
}

proc Help {} {
	global stage helptext
	option add *Dialog.msg.wrapLength 6i
	tk_messageBox -type ok -title Help -message $helptext($stage)
}


###  Model info window  ###

set globinfo(ageScale) 10
set globinfo(htScale) 10

wm title . "$progID  --  Model"

# Trick to get focus
update idletasks
wm deiconify .

frame .fm1
pack .fm1
set stage "model"
source modelinfo.ui.tcl
modelinfo_ui .fm1

focus .fm1.titleEntry

proc Validate {} {
	global globinfo
	if {[string length $globinfo(title)] > 80} {
		set globinfo(title) [string range $globinfo(title) 0 79]
	}
	for {set i 1} {$i <= $globinfo(nglobals)} {incr i} { 
		if {[catch {expr {$globinfo(g$i) + 0}}]} {return "G$i"}
	}
	if {$globinfo(binaries)} {
		if {! [file exists DATA.tmp]} {return "Missing DATA.tmp"}
		if {! [file exists PARS.tmp]} {return "Missing PARS.tmp"}
		if {! [file exists CTRL.tmp]} {return "Missing CTRL.tmp"}
		set f [open CTRL.tmp r]
		gets $f
		gets $f line
		if {$globinfo(nlocals) != [lindex $line 1]} {
			close $f
			return "Wrong number of locals"
		}
		set globinfo(nplots) [lindex $line 2]
		set oldnglobals [lindex $line 0] 
		for {set i 0} {$i <= $oldnglobals} {incr i} {gets $f line}
		set globinfo(ageScale) [lindex $line 1]
		set globinfo(htScale) [lindex $line 2]
		close $f
	} else {
		set globinfo(dataFile) [string trim $globinfo(dataFile)]
		if {[string length $globinfo(dataFile)] > 80} {
			return {File ID too long (>80)}
		}
		if {[catch {expr {$globinfo(ageScale) + 0}}]} {return "Age scale"}
		if {[catch {expr {$globinfo(htScale) + 0}}]} {return "Height scale"}
		for {set i 1} {$i <= $globinfo(nlocals)} {incr i} { 
			if {[catch {expr {$globinfo(l$i) + 0}}]} {return "L$i"}
		}
		if {! [file exists $globinfo(dataFile)]} {return "Data file not found"}
	}
	return ""
}
	

set err start
while 1 {
	tkwait variable nextFlag
	set err [Validate]
	if {[string length $err]} {
		tk_messageBox -type ok -icon error -message "Missing or invalid info: $err"
	} else break
}

destroy .fm1

set base .logFrame

frame $base

pack $base -expand 1 -fill both

source RunLog.ui.tcl
# Default saving extension
set globinfo(ext) {}
RunLog_ui $base


###  Data prep window  ###

proc Quit {} {
	global f
	catch {close $f}
	exit 1
}

proc Display line {
	global base
	$base.logText insert end $line
}

proc LogScroll {} {
	global base
	$base.logText see end
}

proc LogState {normalOrDisabled} {
	global base
        $base.logText configure -state $normalOrDisabled
}

proc LogClear {} {
	global base
	LogState normal
	$base.logText delete 0.0 end
	LogState disabled
}


if {! $globinfo(binaries)} {

	wm title . "$progID  --  Data Preparation"
	set stage "data"

	set data "$globinfo(nlocals) [expr {$globinfo(nlocals) + 1}] \
		$globinfo(ageScale) $globinfo(htScale) 0 0 0 \n"
	for {set i 1} {$i <= $globinfo(nlocals)} {incr i} {
		append zer {0 }
		append loc "$globinfo(l$i) "
	}
	append data $zer \n $loc \n

	set data [exec ./DataPrep.exe $globinfo(dataFile) DATA.tmp PARS.tmp << $data]
	# ignore prompts
	regsub {^.*given in file\):\n\n} $data {} data
	Display $data
	LogScroll
	LogState disabled

	set n 0
	regexp {Using +([0-9]+) plots} $data loc n
	set globinfo(nplots) $n

	if {! [regexp ERROR $data] && ($globinfo(nplots) > 0)} {
		$base.nextButton configure -state normal
	}

    # Trick to get focus
    update idletasks
    wm deiconify .


	tkwait variable nextFlag
	$base.nextButton configure -state disabled
	LogClear
}

set f [open CTRL.tmp w]
puts $f $globinfo(title)
puts $f "$globinfo(nglobals) $globinfo(nlocals) $globinfo(nplots) \
	2 3 0 4 [expr {1 + $globinfo(nplots) / 8}] 200 1.E-6"
for {set i 1} {$i <= $globinfo(nglobals)} {incr i} {
	puts $f $globinfo(g$i)
}
puts $f "$globinfo(model) $globinfo(ageScale) $globinfo(htScale)"
close $f


###  Run it  ###

wm title . "$progID  --  Iteration Log"
set stage "run"

# Default saving extension
set globinfo(ext) log

proc Log {} {
	global f base
	if {[eof $f]} {
		catch {close $f}
		$base.logText insert end "***  Done  ***"
	        $base.logText configure -state disabled
		$base.nextButton configure -state normal
	} else {
		gets $f line
		$base.logText insert end $line\n
		$base.logText see end
		update idletasks
	}
}

LogState normal
if {[catch {open "| ./SDEfit.exe CTRL.tmp DATA.tmp PARS.tmp REPORT.tmp &" r} f]} {
	Display $f\n
} else {
	fileevent $f readable Log
}
tkwait variable nextFlag
LogClear

###  Report  ###

wm title . "$progID  --  Report"
set stage "report"

# Default saving extension
set globinfo(ext) rpt

destroy $base.quitButton
$base.nextButton configure -text End

set globinfo(saved) 0
LogState normal
Display "Model $globinfo(model).  "
Display "Age scale: $globinfo(ageScale).  Height scale: $globinfo(htScale).\n\n"

set f [open REPORT.tmp r]
set data [read $f]
close $f
regsub "0\n0ABS. VALUE OF LOCAL.+" $data {} data
regsub -all -lineanchor {^ }  $data {} data
regsub -all -lineanchor {^0|^1}  $data "\n" data
LogState normal
Display $data
LogState disabled

# Trick to get focus
update idletasks
wm deiconify .


tkwait variable nextFlag
while {! $globinfo(saved)} {
	set n [tk_messageBox -type yesno -icon question -default yes \
		-message {Do you want to save this report?}]
	if {[regexp no $n]}  break
	Save $base
}

exit 0

