*! bamat    Version 1.2.2 written 11 June 1997 by P T Seed (STB-55: sbe33)
*!
*! A matrix of Bland-Altman plots for a series of variables
*! bamat varlist, graph_options

* Amended 7 August 1998 to allow for saving graphs
*
* Amended 3 May 2000 by arr@stata to suppress intermediary graphs and
* display only the final matrix of Bland-Altman plots

prog define bamat
  version 5.0


  local varlist "req ex min(3)"
  local if "opt"
  local in "opt"
  local options "noTABle TItle(string) saving(string) data nograph markout FORmat(string) XLAbel(string) YLAbel(string) text(str) *"

  parse "`*'"
	if index("`options'","xlab") ~= 0 | index("`options'","ylab") ~= 0 {
		di in red "xlabel and ylabel without values not permitted"
		exit 198
	}

  parse "`varlist'", parse(" ")

  if "`table'" == "notable" & "`graph'" == "nograph" & "`data'" == "" {
	di in red "Either table data or graph options must be chosen"
	exit 194 }

  preserve
  tempvar touse
  mark `touse' `if'
  if "`markout'" ~= "" {markout `touse' `varlist'}
  if "`format'" == "" { local format "%6.3f" }
  if "`saving'" ~= "" { local saving "saving(`saving')" }

  if "`table'" ~= "notable" {
	_table `varlist' if `touse', format(`format') `data'
	}

  if "`graph'" ~= "nograph" |"`data'" ~= "" {
  	_limits `varlist' if `touse'
	if "`xlabel'" == "" | "`xlabel'"  == "xlabel" {
  		_mynnum xlabel $xmin $xmax
		local xlabel "xlabel($xlabel)"
		}
	else {local xlabel "xlabel(`xlabel')" }

	if "`ylabel'" == "" {
  		_mynnum ylabel $ymin $ymax
		local ylabel "ylabel($ylabel)"
		}
	else {local ylabel "ylabel(`ylabel')" }

        #delim ;
        di _n  in gr "Range of x values is " in ye %6.0g $xmin in gr " to " in ye %6.0g $xmax
           in gr ", range of y values is " in ye %6.0g $ymin in gr " to " in ye %6.0g $ymax;
        #delim cr
	if "`title'" == "" {_graph `varlist' if `touse', `graph' `saving' `xlabel' `ylabel' `data' `options' }
	else {_graph `varlist' if `touse', title("`title'") `graph' `saving' `xlabel' `ylabel' `data' `options' }
	}
end bamat

prog define _table
    local varlist "req ex"
    local if "opt"
    local options "data format(str)"
    parse "`*'"

    tempvar touse
    mark `touse' `if'

    di in gr _new "Reference ranges for differences between two methods""
    #delimit;
    di in gr _new(2) "Method 1" _col(10) "Method 2" _col(20) "Mean"
    _col(30) "[95% Reference Range]"
    _col(54) "Minimum" _col(64) "Maximum" ;
    #delimit cr
    di in gr _dup(70) "-"

    tempvar av diff
    qui gen `av' = .
    qui gen `diff' = .

    local nvar : word count `varlist'
    local i = 2
    while `i' <= `nvar' {

      local j = 1
      while `j' < `i' {
* di "i = |`i'|, j = |`j'|"
          qui replace `diff' = ``i'' - ``j'' `if'
          label var `diff' " "
          qui replace `av' = (``i'' + ``j'')/2 `if'
          label var `av' " "
          qui summ `diff' `if'
          local mean = _result(3)
          local lrr = `mean' - 2*_result(4)^.5
          local urr = `mean' + 2*_result(4)^.5
          local min = _result(5)
          local max = _result(6)
          di in gr "``i''" _col(10) "``j''" _col(20) in ye `format' `mean' /*
*/ _col(30) `format' `lrr' _col(40) `format' `urr' _col(52) `format' `min' _col(62) `format' `max'
	  local j = `j' +1
	  }
	local i = `i' + 1
	}
    di in gr _dup(70) "-"
end _table


prog define _data
	local av `1'
	local diff `2'
	local m1 `3'
	local m2 `4'
	di _n in gr _dup(40) "-"
	di in gr  "Data for graph comparing `m1' and `m2'"
	di in gr "Difference" _col(20) "Average"
	di in gr _dup(40) "-"
	local k = 1
	while `k' <= _N {
	  if `av'[`k'] ~= . & `diff'[`k'] ~= . { di `diff'[`k'] _col(20) `av'[`k'] }
	  local k = `k' + 1
	  }
  	di in gr _dup(40) "-" _n
end _data


prog define _graph
	local varlist "req ex"
	local if "req"
	local options "title(str) saving(str) xlabel(str) ylabel(str) nograph data *"

	parse "`*'",
	if "`saving'" ~= "" { local saving "saving(`saving')" }

	local nvar : word count `varlist'
	tempvar diff av
	qui gen `diff' = .
	qui gen `av' = .
	label var `diff' " "
	label var `av' " "

	local gonoff : set graphics
	set graphics off
	local i = 1
	while `i' <= `nvar' {
		local j = 1
		while `j' <= `nvar' {
			qui replace `diff' = ``i'' - ``j'' `if'
			qui replace `av' = (``i'' + ``j'')/2 `if'
			tempfile g`i'`j'
		       	local graph2 "`graph2' `i'`j'"
		       	local graphs "`graphs' `g`i'`j''"
		        if `i' == `j' & "`graph'" == "" { _namegr ``i'', saving(`g`i'`j'',  replace) }
* set trace on
			else if `i' ~= `j'{
			  qui summ `diff'
			  local mean = _result(3)
			  local lrr = _result(3) - 2*_result(4)^.5
			  local urr = _result(3) + 2*_result(4)^.5
			  if "`graph'" == "" {
				sort `diff' `av'
* set trace off
				tempvar f n
				qui by `diff' `av' : gen `f' = _N if `diff' ~= . & `av' ~= .
				qui by `diff' `av' : gen `n' = _n if `diff' ~= . & `av' ~= .

	    	      	  	qui graph `diff' `av' `if' & `n' == 1 [fw=`f'], xlabel(`xlabel')  /*
*/ylabel(`ylabel') `options' saving(`g`i'`j'', replace) yline(`lrr', `mean', `urr')
				}
			  if "`data'" ~= "" { _data `av' `diff' ``i'' ``j''}
		          }
			local j = `j' + 1
        		}
		local i = `i' + 1
      		}
	set graphics `gonoff'

  if "`graph'" == "" { graph using `graphs', title("`title'") `saving' }
