
TA.plot <- function(lm.res, fit = fitted(lm.res),
		    res = residuals(lm.res, "pearson"),
		    labels = NULL, main = mk.main(), xlab = "Fitted values", 
		    draw.smooth = n>=10, show.call = TRUE,  show.2sigma = TRUE,
		    lo.iter = NULL, lo.cex = NULL,
		    ...)
{
  ## Purpose: Produce a Tukey-Anscombe plot of a linear model fit
  ##	      Note that residuals and fitted are UN-correlated (IFF intercept..)
  ## -------------------------------------------------------------------------
  ## Arguments: lm.res = RESult of lm(..)
  ##    res : (weighted) residuals by default,
  ##	labels = 'symbols' for point, default(NULL): extract names or use seq.nr
  ##             use '*' to get simple '*' symbols.
  ##
  ## --- see on-line help by  "?TA.plot" !!
  ## -------------------------------------------------------------------------
  ## Uses : n.plot(.)
  ## -------------------------------------------------------------------------
  ## Author: Martin Maechler, Date: Dec 92 / Nov.93;  for R: 1999/2000
  if(missing(main)) {
    call0 <- call <- lm.res $ call
    if(is.call(call[["formula"]]) && any(c("lm", "aov") == call[[1]]))
      call <- call[["formula"]]
    else {  #-- only formula part; no extra  'ARG ='
      if (length(call) >= 3)
	call <- call[c(1, match("formula", names(call)))]
      names(call)[2] <- ""
    }
    mk.main <- function() {
      cal <- if(is.R()) call else get("call", frame = sys.parent())
      if(is.null(cal))
        "Tukey-Anscombe plot of ???"
      else {
	  nc <- nchar(ccal <- deparse(cal)[1])
	  prt.DEBUG("|cal|=", length(cal), "; nchar(ccal) =", nc,": '", ccal,
		    "'\n", sep="")
	  if(nc > 36)
	    warning("TA.plot: 'main' title is long; consider using  cex= .9")
	  ##-- now should even go further:
	  ##--  E.g. if  nc > 50,  use  cex = .8 in the call to n.plot below
	  paste(if(nc < 13) "Tukey-Anscombe plot of :  "
		else if(nc < 24) "T.A. plot of: " else "TA-pl:", ccal)
	}
    }
  }
  yl <- "Residuals"
  if(!is.null(lm.res$weights)&& any(abs(lm.res$resid- res) > 1e-6*mad(res)))
    yl <- paste("WEIGHTED", yl)
  n.plot(fit, res, nam = labels, xlab = xlab, ylab = yl, main = main, ...)
  ##====
  if(show.call)
    mtext(deparse(match.call()), side = 3, line = 0.5, cex = 0.4, adj=1)
  abline(h = 0, lty = 2, col = 2)
  p.mgp <- par("mgp")[1:2] #-- line numbers of margin text: xlab & label
  if(missing(lo.cex))
    lo.cex <- max(.2, min(0.8*par("mex"), .9*-diff(p.mgp))/par("mfg")[4])
  m.line <- if(par("mfg")[4]==1) .2+ p.mgp[1] else
                              max(p.mgp[1] - .2*lo.cex, sum(p.mgp)/2)
  if(show.2sigma) {
    s2 <- c(-2,2) * mad(res, center=0)
    rr <- range(res)
    if(s2[1] < rr[1] || s2[2] > rr[2])
      mtext(paste("2 sigma = ", format(s2[2])),
	    side= 1, line= m.line, adj = 0, cex= lo.cex)
    abline(h= s2, lwd=1.8, lty=4, col=4)
  }
  n <- length(res)
  if(draw.smooth) {
    ##-- lo.iter: idea of Werner Stahel:  no robustness for 'glm'  residuals
    if (is.null(lo.iter))
      lo.iter <- if(inherits(lm.res, "glm")&& lm.res$family[1]!="Gaussian")
	0  else  3
    f <- max(0.2, 1.25 * n^-.2) #'-- Martin's very empirical formula...
    lines(lowess(fit, res, f = f, iter = lo.iter),
	  lwd = .1, lty = 3, col = 3)
    ##- mtext with 2 times a 'cex' gives BUG [change of cex in global par]!
    ##- --> save  ALL  par()s  to restore !
    ##Q&D op <- par()
    ##Q&D  par(err=-1) # eliminate warnings from using ... below;
    ##Q&D  ... is to   get cex=.. and other parameters; this is "quick&dirty"
    ##Q&D  ...  ELIMINATED !! (use them above for n.plot !!)
    mtext(paste("-.-.-.- : lowess smooth (f =", format(round(f,2)),
		if(lo.iter!=3) paste(", it=", lo.iter), ")"),
	  side = 1, line = m.line, cex = lo.cex, adj = 1)
    ##Q&D par(op)
  }
  ##-	 "Correlation:", formatC(cor(fit,res), dig=3),
  ## mtext(paste(" -- Rank corr.:", formatC(cor(rank(fit),rank(res)), dig=3)) )
  invisible()
}


n.plot <- function (x, y, nam = NULL, abbr = n >= 20 || max(nchar(nam)) >= 
    8, xlab = deparse(substitute(x)), ylab = NULL, ...) 
{
    eval(xlab)
    if (exists("DEBUG") && DEBUG) 
        str(x)
    if (missing(y)) {
        if (!is.null(clx <- class(x)) && clx == "formula") {
            warning("n.plot(.) does NOT yet work with  formula object !!")
            plot.formula(x, ...)
            return(invisible(x))
        }
        else if (is.list(x) & length(x) == 2) {
            y <- x[[2]]
            x <- x[[1]]
        }
        else if (is.matrix(x) & ncol(x) == 2) {
            y <- x[, 2]
            x <- x[, 1]
        }
        else {
            y <- x
            x <- seq(x)
        }
    }
    plot(x, y, type = "n", ..., xlab = xlab, ylab = if (is.null(ylab)) 
        deparse(substitute(y)))
    n <- length(x)
    if (is.null(nam)) {
        nam <- names(x)
        if (is.null(nam)) {
            nam <- names(y)
            if (is.null(nam)) 
                nam <- paste(1:n)
        }
    }
    if (abbr) 
        nam <- abbreviate(nam, min = 1)
    cex <- if (!is.na(maybe.cex <- match("cex", names(list(...))))) 
        list(...)[[maybe.cex]]
    else par("cex")
    text(x, y, labels = nam, cex = cex)
    invisible()
}


prt.DEBUG <- function (..., LEVEL = 1) 
if (exists("DEBUG", w = 1) && DEBUG >= LEVEL) cat(paste("in `", 
    sys.call(sys.nframe() - 1)[1], "':", sep = ""), ..., "\n")
