# Rfringe - A library for interferogram analysis
# Author: M.L. Peck (mpeck1@ix.netcom.com)
# Last modified: 18 December 2003
# Non-Gui portions of this software are Copyright (c) 2003, Michael L. Peck.
# Released under the GPL
# "Object" oriented interferogram analysis routines
# Create an "instance" of an interferogram object with
#
# int.inst <- interferogram("pnmfilename")
#
# function returns an environment variable ev and all function calls intended to be user accessible
#
# Functions stored within int.inst are called with (for example)
#
# int.inst$circle.pars()
#
# To access variables defined within interferogram() use
#
# get("var.name", int.inst$ev)
#
# assign("var.name", value, int.inst$ev)
#
interferogram <- function(filename) {
require(pixmap) #always must be present
fname <- filename
image.pix <- read.pnm(fname)
if (class(image.pix) != "pixmapGrey")
image.pix <- addChannels(image.pix, coef=c(1,0,0))
image.mat <- attr(image.pix, "grey")
image.copy <- image.mat
nrm <- nrow(image.mat)+1
X11()
plotwindow <- dev.cur()
plot(image.pix, asp=1, main=paste("Interferogram",basename(fname)))
# Booleans for key steps in analysis
Ap.M <- FALSE # Aperture successfully outlined?
Ob.M <- FALSE # Obstruction measured?
Fr.M <- FALSE # Fringe centers marked?
Fit.M <- FALSE # Zernike fit performed?
Wf.M <- FALSE # Have we filled out a wavefront, and is it current?
ref.adj <- FALSE # Reference surface to be subtracted?
# Fringe centers - the main database
fringes <- data.frame(w=0,xp=0,yp=0,xn=0,yn=0,rho=0,theta=0)
nfringes <- 0
# measured image size & center
xc <- 0
yc <- 0
rx <- 0
ry <- 0
rho.obstruct <- 0
# info that must be input
# image info
tester.id <- ""
test.date <- ""
image.id <- basename(fname)
wl.test <- 632.8
phi <- 0
# Assorted parameters used by autotrace routines
f.part <- 12 #controls window size for local gray scale range
w.hw <- 20 #reset by autotrace
tol.gs <- 0.25 #gray scale tolerance for "magic wand"
m.hw <- 2 #window size for local min search
keep.every <- 4 #fraction to keep
rho.max <- 0.985 #maximum radius to trace to
# info needed for analysis
wl.eval <- wl.test
fringe.scale <- 0.5 #for double pass tests
df.adj <- TRUE
ast.adj <- FALSE
coma.adj <- FALSE
# variable for zernike analysis
maxorder <- NA
zlist <- zlist.qf #default zernikes to fit; overridden by maxorder != NA
pupilsize <- 255 # No. pixels in constructed plots
#things we'll calculate eventually
fit <- NULL
zcoef <- numeric(0)
int.synth <- matrix(0, nrow=pupilsize,ncol=pupilsize)
wf <- matrix(0, nrow=pupilsize,ncol=pupilsize)
rms <- 0
pv <- NA
strehl <- 1
# target conic. The parameters target... are mostly needed for gui wrapper
target.D <- 0
target.rc <- NA
target.fratio <- NA
target.b <- -1
zcoef.ref.s4 <- 0
zcoef.ref.s6 <- 0
##############
# function definitions
# data inputs
image.info <- function(tester =NULL, testdate=NULL, imageid=NULL, testwl=NULL, orientation=NULL) {
if (!is.null(tester)) tester.id <<- tester
if (!is.null(testdate)) test.date <<- testdate
if (!is.null(imageid)) image.id <<- imageid
if (!is.null(testwl)) {
wl.test <<- testwl
Wf.M <<- FALSE
}
if (!is.null(orientation)) phi <<- orientation
}
analysis.info <- function(evalwl = NULL, fringescale=NULL, cancel.defocus=NULL, cancel.ast=NULL, cancel.coma=NULL) {
if (!is.null(evalwl)) wl.eval <<- evalwl
if (!is.null(fringescale)) fringe.scale <<- fringescale
if (!is.null(cancel.defocus)) df.adj <<- cancel.defocus
if (!is.null(cancel.ast)) ast.adj <<- cancel.ast
if (!is.null(cancel.coma)) coma.adj <<- cancel.coma
Wf.M <<- FALSE
}
target.conic.info <- function(D, rc=NA, fratio=NA, b = -1) {
if (b==0) {
ref.adj <<- FALSE
return()
} # stupid call
if (is.na(rc)) rc <- 2*D*fratio #better specify either fratio or rc
sa4 <- (b * (D/rc)^3 * D /64) * (1e6/wl.test)
sa6 <- ((2*b+b^2) * (D/rc)^5 * D/512) * (1e6/wl.test)
zcoef.ref.s6 <<- sa6/(20*sqrt(7))
zcoef.ref.s4 <<- (sa4 + 1.5*sa6)/(6*sqrt(5))
target.D <<- D
target.rc <<- rc
target.fratio <<- fratio
target.b <<- b
ref.adj <<- TRUE
Wf.M <<- FALSE
}
# basic plotting functions
# Plotting colors
fringecolors <- rainbow(8)
fringecolor <- function(i) fringecolors[(i-1) %% length(fringecolors) +1]
ptsym <- 20
ellipse.draw <- function() {
dev.set(plotwindow)
if (rx==0) return
x.e <- seq(-rx,rx, length=101)
y.e <- ry * sqrt(1 - (x.e/rx)^2)
points(x.e+xc, y.e + yc, type='l', lty=1,col='green')
y.e <- -y.e
points(x.e+xc, y.e + yc, type='l', lty=1, col='green')
if (rho.obstruct > 0) {
x.e <- rho.obstruct * x.e
y.e <- rho.obstruct * y.e
points(x.e+xc, y.e + yc, type='l', lty=1,col='green')
y.e <- -y.e
points(x.e+xc, y.e + yc, type='l', lty=1, col='green')
}
}
replot <- function() {
require(pixmap) # to prevent error when called after reload
dev.set(plotwindow)
plot(image.pix, asp=1, main=paste("Interferogram",image.id))
ellipse.draw()
plotwindow <<- dev.cur()
}
plot.fringes <- function() {
replot()
points(fringes$xp, fringes$yp, pch=ptsym, col=fringecolor(fringes$w))
}
# Aperture outlining functions. First the edge of the aperture itself
circle.pars <- function() {
# prompts("Left click on edge of aperture\nPick at least 5 points, preferably more")
# prompts("Right click when done")
scale <- nrm
dev.set(plotwindow)
edge <- locator(type="p", col="green")
x <- edge$x/scale
y <- edge$y/scale
el <- lm(x^2+y^2 ~ x + y + I(y^2))
asp2 <- 1 - coef(el)[4]
xc <- coef(el)[2]/2
yc <- coef(el)[3]/(2*asp2)
rx <- sqrt(coef(el)[1] + xc^2 + yc^2*asp2)
ry <- rx / sqrt(asp2)
if ((abs(scale*(rx-ry)) < 1) || (summary(el)$coefficients[4,4]>0.05)) {
el <- update(el, ~ . - I(y^2))
xc <- coef(el)[2]/2
yc <- coef(el)[3]/2
rx <- sqrt(coef(el)[1] + xc^2 + yc^2)
ry <- rx
}
xc <<- scale*xc
yc <<- scale*yc
rx <<- scale*rx
ry <<- scale*ry
ellipse.draw()
Ap.M <<- TRUE
}
#estimate relative size of obstruction (actually usually a perforation, but never mind)
obstruct.pars <- function() {
# prompts("Left click on edge of obstruction")
# prompts("Right click when done")
edge <- locator(type="p", col="green")
if (is.null(edge)) return
rho.obstruct <<- sqrt(mean((edge$x-xc)^2+(edge$y-yc)^2*(rx/ry)^2))/rx
ellipse.draw()
Ob.M <<- TRUE
}
# Fringe tracing routines.
#utility function returns a matrix same size as image with normalized radius as elements.
rho.int <- function() {
x <- ((1:ncol(image.mat))-xc)/rx
y <- ((1:nrow(image.mat))-nrm+yc)/ry
rho <- function(x,y) sqrt(x^2+y^2)
rhom <- outer(y,x,rho)
return(rhom)
}
visited <- matrix(0, nrow=nrow(image.mat), ncol=ncol(image.mat))
rho.mat <- matrix(0, nrow=nrow(image.mat), ncol=ncol(image.mat))
autotrace <- function() {
if (Fr.M) replot() else dev.set(plotwindow)
rho.mat <<- rho.int()
image.copy[(rho.mat>1) | (rho.mat<rho.obstruct)] <<- 1
w.hw <<- floor(rx/f.part)
visited <<- matrix(0, nrow=nrow(image.mat), ncol=ncol(image.mat))
i <- 1
repeat {
prompts(paste("Left click to pick points in fringe", i, "\n"))
prompts("Right click when done with this fringe\n")
prompts("Right click twice to exit\n\n")
fringe.center <- magicwand(i)
if (is.null(fringe.center)) break
if (i == 1) fringes <<- fringe.center #this is going to wipe out any previously stored fringes
else fringes <<- rbind(fringes,fringe.center)
i <- i + 1
}
rownames(fringes) <<- 1:nrow(fringes)
nfringes <<- max(fringes$w)
prompts(paste("Traced", nfringes, "fringes\n\n"))
Fr.M <<- TRUE
}
magicwand <- function(fringeorder) {
neighbors <- cbind(rep(c(-1,0,1),3),c(rep(-1,3),rep(0,3),rep(1,3)))
f.pts <- matrix(0, nrow=0, ncol=2)
point.n <- 0
repeat {
startp <- locator(1, type='p', col='red')
if (is.null(startp)) break
j <- round(startp$x)
i <- round(nrm-startp$y)
visited[i, j] <- 1
sw <- neighbors
sw[,1] <- sw[,1]+i
sw[,2] <- sw[,2]+j
# get points in fringe
f.pts <- rbind(f.pts,c(i,j))
repeat {
if (point.n >= nrow(f.pts)) break
point.n <- point.n+1
i <- f.pts[point.n, 1]
j <- f.pts[point.n, 2]
sw <- neighbors
sw[,1] <- sw[,1]+i
sw[,2] <- sw[,2]+j
ir <- max(1,i-w.hw):min(nrow(image.copy),i+w.hw)
jr <- max(1,j-w.hw):min(ncol(image.copy),j+w.hw)
im.l <- image.copy[ir,jr]
rho.l <- rho.mat[ir,jr]
grayok <- quantile(im.l[(rho.l <= 1) & (rho.l >= rho.obstruct)], probs=tol.gs)
f.pts <- rbind(f.pts,
sw[which((visited[sw] == 0) & (image.copy[sw] <= grayok)
& (rho.mat[sw] <= rho.max) & (rho.mat[sw] >= rho.obstruct)),])
visited[sw] <- 1
}
points(f.pts[,2],nrm-f.pts[,1],pch=ptsym,col=fringecolor(fringeorder))
}
if (nrow(f.pts) >= 1) {
for (i in (1:nrow(f.pts))) {
localminima <- which(image.copy[f.pts[i,1]+(-m.hw:m.hw),f.pts[i,2]+(-m.hw:m.hw)]
== min(image.copy[f.pts[i,1]+(-m.hw:m.hw),f.pts[i,2]+(-m.hw:m.hw)]), arr.ind=TRUE)
f.pts[i,] <- f.pts[i,] + localminima[floor((nrow(localminima)+1)/2),] -m.hw-1
}
f.pts <- unique(f.pts)
visited[f.pts] <- 1
if (nrow(f.pts) < 5 * keep.every) keepers<-rep(1,nrow(f.pts))
else
keepers <- (1:nrow(f.pts)) %% keep.every
f.order <- order(f.pts[,1], f.pts[,2])
f.pts <- f.pts[f.order,]
f.pts <- matrix(f.pts[(keepers==1),],ncol=2)
yp <- nrm-f.pts[,1]
xp <- f.pts[,2]
xn <- (xp-xc)/rx
yn <- (yp-yc)/ry
rho <- sqrt(xn^2+yn^2)
theta <- atan2(yn,xn)
w <- rep(fringeorder, length(xp))
fringe.center <- data.frame(w, xp, yp, xn, yn, rho, theta)
}
else return(NULL)
return(fringe.center)
}
# manually select points
mtrace <- function(fringeorder, fc) {
temp <- locator(type="p", pch=ptsym, col=fc)
if (is.null(temp)) return(NULL)
xp <- temp$x
yp <- temp$y
visited[cbind((nrm-yp),xp)] <- 1
xn <- (xp-xc)/rx
yn <- (yp-yc)/ry
rho <- sqrt(xn^2+yn^2)
theta <- atan2(yn,xn)
w <- rep(fringeorder, length(xp))
fringe.center <- data.frame(w, xp, yp, xn, yn, rho, theta)
fringe.center <- fringe.center[fringe.center$rho <= 1, ]
return(fringe.center)
}
# Manual fringe editing routines
clearpoints <- function(fringeorder) { # edit out points in fringe fringeorder
replot()
editfringe <- fringes[fringes$w==fringeorder,]
if (is.null(editfringe)) return() #nothing to do
keepfringes <- fringes[fringes$w != fringeorder,]
points(editfringe$xp,editfringe$yp,pch=ptsym, col=fringecolor(fringeorder))
clrpts <- numeric(0)
repeat {
outpt <- identify(editfringe$xp,editfringe$yp, n=1, plot=FALSE)
if (length(outpt)==0) break
visited[nrm-editfringe$yp[outpt],editfringe$xp[outpt]] <<- 0
clrpts <- c(clrpts,outpt)
grayval <- gray(image.mat[nrm-editfringe$yp[outpt],editfringe$xp[outpt]])
points(editfringe$xp[outpt],editfringe$yp[outpt],col=grayval, pch=ptsym)
}
if (length(clrpts)>0) editfringe <- editfringe[-clrpts,]
fringes <<- rbind(keepfringes,editfringe)
rownames(fringes) <<- 1:nrow(fringes)
}
#manually add some points to a fringe
addpoints <- function(fringeorder) {
plotfringes()
points(fringes$xp[fringes$w==fringeorder],fringes$yp[fringes$w==fringeorder],pch=ptsym,col="white")
newpts <- mtrace(fringeorder, fringecolor(fringeorder))
fringes <<- rbind(fringes,newpts)
rownames(fringes) <<- 1:nrow(fringes)
}
#get rid of a whole fringe
clearfringe <- function(fringeorder) {
visited[nrm-fringes$yp[fringes$w==fringeorder],fringes$xp[fringes$w==fringeorder]] <<- 0
fringes <<- fringes[!(fringes$w==fringeorder),]
nfringes <<- max(fringes$w)
}
# Semi-automatic editing routines
#clear an entire fringe & retrace
retrace <- function(fringeorder) {
clearfringe(fringeorder)
plotfringes()
newpts <- magicwand(fringeorder)
if (nrow(newpts)>0) {
fringes <<- rbind(fringes,newpts)
rownames(fringes) <<- 1:nrow(fringes)
}
nfringes <<- max(fringes$w)
}
# add a segment to a fringe without removing any existing points
addsegment <- function(fringeorder) {
plotfringes()
points(fringes$xp[fringes$w==fringeorder],fringes$yp[fringes$w==fringeorder],pch=ptsym, col="white")
newpts <- magicwand(fringeorder)
if (nrow(newpts)>0) {
fringes <<- rbind(fringes,newpts)
rownames(fringes) <<- 1:nrow(fringes)
}
nfringes <<- max(fringes$w)
}
# reorders fringe ordering to accomodate a new fringe. This should always be followed by
# a call to addpoints or addsegment
insertfringe <- function(fringeorder) {
maxw <- max(fringes$w)
minw <- min(fringes$w)
if ((fringeorder<minw) || (fringeorder>maxw)) return
for (i in maxw:fringeorder) {
fringes$w[fringes$w==i] <<- i+1
}
nfringes <<- max(fringes$w)
}
############
# Analysis routines.
fitzernikes <- function() {
if (!is.na(maxorder)) zlist <<- makezlist(maxorder=maxorder)
else zlist <<- zlist.qf
zm <- fillzm(fringes$rho, fringes$theta, phi=-phi, zlist=zlist)
zm.names <- paste("Z",1:ncol(zm),sep="")
colnames(zm) <- zm.names
fmla <- as.formula(paste("fringe.scale*w ~ ", paste(zm.names, collapse="+")))
fringes <- cbind(fringes,zm)
fit <<- lm(fmla, data=fringes)
summarystats() #likely to be wrong at this stage, but that's OK
Fit.M <<- TRUE
Wf.M <<- FALSE
}
summarystats <- function() {
zcoef <<- coef(fit)[-1]*wl.test/wl.eval
zcoef[1:2] <<- 0
if (df.adj) zcoef[3] <<- 0
if (ast.adj) zcoef[4:5] <<- 0
if (coma.adj) zcoef[6:7] <<- 0
if (ref.adj) {
zcoef[8] <<- zcoef[8] - zcoef.ref.s4 * wl.test/wl.eval
zcoef[15] <<- zcoef[15] - zcoef.ref.s6 * wl.test/wl.eval
}
rms <<- sqrt(crossprod(zcoef))
if (!Wf.M) pv <<- NA
else
pv <<- pupilpv(wf)
strehl <<- strehlratio(rms)
}
# basic wavefront analysis
plot.si <- function() {
int.synth <<- synth.interferogram(coef(fit)/fringe.scale, zlist, phi=phi,
size=pupilsize, obstruct=rho.obstruct, iname=image.id)
}
plot.wf <- function() {
if (!Wf.M) {
summarystats()
wf <<- pupil(pupilsize, zcoef=zcoef, zlist=zlist, phi=0)
pv <<- pupilpv(wf)
Wf.M <<- TRUE
}
X11()
axis.scale <- seq(-1,1,length=pupilsize)
image(axis.scale, axis.scale, wf, asp=1, col=topo.colors(256),
xlab="X", ylab="Y", main=paste("Wavefront map of", image.id))
contour(axis.scale,axis.scale, wf, add=TRUE)
}
thetas.contour <- 0
plot.surface <- FALSE
plot.contour <- function(thetas, plot.surf = FALSE) {
thetas.contour <<- thetas
plot.surface <<- plot.surf
profiles <- NULL
rho <- c(seq(1,0, length=101), seq(0,1,length=101))
x <- c(seq(-1,0,length=101), seq(0,1,length=101))
for (i in 1:length(thetas)) {
theta <- c(rep(thetas[i]*pi/180+pi,101), rep(thetas[i]*pi/180,101))
profiles <- cbind(profiles, fillzm(rho, theta, phi=0,zlist=zlist) %*% zcoef)
}
if (plot.surf) {
profiles <- profiles*wl.eval/2
ylabel <- "Surface error (nm)"
tlabel <- "Surface cross sections for"
} else {
ylabel <- "Wavefront error"
tlabel <- "Wavefront cross sections for"
}
ylimit <- range(profiles)
X11()
plot(x, profiles[,1], type='l', xlim=c(-1,1),ylim=ylimit,xlab="X", ylab=ylabel,
main=paste(tlabel, image.id))
grid()
lypos <- .75 *ylimit[1]+.25*ylimit[2]
legend(.75, lypos, legend=thetas, lty=1:length(thetas), col=1:length(thetas))
if (length(thetas)>1) {
for (i in 2:length(thetas)) lines(x, profiles[,i], lty=i, col=i)
}
}
# back end to star test simulator in main body
plot.startest <- function(obstruct=0.0, defocus=5, displaymtf=TRUE) {
fraunhofer(zcoef, zlist, obstruct, lambda=1, defocus=defocus, pupilsize=pupilsize,
displaymtf=displaymtf)
}
# 3d Wavefront plot using RGL library. Warning!! this is highly experimental
# RGL library is obtained from http://wsopuppenkiste.wiso.uni-goettingen.de/~dadler/rgl/
# calls the externally defined routine with the wavefront in this object
plot.wf3d <- function(zoom.wf=1) {
wf.3dplot(wf, zoom.wf)
}
# Print basic summary results. fitzernikes() should be called first.
print.summary <- function() {
summarystats()
prompts(paste("Summary results for", image.id, "\n\n"))
prompts(paste("Tester ", tester.id, "\n"))
prompts(paste("Test date", test.date,"\n\n"))
prompts(paste("Test wavelength ", wl.test, "\n"))
prompts(paste("Evaluation wavelength", wl.eval, "\n\n"))
prompts(paste("RMS ", format(rms, digits=3), "\n"))
prompts(paste("P-V ", format(pv, digits=3), "\n"))
prompts(paste("Strehl ratio", format(strehl, digits=3), "\n"))
astig <- sqrt(coef(fit)[5]^2+coef(fit)[6]^2)*wl.test/wl.eval
angle <- atan2(coef(fit)[6], coef(fit)[5])*90/pi
string <- paste("Astigmatism ",format(astig, digits=3), "Axis", format(angle, digits=1))
if (ast.adj) prompts(paste(string, " [removed]\n")) else prompts(paste(string, "\n"))
coma <- sqrt(coef(fit)[7]^2+coef(fit)[8]^2)*wl.test/wl.eval
angle <- atan2(coef(fit)[8], coef(fit)[7])*180/pi
string <- paste("Coma ",format(coma, digits=3), "Axis", format(angle,digits=1))
if (coma.adj) prompts(paste(string, " [removed]\n")) else prompts(paste(string, "\n"))
prompts(paste("SA ",format(zcoef[8], digits=3), "P-V", format(3.35*zcoef[8], digits=3), "\n"))
if (ref.adj) prompts(paste("Adjusted for target conic", "\n"))
prompts(paste("Based on", nrow(fringes), "points", "\n"))
}
print.details <- function() {
print.summary()
prompts("\n\n")
prompts("Estimated Zernike coefficients and Standard errors\n")
abnamelist <- c("Piston", "Tilt", " ", "Defocus", "Astigmatism", " ", "Coma", " ", "Spherical 3rd",
"Trefoil", " ", "Astigmatism 5th", " ", "Coma 5th", " ", "Spherical 5th",
"Quadratic 7th", " ", "Triangular 7th", " ", "Astigmatism 7th", " ", "Coma 7th", " ", "Spherical 7th",
"5-fold 9th", " ", "Quadratic 9th", " ", "Triangular 9th", " ", "Astigmatism 9th", " ",
"Coma 9th", " ", "Spherical 9th")
if (length(abnamelist) >= length(coef(fit))) abnamelist <- abnamelist[1:length(coef(fit))] else
abnamelist <- c(abnamelist, rep(" ", length(coef(fit))-length(abnamelist)))
pcoefs <- summary(fit)$coefficients[,1:3]
prompts(sprintf("%12s %10s %10s %8s %-20s\n", "Term", "Coef.", "s.e.(Coef)", "t value", "Classical aberration"))
for (i in 1:nrow(pcoefs)) prompts(sprintf("%12s %10.5f %10.5f %8.2f %-20s\n", rownames(pcoefs)[i],
pcoefs[i, 1], pcoefs[i,2], pcoefs[i,3], abnamelist[i]))
prompts(sprintf("\n%s %10.4f %2s %6d %s\n", "Residual standard error", summary(fit)$sigma, "on", fit$df.residual, "degrees of freedom"))
}
print.latex <- function() {
require(tools)
etc <- file.path(path.package(package="Rfringe")[1], "etc", .Platform$OS.type)
Sweave(file.path(etc, "rfireport.rnw"))
system("pdflatex -interaction=batchmode rfireport.tex")
if (!is.null(options("pdfviewer")))
system(paste(options("pdfviewer"), "rfireport.pdf", sep=" "))
}
# Some basic residual plots, put in one window.
plot.residuals <- function() {
if (!Fit.M) return
X11()
screens <- split.screen(c(2,2))
screen(screens[1])
plot(fringes$w,residuals(fit), main=paste('Residuals vs. Fringe order\n', image.id),
xlab='Fringe order', ylab='Residual (waves)')
abline(h=c(-0.1,0.1),lty=2)
screen(screens[2])
plot(fringes$rho,residuals(fit), xlim=c(0,1), main='Residuals vs. Zone radius',
xlab='Relative zone radius', ylab='Residual (waves)')
screen(screens[3])
hist(residuals(fit), main='Residual histogram', xlab='Residual (waves)',
sub=paste('Residual s.d. =',format(summary(fit)$sigma, digits=3)))
screen(screens[4])
qqnorm(residuals(fit), main='Normal Q-Q plot of residuals')
qqline(residuals(fit))
close.screen(all.screens=TRUE)
}
ev <- environment()
isInterferogram <- TRUE
return(list(
ev=ev,
isInterferogram = isInterferogram,
image.info=image.info,
analysis.info=analysis.info,
target.conic.info=target.conic.info,
circle.pars=circle.pars,
obstruct.pars=obstruct.pars,
plot.fringes=plot.fringes,
autotrace=autotrace,
clearpoints=clearpoints,
addpoints=addpoints,
clearfringe=clearfringe,
retrace=retrace,
addsegment=addsegment,
insertfringe=insertfringe,
fitzernikes=fitzernikes,
plot.si = plot.si,
plot.wf = plot.wf,
plot.contour = plot.contour,
plot.wf3d=plot.wf3d,
plot.residuals=plot.residuals,
plot.startest=plot.startest,
print.summary=print.summary,
print.details=print.details,
print.latex=print.latex)
)
}
# Utility function to print a prompt at the console. prompt is a base package function, so called prompts
# Uncomment this for command line based use.
# prompts <- function(string) {
# cat(string, "\n")
# if(.Platform$OS.type == "windows") flush.console()
# else flush.console <- function() {}
# }
gray256 <- grey(seq(0,1,length=256))
grey256 <- gray256
synth.interferogram <- function(zcoef, zlist=zlist.qf, phi = 0, size=255, obstruct=0.0, iname="") {
wf <- pupil(size, obstruct, zcoef[-1], zlist, phi, zcoef[1])
iwf <- cos(2*pi*wf+pi)
X11()
image(iwf, asp=1, col=gray256, xaxt="n", yaxt="n", bty="n", main=paste("Synthetic interferogram",iname))
return(iwf)
}
#experimental 3d wavefront map
wf.3dplot <- function(wf, zoom.wf=1) {
require(rgl)
zlim <- range(wf[!is.na(wf)])
col <- topo.colors(256)[255*(wf-zlim[1])/(zlim[2]-zlim[1])+1]
col[is.na(col)] <- "black"
wf[is.na(wf)] <- 0
xyaxis <- seq(-1,1,length=nrow(wf))
rgl.open()
rgl.bg(sphere=FALSE, fogtype="exp2", color="black")
rgl.surface(-xyaxis, xyaxis, wf*zoom.wf, color=col, shininess=100)
rgl.lines(c(-1,-1.25),c(0,0),c(0,0),color="red")
rgl.lines(c(0,0),c(0,0),c(1,1.25),color="red")
rgl.texts(-1.3,0,0, "X", color="red")
rgl.texts(0,0,1.3, "Y", color="red")
}
# 3D wavefront using base package persp()
wf.persp <- function(wf, zoom.wf=1, theta=0, phi=30, ...) {
wfi <- (wf[-1, -1] + wf[-1, -ncol(wf)] + wf[-nrow(wf), -1] + wf[-nrow(wf), -ncol(wf)])/4
zlim <- range(wfi[!is.na(wfi)])
colors <- matrix("white", nrow=nrow(wf)-1, ncol=ncol(wf)-1)
colors <- topo.colors(256)[255*(wfi-zlim[1])/(zlim[2]-zlim[1])+1]
xyaxis <- seq(-1,1,length=nrow(wf))
par(bg="black")
persp(xyaxis, xyaxis, wf, theta=theta, phi=phi, scale=FALSE,
col=colors, border=NA, shade=0.5,
box=FALSE, axes=FALSE, ...)
par(bg="white")
}
# Assorted routines for manipulation of
# Zernike polynomials
# Author: M.L. Peck (mpeck1@ix.netcom.com)
# Language: R (http://www.r-project.org/)
# Last mod: Sep 03
##utility function returns true if n-m is odd
odd <- function(n,m) {
if (((n-m)%%2) == 0) return(FALSE)
else return(TRUE)
}
##radial zernike polynomials - iterative rewrite
rzernike <- function(rho, n, m) {
if ((n<0) || (m<0) || (n<m) || (odd(n,m))) return(0) #this is an error condition
if ((n==0) && (m==0))return(1)
if (n==m) return(rho^n)
j <- m
rj <- rho^j
r2 <- rho^2
rjm2 <- 0
for (j in seq(m,(n-2),by=2)) {
c2 <- 4*(j+1)*r2-(j-m+2)^2/(j+2)
c4 <- 0
if (j != 0) {
c2 <- c2 - (j+m)^2/j
c4 <- (m^2 - j^2)/j
}
rjp2 <- (j+2)/((j+2)^2-m^2)*(c2 * rj + c4 * rjm2)
rjm2 <- rj
rj <- rjp2
}
return (rj)
}
## Simplified Zernike polynomial
Zernike <- function(rho, theta, n, m, t) {
return( sqrt(n+1) * rzernike(rho, n, m) * switch(t, n=1, c=sqrt(2)*cos(m*theta), s=sqrt(2)*sin(m*theta)))
}
# create a unit aperture in a matrix of size x size elements
# with optional obstruction and fill with wavefront
# Returns matrix of wavefront values. Note this no longer
pupil <- function(size = 255, obstruct = 0.0, zcoef = NULL, zlist=zlist.qf, phi=0, piston=0) {
xs <- seq(-1,1,length=size)
ys <- xs
rhol <- function(x,y) {
return(sqrt(x^2+y^2))
}
rho <- outer(xs,ys,rhol)
rho[rho>1] <- NA
rho[rho<obstruct] <- NA
theta <- outer(-ys,xs,atan2)+pi/2
wf <- matrix(nrow=size, ncol=size)
wf[!is.na(rho)] <- piston
if (!is.null(zcoef)) {
for (i in (1:length(zcoef))[zcoef != 0])
wf <- wf + zcoef[i] * Zernike(rho, theta - pi*phi/180, zlist$n[i], zlist$m[i], zlist$t[i])
}
return(wf)
}
# estimate of rms over pupil
pupilrms <- function(pupil) {
return(sd(pupil[!is.na(pupil)]))
}
# estimate of p-v over pupil
pupilpv <- function(pupil) {
return(max(pupil[!is.na(pupil)])-min(pupil[!is.na(pupil)]))
}
# Mahajans approximation to Strehl ratio
strehlratio <- function(rms) {
return(exp(-(2*pi*rms)^2))
}
#Quickfringe set
zlist.qf <- list(n=c(1,1,2,2,2,3,3,4,3,3,4,4,5,5,6,4,4,5,5,6,6,7,7,8,5,5,6,6,7,7,8,8,9,9,10,12),
m=c(1,1,0,2,2,1,1,0,3,3,2,2,1,1,0,4,4,3,3,2,2,1,1,0,5,5,4,4,3,3,2,2,1,1,0,0),
t=c('c','s','n','c','s','c','s','n','c','s','c','s','c','s','n','c','s','c','s','c','s','c','s','n',
'c','s','c','s','c','s','c','s','c','s','n','n'))
#make a list of all orders up to maxorder
makezlist <- function(minorder=2, maxorder=12) {
n <- numeric()
m <- numeric()
t <- character(length=0)
for (order in seq(minorder, maxorder, by=2)) {
mmax <- order/2
mtemp <- numeric()
for (j in mmax:1) mtemp <- c(mtemp, c(j, j))
mtemp <- c(mtemp, 0)
n <- c(n, order-mtemp)
m <- c(m, mtemp)
t <- c(t, rep(c("c", "s"), mmax), "n")
}
return (list(n=n, m=m, t=t))
}
# Vector of factors from conversion between "normalized" and conventional Zernike definitions
zmult <- function(zlist = zlist.qf) {
mult <- sqrt(zlist$n+1)
mult[zlist$m > 0] <- sqrt(2)*mult[zlist$m > 0]
return(mult)
}
# create a matrix of Zernike polynomial values
fillzm <- function(rho, theta, phi=0, zlist=zlist.qf) {
zm <- matrix(0, nrow=length(rho), ncol=length(zlist$n))
for (i in (1:length(zlist$n))) {
zm[,i] <- Zernike(rho,theta+pi*phi/180, zlist$n[i], zlist$m[i], zlist$t[i])
}
return(zm)
}
# Star test simulator & support routines
# Author: M.L. Peck (mpeck1@ix.netcom.com)
# Language: R (http://www.r-project.org/)
# Last mod: 1 Nov 03
# computes & displays fraunhofer diffraction pattern
# & mtf for wavefront described in zm
fraunhofer <- function(zcoef, zlist=zlist.qf, obstruct=0, lambda = 1, defocus=5,
pupilsize=255, npad =1024, gamma=2,
psfmag=2, displaymtf=TRUE, displaywf=FALSE, fileout=FALSE) {
# calculate phase values for zernike polynomial at wavelength lambda
# assumes z is measured on wavefront
# replaces NA values with 0
wftophase <- function(z, lambda = 1) {
zp <- exp(2i*pi*z/lambda)
zp[is.na(zp)] <- 0
return(zp)
}
# puts matrix z into corner of npadded x npadded matrix
# padded with zeroes
padmatrix <- function(z, npadded) {
nr <- nrow(z)
zpad <- matrix(0,npadded,npadded)
zpad[1:nr,1:nr] <- z
return(zpad)
}
# extract a matrix from the center of a larger matrix
submatrix <- function(z,size=255) {
nr <- nrow(z)
return(z[((nr-size)/2+1):((nr+size)/2),((nr-size)/2+1):((nr+size)/2)])
}
# shuffle quadrants of a 2d fft around to display as an image
fftshift <- function(z) {
nr <- nrow(z)
zs <- matrix(0,nr,nr)
zs[1:(nr/2-1),1:(nr/2-1)] <- z[(nr/2+2):nr,(nr/2+2):nr]
zs[(nr/2):nr,(nr/2):nr] <- z[1:(nr/2+1),1:(nr/2+1)]
zs[(nr/2):nr,1:(nr/2-1)] <- z[1:(nr/2+1),(nr/2+2):nr]
zs[1:(nr/2-1),(nr/2):nr] <- z[(nr/2+2):nr,1:(nr/2+1)]
return(zs)
}
if (!fileout) x11(width=15,height=5)
screens<- split.screen(c(1,3))
wf <- pupil(pupilsize, obstruct, zcoef=zcoef, zlist=zlist)
wf.df <- pupil(pupilsize, obstruct, zcoef=1, zlist=list(n=2, m=0, t='n'))
zp <- wftophase(wf,lambda)
up <- Mod(fft(padmatrix(zp,npad)))
up <- up*up
nrotf <- nrow(wf)
nrpsf <- nrotf
otf <- fft(up, inverse=TRUE)
otf <- otf[1:nrotf,1:nrotf]
mtf <- Re(otf)
mtf <- mtf/max(mtf)
freq <- seq(0,1,length=nrotf)
mtfideal <- 2/pi*(acos(freq)-freq*sqrt(1-freq^2))
psf <- submatrix(fftshift(up),floor(nrpsf/psfmag))
screen(screens[2])
image(psf^(1/gamma),col=gray256,asp=1,bty='n', axes=FALSE)
mtext("0")
if (defocus >5) nrpsf <- 2*nrpsf
if (defocus >15) nrpsf <- npad
zp <- wftophase(wf - defocus/3.46*lambda*wf.df, lambda)
up <- Mod(fft(padmatrix(zp,npad)))
up <- up*up
psf2 <- submatrix(fftshift(up),nrpsf)
screen(screens[1])
image(psf2^(1/gamma),col=gray256, asp=1,bty='n', axes=FALSE)
mtext(-defocus)
zp <- wftophase(wf + defocus/3.46*lambda*wf.df, lambda)
up <- Mod(fft(padmatrix(zp,npad)))
up <- up*up
psf2 <- submatrix(fftshift(up),nrpsf)
screen(screens[3])
image(psf2^(1/gamma),col=gray256,asp=1,bty='n',axes=FALSE)
mtext(defocus)
close.screen(all.screens=TRUE)
if (displaywf) {
x11()
axis.scale <- seq(-1,1,length=pupilsize)
image(axis.scale, axis.scale, wf/lambda, asp=1, col=topo.colors(256),
xlab="X", ylab="Y", main="Wavefront")
contour(axis.scale,axis.scale, wf/lambda, add=TRUE)
}
if (displaymtf) {
x11()
plot(freq,mtf[1,],type="l",ylab="mtf",xlab="relative frequency")
title(main='MTF vs. ideal')
lines(freq,mtf[,1])
lines(freq,mtfideal, lty=5)
grid()
}
return()
}
################################################################################################
# Project management routines
# some simple stuff to analyze multiple interferograms as a unit.
# Note a lot of these are virtual duplicates of the individual analysis routines
project <- function(project.id, project.notes=NULL, project.tester=NULL, project.date=NULL) {
# stuff we just passed
project.id <- project.id
project.notes <- project.notes
project.tester <- project.tester
project.date <- project.date
wl.eval <- NULL
# results from individual test runs
image.ids <- NULL
zcoef <- NULL
zlist <- zlist.qf
rms <- NULL
pv <- NULL
strehl <- NULL
# averaged results
zcoef.mean <- NULL
zcoef.se <- NULL
rms.mean <- NULL
pv.mean <- NULL
strehl.mean <- NULL
pupilsize <- 255
Wf.M <- FALSE
wf <- matrix(0, nrow=pupilsize, ncol=pupilsize)
# add info from interferogram object
# ev is the environment variable for the instance we're adding
project.addto <- function(ev) {
if (is.null(project.tester)) project.tester <<- get("tester.id", ev)
if (is.null(project.date)) project.date <<- get("test.date", ev)
wl.eval <<- get("wl.eval", ev)
image.id.add <- get("image.id", ev)
iindex <- match(image.id.add, image.ids)
# actually replacing data
if (!is.na(iindex)) {
rms[iindex] <<- get("rms", ev)
pv[iindex] <<- get("pv", ev)
strehl[iindex] <<- get("strehl", ev)
zcoef.add <- get("zcoef", ev)
nz <- length(zcoef.add)
if (nz < length(zlist$n)) # fit order was less than current max
zcoef.add <- c(zcoef.add, rep(0, length(zlist$n)-nz))
else if (nz > length(zlist$n)) { #this is dangerous as written because fringe set skips zernikes
zcoef <<- cbind(zcoef, matrix(0, nrow=nrow(zcoef), ncol=nz-length(zlist$n)))
colnames(zcoef) <<- names(zcoef.add)
zlist <<- get("zlist", ev)
}
zcoef[iindex,] <<- zcoef.add
}
else { # adding new data
image.ids <<- c(image.ids, image.id.add)
rms <<- c(rms, get("rms", ev))
pv <<- c(pv, get("pv", ev))
strehl <<- c(strehl, get("strehl", ev))
zcoef.add <- get("zcoef", ev)
if (!is.null(zcoef)) {
nz <- length(zcoef.add)
if (nz < length(zlist$n)) # fit order was less than current max
zcoef.add <- c(zcoef.add, rep(0, length(zlist$n)-nz))
else if (nz > length(zlist$n)) { #this is dangerous as written because fringe set skips zernikes
zcoef <<- cbind(zcoef, matrix(0, nrow=nrow(zcoef), ncol=nz-length(zlist$n)))
colnames(zcoef) <<- names(zcoef.add)
zlist <<- get("zlist", ev)
}
}
else zlist <<- get("zlist", ev)
zcoef <<- rbind(zcoef, zcoef.add)
}
# calculate average of Zernike coefficients
if(nrow(zcoef)>1) {
zcoef.mean <<- mean(data.frame(zcoef))
zcoef.se <<- sqrt(diag(var(zcoef)))/sqrt(nrow(zcoef))
}
else {
zcoef.mean <<- zcoef[1,]
zcoef.se <<- rep(0, length(zcoef.mean))
}
rms.mean <<- sqrt(crossprod(zcoef.mean))
strehl.mean <<- strehlratio(rms.mean)
rownames(zcoef) <<- image.ids
Wf.M <<- FALSE
}
project.removefrom <- function(image.id.out) {
outindex <- match(image.id.out, image.ids)
if (is.na(outindex)) return()
if (length(image.ids) == 1) { #just reset initial values if we took out the last image
image.ids <<- NULL
zcoef <<- NULL
zlist <<- zlist.qf
rms <<- NULL
pv <<- NULL
strehl <<- NULL
# averaged results
zcoef.mean <<- NULL
zcoef.se <<- NULL
rms.mean <<- NULL
pv.mean <<- NULL
strehl.mean <<- NULL
Wf.M <<- FALSE
return()
}
image.ids <<- image.ids[-outindex]
rms <<- rms[-outindex]
pv <<- pv[-outindex]
strehl <<- strehl[-outindex]
nz <- ncol(zcoef)
zcoef <<- matrix(zcoef[-outindex,], ncol=nz)
wt.int <<- rep(1, nrow(zcoef))
if(nrow(zcoef)>1) {
zcoef.mean <<- mean(data.frame(zcoef))
zcoef.se <<- sqrt(diag(var(zcoef)))/sqrt(nrow(zcoef))
}
else {
zcoef.mean <<- zcoef[1,]
zcoef.se <<- rep(0, length(zcoef.mean))
}
rms.mean <<- sqrt(crossprod(zcoef.mean))
strehl.mean <<- strehlratio(rms.mean)
rownames(zcoef) <<- image.ids
Wf.M <<- FALSE
}
plot.wf <- function() {
if (!Wf.M) {
wf <<- pupil(pupilsize, zcoef=zcoef.mean, zlist=zlist, phi=0)
pv.mean <<- pupilpv(wf)
Wf.M <<- TRUE
}
X11()
axis.scale <- seq(-1,1,length=pupilsize)
image(axis.scale, axis.scale, wf, asp=1, col=topo.colors(256),
xlab="X", ylab="Y", main=paste("Averaged wavefront map for", project.id))
contour(axis.scale,axis.scale, wf, add=TRUE)
}
thetas.contour <- 0
plot.surface <- FALSE
plot.contour <- function(thetas, plot.surf = FALSE) {
thetas.contour <<- thetas
plot.surface <<- plot.surf
profiles <- NULL
rho <- c(seq(1,0, length=101), seq(0,1,length=101))
x <- c(seq(-1,0,length=101), seq(0,1,length=101))
for (i in 1:length(thetas)) {
theta <- c(rep(thetas[i]*pi/180+pi,101), rep(thetas[i]*pi/180,101))
profiles <- cbind(profiles, fillzm(rho, theta, phi=0,zlist=zlist) %*% zcoef.mean)
}
if (plot.surf) {
profiles <- profiles*wl.eval/2
ylabel <- "Surface error (nm)"
tlabel <- "Surface cross sections for"
} else {
ylabel <- "Wavefront error"
tlabel <- "Wavefront cross sections for"
}
ylimit <- range(profiles)
X11()
plot(x, profiles[,1], type='l', xlim=c(-1,1),ylim=ylimit,xlab="X", ylab=ylabel,
main=paste(tlabel, project.id))
grid()
lypos <- .75 *ylimit[1]+.25*ylimit[2]
legend(.75, lypos, legend=thetas, lty=1:length(thetas), col=1:length(thetas))
if (length(thetas)>1) {
for (i in 2:length(thetas)) lines(x, profiles[,i], lty=i, col=i)
}
}
# Scatterplot matrix of RMS, Strehl, and P-V
plot.spm <- function() {
panel.box <- function(x) {
par(new=TRUE)
boxplot(x, horizontal=TRUE, names=NULL, axes=FALSE)
}
pairs(cbind(rms,pv,strehl), labels=c("RMS", "P-V", "Strehl"), diag.panel=panel.box,
lower.panel=panel.smooth, cex.labels=2, cex=1.5, pch=20)
}
# back end to star test simulator in main body
plot.startest <- function(obstruct=0.0, defocus=5, displaymtf=TRUE) {
fraunhofer(zcoef.mean, zlist, obstruct, lambda=1, defocus=defocus, pupilsize=pupilsize,
displaymtf=displaymtf)
}
# 3d Wavefront plot using RGL library. Warning!! this is highly experimental
# RGL library is obtained from http://wsopuppenkiste.wiso.uni-goettingen.de/~dadler/rgl/
# calls the externally defined routine with the wavefront in this object
plot.wf3d <- function(zoom.wf=1) {
wf.3dplot(wf, zoom.wf)
}
print.summary <- function() {
prompts(paste("Summary results for", project.id, "\n\n"))
prompts(paste("Comments ", project.notes, "\n"))
prompts(paste("Tester ", project.tester, "\n"))
prompts(paste("Test date", project.date,"\n\n"))
prompts(paste("Evaluation wavelength", wl.eval, "\n\n"))
prompts(paste("RMS ", format(rms.mean, digits=3), "s.d. ", format(sd(rms), digits=3), "\n"))
prompts(paste("P-V ", format(pv.mean, digits=3), "s.d. ", format(sd(pv), digits=3), "\n"))
prompts(paste("Strehl ratio", format(strehl.mean, digits=3), "s.d. ", format(sd(strehl), digits=3), "\n"))
astig <- sqrt(zcoef.mean[4]^2+zcoef.mean[5]^2)
angle <- atan2(zcoef.mean[5], zcoef.mean[4])*90/pi
prompts(paste("Astigmatism ",format(astig, digits=3), "Axis", format(angle, digits=1), "\n"))
coma <- sqrt(zcoef.mean[6]^2+zcoef.mean[7]^2)
angle <- atan2(zcoef.mean[7], zcoef.mean[6])*180/pi
prompts(paste("Coma ",format(coma, digits=3), "Axis", format(angle,digits=1), "\n"))
prompts(paste("SA ",format(zcoef.mean[8], digits=3), "P-V", format(3.35*zcoef.mean[8], digits=3), "\n"))
prompts(paste("Average of", nrow(zcoef), "interferograms", "\n"))
}
# More details
print.details <- function() {
print.summary()
prompts("\n\n")
prompts("Estimated Zernike coefficients and Standard errors\n")
abnamelist <- c("Defocus", "Astigmatism", " ", "Coma", " ", "Spherical 3rd",
"Trefoil", " ", "Astigmatism 5th", " ", "Coma 5th", " ", "Spherical 5th",
"Quadratic 7th", " ", "Triangular 7th", " ", "Astigmatism 7th", " ", "Coma 7th", " ", "Spherical 7th",
"5-fold 9th", " ", "Quadratic 9th", " ", "Triangular 9th", " ", "Astigmatism 9th", " ",
"Coma 9th", " ", "Spherical 9th")
if (length(abnamelist) >= length(zcoef.mean)-2) abnamelist <- abnamelist[1:(length(zcoef.mean)-2)] else
abnamelist <- c(abnamelist, rep(" ", length(zcoef.mean)-2-length(abnamelist)))
prompts(sprintf("%12s %10s %10s %8s %-20s\n", "Term", "Coef.", "s.e.(Coef)", "t value", "Classical aberration"))
for (i in 3:length(zcoef.mean)) prompts(sprintf("%12s %10.5f %10.5f %8.2f %-20s\n", colnames(zcoef)[i],
zcoef.mean[i], zcoef.se[i], zcoef.mean[i]/zcoef.se[i], abnamelist[i-2]))
}
print.latex <- function() {
require(tools)
etc <- file.path(path.package(package="Rfringe")[1], "etc", .Platform$OS.type)
Sweave(file.path(etc, "rfpreport.rnw"))
system("pdflatex -interaction=batchmode rfpreport.tex")
if (!is.null(options("pdfviewer")))
system(paste(options("pdfviewer"), "rfpreport.pdf", sep=" "))
}
ev <- environment()
isIntProject <- TRUE
return(list(
ev=ev,
isIntProject = isIntProject,
project.addto = project.addto,
project.removefrom = project.removefrom,
plot.wf=plot.wf,
plot.contour=plot.contour,
plot.startest=plot.startest,
plot.wf3d=plot.wf3d,
plot.spm=plot.spm,
print.summary=print.summary,
print.details=print.details,
print.latex=print.latex)
)
}
################################################################################################
# Here's the gooey stuff.
# The following is adapted from the package Rcmdr by John Fox. I claim no
# copyright on this material.
# Rfringe main routine. This is the one you call from R
Rfringe <- function(){
require(tcltk)
require(pixmap)
log.font.size <- 10
assign(".logFont", tkfont.create(family="courier", size=log.font.size), envir=.GlobalEnv)
assign(".operatorFont", tkfont.create(family="courier", size=log.font.size),
envir=.GlobalEnv)
assign(".thisint", NULL, envir=.GlobalEnv)
assign(".thisproject", NULL, envir=.GlobalEnv)
log.height <- "25"
log.width <- "80"
assign(".double.click", FALSE, envir=.GlobalEnv)
assign(".grab.focus", TRUE, envir=.GlobalEnv)
if (.Platform$OS.type != "windows") {
default.font.size <- "10"
default.font <- paste("*helvetica-medium-r-normal-*-", default.font.size, "*", sep="")
.Tcl(paste("option add *font ", default.font, sep=""))
}
assign(".rfringe", tktoplevel(), envir=.GlobalEnv)
tkwm.title(.rfringe, "R Fringe")
tkwm.protocol(.rfringe, "WM_DELETE_WINDOW", closeRfringe)
topMenu <- tkmenu(.rfringe)
tkconfigure(.rfringe, menu=topMenu)
.rfringe.done <<- tclVar("0") # to address problem in Debian Linux [?]
etc <- file.path(path.package(package="Rfringe")[1], "etc")
Menus <- read.table(file.path(etc, "Rfringe-menus.txt"), as.is=TRUE)
for (m in 1:nrow(Menus)) {
if (Menus[m, 1] == "menu") assign(Menus[m, 2], tkmenu(eval(parse(text=Menus[m, 3])), tearoff=FALSE))
else if (Menus[m, 1] == "item") {
if (Menus[m, 3] == "command")
tkadd(eval(parse(text=Menus[m, 2])),"command", label=Menus[m, 4], command=eval(parse(text=Menus[m, 5])))
else if (Menus[m, 3] == "cascade")
tkadd(eval(parse(text=Menus[m, 2])),"cascade", label=Menus[m, 4], menu=eval(parse(text=Menus[m, 5])))
else stop(paste("menu defintion error:", Menus[m, ], collapse=" "))
}
else stop(paste("menu defintion error:", Menus[m, ], collapse=" "))
}
controlsFrame <- tkframe(.rfringe)
circleButton <- tkbutton(controlsFrame, text="Aperture edge", command=circlepars)
traceButton <- tkbutton(controlsFrame, text="Trace fringes", command=autotrace)
fitButton <- tkbutton(controlsFrame, text="Fit Zernikes", command=fitzernikes)
wfButton <- tkbutton(controlsFrame, text="Plot wavefront", command=plotwf)
psButton <- tkbutton(controlsFrame, text="Print summary", command=printsummary)
assign(".intName", tclVar("<No interferogram>"), envir=.GlobalEnv)
assign(".projName", tclVar(""), envir=.GlobalEnv)
assign(".intLabel", tkbutton(controlsFrame, textvariable=.intName, fg="red",
relief="groove", command=plotfringes),
envir=.GlobalEnv)
logFrame <- tkframe(.rfringe)
assign(".log", tktext(logFrame, bg="white", font=.logFont,
width=log.width, height=log.height, setgrid="1", wrap="none"), envir=.GlobalEnv)
logXscroll <- tkscrollbar(logFrame, repeatinterval=5, orient="horizontal",
command=function(...) tkxview(.log, ...))
logYscroll <- tkscrollbar(logFrame, repeatinterval=5,
command=function(...) tkyview(.log, ...))
tkconfigure(.log, xscrollcommand=function(...) tkset(logXscroll, ...))
tkconfigure(.log, yscrollcommand=function(...) tkset(logYscroll, ...))
tkgrid(tklabel(controlsFrame, bitmap=paste("@", file.path(etc, "Rfringe-icon.xbm"), sep=""), fg="red"),
tklabel(controlsFrame, text="Interferogram:"), .intLabel,
tklabel(controlsFrame, text=" "), circleButton, traceButton,fitButton, wfButton, psButton,
sticky="w")
tkgrid(controlsFrame, sticky="w")
tkgrid(logFrame, sticky="nsew")
tkgrid(.log, logYscroll)
tkgrid(logXscroll)
tkgrid.configure(.log, sticky="nsew")
tkgrid.configure(logYscroll, sticky="ns")
tkgrid.configure(logXscroll, sticky="ew")
# for (row in 0:2) tkgrid.rowconfigure(.rfringe, row, weight=0)
# for (col in 0:1) tkgrid.columnconfigure(.rfringe, col, weight=0)
tkgrid.rowconfigure(.rfringe, 2, weight=1)
tkgrid.columnconfigure(.rfringe, 0, weight=1)
.Tcl("update idletasks")
tkwm.resizable(.rfringe, 1, 1)
tkwm.deiconify(.rfringe)
tkfocus(.rfringe)
}
prompts <- function(string){
tkinsert(.log, "end", string)
tkyview.moveto(.log, 1)
.Tcl("update idletasks")
}
# function calls
openint <- function() {
checkReplace <- function(name){
tkmessageBox(message=paste("Interferogram", name, "already exists.\nOverwrite data set?"),
icon="warning", type="yesno", default="no")
}
top <- tktoplevel()
tkwm.title(top, "Open Interferogram")
optionsFrame <- tkframe(top)
intname <- tclVar("Interferogram")
tester <- tclVar("")
testdate <- tclVar(date())
entryintname <- tkentry(optionsFrame, width="24", textvariable=intname)
entrytester <- tkentry(optionsFrame, width="24", textvariable=tester)
entrytestdate <- tkentry(optionsFrame, width="24", textvariable=testdate)
onOK <- function(){
intnameValue <- make.names(tclvalue(intname))
if (is.element(intnameValue, listInterferograms(envir=.GlobalEnv))) {
if ("no" == tclvalue(checkReplace(intnameValue))){
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
openint()
return()
}
}
file <- tclvalue(tkgetOpenFile(filetypes='{"PNM" {".pnm" ".pgm" ".ppm"}} {"JPEG" {".jpg" ".jpeg"}} {"TIFF" {".tif" ".tiff" }} {"All Files" {"*"}}'))
if (file == "") {
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
return()
}
file.split <- unlist(strsplit(file, "\\."))
file.ext <- file.split[length(file.split)]
file.base <- file.split[1:(length(file.split)-1)]
if (!(file.ext %in% c("pnm", "pgm", "ppm"))) {
file.target <- paste(c(file.base, "pnm"), collapse=".")
if (.Platform$OS.type == "unix")
system(paste("convert", file, file.target))
else
shell(paste("convert", file, file.target))
file <- file.target
}
command <- paste('interferogram("', file, '")', sep="")
assign(intnameValue, eval(parse(text=command)), envir=.GlobalEnv)
tclvalue(.intName) <- intnameValue
assign(".thisint", eval(as.name(intnameValue)), envir=.GlobalEnv)
.thisint$image.info(tester = tclvalue(tester), testdate=tclvalue(testdate), imageid=tclvalue(intname))
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Load an interferogram image")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Enter name for interferogram:"), entryintname, sticky="w")
tkgrid(tklabel(optionsFrame, text="Tester (optional) :"), entrytester, sticky="w")
tkgrid(tklabel(optionsFrame, text="Test date (optional) :"), entrytestdate, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entryintname)
tkwait.window(top)
}
changeint <- function() {
localInts <- listInterferograms()
localInts <- localInts[localInts != ".thisint"]
if (length(localInts) == 0){
tkmessageBox(message="There are no Interferograms in your workspace",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
top <- tktoplevel()
tkwm.title(top, "Select Interferogram")
IntFrame <- tkframe(top)
IntBox <- tklistbox(IntFrame, height=min(4, length(localInts)),
selectmode="single", background="white")
IntScroll <- tkscrollbar(IntFrame, repeatinterval=5,
command=function(...) tkyview(IntBox, ...))
tkconfigure(IntBox, yscrollcommand=function(...) tkset(IntScroll, ...))
for (ds in localInts) tkinsert(IntBox, "end", ds)
tkselection.set(IntBox, if (is.null(.thisint)) 0 else which(localInts == tclvalue(.intName))-1)
onOK <- function(){
intnameValue <- localInts[as.numeric(tkcurselection(IntBox)) + 1]
tclvalue(.intName) <- intnameValue
assign(".thisint", eval(as.name(intnameValue)), envir=.GlobalEnv)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", command=onOK, default="active")
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12",command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Pick an interferogram in current workspace")
}
helpButton <- tkbutton(top, text="Help", width="12", command=onHelp)
tkgrid(tklabel(top, text="Interferograms (pick one)"), sticky="w")
tkgrid(IntBox, IntScroll, sticky="nw")
tkgrid(IntFrame, sticky="w")
tkgrid(OKbutton, cancelButton, sticky="w")
tkgrid(buttonsFrame, tklabel(top, text=" "), helpButton, sticky="w")
for (row in 0:2) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkgrid.configure(IntScroll, sticky="ns")
tkgrid.configure(helpButton, sticky="e")
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkbind(IntBox, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(top)
tkwait.window(top)
}
opensavedint <- function() {
filename <- tclvalue(tkgetOpenFile(filetypes='{"rdat" {".rdat"}}'))
if (filename == "") {
tkfocus(.rfringe)
return()
}
load.obj <- load(filename, envir=.GlobalEnv)
if (length(load.obj)>1 || !is.element(load.obj, listInterferograms())) {
tkmessageBox(message="File doesn't contain interferogram data", icon="warning", type="ok")
tkfocus(.rfringe)
return()
}
tclvalue(.intName) <- load.obj
assign(".thisint", eval(as.name(load.obj)), envir=.GlobalEnv)
tkfocus(.rfringe)
}
saveint <- function() {
if (is.null(.thisint)) {
tkmessageBox(message="No current interferogram", icon="error", type="ok")
tkfocus(.rfringe)
return()
}
filename <- paste(tclvalue(.intName),".rdat",sep="")
if (file.exists(filename)) {
if ("cancel" == tclvalue(tkmessageBox(message=paste("File", filename, "\nAlready exists. Overwrite?"),
icon="question", type="okcancel", default="ok"))) {
tkfocus(.rfringe)
return()
}
}
save(list=tclvalue(.intName), file=filename)
tkfocus(.rfringe)
}
clearint <- function() {
localInts <- listInterferograms()
localInts <- localInts[localInts != ".thisint"]
if (length(localInts) == 0){
tkmessageBox(message="There are no Interferograms in your workspace",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
top <- tktoplevel()
tkwm.title(top, "Select Interferogram")
IntFrame <- tkframe(top)
IntBox <- tklistbox(IntFrame, height=min(4, length(localInts)),
selectmode="multiple", background="white")
IntScroll <- tkscrollbar(IntFrame, repeatinterval=5,
command=function(...) tkyview(IntBox, ...))
tkconfigure(IntBox, yscrollcommand=function(...) tkset(IntScroll, ...))
for (ds in localInts) tkinsert(IntBox, "end", ds)
tkselection.set(IntBox, if (is.null(.thisint)) 0 else which(localInts == tclvalue(.intName))-1)
onOK <- function(){
intOuts <- localInts[as.numeric(tkcurselection(IntBox)) + 1]
filenames <- paste(intOuts, ".rdat", sep="")
if (any(!file.exists(filenames))) {
if ("cancel" == tclvalue(tkmessageBox(message="One or more files have not been saved. Continue?",
icon="warning", type="okcancel", default="ok"))) {
if(.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
return()
}
}
if (tclvalue(.intName) %in% intOuts) {
assign(".intName", tclVar("<No interferogram>"), envir=.GlobalEnv)
assign(".thisint", NULL, envir=.GlobalEnv)
}
rm(list=intOuts, envir=.GlobalEnv)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", command=onOK, default="active")
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12",command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Clear some interferograms from workspace")
}
helpButton <- tkbutton(top, text="Help", width="12", command=onHelp)
tkgrid(tklabel(top, text="Interferograms"), sticky="w")
tkgrid(IntBox, IntScroll, sticky="nw")
tkgrid(IntFrame, sticky="w")
tkgrid(OKbutton, cancelButton, sticky="w")
tkgrid(buttonsFrame, tklabel(top, text=" "), helpButton, sticky="w")
for (row in 0:2) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkgrid.configure(IntScroll, sticky="ns")
tkgrid.configure(helpButton, sticky="e")
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkbind(IntBox, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(top)
tkwait.window(top)
}
circlepars <- function() {
prompts("Left click on edge of aperture\nPick at least 5 points, preferably more\n")
prompts("Right click when done\n")
.thisint$circle.pars()
tkfocus(.rfringe)
}
obstructpars <- function() {
prompts("Left click on edge of obstruction\n")
prompts("Right click when done\n")
.thisint$obstruct.pars()
tkfocus(.rfringe)
}
autotrace.options <- function() {
top <- tktoplevel()
tkwm.title(top, "Fringe trace options")
optionsFrame <- tkframe(top)
tol.gs <- tclVar(get("tol.gs", .thisint$ev))
m.hw <- get("m.hw", .thisint$ev)
rho.max <- tclVar(get("rho.max", .thisint$ev))
keep.every <- tclVar(get("keep.every", .thisint$ev))
entrytol.gs <- tkentry(optionsFrame, width="6", textvariable=tol.gs)
lbox.m <- tkwidget(optionsFrame, type="spinbox", width="6", state="readonly",
wrap="TRUE", exportselection="FALSE",
from="3", to="15", increment="2")
tkset(lbox.m, 2*m.hw+1)
entrykeep.every <- tkentry(optionsFrame, width="6", textvariable=keep.every)
entryrho.max <- tkentry(optionsFrame, width="6", textvariable=rho.max)
onOK <- function(){
assign("tol.gs", as.numeric(tclvalue(tol.gs)), envir=.thisint$ev)
m.hw <- (as.numeric(tclvalue(tkget(lbox.m)))-1)/2
assign("m.hw", m.hw, envir=.thisint$ev)
assign("rho.max", as.numeric(tclvalue(rho.max)), envir=.thisint$ev)
assign("keep.every", as.numeric(tclvalue(keep.every)), envir=.thisint$ev)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Parameters for fringe trace\nBe careful in changing these!")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Gray scale tolerance for fringe select:"), entrytol.gs, sticky="w")
tkgrid(tklabel(optionsFrame, text="Search window size for local min :"), lbox.m, sticky="w")
tkgrid(tklabel(optionsFrame, text="Trace to rho = :"), entryrho.max, sticky="w")
tkgrid(tklabel(optionsFrame, text="Keep every :"), entrykeep.every, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entrytol.gs)
tkwait.window(top)
}
autotrace <- function() {
if (!get("Ap.M", .thisint$ev)) {
tkmessageBox(message="Must outline aperture\nbefore tracing fringes!!",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
.thisint$autotrace()
tkfocus(.rfringe)
}
imageinfo <- function() {
top <- tktoplevel()
tkwm.title(top, "Image info")
optionsFrame <- tkframe(top)
tester <- tclVar(get("tester.id", .thisint$ev))
testdate <- tclVar(get("test.date", .thisint$ev))
imageid <- tclVar(get("image.id", .thisint$ev))
testwl <- tclVar(get("wl.test", .thisint$ev))
phi <- tclVar(get("phi", .thisint$ev))
entrytester <- tkentry(optionsFrame, width="24", textvariable=tester)
entrytestdate <- tkentry(optionsFrame, width="24", textvariable=testdate)
entryimageid <- tkentry(optionsFrame, width="24", textvariable=imageid)
entrytestwl <- tkentry(optionsFrame, width="6", textvariable=testwl)
entryphi <- tkentry(optionsFrame, width="6", textvariable=phi)
onOK <- function(){
testwl.char <- tclvalue(testwl)
if (testwl.char == "") testwl.char <- "632.8"
phi.char <- tclvalue(phi)
if (phi.char == "") phi.char <- "0"
.thisint$image.info(tester = tclvalue(tester), testdate=tclvalue(testdate), imageid=tclvalue(imageid),
testwl=as.numeric(testwl.char), orientation=as.numeric(phi.char))
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Basic image information\nText fields are optional\nOrientation is measured counterclockwise")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Tester (optional) :"), entrytester, sticky="w")
tkgrid(tklabel(optionsFrame, text="Test date (optional):"), entrytestdate, sticky="w")
tkgrid(tklabel(optionsFrame, text="Image ID (optional) :"), entryimageid, sticky="w")
tkgrid(tklabel(optionsFrame, text="Test wavelength :"), entrytestwl, tklabel(optionsFrame, text="(nm)"), sticky="w")
tkgrid(tklabel(optionsFrame, text="Image orientation:"), entryphi, tklabel(optionsFrame, text="degrees"), sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entrytester)
tkwait.window(top)
}
analysisinfo <- function() {
top <- tktoplevel()
tkwm.title(top, "Info for analysis")
optionsFrame <- tkframe(top)
evalwl <- tclVar(get("wl.eval", .thisint$ev))
fringescale <- tclVar(get("fringe.scale", .thisint$ev))
df.adj <- get("df.adj", .thisint$ev)
ast.adj <- get("ast.adj", .thisint$ev)
coma.adj <- get("coma.adj", .thisint$ev)
dfvar <- if (df.adj) tclVar("1") else tclVar("0")
astvar <- if (ast.adj) tclVar("1") else tclVar("0")
comavar <- if (coma.adj) tclVar("1") else tclVar("0")
entryevalwl <- tkentry(optionsFrame, width="6", textvariable=evalwl)
entryfringescale <- tkentry(optionsFrame, width="6", textvariable=fringescale)
checkdf <- tkcheckbutton(optionsFrame, text="Cancel defocus", variable=dfvar)
checkast <- tkcheckbutton(optionsFrame, text="Cancel astigmatism", variable=astvar)
checkcoma <- tkcheckbutton(optionsFrame, text="Cancel coma", variable=comavar)
onOK <- function(){
evalwl.char <- tclvalue(evalwl)
if (evalwl.char == "") evalwl <- NULL else evalwl <- as.numeric(evalwl.char)
fringescale.char<- tclvalue(fringescale)
if (fringescale.char == "") fringescale.char <- "0.5"
if (tclvalue(dfvar) == "1") df.adj <- TRUE else df.adj <- FALSE
if (tclvalue(astvar) == "1") ast.adj <- TRUE else ast.adj <- FALSE
if (tclvalue(comavar) == "1") coma.adj <- TRUE else coma.adj <- FALSE
.thisint$analysis.info(evalwl=evalwl, fringescale =as.numeric(fringescale.char),
cancel.defocus=df.adj, cancel.ast=ast.adj, cancel.coma=coma.adj)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Information needed for analysis\nFringescale is +- 0.5 for double pass")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Evaluation wavelength:"), entryevalwl, tklabel(optionsFrame, text="(nm)"), sticky="w")
tkgrid(tklabel(optionsFrame, text="Fringe scale :"), entryfringescale, tklabel(optionsFrame, text="waves"), sticky="w")
tkgrid(checkdf, sticky="w")
tkgrid(checkast, sticky="w")
tkgrid(checkcoma, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entryevalwl)
tkwait.window(top)
}
targetconicinfo <- function() {
top <- tktoplevel()
tkwm.title(top, "Target conic")
optionsFrame <- tkframe(top)
D <- tclVar(get("target.D", .thisint$ev))
rcval <- get("target.rc", .thisint$ev)
if (is.na(rcval)) rc <- tclVar("NA") else rc <- tclVar(rcval)
fratioval <- get("target.fratio", .thisint$ev)
if (is.na(fratioval)) fratio <- tclVar("NA") else fratio <- tclVar(fratioval)
b <- tclVar(get("target.b", .thisint$ev))
entryD <- tkentry(optionsFrame, width="12", textvariable=D)
entryrc <- tkentry(optionsFrame, width="12", textvariable=rc)
entryfratio <- tkentry(optionsFrame, width="12", textvariable=fratio)
entryb <- tkentry(optionsFrame, width="12", textvariable=b)
onOK <- function(){
rcval <- as.numeric(tclvalue(rc))
fratioval <- as.numeric(tclvalue(fratio))
if (!is.na(rcval) && rcval>0)
.thisint$target.conic.info(D=as.numeric(tclvalue(D)), rc=rcval, b=as.numeric(tclvalue(b)))
else
.thisint$target.conic.info(D=as.numeric(tclvalue(D)), fratio=fratioval, b=as.numeric(tclvalue(b)))
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Target conic.\nYou only need to enter this\nFor a non-null test at CofC!\nEnter one of (rc, f/ratio). rc overrides f/")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Diameter (mm) :"), entryD, sticky="w")
tkgrid(tklabel(optionsFrame, text="R.C. (mm) :"), entryrc, sticky="w")
tkgrid(tklabel(optionsFrame, text="f/ratio :"), entryfratio, sticky="w")
tkgrid(tklabel(optionsFrame, text="Conic constant:"), entryb, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entryD)
tkwait.window(top)
}
editfringe <- function() {
top <- tktoplevel()
tkwm.title(top, "Fringe editing")
optionsFrame <- tkframe(top)
nfringes <- get("nfringes", .thisint$ev)
tclfringe <- tclVar("1")
editcommand <- tclvar("")
sbox.frsel <- tkwidget(optionsFrame, type="spinbox", width="6", wrap="TRUE", exportselection="FALSE",
from="1", to=nfringes, increment="1", textvariable=tclfringe)
rb.addp <- tkradiobutton(optionsFrame, text="Add points", variable=editcommand, value="addp")
rb.clrp <- tkradiobutton(optionsFrame, text="Clear points", variable=editcommand, value="clrp")
rb.adds <- tkradiobutton(optionsFrame, text="Add segment", variable=editcommand, value="adds")
rb.retf <- tkradiobutton(optionsFrame, text="Retrace fringe", variable=editcommand, value="retf")
rb.insf <- tkradiobutton(optionsFrame, text="Insert fringe", variable=editcommand, value="insf")
rb.clrf <- tkradiobutton(optionsFrame, text="Clear fringe", variable=editcommand, value="clrf")
onOK <- function(){
fringeorder <- as.numeric(tclvalue(tclfringe))
edc <- tclvalue(editcommand)
if (edc == "addp") .thisint$addpoints(fringeorder)
if (edc == "clrp") .thisint$clearpoints(fringeorder)
if (edc == "adds") .thisint$addsegment(fringeorder)
if (edc == "retf") .thisint$retrace(fringeorder)
if (edc == "insf") .thisint$insertfringe(fringeorder)
if (edc == "clrf") .thisint$clearfringe(fringeorder)
if (.grab.focus) tkgrab.set(top)
tkfocus(sbox.frsel)
}
onDone <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
DoneButton <- tkbutton(buttonsFrame, text="Done", width="12", command=onDone)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Fringe editing routines")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Fringe to edit"), sbox.frsel, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(rb.addp, rb.clrp, sticky="w")
tkgrid(rb.adds, rb.retf, sticky="w")
tkgrid(rb.insf, rb.clrf, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, DoneButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onDone)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(sbox.frsel)
tkwait.window(top)
}
maxorder <- function() {
top <- tktoplevel()
tkwm.title(top, "Max order for Zernike fit")
optionsFrame <- tkframe(top)
maxorder <- get("maxorder", .thisint$ev)
tclmo <- tclVar(maxorder)
sbox.mo <- tkwidget(optionsFrame, type="spinbox", width="6", wrap="TRUE", exportselection="FALSE",
from="6", to="20", increment="2", textvariable=tclmo)
onOK <- function(){
maxorder <- as.numeric(tkget(sbox.mo))
assign("maxorder", maxorder, .thisint$ev)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Select maximum polynomial order for Zernike fit.\nLeave blank or enter NA for \'Fringe\' Set.")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Maximum Zernike Polynomial order"), sbox.mo, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(sbox.mo)
tkwait.window(top)
}
fitzernikes <- function() {
if (!get("Fr.M", .thisint$ev)) {
tkmessageBox(message="Must find fringe centers first!!",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
.thisint$fitzernikes()
prompts(paste("Fit", length(coef(get("fit", .thisint$ev))), "Zernike coefficients\n"))
tkfocus(.rfringe)
}
synthint <- function() {
if (!get("Fit.M", .thisint$ev)) {
tkmessageBox(message="Do the fit first!!",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
.thisint$plot.si()
tkfocus(.rfringe)
}
plotwf <- function() {
if (!get("Fit.M", .thisint$ev)) {
tkmessageBox(message="Do the fit first!!",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
.thisint$plot.wf()
tkfocus(.rfringe)
}
plotcontour <- function() {
if (!get("Fit.M", .thisint$ev)) {
tkmessageBox(message="Do the fit first!!",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
top <- tktoplevel()
tkwm.title(top, "Cross sections across diameters")
optionsFrame <- tkframe(top)
thetasval <- tclvar("0")
cscale <- tclvar("showwf")
entrythetas <- tkentry(optionsFrame, width="20", textvariable=thetasval)
rb.showwf <- tkradiobutton(optionsFrame, text="Plot Wavefront error (in waves)", variable=cscale, value="showwf")
rb.showsurf <- tkradiobutton(optionsFrame, text="Plot Surface error (in nm)", variable=cscale, value="showsurf")
onOK <- function(){
plot.surf <- if(tclvalue(cscale)=="showsurf") TRUE else FALSE
thetas <- as.numeric(unlist(strsplit((tclvalue(thetasval)), ",")))
.thisint$plot.contour(thetas, plot.surf)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Plot cross sections across chosen diameters\nEnter one or more azimuth angles separated by commas\nYou can plot surface or wavefront errors")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Azimuth angle(s):"), entrythetas, sticky="w")
tkgrid(rb.showwf, sticky="w")
tkgrid(rb.showsurf, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entrythetas)
tkwait.window(top)
}
wf3d <- function() {
.thisint$plot.wf3d()
tkfocus(.rfringe)
}
wf3d.vanilla <- function() {
wf <- get("wf", .thisint$ev)
wf.persp(wf)
top <- tktoplevel()
tkwm.title(top, "3D persp plot")
thetaval <- tclVar(0)
phival <- tclVar(30)
replot <- function(...) {
wf.persp(wf, theta=as.numeric(tclvalue(thetaval)), phi=as.numeric(tclvalue(phival)))
}
optionsFrame <- tkframe(top)
scaletheta <- tkscale(optionsFrame, label="Theta", digits="3", from="0", to="360",
orient="horizontal", resolution="5", variable=thetaval, command=replot)
scalephi <- tkscale(optionsFrame, label="Phi", digits="3", from="90", to="-90",
orient="vertical", resolution="5", variable=phival, command=replot)
onOK <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Move the sliders to change viewpoint\nin almost real time")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Longitude/Latitude\n(theta, phi)"), scalephi, sticky="w")
tkgrid.configure(scalephi, sticky="ns")
tkgrid(scaletheta, sticky="ew", columnspan="2")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(top)
tkwait.window(top)
}
plotresiduals <- function() {
if (!get("Fit.M", .thisint$ev)) {
tkmessageBox(message="Do the fit first!!",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
.thisint$plot.residuals()
tkfocus(.rfringe)
return()
}
plotstartest <- function() {
if (!get("Fit.M", .thisint$ev)) {
tkmessageBox(message="Do the fit first!!",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
top <- tktoplevel()
tkwm.title(top, "Star Test simulator")
optionsFrame <- tkframe(top)
obstructval <- tclVar(0.25)
dfval <- tclVar(5)
displaymtfval <- tclvar("1")
entryob <- tkentry(optionsFrame, width="6", textvariable=obstructval)
checkmtf <- tkcheckbutton(optionsFrame, text="Calculate MTF", variable=displaymtfval)
scaledf <- tkscale(optionsFrame, label="Defocus (waves)", digits="4", from="0", to="15",
orient="horizontal", resolution= "0.25", variable=dfval)
onOK <- function(){
displaymtf <- if(tclvalue(displaymtfval)=="1") TRUE else FALSE
.thisint$plot.startest(obstruct=as.numeric(tclvalue(obstructval)), defocus=as.numeric(tclvalue(dfval)),
displaymtf=displaymtf)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Simple star test simulator.\nEnter the telescope obstruction and defocus in waves.\nCheck for mtf display")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Telescope obstruction"), entryob, checkmtf, sticky="w")
tkgrid.configure(checkmtf, sticky="e")
tkgrid(scaledf, sticky="ew", columnspan="3")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entryob)
tkwait.window(top)
}
plotfringes <- function() {
.thisint$plot.fringes()
tkfocus(.rfringe)
}
printsummary <- function() {
.thisint$print.summary()
tkfocus(.rfringe)
}
printdetails <- function() {
.thisint$print.details()
tkfocus(.rfringe)
}
pdfreport <- function() {
.thisint$print.latex()
tkfocus(.rfringe)
}
helprfringe <- function() {
helpbox("Documentation for Rfringe is found\nin the manuals Rfringe.pdf\nand Rfringe-install.pdf\nin the doc subdirectory of this package.")
tkfocus(.rfringe)
}
aboutrfringe <- function() {
tkmessageBox(message=paste("Rfringe 1.0.1\nAuthor: M.Peck\nLicensed under terms of the GPL"),
icon="info", type="ok", title="About")
tkfocus(.rfringe)
}
helpbox <- function(string) {
tkmessageBox(message=string, icon="info", type="ok", title="Help??")
}
closeRfringe <- function(){
globals <- NULL
response <- tclvalue(tkmessageBox(message="Exit?",
icon="question", type="okcancel", default="cancel"))
if (response=="cancel") return(invisible(response))
tkdestroy(.rfringe)
tclvalue(.rfringe.done) <<- "1"
return(invisible(response))
}
closeRfringeandr <- function(){
response <- closeRfringe()
if (response == "cancel") return()
quit(save="yes")
}
# So I stop getting errors every time I forget the capital V in "tclVar"
tclvar <- function(...) tclVar(...)
# gets a list of interferograms, identified by having an element "isInterferogram"
listInterferograms <- function(envir=.GlobalEnv, ...) {
names(which(sapply(ls(envir=envir, all=TRUE), function(string) {
x = eval(parse(text=string))
is.recursive(x) && !is.null(x$isInterferogram)
})))
}
#############
# GUI wrappers for project management functions
newproject <- function() {
checkReplace <- function(name){
tkmessageBox(message=paste("Project", name, "already exists.\nOverwrite data set?"),
icon="warning", type="yesno", default="no")
}
top <- tktoplevel()
tkwm.title(top, "New Project")
optionsFrame <- tkframe(top)
projname <- tclVar("Project")
notes <- tclVar("")
tester <- tclVar("")
testdate <- tclVar(date())
entryprojname <- tkentry(optionsFrame, width="40", textvariable=projname)
entrynotes <- tkentry(optionsFrame, width="40", textvariable=notes)
entrytester <- tkentry(optionsFrame, width="40", textvariable=tester)
entrytestdate <- tkentry(optionsFrame, width="40", textvariable=testdate)
onOK <- function(){
projnameValue <- make.names(tclvalue(projname))
if (is.element(projnameValue, listProjects(envir=.GlobalEnv))) {
if ("no" == tclvalue(checkReplace(projnameValue))){
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
return(invisible("cancel"))
}
}
project.notes <- tclvalue(notes)
project.tester <- tclvalue(tester); if (project.tester=="") project.tester<-NULL
project.date <- tclvalue(testdate); if (project.date=="") project.date<-NULL
assign(projnameValue, project(project.id=tclvalue(projname), project.notes=project.notes,
project.tester=project.tester,project.date=project.date), envir=.GlobalEnv)
tclvalue(.projName) <- projnameValue
assign(".thisproject", eval(as.name(projnameValue)), envir=.GlobalEnv)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
return(invisible("ok"))
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
return(invisible("cancel"))
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Create a new project\nto store information\nabout groups of interferograms")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Enter name for project:"), entryprojname, sticky="w")
tkgrid(tklabel(optionsFrame, text="Notes (optional) :"), entrynotes, sticky="w")
tkgrid(tklabel(optionsFrame, text="Tester (optional) :"), entrytester, sticky="w")
tkgrid(tklabel(optionsFrame, text="Test date (optional) :"), entrytestdate, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entryprojname)
tkwait.window(top)
}
addtoproject <- function() {
if (is.null(.thisproject)) {
tkmessageBox(message="No current project", icon="error", type="ok")
tkfocus(.rfringe)
return()
}
.thisproject$project.addto(.thisint$ev)
prompts(paste(tclvalue(.intName), "added to project", tclvalue(.projName), "\n"))
}
batchadd <- function() {
if (is.null(.thisproject)) {
tkmessageBox(message="No current project", icon="error", type="ok")
tkfocus(.rfringe)
return()
}
top <- tktoplevel()
tkwm.title(top, "Add interferograms to a project")
localInts <- listInterferograms()
localInts <- localInts[localInts != ".thisint"]
if (length(localInts) == 0){
tkmessageBox(message="There are no Interferograms in your workspace",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
IntFrame <- tkframe(top)
IntBox <- tklistbox(IntFrame, height=min(4, length(localInts)),
selectmode="multiple", background="white")
IntScroll <- tkscrollbar(IntFrame, repeatinterval=5,
command=function(...) tkyview(IntBox, ...))
tkconfigure(IntBox, yscrollcommand=function(...) tkset(IntScroll, ...))
for (ds in localInts) tkinsert(IntBox, "end", ds)
tkselection.set(IntBox, if (is.null(.thisint)) 0 else which(localInts == tclvalue(.intName))-1)
onOK <- function(){
intnames <- localInts[as.numeric(tkcurselection(IntBox))+1]
for (i in 1:length(intnames)) {
ev <- eval(as.name(intnames[i]))$ev
.thisproject$project.addto(ev)
}
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", command=onOK, default="active")
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12",command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Pick one or more interferograms\nto add to the current project")
}
helpButton <- tkbutton(top, text="Help", width="12", command=onHelp)
tkgrid(tklabel(top, text="Inteferograms"), sticky="w")
tkgrid(IntBox, IntScroll, sticky="nw")
tkgrid(IntFrame, sticky="w")
tkgrid(OKbutton, cancelButton, sticky="w")
tkgrid(buttonsFrame, tklabel(top, text=" "), helpButton, sticky="w")
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkgrid.configure(IntScroll, sticky="ns")
tkgrid.configure(helpButton, sticky="e")
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(top)
tkwait.window(top)
}
removefromproject <- function() {
if (is.null(.thisproject)) {
tkmessageBox(message="No current project", icon="error", type="ok")
tkfocus(.rfringe)
return()
}
image.ids <- get("image.ids", .thisproject$ev)
if (length(image.ids) == 0){
tkmessageBox(message="Project appears to be empty", icon="error", type="ok")
tkfocus(.rfringe)
return()
}
top <- tktoplevel()
tkwm.title(top, "Remove Interferogram")
IntFrame <- tkframe(top)
IntBox <- tklistbox(IntFrame, height=min(4, length(image.ids)),
selectmode="multiple", background="white")
IntScroll <- tkscrollbar(IntFrame, repeatinterval=5,
command=function(...) tkyview(IntBox, ...))
tkconfigure(IntBox, yscrollcommand=function(...) tkset(IntScroll, ...))
for (ds in image.ids) tkinsert(IntBox, "end", ds)
tkselection.set(IntBox, if (is.null(.thisint)) 0 else which(image.ids == get("image.id", .thisint$ev))-1)
onOK <- function(){
intOuts <- image.ids[as.numeric(tkcurselection(IntBox)) + 1]
if (length(intOuts > 0))
for (i in 1:length(intOuts)) .thisproject$project.removefrom(intOuts[i])
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", command=onOK, default="active")
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12",command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Remove one or more interferograms from the current project")
}
helpButton <- tkbutton(top, text="Help", width="12", command=onHelp)
tkgrid(tklabel(top, text="Interferogram"), sticky="w")
tkgrid(IntBox, IntScroll, sticky="nw")
tkgrid(IntFrame, sticky="w")
tkgrid(OKbutton, cancelButton, sticky="w")
tkgrid(buttonsFrame, tklabel(top, text=" "), helpButton, sticky="w")
for (row in 0:2) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkgrid.configure(IntScroll, sticky="ns")
tkgrid.configure(helpButton, sticky="e")
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkbind(IntBox, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(top)
tkwait.window(top)
}
changeproject <- function() {
localProjects <- listProjects()
localProjects <- localProjects[localProjects != ".thisproject"]
if (length(localProjects) == 0){
tkmessageBox(message="There are no Projects in your workspace",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
top <- tktoplevel()
tkwm.title(top, "Select Project")
IntFrame <- tkframe(top)
IntBox <- tklistbox(IntFrame, height=min(4, length(localProjects)),
selectmode="single", background="white")
IntScroll <- tkscrollbar(IntFrame, repeatinterval=5,
command=function(...) tkyview(IntBox, ...))
tkconfigure(IntBox, yscrollcommand=function(...) tkset(IntScroll, ...))
for (ds in localProjects) tkinsert(IntBox, "end", ds)
tkselection.set(IntBox, if (is.null(.thisproject)) 0 else which(localProjects == tclvalue(.projName))-1)
onOK <- function(){
projnameValue <- localProjects[as.numeric(tkcurselection(IntBox)) + 1]
tclvalue(.projName) <- projnameValue
assign(".thisproject", eval(as.name(projnameValue)), envir=.GlobalEnv)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", command=onOK, default="active")
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12",command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Pick a project in current workspace")
}
helpButton <- tkbutton(top, text="Help", width="12", command=onHelp)
tkgrid(tklabel(top, text="Projects (pick one)"), sticky="w")
tkgrid(IntBox, IntScroll, sticky="nw")
tkgrid(IntFrame, sticky="w")
tkgrid(OKbutton, cancelButton, sticky="w")
tkgrid(buttonsFrame, tklabel(top, text=" "), helpButton, sticky="w")
for (row in 0:2) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkgrid.configure(IntScroll, sticky="ns")
tkgrid.configure(helpButton, sticky="e")
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkbind(IntBox, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(top)
tkwait.window(top)
}
opensavedproject <- function() {
filename <- tclvalue(tkgetOpenFile(filetypes='{"pdat" {".pdat"}}'))
if (filename == "") {
tkfocus(.rfringe)
return()
}
load.obj <- load(filename, envir=.GlobalEnv)
if (length(load.obj)>1 || !is.element(load.obj, listProjects())) {
tkmessageBox(message="File doesn't contain project data", icon="warning", type="ok")
tkfocus(.rfringe)
return()
}
tclvalue(.projName) <- load.obj
assign(".thisproject", eval(as.name(load.obj)), envir=.GlobalEnv)
tkfocus(.rfringe)
}
saveproject <- function() {
if (is.null(.thisproject)) {
tkmessageBox(message="No current project", icon="error", type="ok")
tkfocus(.rfringe)
return()
}
filename <- paste(tclvalue(.projName),".pdat",sep="")
if (file.exists(filename)) {
if ("cancel" == tclvalue(tkmessageBox(message=paste("File", filename, "\nAlready exists. Overwrite?"),
icon="question", type="okcancel", default="ok"))) {
tkfocus(.rfringe)
return()
}
}
save(list=tclvalue(.projName), file=filename)
tkfocus(.rfringe)
}
clearproject <- function() {
localProjects <- listProjects()
localProjects <- localProjects[localProjects != ".thisproject"]
if (length(localProjects) == 0){
tkmessageBox(message="There are no projects in your workspace",
icon="error", type="ok")
tkfocus(.rfringe)
return()
}
top <- tktoplevel()
tkwm.title(top, "Select Project")
IntFrame <- tkframe(top)
IntBox <- tklistbox(IntFrame, height=min(4, length(localProjects)),
selectmode="multiple", background="white")
IntScroll <- tkscrollbar(IntFrame, repeatinterval=5,
command=function(...) tkyview(IntBox, ...))
tkconfigure(IntBox, yscrollcommand=function(...) tkset(IntScroll, ...))
for (ds in localProjects) tkinsert(IntBox, "end", ds)
tkselection.set(IntBox, if (is.null(.thisproject)) 0 else which(localProjects == tclvalue(.projName))-1)
onOK <- function(){
intOuts <- localProjects[as.numeric(tkcurselection(IntBox)) + 1]
filenames <- paste(intOuts, ".pdat", sep="")
if (any(!file.exists(filenames))) {
if ("cancel" == tclvalue(tkmessageBox(message="One or more files have not been saved. Continue?",
icon="warning", type="okcancel", default="ok"))) {
if(.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
return()
}
}
if (tclvalue(.projName) %in% intOuts) {
assign(".projName", tclVar(""), envir=.GlobalEnv)
assign(".thisproject", NULL, envir=.GlobalEnv)
}
rm(list=intOuts, envir=.GlobalEnv)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", command=onOK, default="active")
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12",command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Clear some projects from workspace.\nIt's a good idea to save first if you want to retain data")
}
helpButton <- tkbutton(top, text="Help", width="12", command=onHelp)
tkgrid(tklabel(top, text="Projects"), sticky="w")
tkgrid(IntBox, IntScroll, sticky="nw")
tkgrid(IntFrame, sticky="w")
tkgrid(OKbutton, cancelButton, sticky="w")
tkgrid(buttonsFrame, tklabel(top, text=" "), helpButton, sticky="w")
for (row in 0:2) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkgrid.configure(IntScroll, sticky="ns")
tkgrid.configure(helpButton, sticky="e")
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkbind(IntBox, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(top)
tkwait.window(top)
}
plotwf.project <- function() {
.thisproject$plot.wf()
tkfocus(.rfringe)
}
plotcontour.project <- function() {
top <- tktoplevel()
tkwm.title(top, "Cross sections across diameters")
optionsFrame <- tkframe(top)
thetasval <- tclvar("0")
cscale <- tclvar("showwf")
entrythetas <- tkentry(optionsFrame, width="20", textvariable=thetasval)
rb.showwf <- tkradiobutton(optionsFrame, text="Plot Wavefront error (in waves)", variable=cscale, value="showwf")
rb.showsurf <- tkradiobutton(optionsFrame, text="Plot Surface error (in nm)", variable=cscale, value="showsurf")
onOK <- function(){
plot.surf <- if(tclvalue(cscale)=="showsurf") TRUE else FALSE
thetas <- as.numeric(unlist(strsplit((tclvalue(thetasval)), ",")))
.thisproject$plot.contour(thetas, plot.surf)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Plot cross sections across chosen diameters\nEnter one or more azimuth angles separated by commas\nYou can plot surface or wavefront errors")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Azimuth angle(s):"), entrythetas, sticky="w")
tkgrid(rb.showwf, sticky="w")
tkgrid(rb.showsurf, sticky="w")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entrythetas)
tkwait.window(top)
}
wf3d.project <- function() {
.thisproject$plot.wf3d()
tkfocus(.rfringe)
}
wf3d.vanilla.project <- function() {
wf <- get("wf", .thisproject$ev)
wf.persp(wf)
top <- tktoplevel()
tkwm.title(top, "3D persp plot")
thetaval <- tclVar(0)
phival <- tclVar(30)
replot <- function(...) {
wf.persp(wf, theta=as.numeric(tclvalue(thetaval)), phi=as.numeric(tclvalue(phival)))
}
optionsFrame <- tkframe(top)
scaletheta <- tkscale(optionsFrame, label="Theta", digits="3", from="0", to="360",
orient="horizontal", resolution="5", variable=thetaval, command=replot)
scalephi <- tkscale(optionsFrame, label="Phi", digits="3", from="90", to="-90",
orient="vertical", resolution="5", variable=phival, command=replot)
onOK <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Move the sliders to change viewpoint\nin almost real time")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Longitude/Latitude\n(theta, phi)"), scalephi, sticky="w")
tkgrid.configure(scalephi, sticky="ns")
tkgrid(scaletheta, sticky="ew", columnspan="2")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(top)
tkwait.window(top)
}
plotstartest.project <- function() {
top <- tktoplevel()
tkwm.title(top, "Star Test simulator")
optionsFrame <- tkframe(top)
obstructval <- tclVar(0.25)
dfval <- tclVar(5)
displaymtfval <- tclvar("1")
entryob <- tkentry(optionsFrame, width="6", textvariable=obstructval)
checkmtf <- tkcheckbutton(optionsFrame, text="Calculate MTF", variable=displaymtfval)
scaledf <- tkscale(optionsFrame, label="Defocus (waves)", digits="4", from="0", to="15",
orient="horizontal", resolution= "0.25", variable=dfval)
onOK <- function(){
displaymtf <- if(tclvalue(displaymtfval)=="1") TRUE else FALSE
.thisproject$plot.startest(obstruct=as.numeric(tclvalue(obstructval)), defocus=as.numeric(tclvalue(dfval)),
displaymtf=displaymtf)
if (.grab.focus) tkgrab.release(top)
tkdestroy(top)
tkfocus(.rfringe)
}
onCancel <- function() {
if (.grab.focus) tkgrab.release(top)
tkfocus(.rfringe)
tkdestroy(top)
}
buttonsFrame <- tkframe(top)
OKbutton <- tkbutton(buttonsFrame, text="OK", width="12", default="active", command=onOK)
cancelButton <- tkbutton(buttonsFrame, text="Cancel", width="12", command=onCancel)
onHelp <- function() {
if (.Platform$OS.type != "windows") if (.grab.focus) tkgrab.release(top)
helpbox("Simple star test simulator.\nEnter the telescope obstruction and defocus in waves.\nCheck for mtf display")
}
helpButton <- tkbutton(buttonsFrame, text="Help", width="12", command=onHelp)
tkgrid(tklabel(optionsFrame, text="Telescope obstruction"), entryob, checkmtf, sticky="w")
tkgrid.configure(checkmtf, sticky="e")
tkgrid(scaledf, sticky="ew", columnspan="3")
tkgrid(optionsFrame, sticky="w")
tkgrid(OKbutton, cancelButton, tklabel(buttonsFrame, text=" "), helpButton, sticky="w")
tkgrid(buttonsFrame, sticky="w")
tkgrid.configure(helpButton, sticky="e")
for (row in 0:1) tkgrid.rowconfigure(top, row, weight=0)
for (col in 0:0) tkgrid.columnconfigure(top, col, weight=0)
.Tcl("update idletasks")
tkwm.resizable(top, 0, 0)
tkbind(top, "<Return>", onOK)
if (.double.click) tkbind(top, "<Double-ButtonPress-1>", onOK)
tkwm.deiconify(top)
if (.grab.focus) tkgrab.set(top)
tkfocus(entryob)
tkwait.window(top)
}
plotspm.project <- function() {
.thisproject$plot.spm()
tkfocus(.rfringe)
}
printtoc.project <- function() {
if (is.null(.thisproject)) {
tkmessageBox(message="No current project", icon="error", type="ok")
tkfocus(.rfringe)
return()
}
prompts(paste("Contents of", tclvalue(.projName), "\n\n"))
image.ids <- get("image.ids", .thisproject$ev)
for (i in 1:length(image.ids)) prompts(paste(image.ids[i], "\n"))
}
printsummary.project <- function() {
.thisproject$print.summary()
tkfocus(.rfringe)
}
printdetails.project <- function() {
.thisproject$print.details()
tkfocus(.rfringe)
}
pdfreport.project <- function() {
.thisproject$print.latex()
tkfocus(.rfringe)
}
# gets a list of projects, identified by having an element "isProject"
listProjects <- function(envir=.GlobalEnv, ...) {
names(which(sapply(ls(envir=envir, all=TRUE), function(string) !is.null(eval(parse(text=string))$isIntProject))))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.