end _graph

prog define _namegr
  local varlist "req ex"
  local options "saving(string)"
  parse "`*'"

  local f1 = 3000
  local f2 = 1400


  parse "`varlist'", parse (" ")
  local lab1 : var label `1'
  if "`lab1'" == "" { local lab1 "`1'" }

  qui gph open, saving(`saving')
  qui gph font `f1' `f2'
  qui gph text 11188 16000 0 0 `lab1'
  qui gph close
end _namegr

prog define _limits
  local varlist "req ex"
  local if "opt"
  parse "`*'"
  tempvar av diff

  qui gen `diff' = `2' - `1'
  qui gen `av' = (`2' + `1')/2
  qui summ `av' `if'
  global xmin = _result(5)
  global xmax = _result(6)
  qui summ `diff' `if'
  global ymin = _result(5)
  global ymax = _result(6)

  local nvar : word count `varlist'
  local i = 3
  while `i' <= `nvar' {

    local j = 1
    while `j' < `i' {
        qui replace `diff' = ``i'' - ``j'' `if'
        qui replace `av' = (``i'' + ``j'')/2 `if'
	qui summ `av' `if'
	if _result(5) < $xmin {	global xmin = _result(5) }
	if _result(6) > $xmax { global xmax = _result(6) }
        qui summ `diff' `if'
	if _result(5) < $ymin { global ymin = _result(5) }
	if _result(6) > $ymax { global ymax = _result(6) }
	local j = `j' + 1
	}
     local i = `i' + 1
     }
     if $ymax + $ymin > 0 { global ymin = -$ymax }
     else { global ymax = -$ymin }
end _limits

prog define _mynnum
*! _mynnum		Version 1.00 20/3/1997 PTS
*! a version of nicenum to handle numbers less than 1
*! usage: _mynnum global_macro minimum maximum mumber_of_ticks
  version 5.0
  local macro "`1'"
  if `2' ~= `3' {
	if `2' < `3' {
		local min `2'
		local max `3'
		}
	else {
		local min `3'
	  	local max `2'
		}
	}
  else  {
     di in red "Numbers do not differ"
     exit  198
     }
  local nticks `4'
  if "`nticks'" == "" { local nticks = 5 }
  else { cap confirm integer `nticks'
         assert `nticks' > 2
         if _rc ~= 0 {
            di in red "Number of ticks requested must be at least 2"
            exit 198
            }
	}

  local gap = 10^(int(log10(`max' - `min'))-1)

  local nt = int((`max' - `min' )/`gap') + 1
  while `nt' < `nticks' {
	local gap = `gap'/10
  	local nt = int((`max' - `min' )/`gap') + 1
	}

  if `nt' > `nticks' - 1 {
	local gap = `gap' * 2
  	local nt = int((`max' - `min' )/`gap') + 1
	}
  if `nt' > `nticks' - 1 {
	local gap = `gap' * 2.5
	}
  if `nt' > `nticks' - 1 {
	local gap = `gap' * 2
	}


  local tick = `gap'*int(`min'/`gap')
  while `tick' > `min' { local tick = `tick' - `gap' }
  global `macro' "`tick'"
  while `tick' < `max' {
	local tick = `tick' + `gap'
	global `macro' "$`macro', `tick'"
	}

end _mynnum