ebpg_funpak/ 0000755 0000765 0000765 00000000000 12635565422 012437 5 ustar rooks rooks ebpg_funpak/vmc 0000755 0000765 0000765 00000013654 12441200052 013137 0 ustar rooks rooks #!/bin/bash
# Vistec Mission Control
# Console-based system query and diagnostic program, because sometimes you have to
# debug user problems from an ssh session on your cell phone at the airport. Apparently.
# Easily get important PLC and system info from a terminal session! Some limited
# functionality too, so you can do things like run the gun up and down remotely in an
# emergency (you should not do this, in general).
# Note that the system is intentionally designed so there's no non-CSYS way to do things
# like control pumps or valves. No way around that, unfortunately, but this at least
# has the tools to tell you what's going on.
# note my clever nesting of menus and submenus in functions that are basically
# just case structures. Should make this easy to add to or modify. Actual program
# just executes main() and exits (at the very bottom)
. textfx
. $BEAMS_SCRIPTS/pg_mode oper
function vac () {
clear
status=`pg get vacsts`
gun=`pg get vacgun`
chamber=`pg get vacsys`
airlock=`pg get vaclock`; if [ "$airlock" == "########" ]; then airlock="ATM"; fi
backing=`pg get vacline`
if [ "$status" == "0" ]; then stat="${r}NOT OK!${n}"
else stat="OK"
fi
clear
echo -e "Vacuum Status: $stat"
echo "----------------------"
echo "Gun: $gun"
echo "Chamber: $chamber"
echo "Airlock: $airlock"
echo "Pre-vac: $backing"
echo
read -p "Enter for main menu, q to quit " choice
if [ "$choice" == "q" -o "$choice" == "Q" ]; then exit 0
else return 0
fi
}
function ion () {
clear
igp1=`pg get vacigp1`
igp2=`pg get vacigp2`
igp3=`pg get vacigp3`
igp4=`pg get vacigp4`
echo "Ion pump currents"
echo "-----------------"
echo "IGP1: $igp1"
echo "IGP2: $igp2"
echo "IGP3: $igp3"
echo "IGP4: $igp4"
echo
read -p "Enter for main menu, q to quit " choice
if [ "$choice" == "q" -o "$choice" == "Q" ]; then exit 0
else return 0
fi
}
function holders () {
clear
declare -i caspos=`pg get caspos`
declare -a hold=(`pg info subs`)
# the index of the first holder status bit is going to depend on where the little
# ">" showing the cassette position is, which we can infer from the value of $caspos
if [ $caspos -eq 1 ]; then declare -i slot1=${hold[11]}
else declare -i slot1=${hold[10]}
fi
# since these both come after the ">" no matter what, their indices are always the same
declare -i slot2=${hold[16]}
declare -i sys=${hold[22]}
echo "Holder positions"
echo "----------------"
echo "Cassette 1: $slot1"
echo "Cassette 2: $slot2"
echo "Chamber: $sys"
echo
read -p "Enter for main menu, q to quit " choice
if [ "$choice" == "q" -o "$choice" == "Q" ]; then exit 0
else return 0
fi
}
function gun () {
clear
declare -a htstat=( `pg eht comm showehtstatus` )
if [ "${htstat[1]}" == "00" ]; then gunstat="OK"
else gunstat="${r}NOT OK!${n}"
fi
echo -e "Gun Status: $gunstat"
echo "-------------------"
if [ "$gunstat" == "OK" ]; then pg eht comm showgun
else pg eht comm interpret
fi
echo
read -p "Enter for main menu, q to quit " choice
if [ "$choice" == "q" -o "$choice" == "Q" ]; then exit 0
else return 0
fi
}
function gunup () {
clear
echo "Current EHT status:"
if ! pg eht comm deht; then
echo "ERROR: Can't get SAEHT status"; return 1
fi
echo
read -p "Run gun up? [yes/no]: " choice
if [ "$choice" != "yes" -a "$choice" != "YES" ]; then return 0; fi
if /home/pg/users/service/jobfiles/fegup_100; then
read -p "Run-up complete. Enter to return to main menu" blah
else
read -p "Run-up FAILED. Enter to return to main menu" blah
fi
return 0
}
function gundown () {
clear
echo "Current EHT status:"
if ! pg eht comm deht; then
echo "ERROR: Can't get SAEHT status"; return 1
fi
echo
read -p "Run gun down? [yes/no]: " choice
if [ "$choice" != "yes" -a "$choice" != "YES" ]; then return 0; fi
if /home/pg/users/service/jobfiles/fegdown; then
read -p "Run-down complete. Enter to return to main menu" blah
else
read -p "Run-down FAILED. Enter to return to main menu" blah
fi
return 0
}
function gscreset () {
clear
echo "Current EHT status:"
if ! pg eht comm deht; then
echo "ERROR: Can't get SAEHT status"; return 1
fi
echo
echo "WARNING: RESETTING THE GSC WITH THE HIGH VOLTAGE ON WILL"
echo "ALMOST CERTAINLY KILL THE GUN. BE REALLY DAMN SURE YOU"
echo "KNOW WHAT YOU'RE DOING HERE"
echo
read -p "Reset GSC? [yes/no]: " choice
if [ "$choice" != "yes" -a "$choice" != "YES" ]; then return 0; fi
read -p "For serious? [yes/no]: " choice
if [ "$choice" != "yes" -a "$choice" != "YES" ]; then return 0; fi
if pg eht comm gscreset; then
read -p "GSC successfully reset. Enter to return to main menu" blah
else
read -p "GSC failed to reset. Enter to return to main menu" blah
fi
return 0
}
function plc () {
clear
echo "PLC error message(s):"
echo
pg info ebpg plcerrorhistory
echo
read -p "Hit enter to return to main menu" choice
return 0
}
function service () {
clear
echo "THIS IS A REALLY GREAT WAY TO BREAK THE MACHINE!"
read -p "Are you sure you want to be messing around in here? [y/n]: " choice
if [ "$choice" != "y" -a "$choice" != "Y" ]; then main; fi
clear
echo "Available service actions:"
echo
echo "1. Run up gun"
echo "2. Run down gun"
echo "3. GSC reset"
read -p "Enter choice, or enter for main menu: " choice
case "${choice}" in
1)
gunup
;;
2)
gundown
;;
3)
gscreset
;;
*)
return 0
;;
esac
}
function main () {
while [ 1 ]; do
clear
echo -e "${r}EBPG Mission Control${n}"
echo
echo "Main Menu:"
echo
echo "1. View vacuum levels"
echo "2. View ion pump currents"
echo "3. View holder positions"
echo "4. View gun status"
echo "5. View PLC errors"
echo "6. Service menu"
echo
read -p "Enter choice (q to quit): " choice
case "$choice" in
1)
vac
;;
2)
ion
;;
3)
holders
;;
4)
gun
;;
5)
plc
;;
6)
service
;;
q)
exit 0
;;
Q)
exit 0
;;
*)
main
esac
done
}
main
exit 0
ebpg_funpak/ybrsort.py~ 0000755 0000765 0000765 00000106437 12525362775 014735 0 ustar rooks rooks #!/usr/bin/python
"""
ybrsort.py
Requires gpfgtx and gtxgpf programs.
This program reads a gpf file and sorts the shapes into yellow-brick-road
order. This might be described as a "proximity sort", since we will try
to stick together shapes that appear near each other.
The blocks are not sorted. You can use the utility gpfsort for that.
v2 Sorts multiple fields, as does the original radial_sort.py
v3 Finds neighboring shapes with a rolling list instead of recursion.
Otherwise each shape is limited to 900 trapezoids.
v4 Instead of searching n times through the entire list of shapes,
we create a list of shapes which are contained in each subfield.
Then we search through just the local subfields. Big improvement.
v5 If we start gathering shapes in the middle of a long thing, then
the writing order splits, and the beam flips back and forth along
the shape. We needed a better way to pick the starting point.
The last item on the list is likely to be one of the end points
of a structure, so now we use the last point as the starting point
for a second pass. This works quite well.
"""
import os
import sys
import math
import string
import operator
from math import *
version = 5
# Center of the pattern is X0,Y0. 524288 is half of 1048576 = 2^20.
X0 = 0
Y0 = 0
CHUNK = 3 # micron. Size of a chunk sorted as one group of shapes.
# One subfield is typical.
recursion = 0
shape = 0
#-----------------------------------------------------------------------------------------------
def sort_table(table, cols):
"""
sort a table by multiple columns
table: a list of lists (or tuple of tuples) where each inner list represents a row
cols: a list (or tuple) specifying the column numbers to sort by
"""
is_a_list = True
try:
len( cols )
print "..."
except:
is_a_list = False
if is_a_list:
rcols = reversed( cols )
for col in rcols :
table = sorted(table, key=operator.itemgetter(col))
else:
table = sorted(table, key=operator.itemgetter(cols))
return table
#====================================================================================================
# Yellow Brick Road sorting functions
def twiddle( t ): # display an amusing progress report
t += 1
wait = " [%d][%d]" % (shape, recursion)
for i in range( t ): wait += "."
for i in range( t,40 ): wait += " "
print "%s\015" % wait,
if t > 30 : t = 0
sys.stdout.flush()
return t
def YBRdistance( t, p ):
"""
t is an entry in the big table of shapes. p is a coordinate
in mainfield units (field center is 524288,525288).
This function returns the disance in main field units (usually nm).
"""
dx = abs( t[14] - p[0] )
dy = abs( t[15] - p[1] )
d = math.sqrt( dx**2 + dy**2 )
return( d )
def overlap( llx, lly, urx, ury, pllx, plly, purx, pury ) :
if pllx > urx : return False
if purx < llx : return False
if plly > ury : return False
if pury < lly : return False
return True
def local_group( g, R, subfield ):
"""
Gather a list of shapes that are near shape "g".
Look in the nearby subfields.
"""
sx = R[g][18]
sy = R[g][19]
n = len( subfield )
lg = []
for dx in range(-2,3) :
x = sx + dx
if x >= 0 and x < n:
for dy in range(-2,3) :
y = sy + dy
if y >=0 and y < n :
for j in subfield[x][y] : lg.append( j )
#
#
#
#
return lg
def look_for_neighbors( p, R, chunk, city, subfield, first ):
"""
p is an index to one entry in the big table. R is the whole big table of shapes.
w2 and h2 are in main field units. city is the list of
indices into the big table. We use a rolling list here, not recursion.
"""
global shape
global recursion
if first :
saveshape = shape
shape = -shape
if R[p][17] :
#print "Shape %d has already been hit." % p
return city # if this shape has already been hit
t = 0
n = len( R )
g = p # starting point
group = [g] # list of connected shapes
R[g][17] = True # hit!
city.append( g ) # add this shape to the full list
gi = 0 # index into the group list
while gi < len( group ) :
g = group[gi]
pllx = R[g][14] - chunk
purx = R[g][14] + chunk
plly = R[g][15] - chunk
pury = R[g][15] + chunk
lg = local_group( g, R, subfield )
for i in lg : # range(n) :
if i <> g and R[i][16] and not R[i][17] : # if the item is active and has not been hit...
llx = R[i][14] - chunk
urx = R[i][14] + chunk
lly = R[i][15] - chunk
ury = R[i][15] + chunk
if overlap( llx, lly, urx, ury, pllx, plly, purx, pury ) and not R[i][17] :
city.append( i )
group.append( i )
R[i][17] = True # hit!
#end if
#end if
#end for
if gi < len( group ) :
gi += 1
recursion = len(group) - gi
if first :
shape -= 1
else:
shape += 1
if shape % 50 == 0 : t = twiddle( t )
# If this is the first pass then let's go back and UNHIT the items. Slick.
if first:
for i in city : R[i][17] = False
shape = saveshape
return (city)
def presort( R, x, chunk, fullfield ):
"""
Generate a list of shapes in each subfield.
"""
nx = int( fullfield / chunk ) + 1
ny = nx
subfield = [[ [] for i in range(ny)] for j in range(nx) ]
for i in range( len(R) ):
t = R[i]
if t[16] :
sx = R[i][18]
sy = R[i][19]
subfield[sx][sy].append( i )
return subfield
def yellow_brick_road_sort( R, chunk, x0, y0, fullfield ):
"""
Follow the yellow brick road! In other words, gather together
shapes that are near one another. We look_for_neighbors twice:
first to find a good starting point, and then again to create
a list that goes from the "beginning" to the "end" of each shape.
R is the big table of shapes. (xblock,yblock) in this program is
the region of "nearness", in main field units, usually a subfield
of 3 um. (x0,y0) is the starting point, which shouldn't matter.
"""
print "\nPresorting..."
subfield = presort( R, x, chunk, fullfield )
print "\nSorting...\n"
ncity = len( R )
print "Number of shapes: %d\n" % ncity
mind = YBRdistance( R[0], [x0, y0] )
munchkindex = 0
for i in range( ncity ):
d = YBRdistance( R[i], [x0, y0] )
if d < mind :
mind = d
munchkindex = i
#print "\nMunchkinland is nearest to shape %d" % munchkindex
firstpass = []
fulltrip = []
firstpass = look_for_neighbors( munchkindex, R, chunk, firstpass, subfield, first=True )
fulltrip = look_for_neighbors( firstpass[-1], R, chunk, fulltrip, subfield, first=False )
for i in range( munchkindex, ncity ):
if not R[i][17] : # if not (i in city):
firstpass = []
firstpass = look_for_neighbors( i, R, chunk, firstpass, subfield, first=True )
if len(firstpass) > 0 :
fulltrip = look_for_neighbors( firstpass[-1], R, chunk, fulltrip, subfield, first=False )
if len( fulltrip ) == ncity : break
for i in range( 0, munchkindex ):
if not R[i][17] : # if not (i in city):
firstpass = []
firstpass = look_for_neighbors( i, R, chunk, firstpass, subfield, first=True )
if len(firstpass) > 0 :
fulltrip = look_for_neighbors( firstpass[-1], R, chunk, fulltrip, subfield, first=False )
if len( fulltrip ) == ncity : break
return( fulltrip )
#====================================================================================================
# Parse one line of "repetition". This is woefully and gloriously complex,
# and should not be necessary.
def parse( bit, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, \
s1dy, s2dx, s2dy, base, height, msf, main_resol, sub_resol ) :
if not hasattr( parse, "init" ):
parse.init = True
parse.m1c = 0
parse.m2c = 0 # static variables
parse.s1c = 0
parse.s2c = 0
bits = string.split( bit )
if "Repetition Main 1 X Count" in bit:
mx1c = int( bits[5] )
parse.m1c = mx1c
elif "Repetition Main 1 X LSW" in bit:
m1dx = int( bits[5] )
elif "Repetition Main 1 Y Count" in bit:
my1c = int( bits[5] )
elif "Repetition Main 1 Y LSW" in bit:
m1dy = int( bits[5] )
elif "Repetition Main 1 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.m1c = int( bits[4] )
elif "Repetition Main 2 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.m2c = int( bits[4] )
elif "Repetition Main 2 X LSW" in bit:
m2dx = int( bits[5] )
elif "Repetition Main 2 X Count" in bit:
mx2c = int( bits[5] )
elif "Repetition Main 2 Y Count" in bit:
my2c = int( bits[5] )
parse.m2c = my2c
elif "Repetition Main 2 Y LSW" in bit:
m2dy = int( bits[5] )
elif "Repetition Sub 1 X" in bit and not ("Count" in bits):
s1dx = int( bits[4] )
elif "Repetition Sub 1 X Count" in bit:
sx1c = int( bits[5] )
parse.s1c = sx1c
elif "Repetition Sub 1 Y Count" in bit:
sy1c = int( bits[5] )
elif "Repetition Sub 1 Y" in bit and not ("Count" in bits):
s1dy = int( bits[4] )
elif "Repetition Sub 1 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.s1c = int( bits[4] )
elif "Repetition Sub 2 X" in bit and not ("Count" in bits):
s2dx = int( bits[4] )
elif "Repetition Sub 2 X Count" in bit:
sx2c = int( bits[5] )
elif "Repetition Sub 2 Y" in bit and not ("Count" in bits):
s2dy = int( bits[4] )
elif "Repetition Sub 2 Y Count" in bit:
sy2c = int( bits[5] )
parse.s2c = sy2c
elif "Repetition Sub 2 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.s2c = int( bits[4] )
elif "Repetition" in bits:
print "\nUnknown repetition line: [%d]\n" % bit
# Are the following correct? It might be that some parameters need to be
# retained and used by implication in successive Activate lines.
if "Activate" in bits and "SRV1" in bits and not ("SRV2" in bits):
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
sx2c = 0
sy2c = 0
s2dx = 0
s2dy = 0
if "Activate" in bits and "SRV2" in bits and not ("SRV1" in bits):
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
sx1c = 0
sy1c = 0
s1dx = 0
s1dy = 0
if "Activate" in bits and "MRV1" in bits and not ("MRV2" in bits):
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
mx2c = 0
my2c = 0
m2dx = 0
m2dy = 0
if "Activate" in bits and "MRV2" in bits and not ("MRV1" in bits):
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
mx1c = 0
my1c = 0
m1dx = 0
m1dy = 0
if "Activate" in bits and "SRV1" in bits and "SRV2" in bits:
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
if "Activate" in bits and "MRV1" in bits and "MRV2" in bits:
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
if "Activate" in bits and "MRV1" in bits:
mx1c = parse.m1c
if "Activate" in bits and "MRV2" in bits:
my2c = parse.m2c
if "Activate" in bits and "SRV1" in bits:
sx1c = parse.s1c
if "Activate" in bits and "SRV2" in bits:
sy2c = parse.s2c
# RYH and RXB are used to chop shapes into subfield traps.
# The savings in space is negligible, but it might prevent
# blanking between shapes. Let's hope so; otherwise,
# it's just stupid.
# V1 is X only, V2 is Y only
if "RXB" in bits or "RYH" in bits:
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
if sub_resol <= 0 :
print "\nERROR: subfield resolution not defined.\m"
sys.exit()
h = int( height )
b = int( base )
m = int( msf )
if "RYH" in bits:
if "SRV1" in bits or "SRV2" in bits:
s2dy = (h + 1) * m
elif "MRV1" in bits or "MRV2" in bits:
m2dy = (h + 1) * m * main_resol/sub_resol
if "RXB" in bits:
if "SRV1" in bits or "SRV2" in bits:
s1dx = (b + 1) * m
elif "MRV1" in bits or "MRV2" in bits:
m1dx = (b + 1) * m * main_resol/sub_resol
return( (mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy ) )
#-----------------------------------------------------------------------------------------------
def expand_array( entry, n, table, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, \
m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy, mainpersub, chunk ):
# Loop over x and y repeats, generating new table entries
# Could there be both main and subfield repeats on the same line?
# That would be perverse, so let's just check for perversity first.
# Be sure to turn off "compaction" of any sort in Beamer.
main_repeat = mx1c > 0 or mx2c > 0 or my1c > 0 or my2c > 0
sub_repeat = sx1c > 0 or sx2c > 0 or sy1c > 0 or sy2c > 0
if not main_repeat and not sub_repeat:
print "\nERROR: an array contains no repetition values\n"
sys.exit()
if main_repeat and sub_repeat:
print "\nERROR: mainfield and subfield arrays appear sumultaneously. This freaks me out, man."
print "Try disabling all compaction modes in Beamer (or whatever you used to generate gpf)."
print "Be sure to disable Beamer's 'compaction diagonal array' option, which is evil."
print "Program aborted."
sys.exit()
activate_line = entry[0]
main_x_lsw = entry[1]
main_y_lsw = entry[2]
freq_lsw = entry[3]
freq_msw = entry[4]
base_lsw = entry[5]
height_lsw = entry[6]
msf = entry[7]
shift_lt_lsw = entry[8]
shift_rb_lsw = entry[9]
offset_x_lsw = entry[10]
offset_y_lsw = entry[11]
shift_rb_used = entry[12]
shift_lt_used = entry[13]
table[n][0] = "deleted"
table[n][16] = False # the item is no longer active
if main_repeat:
# strip out MRV1, MRV2, RXB, and RYH from acitivate line
# loop over mx1c and my2c. Watch for nonzero my1c and mx2c.
newline = ""
words = string.split( activate_line )
begin = False
for word in words:
if (word == "Activate"): begin = True
if begin and word <> "MRV1" and word <> "MRV2" and word <> "RXB" and word <> "RYH" :
newline = newline + " " + word
#print "[%s]" % newline
if my1c <> 0 or mx2c <> 0 :
print "\nERROR: strange array with my1c or mx2c not zero: [%s]." % activate_line
print "What does it mean?\n"
sys.exit()
mainx = int( main_x_lsw )
mainy = int( main_y_lsw )
for row in range( my2c+1 ):
y = mainy + m2dy * row
mainy_s = "%d" % y
for col in range( mx1c+1 ):
x = mainx + m1dx * col
mainx_s = "%d" % x
fx = x + float(offset_x_lsw) / mainpersub
fy = y + float(offset_y_lsw) / mainpersub
sx = int( fx / chunk )
sy = int( fy / chunk )
table.append( [ newline, \
mainx_s, \
mainy_s, \
freq_lsw, \
freq_msw, \
base_lsw, \
height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
offset_x_lsw, \
offset_y_lsw, \
shift_rb_used, \
shift_lt_used, \
fx, \
fy, \
True, \
False, \
sx, sy ] ) # [16] = "active", [17] = "hit"
else: # subfield repeat
# strip out SRV1, SRV2, RXB, and RYH from acitivate line
# loop over sx1c and sy2c. Watch for nonzero sy1c and sx2c.
newline = ""
words = string.split( activate_line )
begin = False
for word in words:
if (word == "Activate"): begin = True
if begin and word <> "SRV1" and word <> "SRV2" and word <> "RXB" and word <> "RYH" :
newline = newline + " " + word
#print "[%s]" % newline
if sy1c <> 0 or sx2c <> 0 :
print "\nERROR: strange array with sy1c or sx2c not zero: [%s]." % activate_line
print "What does it mean?\n"
sys.exit()
subx = int( offset_x_lsw )
suby = int( offset_y_lsw )
for row in range( sy2c+1 ):
y = suby + s2dy * row
suby_s = "%d" % y
for col in range( sx1c+1 ):
x = subx + s1dx * col
subx_s = "%d" % x
fx = float(main_x_lsw) + x / mainpersub
fy = float(main_y_lsw) + y / mainpersub
sx = int( fx / chunk )
sy = int( fy / chunk )
table.append( [ newline, \
main_x_lsw, \
main_y_lsw, \
freq_lsw, \
freq_msw, \
base_lsw, \
height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
subx_s, \
suby_s, \
shift_rb_used, \
shift_lt_used, \
fx, \
fy, \
True, \
False, \
sx, sy ] ) # [16] = "active", [17] = "hit"
return( table )
#-----------------------------------------------------------------------------------------------
def flatten( table, main_resol, sub_resol, mainpersub, chunk ):
# look for repetition lines, creating explicit shapes instead
mx1c = 0 # main x1 count
mx2c = 0 # main x2 count
my1c = 0
my2c = 0
sx1c = 0 # subfield x1 count
sx2c = 0 # subfield x2 count
sy1c = 0
sy2c = 0
m1dx = 0 # main 1 delta x, in mainfield resolution units
m1dy = 0
s1dx = 0 # subfield 1 delta x, in subfield resolution units
s1dy = 0
m2dx = 0
m2dy = 0
s2dx = 0
s2dy = 0
#print "mx1c mx2c my1c my2c sx1c sx2c sy1c sy2c m1dx m1dy m2dx m2dy s1dx s1dy s2dx s2dy"
n = 0
for entry in table:
base = entry[5]
height = entry[6]
line = entry[0]
msf = entry[7]
item = string.split( line )
if "SRV1" in item or "SRV2" in item or "MRV1" in item or "MRV2" in item :
part = string.split( line, "\n" )
for bit in part:
mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy = \
parse( bit, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, \
s2dx, s2dy, base, height, msf, main_resol, sub_resol )
table = expand_array( entry, n, table, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, \
m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy, mainpersub, chunk )
n = n + 1
return( table )
#-----------------------------------------------------------------------------------------------
# MAIN
print
print "GPF yellow brick road sorting utility, version %d" % version
print
if len( sys.argv ) == 1 :
print "\nUse: radial_sort.py file.gpf"
print "\n The output file will be file_sorted.gpf\n\n"
sys.exit()
if len( sys.argv ) > 1 :
if sys.argv[1] == "-h" or sys.argv[1] == "-help" or sys.argv[1] == "--help" :
print "\nUse: radial_sort.py file.gpf"
print "\n The output file will be file_sorted.gpf\n\n"
sys.exit()
filein = sys.argv[1]
else:
print
print "Enter input gpf file name> ",
filein = sys.stdin.readline()
filein = filename[0:-1]
if not (".gpf" in filein) and not ("." in filein):
filein = filein + ".gpf"
name = string.split( filein, "." )
fileout = name[0] + "_sorted.gpf"
print
print "Input gpf file: ", filein
print "Output gpf file: ", fileout
print
print "\nConverting to gtx...\n"
os.system( "gpfgtx %s temp_in.gtx" % filein )
gtxin = open( "temp_in.gtx", "rb" )
gtxout = open( "temp_out.gtx", "w" )
print "\nCopying header... \n"
word = []
# copy header
line = gtxin.readline()
if not line:
print "\nERROR: unexpected end of file.\n\n"
sys.exit()
word = string.split( line )
if len( word ) == 0 :
word.append( "\n" )
bss = 0.0
mfr = 0.0
sfr = 0.0
while word[0] <> "END" :
gtxout.write( line )
line = gtxin.readline()
if not line:
print "\nERROR: unexpected end of file.\n\n"
sys.exit()
word = string.split( line )
if len( word ) == 0 :
word.append( "\n" )
if word[0] == "BeamStepSize" :
stuff = string.split( word[1], "," )
sub_resol = int( stuff[0] )
msf = sub_resol
bss = sub_resol
print " Subfield step size (bits) : ", bss
elif word[0] == "Resolution":
stuff = string.split( word[1], "," )
main_resol = int( stuff[0] )
elif word[0] == "MainFieldResolution" :
stuff = string.split( word[1], "," )
mfr = float( stuff[0] )
print " Main field resolution (um) : ", mfr
elif word[0] == "SubFieldResolution" :
stuff = string.split( word[1], "," )
sfr = float( stuff[0] )
print " Subfield resolution (um) : ", sfr
elif word[0] == "MainFieldSize" :
stuff = string.split( word[1], "," )
mfsx = float( stuff[0] )
mfsy = float( stuff[1] )
print " Main field block size (um) : ", mfsx * sfr * bss, mfsy * sfr * bss
xblocksize = mfsx * bss * sfr / mfr
yblocksize = mfsy * bss * sfr / mfr
print " Block size, mainfield bits: ", xblocksize, yblocksize
elif word[0] == "NrMainFieldBits" :
nmfb = int( word[1] )
print " Number of main field bits: ", nmfb
fullfield = math.pow( 2, nmfb )
mainpersub = mfr / sfr
if bss == 0.0 or mfr == 0.0 or sfr == 0.0 :
print "\nERROR: units not found in header.\n"
sys.exit()
gtxout.write( line ) # write "END" after header
bss_sub = msf
#print " Number of subfield bits in a beam step: %d\n" % bss_sub
chunk = CHUNK / mfr # usually, 1 um / 0.001 = 1000 bits
#print "chunk = ", chunk
print
print "Reading..."
print
end_of_file = False
while not end_of_file: # while not EOF, sort each field
new_field = True
main_x_lsw = 0
main_y_lsw = 0
base_lsw = "0"
height_lsw = "0"
shift_lt_lsw = "0"
shift_rb_lsw = "0"
offset_x_lsw = "0"
offset_y_lsw = "0"
msf = 0
freq_msw = "0"
freq_lsw = "0"
append_next_line = False
n = 0
end_of_field = False
nbad = 0
table = []
while True: # for each_line in gtxin.readlines() :
each_line = gtxin.readline()
if len( each_line ) == 0 :
end_of_file = True
break
if end_of_field : # or n > 1000000 :
break
if append_next_line: # True for repetition lines
line = line + "\n" + each_line[:-1]
append_next_line = False
else:
line = each_line[:-1]
word = string.split( each_line )
unknown = False
if len( word ) > 0:
if word[0] == "END":
end_of_field = True
elif word[0] == "Main":
if word[1] == "X":
main_x_lsw = int( word[3] )
else:
main_y_lsw = int( word[3] )
elif word[0] == "Frequency":
if word[1] == "LSW":
freq_lsw = word[2]
else:
freq_msw = word[2]
elif word[0] == "Base":
base_lsw = word[2]
elif word[0] == "Height":
height_lsw = word[2]
elif word[0] == "MSF":
msf = word[1] # subfield (e.g. 20 => 10nm)
elif word[0] == "Shift":
if word[1] == "LT":
shift_lt_lsw = word[3]
else:
shift_rb_lsw = word[3]
elif word[0] == "Offset":
if word[1] == "X":
offset_x_lsw = word[3]
else:
offset_y_lsw = word[3]
elif word[0] == "Repetition":
append_next_line = True # tricky!
elif word[0] == "Activate":
n = n + 1
attributes = string.split( line )
if "hb" in attributes : # careful! hb applies only to this item
this_height_lsw = base_lsw
else:
this_height_lsw = height_lsw
shift_rb_used = not ("rb45" in attributes or "rb90" in attributes)
shift_lt_used = not ("lt45" in attributes or "lt90" in attributes)
x = float( main_x_lsw )
y = float( main_y_lsw )
if False :
# if bad_shape( shift_rb_used, shift_lt_used, bss_sub, \
# base_lsw, this_height_lsw, shift_lt_lsw, shift_rb_lsw, line ) :
nbad = nbad + 1
#print "base: ", base_lsw
#print "height: ", this_height_lsw
#print "shift lt: ", shift_lt_lsw
#print "shift rb: ", shift_rb_lsw
#print line
else:
x = int(main_x_lsw) + int(offset_x_lsw) / mainpersub
y = int(main_y_lsw) + int(offset_y_lsw) / mainpersub
sx = int( x / chunk ) # subfield x
sy = int( y / chunk ) # subfield y
table.append( [ line, \
main_x_lsw, \
main_y_lsw, \
freq_lsw, \
freq_msw, \
base_lsw, \
this_height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
offset_x_lsw, \
offset_y_lsw, \
shift_rb_used, \
shift_lt_used, \
x, \
y, \
True, \
False, \
sx, sy ] ) # [16] = "active", [17] = "hit"
else:
print line
print
gtxout.write( "%s\n" % line ) # this line is part of the field header... we hope!
sys.stdout.flush()
# end if word[0]
if (n > 0) and (n % 1000 == 0) :
print " shape %d \015" % n,
sys.stdout.flush()
# end if len( word ) > 0
# end while each_line
if end_of_file: break
print " shape %d " % n
print "\nFlattening..."
sys.stdout.flush()
table = flatten( table, main_resol, sub_resol, mainpersub, chunk )
#-----------------------------------------------------------------
# SORT THE TABLE - TAKES QUITE A WHILE - SCALES AS N^2
order = yellow_brick_road_sort( table, chunk, 0, 0, fullfield )
print "\n"
#---------------------------------------------------------------
# Write the rest of the gtx file (the header was copied already)
num_shapes = len( table ) # well, that also includes deleted array lines
if num_shapes < 1 :
print "\nERROR: there are no shapes in this gtx file.\n"
sys.exit()
print "Writing temp_out.gtx...\n"
activate_line = table[order[0]][0]
prev_main_x_lsw = table[order[0]][1]
prev_main_y_lsw = table[order[0]][2]
prev_freq_lsw = table[order[0]][3]
prev_freq_msw = table[order[0]][4]
prev_base_lsw = table[order[0]][5]
prev_height_lsw = table[order[0]][6]
prev_msf = table[order[0]][7]
prev_shift_lt_lsw = table[order[0]][8]
prev_shift_rb_lsw = table[order[0]][9]
prev_offset_x_lsw = table[order[0]][10]
prev_offset_y_lsw = table[order[0]][11]
shift_rb_used = table[order[0]][12]
shift_lt_used = table[order[0]][13]
if not ("deleted" in activate_line):
gtxout.write( " Frequency LSW %s\n" % prev_freq_lsw )
gtxout.write( " Frequency MSW %s\n" % prev_freq_msw )
gtxout.write( " MSF %s\n" % prev_msf )
gtxout.write( " Main X LSW %s\n" % prev_main_x_lsw )
gtxout.write( " Main Y LSW %s\n" % prev_main_y_lsw )
gtxout.write( " Offset X LSW %s\n" % prev_offset_x_lsw )
gtxout.write( " Offset Y LSW %s\n" % prev_offset_y_lsw )
gtxout.write( " Base LSW %s\n" % prev_base_lsw )
if not ("hb" in activate_line ) :
gtxout.write( " Height LSW %s\n" % prev_height_lsw )
if shift_lt_used:
gtxout.write( " Shift LT LSW %s\n" % prev_shift_lt_lsw )
if shift_rb_used:
gtxout.write( " Shift RB LSW %s\n" % prev_shift_rb_lsw )
gtxout.write( "%s\n" % activate_line )
new_field = False
elif new_field:
new_field = False
gtxout.write( " Frequency LSW %s\n" % prev_freq_lsw )
gtxout.write( " Frequency MSW %s\n" % prev_freq_msw )
gtxout.write( " MSF %s\n" % prev_msf )
gtxout.write( " Main X LSW %s\n" % prev_main_x_lsw )
gtxout.write( " Main Y LSW %s\n" % prev_main_y_lsw )
gtxout.write( " Offset X LSW %s\n" % prev_offset_x_lsw )
gtxout.write( " Offset Y LSW %s\n" % prev_offset_y_lsw )
gtxout.write( " Base LSW %s\n" % prev_base_lsw )
if num_shapes > 1 :
for n in range( 1, len( order ) ):
item = table[ order[n] ]
if n % 1000 == 0 :
print " shape %d \015" % n,
sys.stdout.flush()
activate_line = item[0]
main_x_lsw = item[1]
main_y_lsw = item[2]
freq_lsw = item[3]
freq_msw = item[4]
base_lsw = item[5]
height_lsw = item[6]
msf = item[7]
shift_lt_lsw = item[8]
shift_rb_lsw = item[9]
offset_x_lsw = item[10]
offset_y_lsw = item[11]
shift_rb_used = item[12]
shift_lt_used = item[13]
# Setting values by implication does not work reliably,
# so the output will be rather verbose. Oh well.
if not ("deleted" in activate_line) :
if True: # freq_lsw <> prev_freq_lsw :
gtxout.write( " Frequency LSW %s\n" % freq_lsw )
if True: # freq_msw <> prev_freq_msw :
gtxout.write( " Frequency MSW %s\n" % freq_msw )
if True: # msf <> prev_msf :
gtxout.write( " MSF %s\n" % msf )
if True: # main_x_lsw <> prev_main_x_lsw :
gtxout.write( " Main X LSW %s\n" % main_x_lsw )
if True: # main_y_lsw <> prev_main_y_lsw :
gtxout.write( " Main Y LSW %s\n" % main_y_lsw )
if True: # PROBLEM: offset_x_lsw <> prev_offset_x_lsw :
gtxout.write( " Offset X LSW %s\n" % offset_x_lsw )
if True: # offset_y_lsw <> prev_offset_y_lsw :
gtxout.write( " Offset Y LSW %s\n" % offset_y_lsw )
if True: # base_lsw <> prev_base_lsw :
gtxout.write( " Base LSW %s\n" % base_lsw )
if (not ("hb" in activate_line )): # PROBLEM: and (height_lsw <> prev_height_lsw) :
gtxout.write( " Height LSW %s\n" % height_lsw )
if shift_lt_used:
gtxout.write( " Shift LT LSW %s\n" % shift_lt_lsw )
if shift_rb_used:
gtxout.write( " Shift RB LSW %s\n" % shift_rb_lsw )
gtxout.write( "%s\n" % activate_line )
new_field = False
prev_main_x_lsw = item[1]
prev_main_y_lsw = item[2]
prev_freq_lsw = item[3]
prev_freq_msw = item[4]
prev_base_lsw = item[5]
prev_height_lsw = item[6]
prev_msf = item[7]
prev_shift_lt_lsw = item[8]
prev_shift_rb_lsw = item[9]
prev_offset_x_lsw = item[10]
prev_offset_y_lsw = item[11]
# end for item
# end if num_shapes > 1
gtxout.write( "END\n" )
shape = 0
# end while not EOF
gtxin.close()
gtxout.close()
print "\nConverting back to gpf...\n"
os.system( "gtxgpf temp_out.gtx %s" % fileout )
print
print "Output file: %s" % fileout
print "\n\nDone.\n"
print
ebpg_funpak/CONTENTS 0000644 0000765 0000765 00000013262 12526721227 013617 0 ustar rooks rooks EBPG FUN PAK CONTENTS MAY 2015
align_window.sh Uses "pg image grab" and "find_edge" to align to
a large silicon nitride window. This can be easily
adapted to align to any square marker, regardless
of size. This routine can be used with cjob jobs--
look at the file for details. [Yale]
Be sure to "export PG_IMAGES=." so that the grabbed
images end up in the current directory.
bash_float Library of floating-point functions for bash. Keep it
in the same directory as sys_monitor. [Bryan Cord, Un. Minn.]
calc.py Calculator for EBPG exposure parameters.
Requires the gtk library. [Yale]
countdown an alternative to the bash 'sleep' function,
displaying the minutes left before waking up.
You could put this in /home/pg/bin [Yale]
current/ set_current.py program lets you set any
reasonable current on the EBPG.
Requires numpy and scipy libraries. Versions of
numpy and scipy that are likely to work are included
in this directory.
See INSTALLcurrent.txt file for details.[Yale]
false_alarms.errors List of errors that it's safe for sys_monitor to ignore.
See also gun_trips.errors. Keep w/ sys_monitor
[Bryan Cord, Un. Minn.]
find_edge.c Finds the edge in an image (collected with
"pg image grab") and then moves the stage
to that edge. Build the executable file with the
command "make find_edge". It's nice to have
gnuplot installed so you can see the results.
Test the program with the command "find_edge -h" and
find_edge horizontal dark-bright marker.img 128 128 1000 plot
Be sure to "export PG_IMAGES=." so that the grabbed
images end up in the current directory. [Yale]
gpfmerge A python program which merges together gpf pattern files.
Requires the ebpg utilities gpfgtx and gtxgpf, and so this
program is most easily installed on the ebpg control
computer. [Yale]
gpfsort A python program which sorts gpf exposure fields
vertically, horizontally, for minimum travel, or along
a yellow brick road (by proximity). You almost always
want to follow the yellow brick road. It's nice to have
gnuplot installed so you can see the results immediately.
To sort the shapes inside a field, use radial_sort.py or
ybrsort.py (gpfsort requires the ebpg utilities gpfgtx
and gtxgpf, and so this program is most easily installed
on the ebpg control computer. [Yale]
gun_plotter Python script to make plots of the logs generated by
sys_monitor [Bryan Cord, Un. Minn.]
looper Quickie script to run a command repeatedly at set
intervals and log the output [Bryan Cord, Un. Minn.]
mss Experimental program to get true (not screwed up by
the mark edges) spot size measurements of different beams.
Method is explained in the script comments.
[Bryan Cord, Un. Minn.]
pgreset A bash script which stops ebpg software, performs
a cold or hot start, and restarts csem and csys. You
would put this in /home/pg/bin typically. [Yale]
prealign_utils/ A set of scripts for pre-aligning a sample. The user
is prompted for the vectors from the Faraday cup to
each mark. The marks are scanned (possibly several times)
and the locations saved in a file for later use by
an exposure script. [Bryan Cord, Un. Minn.]
radial_sort.py Sorts gpf shapes into a spiral order inside each field,
starting from the center of a field. This sorts the
shapes, not the fields. See gpfsort for field sorting.
See ybrsort.py for proximity sorting of shapes. [Yale]
sys_monitor Monitors and logs various system parameters. Also
reports problems via the mail command. Contender for
longest bash script of all time. Awful structure is
a consequence of three years of feature creep.
Sorry about that. [Bryan Cord, Un. Minn.]
textfx Library of escape characters to make bold/italic/etc text
in an xterm. Keep w/ sys_monitor. [Bryan Cord, Un. Minn.]
vac_plotter Same as gun_plotter, but for vacuum level logs
[Bryan Cord, Un. Minn.]
vmc Console-based monitor/control system for ssh-based
tool admin. [Bryan Cord, Un. Minn.]
writejob Job command wrapper w/ simplified command line
[Bryan Cord, Un. Minn.]
ybrsort.py Sort the (gpf) shapes of each field so that connected
features will be written consecutively. In other words,
"follow the yellow brick road" inside each field. This is
particularly useful for waveguides. Requires the ebpg
utilities gpfgtx and gtxgpf, and so this program is most
easily installed on the ebpg control computer. [Yale]
ebpg_funpak/README 0000777 0000000 0000000 00000000000 12441176371 014100 2CONTENTS ustar root root ebpg_funpak/gpf_field_sort 0000777 0000765 0000765 00000000000 12547004374 016750 2gpfsort ustar rooks rooks ebpg_funpak/gpf_shape_sort 0000777 0000765 0000765 00000000000 12547004420 017424 2ybrsort.py ustar rooks rooks ebpg_funpak/pgreset 0000750 0000765 0000765 00000005424 12441200052 014012 0 ustar rooks rooks #!/usr/bin/python
import sys
import os
def zap( something ):
os.system( "ps ax | grep -e '%s' > /tmp/hitlist" % something )
os.system( "cat /tmp/hitlist" )
hitlist = open( "/tmp/hitlist" )
for line in hitlist.readlines():
if "grep" not in line:
word = line[0:6]
print "kill %s" % word
os.system( "kill -9 %s" % word )
def motorized_aperture() :
os.system( "pg get smc > /tmp/smc.log" )
log = open( "/tmp/smc.log" )
line = log.readline()
log.close()
smc = (line[:-1] == "1")
return smc
zap( "pg [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]" )
zap( "csys" )
zap( "cpro" )
zap( "cebpg" )
zap( "csem" )
zap( "ebpg hot" )
print
print "PGRESET"
print
print "Shutting down all pg applications..."
#print "Shut down all pg applications (csys, cpro, csem, cebpg)"
#print "if they are not already gone, then press Enter."
#sys.stdin.readline()
#print
#print "Unlinking semaphores..."
#print
#os.system( "semunlink" )
#os.system( "sleep 1" )
#os.system( "semunlink" )
#os.system( "sleep 1" )
# we can't do this:
#
# os.system( "pg ebpg shut" )
#
# because the bloody thing is stuck!
frozen = False
if len( sys.argv ) > 1:
if sys.argv[1] == "frozen":
frozen = True
print "\nBeams frozen start!!! \n"
print "cp /home/pg/bin/B027_globaldata /home/pg/archive/"
os.system( "cp /home/pg/bin/B027_globaldata /home/pg/archive/" )
print "\nBeams cold start..."
print
os.system( "$pg cold" )
print
os.system( "check_blanker" )
print
print
print "Resetting digital corrections..."
print
os.system( "pg deselect pattern" )
os.system( "pg adj resol 0.5nm --main=0.5nm --trap=0.5nm" )
os.system( "pg adj resol 1nm --main=1nm --trap=0.25nm" )
os.system( "pg adj resol 1nm --main=1nm --trap=0.5nm" )
else:
print "Beams hot start"
print
os.system( "$pg hot" )
if motorized_aperture():
print "\nHoming apertures..."
os.system( "pg apert move home" )
print "\nSetting 300 um aperture..."
os.system( "pg set apert 300" )
print
print "Setting height offset to 0..."
print
os.system( "pg set heightoffset 0" )
print
print "Setting exposure defaults..."
os.system( "/home/pg/jobs/job.ini" )
print
print "Restarting applications..."
print
os.system( "csys -f &" )
os.system( "sleep 1" )
os.system( "csem &" )
#os.system( "sleep 1" )
#os.system( "cpro &" )
print
print "Deleting wafer coordinate systems..."
os.system( "pg map subs cjob_* delete" )
os.system( "pg deselect map subs" )
print
print "Done. Csys and Csem should have restarted."
print
print
print "To restore table symbols, type the command"
print "restore_symbols\n"
print
if frozen:
print "\nBe sure to load an archive, calibrate, and save.\n"
ebpg_funpak/gpfmerge 0000755 0000765 0000765 00000026531 12441200052 014144 0 ustar rooks rooks #!/usr/bin/python
"""
Merge a set of GPF files, checking that the headers match.
You'll want to run the merged pattern through the traveling salesman
program later.
Requires gpfgtx and gtxgpf programs.
This program reads a set of gpf files listed on the command line,
then spits the results into merged.gpf.
"""
import os
import sys
import string
version = 1
def count_fields( names ):
n = 0
for name in names:
name_gtx = name[:-3] + "gtx"
fp = open( name_gtx, "rb" )
for line in fp.readlines():
found = False
word = string.split( line )
if len( word ) > 0:
if word[0] == "NrMainFields":
n = n + int( word[1] )
found = True
break
elif word[0] == "END":
print "\nERROR: unexpected end of file\n"
sys.exit()
if not found:
print "\nERROR: invalid header. Number of fields not found.\n"
sys.exit()
fp.close()
return( n )
#===============================================================================================
if __name__=='__main__':
print
print "GPF merging utility, version %d" % version
print
if len( sys.argv ) < 3 :
print "\nUse: gpfmerge file1.gpf file2.gpf ..."
print "\n The output file will be merged.gpf\n\n"
sys.exit()
if len( sys.argv ) > 1 :
if sys.argv[1] == "-h" or sys.argv[1] == "-help" or sys.argv[1] == "--help" :
print "\nUse: gpfmerge file1.gpf file2.gpf ..."
print "\n The output file will be merged.gpf\n\n"
sys.exit()
print
print "Files to be merged:"
names = []
n = 0
for name in sys.argv:
if n > 0:
if not ( ".gpf" in name ):
print "\nERROR: files to be merged must all be .gpf files.\n"
sys.exit()
try:
fp = open( name, "r" )
fp.close()
except:
print "\nERROR: unable to open %s\n" % name
sys.exit()
names.append( name )
print " %s" % name
n += 1
n -= 1
print "\nMerging %d files...\n" % n
try:
gtxout = open( "merged.gtx", "w" )
except:
print "\nERROR: unable to open merged.gtx for writing\n"
print "\nConverting to gtx...\n"
for name in names:
name_gtx = name[:-3] + "gtx"
print " gpfgtx %s %s" % (name, name_gtx)
os.system( "gpfgtx %s %s" % (name, name_gtx) )
print
print "Counting fields... ",
nfields = count_fields( names )
print "%d\n" % nfields
print
print "Reading header...\n"
name_gtx = names[0][:-3] + "gtx"
gtxin = open( name_gtx, "rb" )
word = []
end_of_header = False
random = False
while not end_of_header :
line = gtxin.readline()
if not line:
print "\nERROR: unexpected end of file.\n\n"
sys.exit()
word = string.split( line )
if len( word ) > 0: end_of_header = word[0] == "END"
if len( word ) > 0:
if word[0] == "NrMainFields":
gtxout.write( " NrMainFields %d\n" % nfields )
elif word[0] == "MainFieldPlacement":
gtxout.write( " MainFieldPlacement RANDOM\n" )
else:
gtxout.write( line )
else:
gtxout.write( "\n" )
if len( line ) > 24 :
value = line[24:]
else:
value = ""
if len( word ) > 0:
if word[0] == "MainFieldResolution" :
mainfieldresolution = value
elif word[0] == "SubFieldResolution" :
subfieldresolution = value
elif word[0] == "Resolution":
resolution = value
elif word[0] == "BeamStepSize":
beamstepsize = value
elif word[0] == "SubFieldPlacement":
subfieldplacement = value
elif word[0] == "MainFieldPlacement":
mainfieldplacement = value
random = "RANDOM" in value
elif word[0] == "SubFieldPlacement":
subfieldplacement = value
elif word[0] == "NrMainFieldBits":
nrmainfieldbits = value
elif word[0] == "NrSubFieldBits":
nrsubfieldbits = value
elif word[0] == "MaxMSF":
maxmsf = value
elif word[0] == "MinFreqFactor":
minfreqfactor = value
elif word[0] == "MaxFreqFactor":
maxfreqfactor = value
elif word[0] == "NrFreqFactors":
nrfreqfactors = value
# end if word
# end if len
# end while not end of header
print
print "Copying fields..."
print
end_of_file = False
n = 0
while not end_of_file: # while not EOF
each_line = gtxin.readline()
if len( each_line ) == 0 :
end_of_file = True
break
else:
word = string.split( each_line )
if random:
gtxout.write( each_line )
else:
if len( word ) > 0 :
if word[0] == "FIELD":
place_x = float( word[4][1:] )
place_y = float( word[6] )
gtxout.write( "FIELD %f,%f ! (um)\n" % (place_x, place_y) )
elif word[0] == "FIELDOFFSET":
d = string.split( word[1], "," )
if (float( d[0] ) <> 0.0) or (float(d[1]) <> 0.0):
print "\nWARNING: non-zero field offset: %s\n" % word[1]
else:
gtxout.write( each_line )
else:
gtxout.write( each_line )
n = n + 1
if (n > 0) and (n % 10000 == 0) :
print " shape %d \015" % n,
sys.stdout.flush()
# end while not end of file
# if end_of_file: break
# for the rest of the input files,
# read and check the headers
# append all the fields
for name in names[1:] :
gtxin.close()
name_gtx = name[:-3] + "gtx"
print " merging %s" % name
gtxin = open( name_gtx, "rb" )
word = []
end_of_header = False
while not end_of_header :
line = gtxin.readline()
if not line:
print "\nERROR: unexpected end of file.\n\n"
sys.exit()
word = string.split( line )
if len( word ) > 0: end_of_header = word[0] == "END"
if len( line ) > 24 :
value = line[24:]
else:
value = ""
if len( word ) > 0:
if word[0] == "MainFieldResolution" :
if mainfieldresolution <> value :
print "\nERROR: inconsistent main field resolution\n"
sys.exit()
elif word[0] == "SubFieldResolution" :
if subfieldresolution <> value :
print "\nERROR: inconsistent subfield resolution\n"
sys.exit()
elif word[0] == "Resolution":
if resolution <> value :
print "\nERROR: inconsistent resolution\n"
sys.exit()
elif word[0] == "BeamStepSize":
if beamstepsize <> value :
print "\nERROR: inconsistent beam step size\n"
sys.exit()
elif word[0] == "SubFieldPlacement":
if subfieldplacement <> value :
print "\nERROR: inconsistent subfield placement\n"
sys.exit()
elif word[0] == "MainFieldPlacement":
random = "RANDOM" in value
elif word[0] == "SubFieldPlacement":
if subfieldplacement <> value :
print "\nERROR: inconsistent subfield placement\n"
sys.exit()
elif word[0] == "NrMainFieldBits":
if nrmainfieldbits <> value :
print "\nERROR: inconsistent number of main field bits\n"
sys.exit()
elif word[0] == "NrSubFieldBits":
if nrsubfieldbits <> value :
print "\nERROR: inconsistent number of subfield bits\n"
sys.exit()
elif word[0] == "MaxMSF":
if maxmsf <> value :
print "\nERROR: inconsistent maximum MSF\n"
sys.exit()
elif word[0] == "MinFreqFactor":
if minfreqfactor <> value :
print "\nERROR: inconsistent minimum frequency factor\n"
sys.exit()
elif word[0] == "MaxFreqFactor":
if maxfreqfactor <> value :
print "\nERROR: inconsistent maximum frequency factor\n"
sys.exit()
elif word[0] == "NrFreqFactors":
if nrfreqfactors <> value :
print "\nERROR: inconsistent number of frequency factors\n"
sys.exit()
# end if word
# end if len
# end while not end of header
end_of_file = False
n = 0
while not end_of_file: # while not EOF
each_line = gtxin.readline()
if len( each_line ) == 0 :
end_of_file = True
break
else:
word = string.split( each_line )
if random:
gtxout.write( each_line )
else:
if len( word ) > 0 :
if word[0] == "FIELD":
place_x = float( word[4][1:] )
place_y = float( word[6] )
gtxout.write( "FIELD %f,%f ! (um)\n" % (place_x, place_y) )
elif word[0] == "FIELDOFFSET":
d = string.split( word[1], "," )
if (float( d[0] ) <> 0.0) or (float(d[1]) <> 0.0):
print "\nWARNING: non-zero field offset: %s\n" % word[1]
else:
gtxout.write( each_line )
else:
gtxout.write( each_line )
n = n + 1
if (n > 0) and (n % 10000 == 0) :
print " shape %d \015" % n,
sys.stdout.flush()
# end for name
gtxin.close()
gtxout.close()
print "\n\nConverting to gpf...\n"
os.system( "gtxgpf merged.gtx merged.gpf" )
os.system( "rm merged.gtx" )
for name in names:
name_gtx = name[:-3] + "gtx"
os.system( "rm %s" % name_gtx )
print
print "\n\nFile merged.gpf created.\n"
print "You should run this through gpfsort to sort the fields optimally,"
print "and you should delete the gtx files."
print
print
ebpg_funpak/vac_plotter 0000755 0000765 0000765 00000013736 12441200052 014675 0 ustar rooks rooks #!/usr/bin/python
: '
-------------------------------------------------------------------------------
Copyright (c) 2014 bryan cord, university of minnesota.
All rights reserved.
Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are
duplicated in all such forms and that any documentation,
advertising materials, and other materials related to such
distribution and use acknowledge that the software was developed
by UMN. The name of the University may not be used to endorse or promote
products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-------------------------------------------------------------------------------
'
# vac_plotter: Script to display the vacuum log files generated by sys_monitor. Originally just
# for the gun vacuum, modified to take logging of system and line vacuum levels into
# account. -BC 6/28/12
# the log file we'll be reading out of. It's generated by the sys_monitor script
# (/home/pg/users/service/jobfiles/sys_monitor), which runs continuously.
LOG_FILENAME='/home/pg/log/vac_loop.log'
# y axis labels
labels = { 'gun':'Gun Vacuum (mBar)', 'vacgun':'Gun Vacuum (mBar)', 'sys':'Chamber Pressure (mBar)', 'vacsys':'Chamber Pressure (mBar)', 'system':'Chamber Pressure (mBar)', 'line':'Roughing Line Pressure (mBar)', 'vacline':'Roughing Line Pressure (mBar)' }
# default axis limits for each parameter when plotting (go slightly above/below to make the labels show up)
gunlimits=[9.999e-10,1.001e-8]
syslimits=[9.999e-8,1.001e-3]
linelimits=[9.999e-3,1.001]
limits = { 'gun':gunlimits, 'vacgun':gunlimits, 'sys':syslimits, 'vacsys':syslimits, 'system':syslimits, 'line':linelimits, 'vacline':linelimits }
# The log file is assumed to have lines formatted like this:
# NUM DATE/TIME GUNVAC SYSVAC LINEVAC
# NUM is just the measurement number and not really used. Legacy thing.
# DATE/TIME format should go like this:
# YYYY-MM-DD_HH:MM:SS (e.g. 2011-10-17_13:18:21)
# GUNVAC is G5 in CSYS, SYSVAC is G4, and LINEVAC is G6.
# all three vacuum outputs are in mBar and are the result of
# "pg get /measure", so they'll look like 1.25e-9_mBar, for example
def usage():
print
print "EBPG5000+ Gun Vacuum Log Viewer"
print
print "Usage: vac_plotter [vac1] [vac2]"
print "Plots a log of the given vacuum pressure over time. Options are gun, system,"
print "and line. Default is gun."
print
print "Edit LOG_FILENAME variable at the top of the script to point to log location."
sys.exit()
import os
import sys
import time
import datetime
import pylab
if len(sys.argv) > 3: usage()
# initialize the blank arrays
vac=[]
vacsys=[]
vacline=[]
times=[]
# you can set the parameter to plot in the command line (default is
# gun if no input or invalid input)
dict_in = {'gun':vac, 'vacgun':vac, 'vacsys':vacsys, 'sys':vacsys, 'system':vacsys, 'vacline':vacline, 'line':vacline}
if len(sys.argv) < 3:
try:
plotparam1=dict_in.get(sys.argv[1])
except IndexError:
plotparam1=vac # no input means we plot the gun vacuum
if plotparam1 == None:
print "Invalid input requested. Use 'gun', 'system', or 'line'."
usage()
doubleplot=False
else:
plotparam1=dict_in.get(sys.argv[1])
plotparam2=dict_in.get(sys.argv[2])
if plotparam1 == None or plotparam2 == None:
print "Invalid input(s) requested. Use 'gun', 'system', or 'line'."
usage()
doubleplot=True
# step 1: parse the existing log file data
try: log_in=open(LOG_FILENAME,'r')
except IOError:
print "ERROR: log file %s not found." % LOG_FILENAME
usage()
for currentLine in log_in.readlines():
splitLine=currentLine.split()
# skip non-data lines, like the header and any errors
if splitLine[0] == 'NR' or (len(splitLine) != 3 and len(splitLine) != 5 ): continue
hour=minute=second=day=month=year=0
datestring=splitLine[1]
(year,month,day) = datestring.split('_')[0].split('-')
(hour,minute,second) = datestring.split('_')[1].split(':')
# create and append a datetime object to the times[] array
times.append(datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), int(second)))
# grab the gun vacuum level, separating it from its units (always mBar)
vac_i = splitLine[2].split('_')[0]
vac.append(float(vac_i))
# if the line and system vacuum are present, get those too (they may not be)
try:
vacsys_i = splitLine[3].split('_')[0]
vacsys.append(float(vacsys_i))
vacline_i = splitLine[4].split('_')[0]
vacline.append(float(vacline_i))
except IndexError:
vacsys.append(0)
vacline.append(0)
except ValueError:
vacsys.append(1)
vacline.append(1)
log_in.close()
start_date=times[0]
end_date=times[len(times)-1]
# this is where we do the plotting
from pylab import *
# set the plot title and x-axis label
figure("EBPG5000+ Gun Vacuum Log Viewer") # first create a figure
xlabel('Time')
if doubleplot:
# if we're plotting two parameters, we have to create two y-axes
# and plot on each one
hold(True)
axis1=subplot(111) # y1 is a subplot taking up the whole area
pylab.plot_date(pylab.date2num(times),plotparam1,'ro',ms=3,lw=1,label=sys.argv[1])
axis1.set_yscale('log')
pylab.ylim(limits.get(sys.argv[1],vac))
axis2=twinx() # y2 is a clone of y1, but gets different limits in the next plot
pylab.plot_date(pylab.date2num(times),plotparam2,'gs',ms=3,lw=1,label=sys.argv[2])
axis2.set_yscale('log')
pylab.ylim(limits.get(sys.argv[2],sys))
# shove some labels on each axis (dictionary is up top)
axis1.set_ylabel(labels.get(sys.argv[1],vac))
axis2.set_ylabel(labels.get(sys.argv[2],sys))
else:
pylab.plot_date(pylab.date2num(times),plotparam1,'ro',ms=3,lw=1)
yscale('log')
try:
ylabel(labels.get(sys.argv[1],vac))
pylab.ylim(limits.get(sys.argv[1],vac))
except IndexError: # again, no command line input means gun vacuum
ylabel(labels.get('gun'))
pylab.ylim(limits.get('gun'))
show()
ebpg_funpak/makefile 0000750 0000765 0000765 00000000075 12441200052 014113 0 ustar rooks rooks find_edge: find_edge.c
gcc find_edge.c -lm -o find_edge
ebpg_funpak/mss 0000755 0000765 0000765 00000023062 12441200052 013146 0 ustar rooks rooks #!/usr/bin/python
"""
mss - measure/estimate true(r) spot size.
10/2013 bc
-------------------------------------------------------------------------------
Copyright (c) 2014 bryan cord, university of minnesota.
All rights reserved.
Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are
duplicated in all such forms and that any documentation,
advertising materials, and other materials related to such
distribution and use acknowledge that the software was developed
by UMN. The name of the University may not be used to endorse or promote
products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-------------------------------------------------------------------------------
The Vistec has a built-in command to measure beam spot size. It does this by scanning
the beam along the edge of a gold calibration mark and measuring the slope of the signal;
if the edge of the mark is vertical, the slope should roughly correlate to the beam width.
Unfortunately, the slope of real-world marks is never vertical, and measurements tend to
be dominated by the mark slope, particularly at lower beam currents. This is an attempted
workaround.
We should be able to to estimate the spot size at a given current by using
the following relationship:
xspot=sqrt( xmea^2 - xslope^2)
Where xmea is the spot size measured with "pg measure spot size" and xslope is the measured
contribution of the alignment mark slope to the spot size. xslope is calculated by shifting
to a low beam current and using the following relationship:
xslope=sqrt(xmea^2 - xmin^2)
Where xmin is the minimum theoretical spot size for the given aperture. Obviously this
assumes that the contribution to the spot size from the slope of the mark edge also has
a gaussian profile, but it's probably close enough for an estimate.
The following constant values are used for xmin:
100um - 3nm
200um - 2nm
300um - 5nm
400um - 10nm
These values are taken from Vistec's data on theoretical spot size at a source brightness of
0.3-0.5 mA/Sr, which is standard operating brightness generally. The assumption is that when
the current is low, the spot will be very close to its theoretical minimum; any deviation between
the minimum spot and the measured spot is due to the finite slope of the alignment mark. Once we
know how much the slope is affecting the spot measurement, we can subtract that out of future
measurements.
Since xslope changes frequently depending on the specific cal mark used and how scummy the edges of
the mark are, it's a good idea to re-measure it every time we do a measurement. If you want to just
use the last measured slope value though, there's a command line option for that (--nocal).
9/5/14: Preliminary work on adding standard deviation calculation to the spot measurement (need to
look up my error-propagation equations)
9/8/14: Gave up on that and just downloaded the uncertainties library, which does EP for you.
Quit reinventing the wheel, Bryan!
9/9/14: Realized I had the error-prop stuff right in my own code when uncertainties started spitting
out the same answers. Went back to my own stuff to improve portability.
9/10/14: Added option to skip the autofocus (--nofocus), allowing defocused beams to be measured too.
10/6/14: Histogram now gets plotted in addition to spitting out the average. --nohist to bypass this.
"""
import os
import sys
import time
import numpy #statistics functions
#from uncertainties import ufloat
#from uncertainties.umath import *
# Define some constants. These are pretty self-explanatory.
LOWBEAM = "1na"
SLOPE_FILE = "savedSlope.txt"
SPOTMEAS_AMOUNT = 15
EDGEMEAS_AMOUNT = 15
minSpot = { '100':3 , '200':2 , '300':5 , '400':10 }
def get_spot(n=10):
# measure the spot size n times and return the average
# TO DO 8/29/14: Add option to plot a histogram of all the spot measurements somehow.
sslist=[]
for i in range(n):
ss_in = os.popen('pg measure spot size').read().split(':')[1]
ssx = float(ss_in.split(',')[0].split('_')[0])
ssy = float(ss_in.split(',')[1].split('_')[0])
#print "%s,%s" % (str(ssx),str(ssy))
#sum_ss = sum_ss + (ssx+ssy)/2
#sd_ss = sd_ss + ((ssx+ssy)/2)**2
sslist.append(i)
sslist[i] = (ssx+ssy)/2 # average the x and y spot measurements for now, I guess?
ss = numpy.mean(numpy.array(sslist))
sigma = numpy.std(numpy.array(sslist))
return (ss,sigma,sslist)
# get the theoretical minimum current using the aperture setting. The str(int()) thing happening below
# was the only way I could immediately think of to strip the leading space out of the pg get apert
# output. Vistec is the worst.
aperture = str(int(os.popen('pg get apert').read().split('_')[0]))
xmin = float( minSpot.get(aperture) )
if xmin == 'None':
print "ERROR: Invalid aperture setting. Needs to be [100|200|300|400]um."
sys.exit()
doCal = True
doFocus = True
doHist = True
# now you can specify that you just want to use the last valid edge slope measurement
# (use -n or --nocal at command line). Useful for repeated spot measurements or whatever.
for each in sys.argv:
if each == "-n" or each == "--nocal":
try:
loadSlope = open(SLOPE_FILE,'r')
inSlope = int(loadSlope.readline())
inSigma = float(loadSlope.readline())
# a lot of bullshit to get the date/time of the slope measurement. Whatevs.
slopeRawTime = os.path.getmtime(loadSlope.name)
slopeTimeStr = time.strftime('%x %X',time.gmtime(slopeRawTime) )
doCal = False
loadSlope.close()
except:
print "Warning: Slope file not found or corrupt. Calibrating normally..."
#if the slope file is nonexistent or garbage, just do the calibration
doCal = True
# Also possible to disable autofocus, in case you want to measure a defocused beam
if each == "-f" or each == "--nofocus": doFocus = False
if each == "-h" or each == "--nohist": doHist = False
if doCal:
# temporarily save the current beam (this was actually easier than figuring out which beam was loaded)
print "Saving current beam settings..."
os.system('pg archive save beam MSS_TEMP')
# load the small beam, focus it, and measure the spot
beam = "%s_%sum" % (LOWBEAM,aperture)
print "Loading 1nA beam to calibrate edge measurement..."
os.system('pg archive restore beam %s &> /dev/null' % beam)
print "Waiting for lenses to stabilize..."
time.sleep(10) # 10s stabilization after switching C2/FL current makes measurements more repeatable
print "Running autofocus..."
stat = os.system('pg adjust focus auto')
if stat != 0:
print "ERROR: Autofocus failure. Check holder settings and rerun the script."
sys.exit()
print "Measuring mark edge slope..."
(xmea,sigs,slopelist) = get_spot(EDGEMEAS_AMOUNT)
xslope = ( xmea**2 - xmin**2 )**0.5
print "Mark edge slope: %s nm" % str(int(round(xslope)))
print "Uncertainty: %s nm"% str(round(sigs,2))
# save the measurement somewhere, in case we want to use it again
slopeFile = open(SLOPE_FILE,'w')
slopeFile.writelines(str(round(xslope)))
slopeFile.writelines("\n")
slopeFile.writelines(str(round(sigs,2)))
slopeFile.close()
# now reload the original beam
print "Reloading original beam settings..."
os.system('pg archive restore beam MSS_TEMP &> /dev/null')
print "Waiting for lenses to stabilize..."
time.sleep(10)
os.system('pg measure current > /dev/null')
else:
print "Using saved edge slope measurement from %s (%s+/-%s)" % (slopeTimeStr, inSlope,inSigma)
xslope = inSlope
sigs = inSigma
if doFocus:
print "Running autofocus..."
stat = os.system('pg adjust focus auto')
if stat != 0:
print "ERROR: Autofocus failure. Rerun the script."
sys.exit()
else:
print "Warning: Skipping autofocus..."
print "Measuring spot size..."
(xmea,sigmax,xlist) = get_spot(SPOTMEAS_AMOUNT)
# use the array of results from get_spot to calculate a true spot size array
xtruelist=[]
for xi in xlist: xtruelist.append( int(round( abs( xi**2 - xslope**2)**0.5 , 2)))
# calculate the averaged spot
xtrue = int(round( abs( xmea**2 - xslope**2)**0.5 , 2))
current = os.popen('pg get bcm').read()[:-1] # remove the trailing newline
"""
propagate the error. I think this is right?
F=X^2 --> sigF = 2*(sigX/X)*F
F=X+Y --> sigF = sqrt(sigX^2 + sigY^2)
F=sqrt(X) --> sigF = 1/2 * sigX/X * F
F=sqrt(X^2 - Y^2) --> sigF= (2*(sigX/X)*X^2 + 2*(sigY/Y)*Y^2)/(X^2 - Y^2)*1/2*sqrt(X^2 + Y^2)
sigF = (XsigX + YsigY)/sqrt(X^2 + Y^2)
This seems to work, in that it gives the same results as the uncertainties package (not used here for
increased portability. Code from that is below)
uslope = ufloat(xslope,sigs)
uspot = ufloat(xmea,sigmax)
uxtrue = abs( uspot**2 - uslope**2)**0.5
"""
# I can has algebra?
true_sigma = (xslope*sigs + xmea*sigmax) / (xslope**2 + xmea**2)**(0.5)
print
print "BEAM INFORMATION"
print "----------------"
print "Beam Current: %s" % (current)
print "Estimated Spot Size: %s nm" % int(round(xtrue))
print "Uncertainty: %s nm" % int(round(true_sigma,2))
print
if float(current.split('_')[0]) < 5.0 :
print "WARNING: mss is not very accurate at sub-5nA beam currents"
print "Assume %s nm as the approximate spot for these beams" % str(xmin)
os.system("rm /home/pg/archive/MSS_TEMP* &> /dev/null")
# plot a histogram of the measurement results we averaged for the final number
if doHist:
import matplotlib.pyplot as plt
plt.hist(xtruelist)
plt.xlabel("Spot Size (nm)")
plt.ylabel("Counts")
plt.title("Spot Size Measurement Distribution (n=%s)" % SPOTMEAS_AMOUNT)
plt.show()
sys.exit()
ebpg_funpak/looper 0000755 0000765 0000765 00000003560 12441200052 013645 0 ustar rooks rooks #!/bin/bash
: '
-------------------------------------------------------------------------------
Copyright (c) 2014 bryan cord, university of minnesota.
All rights reserved.
Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are
duplicated in all such forms and that any documentation,
advertising materials, and other materials related to such
distribution and use acknowledge that the software was developed
by UMN. The name of the University may not be used to endorse or promote
products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-------------------------------------------------------------------------------
'
# Looper: generic script to monitor/log the output of a command.
# Also a pretty good movie!
# written so I could quickly generate logs of the EHT situation
# during the Great EHT Clusterfuck of April 2012. - BC
error_handler()
{
exit $1
}
usage()
{
echo -e "looper: loop a command at regular intervals and log the output"
echo
echo -e "Usage: looper \"\" [logfile]"
echo -e "Leave out [logfile] for screen output only"
exit 1
}
declare -i sleepytime=$2
if [ "$#" != "2" -a "$#" != "3" ]; then usage; fi
if [ $sleepytime -eq 0 ]; then usage; fi
trap 'error=$? ; error_handler $error' ERR
trap 'exit 0' SIGINT
if [ ! $3 ]; then logfile=/dev/null; else logfile=$3; fi
echo "Logging command \"$1\" at $2 sec intervals."
if [ $3 ]; then echo "Logging to file $3."; fi
echo "CTRL-C to stop."
echo
while [ 1 ]; do
if [ $3 ]; then echo -e "`date +%D`\t`date +%T`\t`$1`" | tee -a $logfile
else echo -e "`date +%D`\t`date +%T`\t`$1`"
fi
sleep $2
done
ebpg_funpak/ybrsort.py 0000755 0000765 0000765 00000107411 12551464642 014523 0 ustar rooks rooks #!/usr/bin/python
"""
ybrsort.py
Requires gpfgtx and gtxgpf programs.
This program reads a gpf file and sorts the shapes into yellow-brick-road
order. This might be described as a "proximity sort", since we will try
to stick together shapes that appear near each other.
The blocks are not sorted. You can use the utility gpfsort for that.
v2 Sorts multiple fields, as does the original radial_sort.py
v3 Finds neighboring shapes with a rolling list instead of recursion.
Otherwise each shape is limited to 900 trapezoids.
v4 Instead of searching n times through the entire list of shapes,
we create a list of shapes which are contained in each subfield.
Then we search through just the local subfields. Big improvement.
v5 If we start gathering shapes in the middle of a long thing, then
the writing order splits, and the beam flips back and forth along
the shape. We needed a better way to pick the starting point.
The last item on the list is likely to be one of the end points
of a structure, so now we use the last point as the starting point
for a second pass. This works quite well.
"""
import os
import sys
import math
import string
import operator
from math import *
version = 5
# Center of the pattern is X0,Y0. 524288 is half of 1048576 = 2^20.
X0 = 0
Y0 = 0
CHUNK = 1 # micron. Size of a chunk sorted as one group of shapes.
# One micron is typical. Smaller values will speed up
# this program, and will use more memory.
recursion = 0
shape = 0
#-----------------------------------------------------------------------------------------------
def sort_table(table, cols):
"""
sort a table by multiple columns
table: a list of lists (or tuple of tuples) where each inner list represents a row
cols: a list (or tuple) specifying the column numbers to sort by
"""
is_a_list = True
try:
len( cols )
print "..."
except:
is_a_list = False
if is_a_list:
rcols = reversed( cols )
for col in rcols :
table = sorted(table, key=operator.itemgetter(col))
else:
table = sorted(table, key=operator.itemgetter(cols))
return table
#====================================================================================================
# Yellow Brick Road sorting functions
def twiddle( t ): # display an amusing progress report
t += 1
wait = " [%d][%d]" % (shape, recursion)
for i in range( t ): wait += "."
for i in range( t,40 ): wait += " "
print "%s\015" % wait,
if t > 30 : t = 0
sys.stdout.flush()
return t
def YBRdistance( t, p ):
"""
t is an entry in the big table of shapes. p is a coordinate
in mainfield units (field center is 524288,525288).
This function returns the disance in main field units (usually nm).
"""
dx = abs( t[14] - p[0] )
dy = abs( t[15] - p[1] )
d = math.sqrt( dx**2 + dy**2 )
return( d )
def overlap( llx, lly, urx, ury, pllx, plly, purx, pury ) :
if pllx > urx : return False
if purx < llx : return False
if plly > ury : return False
if pury < lly : return False
return True
def local_group( g, R, subfield ):
"""
Gather a list of shapes that are near shape "g".
Look in the nearby subfields.
"""
sx = R[g][18]
sy = R[g][19]
n = len( subfield )
lg = []
for dx in range(-2,3) :
x = sx + dx
if x >= 0 and x < n:
for dy in range(-2,3) :
y = sy + dy
if y >=0 and y < n :
for j in subfield[x][y] : lg.append( j )
#
#
#
#
return lg
def look_for_neighbors( p, R, chunk, city, subfield, first ):
"""
p is an index to one entry in the big table. R is the whole big table of shapes.
w2 and h2 are in main field units. city is the list of
indices into the big table. We use a rolling list here, not recursion.
"""
global shape
global recursion
if first :
saveshape = shape
shape = -shape
if R[p][17] :
#print "Shape %d has already been hit." % p
return city # if this shape has already been hit
t = 0
n = len( R )
g = p # starting point
group = [g] # list of connected shapes
R[g][17] = True # hit!
city.append( g ) # add this shape to the full list
gi = 0 # index into the group list
while gi < len( group ) :
g = group[gi]
pllx = R[g][14] - chunk
purx = R[g][14] + chunk
plly = R[g][15] - chunk
pury = R[g][15] + chunk
lg = local_group( g, R, subfield )
for i in lg : # range(n) :
if i <> g and R[i][16] and not R[i][17] : # if the item is active and has not been hit...
llx = R[i][14] - chunk
urx = R[i][14] + chunk
lly = R[i][15] - chunk
ury = R[i][15] + chunk
if overlap( llx, lly, urx, ury, pllx, plly, purx, pury ) and not R[i][17] :
city.append( i )
group.append( i )
R[i][17] = True # hit!
#end if
#end if
#end for
if gi < len( group ) :
gi += 1
recursion = len(group) - gi
if first :
shape -= 1
else:
shape += 1
if shape % 50 == 0 : t = twiddle( t )
# If this is the first pass then let's go back and UNHIT the items. Slick.
if first:
for i in city : R[i][17] = False
shape = saveshape
return (city)
def presort( R, x, chunk, fullfield ):
"""
Generate a list of shapes in each subfield.
"""
nx = int( fullfield / chunk ) + 1
ny = nx
subfield = [[ [] for i in range(ny)] for j in range(nx) ]
for i in range( len(R) ):
t = R[i]
if t[16] :
sx = R[i][18]
sy = R[i][19]
subfield[sx][sy].append( i )
return subfield
def yellow_brick_road_sort( R, chunk, x0, y0, fullfield ):
"""
Follow the yellow brick road! In other words, gather together
shapes that are near one another. We look_for_neighbors twice:
first to find a good starting point, and then again to create
a list that goes from the "beginning" to the "end" of each shape.
R is the big table of shapes. (xblock,yblock) in this program is
the region of "nearness", in main field units, usually a subfield
of 3 um. (x0,y0) is the starting point, which shouldn't matter.
"""
print "\nPresorting..."
subfield = presort( R, x, chunk, fullfield )
print "\nSorting...\n"
ncity = len( R )
print "Number of shapes: %d\n" % ncity
mind = YBRdistance( R[0], [x0, y0] )
munchkindex = 0
for i in range( ncity ):
d = YBRdistance( R[i], [x0, y0] )
if d < mind :
mind = d
munchkindex = i
#print "\nMunchkinland is nearest to shape %d" % munchkindex
firstpass = []
fulltrip = []
firstpass = look_for_neighbors( munchkindex, R, chunk, firstpass, subfield, first=True )
fulltrip = look_for_neighbors( firstpass[-1], R, chunk, fulltrip, subfield, first=False )
for i in range( munchkindex, ncity ):
if not R[i][17] : # if not (i in city):
firstpass = []
firstpass = look_for_neighbors( i, R, chunk, firstpass, subfield, first=True )
if len(firstpass) > 0 :
fulltrip = look_for_neighbors( firstpass[-1], R, chunk, fulltrip, subfield, first=False )
if len( fulltrip ) == ncity : break
for i in range( 0, munchkindex ):
if not R[i][17] : # if not (i in city):
firstpass = []
firstpass = look_for_neighbors( i, R, chunk, firstpass, subfield, first=True )
if len(firstpass) > 0 :
fulltrip = look_for_neighbors( firstpass[-1], R, chunk, fulltrip, subfield, first=False )
if len( fulltrip ) == ncity : break
return( fulltrip )
#====================================================================================================
# Parse one line of "repetition". This is woefully and gloriously complex,
# and should not be necessary.
def parse( bit, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, \
s1dy, s2dx, s2dy, base, height, msf, main_resol, sub_resol ) :
if not hasattr( parse, "init" ):
parse.init = True
parse.m1c = 0
parse.m2c = 0 # static variables
parse.s1c = 0
parse.s2c = 0
bits = string.split( bit )
if "Repetition Main 1 X Count" in bit:
mx1c = int( bits[5] )
parse.m1c = mx1c
elif "Repetition Main 1 X LSW" in bit:
m1dx = int( bits[5] )
elif "Repetition Main 1 Y Count" in bit:
my1c = int( bits[5] )
elif "Repetition Main 1 Y LSW" in bit:
m1dy = int( bits[5] )
elif "Repetition Main 1 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.m1c = int( bits[4] )
elif "Repetition Main 2 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.m2c = int( bits[4] )
elif "Repetition Main 2 X LSW" in bit:
m2dx = int( bits[5] )
elif "Repetition Main 2 X Count" in bit:
mx2c = int( bits[5] )
elif "Repetition Main 2 Y Count" in bit:
my2c = int( bits[5] )
parse.m2c = my2c
elif "Repetition Main 2 Y LSW" in bit:
m2dy = int( bits[5] )
elif "Repetition Sub 1 X" in bit and not ("Count" in bits):
s1dx = int( bits[4] )
elif "Repetition Sub 1 X Count" in bit:
sx1c = int( bits[5] )
parse.s1c = sx1c
elif "Repetition Sub 1 Y Count" in bit:
sy1c = int( bits[5] )
elif "Repetition Sub 1 Y" in bit and not ("Count" in bits):
s1dy = int( bits[4] )
elif "Repetition Sub 1 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.s1c = int( bits[4] )
elif "Repetition Sub 2 X" in bit and not ("Count" in bits):
s2dx = int( bits[4] )
elif "Repetition Sub 2 X Count" in bit:
sx2c = int( bits[5] )
elif "Repetition Sub 2 Y" in bit and not ("Count" in bits):
s2dy = int( bits[4] )
elif "Repetition Sub 2 Y Count" in bit:
sy2c = int( bits[5] )
parse.s2c = sy2c
elif "Repetition Sub 2 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.s2c = int( bits[4] )
elif "Repetition" in bits:
print "\nUnknown repetition line: [%d]\n" % bit
# Are the following correct? It might be that some parameters need to be
# retained and used by implication in successive Activate lines.
if "Activate" in bits and "SRV1" in bits and not ("SRV2" in bits):
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
sx2c = 0
sy2c = 0
s2dx = 0
s2dy = 0
if "Activate" in bits and "SRV2" in bits and not ("SRV1" in bits):
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
sx1c = 0
sy1c = 0
s1dx = 0
s1dy = 0
if "Activate" in bits and "MRV1" in bits and not ("MRV2" in bits):
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
mx2c = 0
my2c = 0
m2dx = 0
m2dy = 0
if "Activate" in bits and "MRV2" in bits and not ("MRV1" in bits):
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
mx1c = 0
my1c = 0
m1dx = 0
m1dy = 0
if "Activate" in bits and "SRV1" in bits and "SRV2" in bits:
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
if "Activate" in bits and "MRV1" in bits and "MRV2" in bits:
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
if "Activate" in bits and "MRV1" in bits:
mx1c = parse.m1c
if "Activate" in bits and "MRV2" in bits:
my2c = parse.m2c
if "Activate" in bits and "SRV1" in bits:
sx1c = parse.s1c
if "Activate" in bits and "SRV2" in bits:
sy2c = parse.s2c
# RYH and RXB are used to chop shapes into subfield traps.
# The savings in space is negligible, but it might prevent
# blanking between shapes. Let's hope so; otherwise,
# it's just stupid.
# V1 is X only, V2 is Y only
if "RXB" in bits or "RYH" in bits:
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
if sub_resol <= 0 :
print "\nERROR: subfield resolution not defined.\m"
sys.exit()
h = int( height )
b = int( base )
m = int( msf )
if "RYH" in bits:
if "SRV1" in bits or "SRV2" in bits:
s2dy = (h + 1) * m
elif "MRV1" in bits or "MRV2" in bits:
m2dy = (h + 1) * m * main_resol/sub_resol
if "RXB" in bits:
if "SRV1" in bits or "SRV2" in bits:
s1dx = (b + 1) * m
elif "MRV1" in bits or "MRV2" in bits:
m1dx = (b + 1) * m * main_resol/sub_resol
return( (mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy ) )
#-----------------------------------------------------------------------------------------------
def expand_array( entry, n, table, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, \
m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy, mainpersub, chunk ):
# Loop over x and y repeats, generating new table entries
# Could there be both main and subfield repeats on the same line?
# That would be perverse, so let's just check for perversity first.
# Be sure to turn off "compaction" of any sort in Beamer.
main_repeat = mx1c > 0 or mx2c > 0 or my1c > 0 or my2c > 0
sub_repeat = sx1c > 0 or sx2c > 0 or sy1c > 0 or sy2c > 0
if not main_repeat and not sub_repeat:
print "\nERROR: an array contains no repetition values\n"
sys.exit()
if main_repeat and sub_repeat:
print "\nERROR: mainfield and subfield arrays appear sumultaneously. This freaks me out, man."
print "Try disabling all compaction modes in Beamer (or whatever you used to generate gpf)."
print "Be sure to disable Beamer's 'compaction diagonal array' option, which is evil."
print "Program aborted."
sys.exit()
activate_line = entry[0]
main_x_lsw = entry[1]
main_y_lsw = entry[2]
freq_lsw = entry[3]
freq_msw = entry[4]
base_lsw = entry[5]
height_lsw = entry[6]
msf = entry[7]
shift_lt_lsw = entry[8]
shift_rb_lsw = entry[9]
offset_x_lsw = entry[10]
offset_y_lsw = entry[11]
shift_rb_used = entry[12]
shift_lt_used = entry[13]
table[n][0] = "deleted"
table[n][16] = False # the item is no longer active
if main_repeat:
# strip out MRV1, MRV2, RXB, and RYH from acitivate line
# loop over mx1c and my2c. Watch for nonzero my1c and mx2c.
newline = ""
words = string.split( activate_line )
begin = False
for word in words:
if (word == "Activate"): begin = True
if begin and word <> "MRV1" and word <> "MRV2" and word <> "RXB" and word <> "RYH" :
newline = newline + " " + word
#print "[%s]" % newline
if my1c <> 0 or mx2c <> 0 :
print "\nERROR: strange array with my1c or mx2c not zero: [%s]." % activate_line
print "What does it mean?"
print "Try disabling all compaction modes in Beamer (or whatever you used to generate gpf)."
print "Be sure to disable Beamer's 'compaction diagonal array' option, which is evil.\n"
sys.exit()
mainx = int( main_x_lsw )
mainy = int( main_y_lsw )
for row in range( my2c+1 ):
y = mainy + m2dy * row
mainy_s = "%d" % y
for col in range( mx1c+1 ):
x = mainx + m1dx * col
mainx_s = "%d" % x
fx = x + float(offset_x_lsw) / mainpersub
fy = y + float(offset_y_lsw) / mainpersub
sx = int( fx / chunk )
sy = int( fy / chunk )
table.append( [ newline, \
mainx_s, \
mainy_s, \
freq_lsw, \
freq_msw, \
base_lsw, \
height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
offset_x_lsw, \
offset_y_lsw, \
shift_rb_used, \
shift_lt_used, \
fx, \
fy, \
True, \
False, \
sx, sy ] ) # [16] = "active", [17] = "hit"
else: # subfield repeat
# strip out SRV1, SRV2, RXB, and RYH from acitivate line
# loop over sx1c and sy2c. Watch for nonzero sy1c and sx2c.
newline = ""
words = string.split( activate_line )
begin = False
for word in words:
if (word == "Activate"): begin = True
if begin and word <> "SRV1" and word <> "SRV2" and word <> "RXB" and word <> "RYH" :
newline = newline + " " + word
#print "[%s]" % newline
if sy1c <> 0 or sx2c <> 0 :
print "\nERROR: strange array with sy1c or sx2c not zero: [%s]." % activate_line
print "What does it mean?"
print "Try disabling all compaction modes in Beamer (or whatever you used to generate gpf)."
print "Be sure to disable Beamer's 'compaction diagonal array' option, which is evil.\n"
sys.exit()
subx = int( offset_x_lsw )
suby = int( offset_y_lsw )
for row in range( sy2c+1 ):
y = suby + s2dy * row
suby_s = "%d" % y
for col in range( sx1c+1 ):
x = subx + s1dx * col
subx_s = "%d" % x
fx = float(main_x_lsw) + x / mainpersub
fy = float(main_y_lsw) + y / mainpersub
sx = int( fx / chunk )
sy = int( fy / chunk )
table.append( [ newline, \
main_x_lsw, \
main_y_lsw, \
freq_lsw, \
freq_msw, \
base_lsw, \
height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
subx_s, \
suby_s, \
shift_rb_used, \
shift_lt_used, \
fx, \
fy, \
True, \
False, \
sx, sy ] ) # [16] = "active", [17] = "hit"
return( table )
#-----------------------------------------------------------------------------------------------
def flatten( table, main_resol, sub_resol, mainpersub, chunk ):
# look for repetition lines, creating explicit shapes instead
mx1c = 0 # main x1 count
mx2c = 0 # main x2 count
my1c = 0
my2c = 0
sx1c = 0 # subfield x1 count
sx2c = 0 # subfield x2 count
sy1c = 0
sy2c = 0
m1dx = 0 # main 1 delta x, in mainfield resolution units
m1dy = 0
s1dx = 0 # subfield 1 delta x, in subfield resolution units
s1dy = 0
m2dx = 0
m2dy = 0
s2dx = 0
s2dy = 0
#print "mx1c mx2c my1c my2c sx1c sx2c sy1c sy2c m1dx m1dy m2dx m2dy s1dx s1dy s2dx s2dy"
n = 0
for entry in table:
base = entry[5]
height = entry[6]
line = entry[0]
msf = entry[7]
item = string.split( line )
if "SRV1" in item or "SRV2" in item or "MRV1" in item or "MRV2" in item :
part = string.split( line, "\n" )
for bit in part:
mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy = \
parse( bit, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, \
s2dx, s2dy, base, height, msf, main_resol, sub_resol )
table = expand_array( entry, n, table, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, \
m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy, mainpersub, chunk )
n = n + 1
return( table )
#-----------------------------------------------------------------------------------------------
# MAIN
print
print "GPF yellow brick road sorting utility, version %d" % version
print
if len( sys.argv ) == 1 :
print "\nUse: radial_sort.py file.gpf"
print "\n The output file will be file_sorted.gpf\n\n"
sys.exit()
if len( sys.argv ) > 1 :
if sys.argv[1] == "-h" or sys.argv[1] == "-help" or sys.argv[1] == "--help" :
print "\nUse: radial_sort.py file.gpf"
print "\n The output file will be file_sorted.gpf\n\n"
sys.exit()
filein = sys.argv[1]
else:
print
print "Enter input gpf file name> ",
filein = sys.stdin.readline()
filein = filename[0:-1]
if not (".gpf" in filein) and not ("." in filein):
filein = filein + ".gpf"
name = string.split( filein, "." )
fileout = name[0] + "_sorted.gpf"
print
print "Input gpf file: ", filein
print "Output gpf file: ", fileout
print
print "\nConverting to gtx...\n"
os.system( "gpfgtx %s temp_in.gtx" % filein )
gtxin = open( "temp_in.gtx", "rb" )
gtxout = open( "temp_out.gtx", "w" )
print "\nCopying header... \n"
word = []
# copy header
line = gtxin.readline()
if not line:
print "\nERROR: unexpected end of file.\n\n"
sys.exit()
word = string.split( line )
if len( word ) == 0 :
word.append( "\n" )
bss = 0.0
mfr = 0.0
sfr = 0.0
while word[0] <> "END" :
gtxout.write( line )
line = gtxin.readline()
if not line:
print "\nERROR: unexpected end of file.\n\n"
sys.exit()
word = string.split( line )
if len( word ) == 0 :
word.append( "\n" )
if word[0] == "BeamStepSize" :
stuff = string.split( word[1], "," )
sub_resol = int( stuff[0] )
msf = sub_resol
bss = sub_resol
print " Subfield step size (bits) : ", bss
elif word[0] == "Resolution":
stuff = string.split( word[1], "," )
main_resol = int( stuff[0] )
elif word[0] == "MainFieldResolution" :
stuff = string.split( word[1], "," )
mfr = float( stuff[0] )
print " Main field resolution (um) : ", mfr
elif word[0] == "SubFieldResolution" :
stuff = string.split( word[1], "," )
sfr = float( stuff[0] )
print " Subfield resolution (um) : ", sfr
elif word[0] == "MainFieldSize" :
stuff = string.split( word[1], "," )
mfsx = float( stuff[0] )
mfsy = float( stuff[1] )
print " Main field block size (um) : ", mfsx * sfr * bss, mfsy * sfr * bss
xblocksize = mfsx * bss * sfr / mfr
yblocksize = mfsy * bss * sfr / mfr
print " Block size, mainfield bits: ", xblocksize, yblocksize
elif word[0] == "NrMainFieldBits" :
nmfb = int( word[1] )
print " Number of main field bits: ", nmfb
fullfield = math.pow( 2, nmfb )
mainpersub = mfr / sfr
if bss == 0.0 or mfr == 0.0 or sfr == 0.0 :
print "\nERROR: units not found in header.\n"
sys.exit()
gtxout.write( line ) # write "END" after header
bss_sub = msf
#print " Number of subfield bits in a beam step: %d\n" % bss_sub
chunk = CHUNK / mfr # usually, 1 um / 0.001 = 1000 bits
#print "chunk = ", chunk
print
print "Reading..."
print
end_of_file = False
while not end_of_file: # while not EOF, sort each field
new_field = True
main_x_lsw = 0
main_y_lsw = 0
base_lsw = "0"
height_lsw = "0"
shift_lt_lsw = "0"
shift_rb_lsw = "0"
offset_x_lsw = "0"
offset_y_lsw = "0"
msf = 0
freq_msw = "0"
freq_lsw = "0"
append_next_line = False
n = 0
end_of_field = False
nbad = 0
table = []
while True: # for each_line in gtxin.readlines() :
each_line = gtxin.readline()
if len( each_line ) == 0 :
end_of_file = True
break
if end_of_field : # or n > 1000000 :
break
if append_next_line: # True for repetition lines
line = line + "\n" + each_line[:-1]
append_next_line = False
else:
line = each_line[:-1]
word = string.split( each_line )
unknown = False
if len( word ) > 0:
if word[0] == "END":
end_of_field = True
elif word[0] == "Main":
if word[1] == "X":
main_x_lsw = int( word[3] )
else:
main_y_lsw = int( word[3] )
elif word[0] == "Frequency":
if word[1] == "LSW":
freq_lsw = word[2]
else:
freq_msw = word[2]
elif word[0] == "Base":
base_lsw = word[2]
elif word[0] == "Height":
height_lsw = word[2]
elif word[0] == "MSF":
msf = word[1] # subfield (e.g. 20 => 10nm)
elif word[0] == "Shift":
if word[1] == "LT":
shift_lt_lsw = word[3]
else:
shift_rb_lsw = word[3]
elif word[0] == "Offset":
if word[1] == "X":
offset_x_lsw = word[3]
else:
offset_y_lsw = word[3]
elif word[0] == "Repetition":
append_next_line = True # tricky!
elif word[0] == "Activate":
n = n + 1
attributes = string.split( line )
if "hb" in attributes : # careful! hb applies only to this item
this_height_lsw = base_lsw
else:
this_height_lsw = height_lsw
shift_rb_used = not ("rb45" in attributes or "rb90" in attributes)
shift_lt_used = not ("lt45" in attributes or "lt90" in attributes)
x = float( main_x_lsw )
y = float( main_y_lsw )
if False :
# if bad_shape( shift_rb_used, shift_lt_used, bss_sub, \
# base_lsw, this_height_lsw, shift_lt_lsw, shift_rb_lsw, line ) :
nbad = nbad + 1
#print "base: ", base_lsw
#print "height: ", this_height_lsw
#print "shift lt: ", shift_lt_lsw
#print "shift rb: ", shift_rb_lsw
#print line
else:
x = int(main_x_lsw) + int(offset_x_lsw) / mainpersub
y = int(main_y_lsw) + int(offset_y_lsw) / mainpersub
sx = int( x / chunk ) # subfield x
sy = int( y / chunk ) # subfield y
table.append( [ line, \
main_x_lsw, \
main_y_lsw, \
freq_lsw, \
freq_msw, \
base_lsw, \
this_height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
offset_x_lsw, \
offset_y_lsw, \
shift_rb_used, \
shift_lt_used, \
x, \
y, \
True, \
False, \
sx, sy ] ) # [16] = "active", [17] = "hit"
else:
print line
print
gtxout.write( "%s\n" % line ) # this line is part of the field header... we hope!
sys.stdout.flush()
# end if word[0]
if (n > 0) and (n % 1000 == 0) :
print " shape %d \015" % n,
sys.stdout.flush()
# end if len( word ) > 0
# end while each_line
if end_of_file: break
print " shape %d " % n
print "\nFlattening..."
sys.stdout.flush()
table = flatten( table, main_resol, sub_resol, mainpersub, chunk )
#-----------------------------------------------------------------
# SORT THE TABLE - TAKES QUITE A WHILE - SCALES AS N^2
order = yellow_brick_road_sort( table, chunk, 0, 0, fullfield )
print "\n"
#---------------------------------------------------------------
# Write the rest of the gtx file (the header was copied already)
num_shapes = len( table ) # well, that also includes deleted array lines
if num_shapes < 1 :
print "\nERROR: there are no shapes in this gtx file.\n"
sys.exit()
print "Writing temp_out.gtx...\n"
activate_line = table[order[0]][0]
prev_main_x_lsw = table[order[0]][1]
prev_main_y_lsw = table[order[0]][2]
prev_freq_lsw = table[order[0]][3]
prev_freq_msw = table[order[0]][4]
prev_base_lsw = table[order[0]][5]
prev_height_lsw = table[order[0]][6]
prev_msf = table[order[0]][7]
prev_shift_lt_lsw = table[order[0]][8]
prev_shift_rb_lsw = table[order[0]][9]
prev_offset_x_lsw = table[order[0]][10]
prev_offset_y_lsw = table[order[0]][11]
shift_rb_used = table[order[0]][12]
shift_lt_used = table[order[0]][13]
if not ("deleted" in activate_line):
gtxout.write( " Frequency LSW %s\n" % prev_freq_lsw )
gtxout.write( " Frequency MSW %s\n" % prev_freq_msw )
gtxout.write( " MSF %s\n" % prev_msf )
gtxout.write( " Main X LSW %s\n" % prev_main_x_lsw )
gtxout.write( " Main Y LSW %s\n" % prev_main_y_lsw )
gtxout.write( " Offset X LSW %s\n" % prev_offset_x_lsw )
gtxout.write( " Offset Y LSW %s\n" % prev_offset_y_lsw )
gtxout.write( " Base LSW %s\n" % prev_base_lsw )
if not ("hb" in activate_line ) :
gtxout.write( " Height LSW %s\n" % prev_height_lsw )
if shift_lt_used:
gtxout.write( " Shift LT LSW %s\n" % prev_shift_lt_lsw )
if shift_rb_used:
gtxout.write( " Shift RB LSW %s\n" % prev_shift_rb_lsw )
gtxout.write( "%s\n" % activate_line )
new_field = False
elif new_field:
new_field = False
gtxout.write( " Frequency LSW %s\n" % prev_freq_lsw )
gtxout.write( " Frequency MSW %s\n" % prev_freq_msw )
gtxout.write( " MSF %s\n" % prev_msf )
gtxout.write( " Main X LSW %s\n" % prev_main_x_lsw )
gtxout.write( " Main Y LSW %s\n" % prev_main_y_lsw )
gtxout.write( " Offset X LSW %s\n" % prev_offset_x_lsw )
gtxout.write( " Offset Y LSW %s\n" % prev_offset_y_lsw )
gtxout.write( " Base LSW %s\n" % prev_base_lsw )
if num_shapes > 1 :
for n in range( 1, len( order ) ):
item = table[ order[n] ]
if n % 1000 == 0 :
print " shape %d \015" % n,
sys.stdout.flush()
activate_line = item[0]
main_x_lsw = item[1]
main_y_lsw = item[2]
freq_lsw = item[3]
freq_msw = item[4]
base_lsw = item[5]
height_lsw = item[6]
msf = item[7]
shift_lt_lsw = item[8]
shift_rb_lsw = item[9]
offset_x_lsw = item[10]
offset_y_lsw = item[11]
shift_rb_used = item[12]
shift_lt_used = item[13]
# Setting values by implication does not work reliably,
# so the output will be rather verbose. Oh well.
if not ("deleted" in activate_line) :
if True: # freq_lsw <> prev_freq_lsw :
gtxout.write( " Frequency LSW %s\n" % freq_lsw )
if True: # freq_msw <> prev_freq_msw :
gtxout.write( " Frequency MSW %s\n" % freq_msw )
if True: # msf <> prev_msf :
gtxout.write( " MSF %s\n" % msf )
if True: # main_x_lsw <> prev_main_x_lsw :
gtxout.write( " Main X LSW %s\n" % main_x_lsw )
if True: # main_y_lsw <> prev_main_y_lsw :
gtxout.write( " Main Y LSW %s\n" % main_y_lsw )
if True: # PROBLEM: offset_x_lsw <> prev_offset_x_lsw :
gtxout.write( " Offset X LSW %s\n" % offset_x_lsw )
if True: # offset_y_lsw <> prev_offset_y_lsw :
gtxout.write( " Offset Y LSW %s\n" % offset_y_lsw )
if True: # base_lsw <> prev_base_lsw :
gtxout.write( " Base LSW %s\n" % base_lsw )
if (not ("hb" in activate_line )): # PROBLEM: and (height_lsw <> prev_height_lsw) :
gtxout.write( " Height LSW %s\n" % height_lsw )
if shift_lt_used:
gtxout.write( " Shift LT LSW %s\n" % shift_lt_lsw )
if shift_rb_used:
gtxout.write( " Shift RB LSW %s\n" % shift_rb_lsw )
gtxout.write( "%s\n" % activate_line )
new_field = False
prev_main_x_lsw = item[1]
prev_main_y_lsw = item[2]
prev_freq_lsw = item[3]
prev_freq_msw = item[4]
prev_base_lsw = item[5]
prev_height_lsw = item[6]
prev_msf = item[7]
prev_shift_lt_lsw = item[8]
prev_shift_rb_lsw = item[9]
prev_offset_x_lsw = item[10]
prev_offset_y_lsw = item[11]
# end for item
# end if num_shapes > 1
gtxout.write( "END\n" )
shape = 0
# end while not EOF
gtxin.close()
gtxout.close()
print "\nConverting back to gpf...\n"
os.system( "gtxgpf temp_out.gtx %s" % fileout )
print
print "Output file: %s" % fileout
print "\n\nDone.\n"
print
ebpg_funpak/radial_sort.py 0000755 0000765 0000765 00000073227 12524210015 015310 0 ustar rooks rooks #!/usr/bin/python
"""
radial_sort.py
Requires gpfgtx and gtxgpf programs.
This program reads a gpf file and sorts the shapes into radial
order. Actually, this might more accurately be described as a "spiral
sort". The shapes in a radial region are also sorted by angle, so the
resulting writing order should be fastest tangentailly and slower
radially. The center point is fixed, usually at the field center, as
specified by the constants X0 and Y0.
At the bottom, the "if not deleted" block creates problems when
we try to set various parameters by implication. Sometimes it
works and sometimes not. Running gtxgpf will tell you if this
compaction step has created bad shapes.
It would be wise to look for bad shapes, but currently the
"bad_shape" function does not work. I'm not sure why.
v2 Sorts multiple fields
v3 Does not use any implied parameters, since this is
mysteriously difficult to get right.
"""
import os
import sys
import math
import string
import operator
from math import *
version = 3
# Center of the pattern is X0,Y0. 524288 is half of 1048576 = 2^20.
# If the center of the pattern is not in the center of the field,
# then you should change this:
X0 = 524288
Y0 = 524288
CHUNK = 1.0 # micron. Size of a chunk sorted as one group of shapes.
PI = 3.1415926
PI2 = PI / 2.0
TWOPI = 2.0 * PI
#-----------------------------------------------------------------------------------------------
def sort_table(table, cols):
"""
sort a table by multiple columns
table: a list of lists (or tuple of tuples) where each inner list represents a row
cols: a list (or tuple) specifying the column numbers to sort by
"""
is_a_list = True
try:
len( cols )
print "..."
except:
is_a_list = False
if is_a_list:
rcols = reversed( cols )
for col in rcols :
table = sorted(table, key=operator.itemgetter(col))
else:
table = sorted(table, key=operator.itemgetter(cols))
return table
#-----------------------------------------------------------------------------------------------
def bad_shape( shift_rb_used, shift_lt_used, \
bss_sub, base_lsw, height_lsw, \
shift_lt_lsw, shift_rb_lsw, activate_line ):
# Look for illegal shapes.
# This has some unknown problem. It does not yet work.
base = int( base_lsw )
height = int( height_lsw )
if height == 0 : return( True )
attributes = string.split( activate_line )
if shift_rb_used:
srb = int( shift_rb_lsw )
elif "rb45" in attributes:
srb = height
else:
srb = 0
if shift_lt_used:
slt = int( shift_lt_lsw )
elif "lt45" in attributes:
slt = height
else:
slt = 0
if "ltNeg" in attributes : slt = -slt
if "rbNeg" in attributes : srb = -srb
return ( slt > (base * bss_sub + srb) )
#-----------------------------------------------------------------------------------------------
def angle_360( x, y ):
# calculate the angle in the range 0..2PI
if x == 0.0 :
if y > 0.0 :
a = PI2
else:
a = -PI2
elif y == 0.0 :
if x > 0.0 :
a = 0.0
else:
a = PI
elif x > 0.0 and y > 0.0 :
a = math.atan( y / x )
elif x < 0.0 and y > 0.0 :
a = PI - math.atan( y / (-x) )
elif x < 0.0 and y < 0.0 :
a = PI + math.atan( y / x )
else:
a = TWOPI - math.atan( -y/x )
return( a )
#-----------------------------------------------------------------------------------------------
def sorting_parameter( x, y, chunk ):
r = chunk * math.floor( math.sqrt( x * x + y * y ) / chunk )
a = angle_360( x, y )
s = chunk * math.floor((r * a + 1000 * r) / chunk )
return( s )
#-----------------------------------------------------------------------------------------------
# Parse one line of "repetition". This is woefully and gloriously complex,
# and should not be necessary.
def parse( bit, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, \
s1dy, s2dx, s2dy, base, height, msf, main_resol, sub_resol ) :
if not hasattr( parse, "init" ):
parse.init = True
parse.m1c = 0
parse.m2c = 0 # static variables
parse.s1c = 0
parse.s2c = 0
bits = string.split( bit )
if "Repetition Main 1 X Count" in bit:
mx1c = int( bits[5] )
parse.m1c = mx1c
elif "Repetition Main 1 X LSW" in bit:
m1dx = int( bits[5] )
elif "Repetition Main 1 Y Count" in bit:
my1c = int( bits[5] )
elif "Repetition Main 1 Y LSW" in bit:
m1dy = int( bits[5] )
elif "Repetition Main 1 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.m1c = int( bits[4] )
elif "Repetition Main 2 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.m2c = int( bits[4] )
elif "Repetition Main 2 X LSW" in bit:
m2dx = int( bits[5] )
elif "Repetition Main 2 X Count" in bit:
mx2c = int( bits[5] )
elif "Repetition Main 2 Y Count" in bit:
my2c = int( bits[5] )
parse.m2c = my2c
elif "Repetition Main 2 Y LSW" in bit:
m2dy = int( bits[5] )
elif "Repetition Sub 1 X" in bit and not ("Count" in bits):
s1dx = int( bits[4] )
elif "Repetition Sub 1 X Count" in bit:
sx1c = int( bits[5] )
parse.s1c = sx1c
elif "Repetition Sub 1 Y Count" in bit:
sy1c = int( bits[5] )
elif "Repetition Sub 1 Y" in bit and not ("Count" in bits):
s1dy = int( bits[4] )
elif "Repetition Sub 1 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.s1c = int( bits[4] )
elif "Repetition Sub 2 X" in bit and not ("Count" in bits):
s2dx = int( bits[4] )
elif "Repetition Sub 2 X Count" in bit:
sx2c = int( bits[5] )
elif "Repetition Sub 2 Y" in bit and not ("Count" in bits):
s2dy = int( bits[4] )
elif "Repetition Sub 2 Y Count" in bit:
sy2c = int( bits[5] )
parse.s2c = sy2c
elif "Repetition Sub 2 Count" in bit and not ("Y" in bits) and not ("X" in bits) :
parse.s2c = int( bits[4] )
elif "Repetition" in bits:
print "\nUnknown repetition line: [%d]\n" % bit
# Are the following correct? It might be that some parameters need to be
# retained and used by implication in successive Activate lines.
if "Activate" in bits and "SRV1" in bits and not ("SRV2" in bits):
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
sx2c = 0
sy2c = 0
s2dx = 0
s2dy = 0
if "Activate" in bits and "SRV2" in bits and not ("SRV1" in bits):
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
sx1c = 0
sy1c = 0
s1dx = 0
s1dy = 0
if "Activate" in bits and "MRV1" in bits and not ("MRV2" in bits):
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
mx2c = 0
my2c = 0
m2dx = 0
m2dy = 0
if "Activate" in bits and "MRV2" in bits and not ("MRV1" in bits):
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
mx1c = 0
my1c = 0
m1dx = 0
m1dy = 0
if "Activate" in bits and "SRV1" in bits and "SRV2" in bits:
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
mx1c = 0
my1c = 0
mx2c = 0
my2c = 0
if "Activate" in bits and "MRV1" in bits and "MRV2" in bits:
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
sx1c = 0
sy1c = 0
sx2c = 0
sy2c = 0
if "Activate" in bits and "MRV1" in bits:
mx1c = parse.m1c
if "Activate" in bits and "MRV2" in bits:
my2c = parse.m2c
if "Activate" in bits and "SRV1" in bits:
sx1c = parse.s1c
if "Activate" in bits and "SRV2" in bits:
sy2c = parse.s2c
# RYH and RXB are used to chop shapes into subfield traps.
# The savings in space is negligible, but it might prevent
# blanking between shapes. Let's hope so; otherwise,
# it's just stupid.
# V1 is X only, V2 is Y only
if "RXB" in bits or "RYH" in bits:
s1dx = 0
s1dy = 0
s2dx = 0
s2dy = 0
m1dx = 0
m1dy = 0
m2dx = 0
m2dy = 0
if sub_resol <= 0 :
print "\nERROR: subfield resolution not defined.\m"
sys.exit()
h = int( height )
b = int( base )
m = int( msf )
if "RYH" in bits:
if "SRV1" in bits or "SRV2" in bits:
s2dy = (h + 1) * m
elif "MRV1" in bits or "MRV2" in bits:
m2dy = (h + 1) * m * main_resol/sub_resol
if "RXB" in bits:
if "SRV1" in bits or "SRV2" in bits:
s1dx = (b + 1) * m
elif "MRV1" in bits or "MRV2" in bits:
m1dx = (b + 1) * m * main_resol/sub_resol
return( (mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy ) )
#-----------------------------------------------------------------------------------------------
def expand_array( entry, n, table, chunk, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, \
m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy ):
# Loop over x and y repeats, generating new table entries
# Could there be both main and subfield repeats on the same line?
# That would be perverse, so let's just check for perversity first.
main_repeat = mx1c > 0 or mx2c > 0 or my1c > 0 or my2c > 0
sub_repeat = sx1c > 0 or sx2c > 0 or sy1c > 0 or sy2c > 0
if main_repeat and sub_repeat:
print "\nERROR: mainfield and subfield arrays appear sumultaneously. This freaks me out, man."
print "Try disabling all compaction modes in Beamer (or whatever you used to generate gpf)."
print "Be sure to disable Beamer's 'compaction diagonal array' option, which is evil."
print "Program aborted."
sys.exit()
if not main_repeat and not sub_repeat:
print "\nERROR: an array contains no repetition values\n"
sys.exit()
activate_line = entry[0]
main_x_lsw = entry[1]
main_y_lsw = entry[2]
freq_lsw = entry[3]
freq_msw = entry[4]
base_lsw = entry[5]
height_lsw = entry[6]
msf = entry[7]
shift_lt_lsw = entry[8]
shift_rb_lsw = entry[9]
offset_x_lsw = entry[10]
offset_y_lsw = entry[11]
shift_rb_used = entry[12]
shift_lt_used = entry[13]
table[n][0] = "deleted"
if main_repeat:
# strip out MRV1, MRV2, RXB, and RYH from acitivate line
# loop over mx1c and my2c. Watch for nonzero my1c and mx2c.
newline = ""
words = string.split( activate_line )
begin = False
for word in words:
if (word == "Activate"): begin = True
if begin and word <> "MRV1" and word <> "MRV2" and word <> "RXB" and word <> "RYH" :
newline = newline + " " + word
#print "[%s]" % newline
if my1c <> 0 or mx2c <> 0 :
print "\nERROR: strange array with my1c or mx2c not zero: [%s]." % activate_line
print "What does it mean?\n"
sys.exit()
mainx = int( main_x_lsw )
mainy = int( main_y_lsw )
for row in range( my2c+1 ):
y = mainy + m2dy * row
mainy_s = "%d" % y
for col in range( mx1c+1 ):
x = mainx + m1dx * col
mainx_s = "%d" % x
s = sorting_parameter( x, y, chunk )
table.append( [ newline, \
mainx_s, \
mainy_s, \
freq_lsw, \
freq_msw, \
base_lsw, \
height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
offset_x_lsw, \
offset_y_lsw, \
shift_rb_used, \
shift_lt_used, \
s ] )
else: # subfield repeat
# strip out SRV1, SRV2, RXB, and RYH from acitivate line
# loop over sx1c and sy2c. Watch for nonzero sy1c and sx2c.
newline = ""
words = string.split( activate_line )
begin = False
for word in words:
if (word == "Activate"): begin = True
if begin and word <> "SRV1" and word <> "SRV2" and word <> "RXB" and word <> "RYH" :
newline = newline + " " + word
#print "[%s]" % newline
if sy1c <> 0 or sx2c <> 0 :
print "\nERROR: strange array with sy1c or sx2c not zero: [%s]." % activate_line
print "What does it mean?\n"
sys.exit()
subx = int( offset_x_lsw )
suby = int( offset_y_lsw )
for row in range( sy2c+1 ):
y = suby + s2dy * row
suby_s = "%d" % y
for col in range( sx1c+1 ):
x = subx + s1dx * col
subx_s = "%d" % x
s = sorting_parameter( x, y, chunk )
table.append( [ newline, \
main_x_lsw, \
main_y_lsw, \
freq_lsw, \
freq_msw, \
base_lsw, \
height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
subx_s, \
suby_s, \
shift_rb_used, \
shift_lt_used, \
s ] )
return( table )
#-----------------------------------------------------------------------------------------------
def flatten( table, main_resol, sub_resol, chunk ):
# look for repetition lines, creating explicit shapes instead
mx1c = 0 # main x1 count
mx2c = 0 # main x2 count
my1c = 0
my2c = 0
sx1c = 0 # subfield x1 count
sx2c = 0 # subfield x2 count
sy1c = 0
sy2c = 0
m1dx = 0 # main 1 delta x, in mainfield resolution units
m1dy = 0
s1dx = 0 # subfield 1 delta x, in subfield resolution units
s1dy = 0
m2dx = 0
m2dy = 0
s2dx = 0
s2dy = 0
#print "mx1c mx2c my1c my2c sx1c sx2c sy1c sy2c m1dx m1dy m2dx m2dy s1dx s1dy s2dx s2dy"
n = 0
for entry in table:
base = entry[5]
height = entry[6]
line = entry[0]
msf = entry[7]
item = string.split( line )
if "SRV1" in item or "SRV2" in item or "MRV1" in item or "MRV2" in item :
part = string.split( line, "\n" )
for bit in part:
mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy = \
parse( bit, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, \
s2dx, s2dy, base, height, msf, main_resol, sub_resol )
#print "%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d " % \
#(mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy )
table = expand_array( entry, n, table, chunk, mx1c, mx2c, my1c, my2c, sx1c, sx2c, sy1c, sy2c, \
m1dx, m1dy, m2dx, m2dy, s1dx, s1dy, s2dx, s2dy )
n = n + 1
return( table )
#-----------------------------------------------------------------------------------------------
# MAIN
print
print "GTX sorting utility, version %d" % version
print
if len( sys.argv ) == 1 :
print "\nUse: radial_sort.py file.gpf"
print "\n The output file will be file_sorted.gpf\n\n"
sys.exit()
if len( sys.argv ) > 1 :
if sys.argv[1] == "-h" or sys.argv[1] == "-help" or sys.argv[1] == "--help" :
print "\nUse: radial_sort.py file.gpf"
print "\n The output file will be file_sorted.gpf\n\n"
sys.exit()
filein = sys.argv[1]
else:
print
print "Enter input gpf file name> ",
filein = sys.stdin.readline()
filein = filename[0:-1]
if not (".gpf" in filein) and not ("." in filein):
filein = filein + ".gpf"
name = string.split( filein, "." )
fileout = name[0] + "_sorted.gpf"
print
print "Input gpf file: ", filein
print "Output gpf file: ", fileout
print
print "\nConverting to gtx...\n"
os.system( "gpfgtx %s temp_in.gtx" % filein )
gtxin = open( "temp_in.gtx", "rb" )
gtxout = open( "temp_out.gtx", "w" )
print "\nCopying header... \n"
word = []
# copy header
line = gtxin.readline()
if not line:
print "\nERROR: unexpected end of file.\n\n"
sys.exit()
word = string.split( line )
if len( word ) == 0 :
word.append( "\n" )
bss = 0.0
mfr = 0.0
sfr = 0.0
while word[0] <> "END" :
gtxout.write( line )
line = gtxin.readline()
if not line:
print "\nERROR: unexpected end of file.\n\n"
sys.exit()
word = string.split( line )
if len( word ) == 0 :
word.append( "\n" )
if word[0] == "BeamStepSize" :
stuff = string.split( word[1], "," )
sub_resol = int( stuff[0] )
msf = sub_resol
bss = sub_resol
print " Beam step size (bits) : ", bss
elif word[0] == "Resolution":
stuff = string.split( word[1], "," )
main_resol = int( stuff[0] )
elif word[0] == "MainFieldResolution" :
stuff = string.split( word[1], "," )
mfr = float( stuff[0] )
print " Main field resolution (um) : ", mfr
elif word[0] == "SubFieldResolution" :
stuff = string.split( word[1], "," )
sfr = float( stuff[0] )
print " Subfield resolution (um) : ", sfr
if bss == 0.0 or mfr == 0.0 or sfr == 0.0 :
print "\nERROR: units not found in header.\n"
sys.exit()
gtxout.write( line ) # write "END" after header
bss_sub = msf
#print " Number of subfield bits in a beam step: %d\n" % bss_sub
chunk = CHUNK / mfr # usually, 1 um / 0.001 = 1000 bits
#print "chunk = ", chunk
print
print "Reading..."
print
end_of_file = False
while not end_of_file: # while not EOF, sort each field
new_field = True
main_x_lsw = 0
main_y_lsw = 0
base_lsw = "0"
height_lsw = "0"
shift_lt_lsw = "0"
shift_rb_lsw = "0"
offset_x_lsw = "0"
offset_y_lsw = "0"
msf = 0
freq_msw = "0"
freq_lsw = "0"
append_next_line = False
n = 0
end_of_field = False
nbad = 0
table = []
while True: # for each_line in gtxin.readlines() :
each_line = gtxin.readline()
if len( each_line ) == 0 :
end_of_file = True
break
if end_of_field : # or n > 1000000 :
break
if append_next_line: # True for repetition lines
line = line + "\n" + each_line[:-1]
append_next_line = False
else:
line = each_line[:-1]
word = string.split( each_line )
unknown = False
if len( word ) > 0:
if word[0] == "END":
end_of_field = True
elif word[0] == "Main":
if word[1] == "X":
main_x_lsw = int( word[3] )
else:
main_y_lsw = int( word[3] )
elif word[0] == "Frequency":
if word[1] == "LSW":
freq_lsw = word[2]
else:
freq_msw = word[2]
elif word[0] == "Base":
base_lsw = word[2]
elif word[0] == "Height":
height_lsw = word[2]
elif word[0] == "MSF":
msf = word[1] # subfield (e.g. 20 => 10nm)
elif word[0] == "Shift":
if word[1] == "LT":
shift_lt_lsw = word[3]
else:
shift_rb_lsw = word[3]
elif word[0] == "Offset":
if word[1] == "X":
offset_x_lsw = word[3]
else:
offset_y_lsw = word[3]
elif word[0] == "Repetition":
append_next_line = True # tricky!
elif word[0] == "Activate":
n = n + 1
attributes = string.split( line )
if "hb" in attributes : # careful! hb applies only to this item
this_height_lsw = base_lsw
else:
this_height_lsw = height_lsw
shift_rb_used = not ("rb45" in attributes or "rb90" in attributes)
shift_lt_used = not ("lt45" in attributes or "lt90" in attributes)
x = float( main_x_lsw ) - X0
y = float( main_y_lsw ) - Y0
# We want to sort by radius, sort of.
# Shapes are grouped into chunks (say, 1x1 um)
# and then sorted by the parameter "s",
# which is weighted so that radial movement will
# be slower than tangential.
s = sorting_parameter( x, y, chunk )
if False :
# if bad_shape( shift_rb_used, shift_lt_used, bss_sub, \
# base_lsw, this_height_lsw, shift_lt_lsw, shift_rb_lsw, line ) :
nbad = nbad + 1
#print "base: ", base_lsw
#print "height: ", this_height_lsw
#print "shift lt: ", shift_lt_lsw
#print "shift rb: ", shift_rb_lsw
#print line
else:
table.append( [ line, \
main_x_lsw, \
main_y_lsw, \
freq_lsw, \
freq_msw, \
base_lsw, \
this_height_lsw, \
msf, \
shift_lt_lsw, \
shift_rb_lsw, \
offset_x_lsw, \
offset_y_lsw, \
shift_rb_used, \
shift_lt_used, \
s ] )
else:
print line
print
gtxout.write( "%s\n" % line ) # this line is part of the field header... we hope!
sys.stdout.flush()
# end if word[0]
if (n > 0) and (n % 1000 == 0) :
print " shape %d \015" % n,
sys.stdout.flush()
# end if len( word ) > 0
# end while each_line
if end_of_file: break
print " shape %d " % n
print "\nFlattening...\n"
sys.stdout.flush()
table = flatten( table, main_resol, sub_resol, chunk )
print "\nSorting by angle and radius... ",
sys.stdout.flush()
table = sort_table( table, 14 )
print "Done.\n"
# print "\nNumber of bad shapes: %d\n" % nbad
#---------------------------------------------------------------
# Write the rest of the gtx file (the header was copied already)
num_shapes = len( table )
#print "\n\nNumber of shapes: %d\n" % num_shapes
if num_shapes < 1 :
print "\nERROR: there are no shapes in this gtx file.\n"
sys.exit()
print "Writing..."
activate_line = table[0][0]
prev_main_x_lsw = table[0][1]
prev_main_y_lsw = table[0][2]
prev_freq_lsw = table[0][3]
prev_freq_msw = table[0][4]
prev_base_lsw = table[0][5]
prev_height_lsw = table[0][6]
prev_msf = table[0][7]
prev_shift_lt_lsw = table[0][8]
prev_shift_rb_lsw = table[0][9]
prev_offset_x_lsw = table[0][10]
prev_offset_y_lsw = table[0][11]
shift_rb_used = table[0][12]
shift_lt_used = table[0][13]
if not ("deleted" in activate_line):
gtxout.write( " Frequency LSW %s\n" % prev_freq_lsw )
gtxout.write( " Frequency MSW %s\n" % prev_freq_msw )
gtxout.write( " MSF %s\n" % prev_msf )
gtxout.write( " Main X LSW %s\n" % prev_main_x_lsw )
gtxout.write( " Main Y LSW %s\n" % prev_main_y_lsw )
gtxout.write( " Offset X LSW %s\n" % prev_offset_x_lsw )
gtxout.write( " Offset Y LSW %s\n" % prev_offset_y_lsw )
gtxout.write( " Base LSW %s\n" % prev_base_lsw )
if not ("hb" in activate_line ) :
gtxout.write( " Height LSW %s\n" % prev_height_lsw )
if shift_lt_used:
gtxout.write( " Shift LT LSW %s\n" % prev_shift_lt_lsw )
if shift_rb_used:
gtxout.write( " Shift RB LSW %s\n" % prev_shift_rb_lsw )
gtxout.write( "%s\n" % activate_line )
new_field = False
elif new_field:
new_field = False
gtxout.write( " Frequency LSW %s\n" % prev_freq_lsw )
gtxout.write( " Frequency MSW %s\n" % prev_freq_msw )
gtxout.write( " MSF %s\n" % prev_msf )
gtxout.write( " Main X LSW %s\n" % prev_main_x_lsw )
gtxout.write( " Main Y LSW %s\n" % prev_main_y_lsw )
gtxout.write( " Offset X LSW %s\n" % prev_offset_x_lsw )
gtxout.write( " Offset Y LSW %s\n" % prev_offset_y_lsw )
gtxout.write( " Base LSW %s\n" % prev_base_lsw )
n = 0
if num_shapes > 1 :
for item in table[1:] :
if n % 1000 == 0 :
print " shape %d \015" % n,
sys.stdout.flush()
n = n + 1
activate_line = item[0]
main_x_lsw = item[1]
main_y_lsw = item[2]
freq_lsw = item[3]
freq_msw = item[4]
base_lsw = item[5]
height_lsw = item[6]
msf = item[7]
shift_lt_lsw = item[8]
shift_rb_lsw = item[9]
offset_x_lsw = item[10]
offset_y_lsw = item[11]
shift_rb_used = item[12]
shift_lt_used = item[13]
# Setting values by implication does not work reliably,
# so the output will be rather verbose. Oh well.
if not ("deleted" in activate_line) :
if True: # freq_lsw <> prev_freq_lsw :
gtxout.write( " Frequency LSW %s\n" % freq_lsw )
if True: # freq_msw <> prev_freq_msw :
gtxout.write( " Frequency MSW %s\n" % freq_msw )
if True: # msf <> prev_msf :
gtxout.write( " MSF %s\n" % msf )
if True: # main_x_lsw <> prev_main_x_lsw :
gtxout.write( " Main X LSW %s\n" % main_x_lsw )
if True: # main_y_lsw <> prev_main_y_lsw :
gtxout.write( " Main Y LSW %s\n" % main_y_lsw )
if True: # PROBLEM: offset_x_lsw <> prev_offset_x_lsw :
gtxout.write( " Offset X LSW %s\n" % offset_x_lsw )
if True: # offset_y_lsw <> prev_offset_y_lsw :
gtxout.write( " Offset Y LSW %s\n" % offset_y_lsw )
if True: # base_lsw <> prev_base_lsw :
gtxout.write( " Base LSW %s\n" % base_lsw )
if (not ("hb" in activate_line )): # PROBLEM: and (height_lsw <> prev_height_lsw) :
gtxout.write( " Height LSW %s\n" % height_lsw )
if shift_lt_used:
gtxout.write( " Shift LT LSW %s\n" % shift_lt_lsw )
if shift_rb_used:
gtxout.write( " Shift RB LSW %s\n" % shift_rb_lsw )
gtxout.write( "%s\n" % activate_line )
new_field = False
prev_main_x_lsw = item[1]
prev_main_y_lsw = item[2]
prev_freq_lsw = item[3]
prev_freq_msw = item[4]
prev_base_lsw = item[5]
prev_height_lsw = item[6]
prev_msf = item[7]
prev_shift_lt_lsw = item[8]
prev_shift_rb_lsw = item[9]
prev_offset_x_lsw = item[10]
prev_offset_y_lsw = item[11]
# end for item
# end if num_shapes > 1
if n > 0 : print " shape %d " % (n+1)
gtxout.write( "END\n" )
# end while not EOF
gtxin.close()
gtxout.close()
print "\nConverting back to gpf...\n"
os.system( "gtxgpf temp_out.gtx %s" % fileout )
print
print "\n\nDone.\n"
print
ebpg_funpak/align_window.sh 0000750 0000765 0000765 00000005121 12441200051 015424 0 ustar rooks rooks #!/bin/bash
# align_window.sh
# Assuming the stage is positioned near the center of a
# nitride window, move -SIZEX/2, 0 and then scan the
# left side of the window. Next move by SIZEX,0 and
# scan the right side. Same for top and bottom Calculate
# the center coordinate and then move there.
# Sides are scanned with a 128 um square raster,
# with accuracy 1000nm = 1um, which is good enough
# for lining up nitride windows.
# Edges are scanned with
#
# pg image grab offset step(nm) number filename
#
# Be sure to
#
# export PG_IMAGES=.
#
# so that the grabbed images end up in the current directory.
# You should put this command in /etc/bashrc or /home/pg/local_commands
#
#
# This script finishes by moving to the center of the window,
# which is appropriate as a drop-in mark alignment routine.
# To use this script for alignment, choose the JOY mark type,
# then at the top of the wrapper script or in .ini,
# include the line
#
# export PG_USER_JOYMARKER="/home/pg/user/whatever/align_window.sh"
mnemonics_error_handler ()
{
exit $1
}
trap 'error=$? ; mnemonics_error_handler $error' ERR
trap 'trap - ERR' EXIT
# size of the nitride window, in microns:
SIZEX=2080
SIZEY=2080
PLOT="plot"
#PLOT=""
# We assume that the user or the job has moved to the
# center of the window. Move first to the left side.
place=`pg get tab`
dx=`dc -e "6 k $SIZEX 2 / n"`
dy=`dc -e "6 k $SIZEY 2 / n"`
pg mov pos --rel -$dx,0
echo
echo "Scanning left side..."
semoff
pg image grab 0,0 1000,1000 128,128 marker
#Use: find_edge [vertical|horizontal] [bright-dark|dark-bright] imagefile.img xpixels ypixels nm/pixel [plot]
find_edge vertical bright-dark marker.img 128 128 1000 $PLOT
lx=`pg get tab_x | awk -F_ '$0=$1'`
echo "Scanning right side..."
pg mov pos $place
pg mov pos --rel $dx,0
pg image grab 0,0 1000,1000 128,128 marker
find_edge vertical dark-bright marker.img 128 128 1000 $PLOT
rx=`pg get tab_x | awk -F_ '$0=$1'`
echo "Scanning top side..."
pg mov pos $place
pg mov pos --rel 0,$dy
pg image grab 0,0 1000,1000 128,128 marker
find_edge horizontal bright-dark marker.img 128 128 1000 $PLOT
ty=`pg get tab_y | awk -F_ '$0=$1'`
echo "Scanning bottom side..."
pg mov pos $place
pg mov pos --rel 0,-$dy
pg image grab 0,0 1000,1000 128,128 marker
find_edge horizontal dark-bright marker.img 128 128 1000 $PLOT
by=`pg get tab_y | awk -F_ '$0=$1'`
# calculate the center point, in microns
cx=`dc -e "6 k $lx $rx + 2.0 / 1000.0 * n"`
cy=`dc -e "6 k $ty $by + 2.0 / 1000.0 * n"`
echo
echo "pg move pos $cx,$cy"
echo
pg move pos $cx,$cy
echo "alignment complete"
echo
ebpg_funpak/false_alarm.errors 0000644 0000765 0000765 00000000431 12441200052 016115 0 ustar rooks rooks # error codes that are false alarms, used by sys_monitor.
# update as needed; read in by a cat command so extra text
# in here is fine as long as the error codes are discrete words.
ENG_E_OPEABO Operator aborted command
ENG_E_STLOCKED Stage locked
ECC_E_NOMARK Mark not found
ebpg_funpak/textfx 0000644 0000765 0000765 00000000127 12441200052 013660 0 ustar rooks rooks n="\033[00m" #normal
b="\033[01m" #bold
u="\033[04m" #underline
r="\033[07m" #reversed
ebpg_funpak/gun_plotter 0000750 0000765 0000765 00000017161 12441200052 014704 0 ustar rooks rooks #!/usr/bin/python
: '
-------------------------------------------------------------------------------
Copyright (c) 2014 bryan cord, university of minnesota.
All rights reserved.
Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are
duplicated in all such forms and that any documentation,
advertising materials, and other materials related to such
distribution and use acknowledge that the software was developed
by UMN. The name of the University may not be used to endorse or promote
products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-------------------------------------------------------------------------------
'
# gun_plotter: Script to make plots of the various column parameters logged by sys_monitor script,
# mostly written so I'd have an excuse to learn something about how Pylab works.
# -BC 10/17/11
# modified 5/3/12 to plot logs that also have leakage current as the last column
# the log file we'll be reading out of. It's generated by the sys_monitor script
# (/home/pg/users/service/jobfiles/sys_monitor), which runs continuously.
LOG_FILENAME='/home/pg/log/ext_loop.log'
# The log file is assumed to have lines formatted like this:
# NUM DATE/TIME EHT FILCUR EXTVOL EXTCUR (LEAKAGE)
# NUM is just the measurement number and not really used. Legacy thing.
# Leakage/emission current is optional and I only started keeping track of it today (5/3/12)
# Two types of DATE/TIME format are allowed:
# Mon-DD_HH:MM:SS (e.g. Oct-17_13:18:21) (old format, from Ray's original script)
# YYYY-MM-DD_HH:MM:SS (e.g. 2011-10-17_13:18:21) (new format)
# all the other stuff in the log is the raw output of
# "pg get /measure", so it'll look like 185.134_uA, for example
# axis label dictionary, change to suit
labels = {
'extcur':'Extractor Current (uA)',
'extvol':'Extractor Voltage (kV)',
'eht':'EHT (kV)',
'htval':'EHT (kV)',
'filcur':'Filament Current (A)',
'leakage':'Emission Current (uA)',
'emc':'Emission Current (uA)',
'usage':'Usage'
}
# change abbreviated months into their correct numeric value
monthdict = {'Jan':1, 'Feb':2, 'Mar':3, 'Apr':4, 'May':5, 'Jun':6, 'Jul':7, 'Aug':8, 'Sep':9, 'Oct':10,
'Nov':11, 'Dec':12}
# some unit conversion dictionaries. Can you tell I just learned dictionaries?
kV_scale = {'kV':1, 'V':1e-3, 'mV':1e-6, 'uV':1e-9 }
uA_scale = {'mA':1e3, 'uA':1, 'nA':1e-3, 'pA':1e-6 }
A_scale = {'A':1, 'mA':1e-3, 'uA':1e-6, 'nA':1e-9, 'pA':1e-12 }
# axis limits for each parameter when plotting
limits={
'eht':[95,100],
'htval':[95,100],
'filcur':[2,2.5],
'extvol':[1,10],
'extcur':[0,300],
'leakage':[0,1],
'emc':[0,1],
'usage':[0,1.1]
}
def usage():
print
print "EBPG5000+ Column Log Viewer"
print
print "Usage: gun_plotter [parameter2]"
print "plottable parameters are usage, eht, filcur, extvol, leakage, or extcur (default)"
print
print "Edit LOG_FILENAME variable at the top of the script to point to log location."
sys.exit()
import sys
import datetime
try: import pylab
except ImportError:
print "ERROR: Pylab module not installed. Use \"yum install pylab\" to install"
sys.exit()
if len(sys.argv) < 2: usage()
# initialize the blank arrays
times=[]
eht=[]
filcur=[]
extvol=[]
extcur=[]
leakage=[]
usage=[]
# you can set the parameter to plot in the command line (default is
# extcur if no input or invalid input)
dict_in = {'extcur':extcur, 'extvol':extvol, 'eht':eht, 'filcur':filcur, 'htval':eht, 'leakage':leakage, 'emc':leakage, 'usage':usage}
if len(sys.argv) < 3:
try: plotparam1=dict_in.get(sys.argv[1],extcur)
except ValueError:
print "ERROR: parameter %s not valid" % (sys.argv[1])
usage()
doubleplot=False
else:
try: plotparam1=dict_in.get(sys.argv[1],extcur)
except ValueError:
print "ERROR: parameter %s not valid" % (sys.argv[1])
usage()
try: plotparam2=dict_in.get(sys.argv[2],extcur)
except ValueError:
print "ERROR: parameter %s not valid" % (sys.argv[1])
usage()
doubleplot=True
# step 1: parse the existing log file data
try: log_in=open(LOG_FILENAME,'r')
except IOError:
print "ERROR: Log file %s not found" % LOG_FILENAME
usage()
for currentLine in log_in.readlines():
splitLine=currentLine.split()
# skip non-data lines, like the header and any errors (modified for leakage current column)
if splitLine[0] == 'NR' or (len(splitLine) != 6 and len(splitLine) != 7 and len(splitLine) != 8): continue
hour=minute=second=day=month=year=0
datestring=splitLine[1]
# are we dealing with the old date format (Mon-DD_HH:MM:SS)
# or the new date format (YY-MM-DD_HH:MM:SS)?
if len(datestring.split('-')) > 2:
# new format, so that's easy
(year,month,day) = datestring.split('_')[0].split('-')
(hour,minute,second) = datestring.split('_')[1].split(':')
else:
# old format, so slightly more complicated
year=2011 # thankfully I changed date formats before 2012
(month,day) = datestring.split('_')[0].split('-')
# we need a dictionary to change months into numerics
month = monthdict.get(month)
day=int(day)
(hour,minute,second) = datestring.split('_')[1].split(':')
# create and append a datetime object to the times[] array
times.append(datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), int(second)))
# grab the other parameters, making sure to split off their units and scale them, if necessary.
eht_i = float(splitLine[2].split('_')[0])
eht.append(eht_i*float(kV_scale.get(splitLine[2].split('_')[1])))
filcur_i = float(splitLine[3].split('_')[0])
filcur.append(filcur_i*float(A_scale.get(splitLine[3].split('_')[1])))
extvol_i = float(splitLine[4].split('_')[0])
extvol.append(extvol_i*float(kV_scale.get(splitLine[4].split('_')[1])))
extcur_i = float(splitLine[5].split('_')[0])
extcur.append(extcur_i*float(uA_scale.get(splitLine[5].split('_')[1])))
# added this on because later logs include the leakage current. If we're parsing
# the part of the log where it doesn't exist, just fudge it as zero. Also get rid of
# the sign, if any, cause magnitude is all that matters really.
try:
leakage_i = float(splitLine[6].split('_')[0])
leakage.append(abs(leakage_i*float(uA_scale.get(splitLine[6].split('_')[1]))))
except IndexError:
leakage.append(0)
try:
usage.append(float(splitLine[7]))
except IndexError:
usage.append(0)
log_in.close()
start_date=times[0]
end_date=times[len(times)-1]
# this is where we do the plotting
from pylab import *
figure("EBPG5000+ Column Monitor Log Viewer") # first create a figure
# set the plot title and x-axis label
#title('EBPG5000+ Column Monitor Viewer')
xlabel('Time')
if doubleplot:
# if we're plotting two parameters, we have to create two y-axes
# and plot on each one
hold(True)
axis1=subplot(111) # y1 is a subplot taking up the whole area
pylab.plot_date(pylab.date2num(times),plotparam1,'ro',ms=3,lw=1,label=sys.argv[1])
pylab.ylim(limits.get(sys.argv[1],'extcur'))
axis2=twinx() # y2 is a clone of y1, but gets different limits in the next plot
pylab.plot_date(pylab.date2num(times),plotparam2,'gs',ms=3,lw=1,label=sys.argv[2])
pylab.ylim(limits.get(sys.argv[2],'extcur'))
# shove some labels on each axis (dictionary is up top)
axis1.set_ylabel(labels.get(sys.argv[1],'extcur'))
axis2.set_ylabel(labels.get(sys.argv[2],'extcur'))
else:
# for a single parameter plot things are way simpler
pylab.plot_date(pylab.date2num(times),plotparam1,'ro',ms=3,lw=1)
ylabel(labels.get(sys.argv[1],'extcur'))
pylab.ylim(limits.get(sys.argv[1],'extcur'))
show()
ebpg_funpak/current_v5.tar 0000664 0000765 0000765 00043740000 12635565353 015260 0 ustar rooks rooks current/ 0000755 0000765 0000765 00000000000 12635565250 011637 5 ustar rooks rooks current/c1c2cur.dat 0000664 0000765 0000765 00000000651 12635565233 013600 0 ustar rooks rooks C1 C2 CURRENT (300 um aperture)
24064 6848 9.9731_nA
24607 7443 15.3905_nA
18826 5016 1.1235_nA
19645 5143 1.4620_nA
24898 7871 20.2628_nA
25078 8198 24.5326_nA
20965 5406 1.9876_nA
25269 8604 30.2827_nA
21976 5688 3.0586_nA
16000 4705 519.2_pA
25667 9781 50.7128_nA
22993 6129 5.0527_nA
25807 10346 63.3028_nA
23658 6512 7.5797_nA
23754 6583 8.0657_nA
26049 11684 95.3525_nA
26072 11836 100.2120_nA
24000 6781 9.6837_nA
current/peek.sh 0000754 0000765 0000765 00000004106 12635565250 013122 0 ustar rooks rooks #!/bin/bash
#
# Collect c1, c2, current points for the set_current.py program.
# Load each 300um archive file in /home/pg/archive, measure the
# beam current, and spit out values of lens 1, lens 2 and current.
# Set_current.py interpolates these values. This script generates
# the file c1c2cur.dat, in /home/pg/bin. The program set_current.py
# reads this file and sorts it by current. You no longer need to
# edit c1c2cur.dat.
#
# M. Rooks, Yale University
#
mnemonics_error_handler ()
{
exit $1
}
trap 'error=$? ; mnemonics_error_handler $error' ERR
trap 'trap - ERR' EXIT
function peek {
echo
echo "------------------------------------------ Looking at $1 $i of $n"
echo
ans="c"
if [ ${ans:-"c"} == "q" ]; then gracefulexit ; fi
if [ ${ans:-"c"} != "s" ]
then
pg set apert $ap
pg archive restore beam $1
c1=`pg get cc1 --bin`
c2=`pg get cc2 --bin`
mvm
mcur
current=`pg get bcm`
echo "$c1 $c2 $current"
echo "$c1 $c2 $current" >> /home/pg/bin/c1c2cur.dat
fi
}
function gracefulexit {
pg set beampar 10s
popd > /dev/null
echo
echo "Well ok then."
echo
exit
}
echo
echo "Peek at archive files..."
echo
pushd . > /dev/null
cd /home/pg/archive
pg set beamapertinv 0
pg set beampar 0s
echo
echo
echo "====================================================================="
echo
echo "Switch to the 300 um aperture."
echo -n -e "Press Enter, \033[4mq\033[0muit, or \033[4ms\033[0mkip the 300 um archives. "
read ans
if [ ${ans:-"c"} == "q" ]; then gracefulexit ; fi
if [ ${ans:-"c"} != "s" ];
then
pg set apert 300
ap=300
# count the files
n=0
for f in *_300um_2.beam_100
do
n=$[$n+1]
done
# peek at the files
echo "C1 C2 CURRENT (300 um aperture)" > /home/pg/bin/c1c2cur.dat
i=0
for f in *_300um_2.beam_100
do
i=$[$i+1]
peek ${f%".beam_100"}
done
fi
pg set beampar 10s
pg set beamapertinv 1
popd > /dev/null
echo
echo "Done."
echo
current/numpy-1.6.2.tar.gz 0000644 0000765 0000765 00011771662 12441200053 014603 0 ustar rooks rooks ^`P numpy-1.6.2.tar [s8W`v.GffeIYcK^Q㶶\ IP˚neɤ*ݚ)@?bn8w_?;9?<6%-wk1T,W)XIgbvh6~d+G?ѱ?_}e]=[\uwWם{^w_qz| ǟBue"3bƁWH˃VONUrgdyY#<*MZIK:C![LbL:~\q [p{+4D?dZ
@4$EJ'G?W)^y8+"ipbEw8n7ދHpm;>YJ-:\>i^dھ+[I+^{C=ܩ\',2ȒsI*B_Pb
?ŋyts;mfn]}!Vt$D,\LE簣a"zz8s+dU>됞b'If(r8g,!'0*4,#,G)!ss^3aM*9)Sr4՚5N-Gѿ^_EOYi/B/:Me*^/vT4`a.m!s/4r0҈
j\%{֗J4S8@Iݸߔ-% TsWkxQ<3ʈu*ɹDٿ{-Q"rF+ԻH4!lV
g^щd3oALT?aX%ȩQ}{9Es-cƠtS^lϯiyr1.)k
qgh
J3X+3;m8Rt'~mE'ʒ9E5oK!:*cg&