;trace 3-D file access widgets
 ;========================================================
subr auto_sizer_cb
 ;for changing the auto size flag
 if $radio_state then $auto_size_flag = 1 else $auto_size_flag = 0
 endsubr
 ;======================================================== 
func textplusupdown(parent, textw, text_cb, up_cb, dn_cb)
 ;makes a text widget with up and down arrows to the right, return value
 ;of form container. The argument textw is also returned. up_cb and dn_cb
 ;are the call back routines to be used for the arrows
 r1 = xmform(parent, 0, 0, 0, 0)
 bq = xmboard(r1, 0, 0)
 textw = xmtextfield(r1, '', 256, text_cb, $f3, 'white')
 xmposition, xmarrow(bq, 3, dn_cb), 0, 20, 19, 19
 xmposition, xmarrow(bq, 2, up_cb), 0, 0, 19, 19
 xmattach, textw, 0, 1, 0, 0, 0
 xmattach, textw, bq, 0, 1, -1, -1
 xmattach, bq, 0, 0, 1, 0, 0

 return, r1
 endfunc
 ;======================================================== 
func buttonplusupdown(parent, label, main_cb, up_cb, dn_cb)
 ;returns an array of widgets, 0 is a form container, 1 is main button,
 ;2 is up, and 3 is down
 warr = intarr(4)
 ff = xmform(parent)
 f2 = xmform(ff)
 b1 = xmbutton(f2, label, main_cb, $f4, 'grey')
 xmsize, b1, 80, 40
 bdn = xmarrow(f2, 3, dn_cb, 'grey')
 bup = xmarrow(ff, 2, up_cb, 'grey')
 xmsize, bdn, 80, 30
 xmsize, bup, 80, 30
 warr(0) = ff	warr(1) = b1	warr(2) = bup	warr(3) = bdn
 xmattach, b1,  0, 1, 1, 1, 0
 xmattach, bdn, b1, -1, -1, 1, 0
 xmattach, f2, 0, 1, 0, 0, 1
 xmattach, bup, 0, 1, 1, 1, 0
 xmattach, bup, f2, -1, -1, 0, 1
 return, warr
 endfunc
 ;========================================================= 
subr t3d_cruise_delay_cb
 $t3d_cruise_delay = float(xmtextfieldgetstring($t3d_cruise_delaytx)
 endsubr
 ;========================================================= 
subr t3d_filepath_cb
 ;load with the primary path
 ptrace = getenv('ANA_TRACE_HOURLY')
 if ptrace eq '' then ptrace = '/hosts/vestige/archive/sci/trace/tri/'
 ;remove a week part if still present
 iq = strpos(ptrace,'week')
 if iq gt 0 then ptrace = ptrace(0:(iq-1))
 xmtextfieldsetstring,$t3dtext1, ptrace
 $primary = 1
 ;;base_path = ptrace
 endsubr
 ;======================================================== 
subr t3d_filepath2_cb
 ;load with the secondary path
 ptrace = getenv('ANA_TRACE_HOURLY_SEC')
 if ptrace eq '' then ptrace = '/hosts/vestige/spare/trace/'
 ;remove a week part if still present
 iq = strpos(ptrace,'week')
 if iq gt 0 then ptrace = ptrace(0:(iq-1))
 xmtextfieldsetstring,$t3dtext1, ptrace
 $primary = 0
 ;;base_path = ptrace
 endsubr
 ;======================================================= 
subr t3d_cruise_delaydn
 $t3d_cruise_delay -= .5
 if abs($t3d_cruise_delay) lt 0.0001 then $t3d_cruise_delay = 0.0
 xmtextfieldsetstring, $t3d_cruise_delaytx, string($t3d_cruise_delay)
 endsubr
 ;======================================================= 
subr t3d_cruise_delayup
 $t3d_cruise_delay += .5
 if abs($t3d_cruise_delay) lt 0.0001 then $t3d_cruise_delay = 0.0
 xmtextfieldsetstring, $t3d_cruise_delaytx, string($t3d_cruise_delay)
 endsubr
 ;======================================================= 
subr t3d_cruise_cb
 ;check the range, etc
 istart = fix(xmtextfieldgetstring($t3d_range_textarr(1))
 iend = fix(xmtextfieldgetstring($t3d_range_textarr(2))
 inc = fix(xmtextfieldgetstring($t3d_range_textarr(3))
 istart = istart>0	inc = inc>1	iend = iend<($t3d_nimages-1)
 $t3d_cruise_stop = 0
 change_button_label, $t3d_cruise,'STOP','red'
 xtloop, 2
 ;$t3d_view_flag determines the functions done
 for i = istart, iend, inc do {
 xmtextfieldsetstring, $t3d_image, string(i)
 if $t3d_view_flag eq 0 or $t3d_view_flag eq 2 then t3d_inspect, i
 xtloop, 2	 if $t3d_cruise_stop then break
 if $t3d_view_flag gt 0 then t3d_view, i
 xtloop, 2	 if $t3d_cruise_stop then break
 wait, $t3d_cruise_delay
 }
 change_button_label, $t3d_cruise,'cruise','grey'
 $t3d_cruise_stop = 1
 xtloop, 2
 endsubr
 ;======================================================= 
subr t3d_list_entry_cb
 ;list entry callback
 iq = $list_item_position - 1
 ;alas, in case the file got changed
 if $t3d_file_name ne $t3d_list_file_name then {
   ;break into path and name and load the text widgets
   ;xmtextfieldsetstring, $t3dtext1, getfilepath($t3d_list_file_name)
   ;xmtextfieldsetstring, $t3dtext2, removepath($t3d_list_file_name)
   $t3d_file_name = $t3d_list_file_name
   if t3d_open_file() ne 1 then errormess,'problem opening file'
   }
 xmtextfieldsetstring, $t3d_image, string(iq)
 if $t3d_view_flag eq 0 or $t3d_view_flag eq 2 then t3d_inspect, iq
 if $t3d_view_flag gt 0 then t3d_view, iq
 ;also keep the position and file for possible logging
 ;actually already have the file name in $t3d_list_file_name
 $t3d_list_file_image = iq
 endsubr
 ;======================================================= 
subr t3d_filelist_entry_cb
 ;file list entry callback
 iq = $list_item_position - 1
 ;xmtextfieldsetstring, $t3dtext2, $list_item
 $t3d_file_name = $t3d_week_name +'/' + $list_item
 if t3d_open_file() ne 1 then { errormess,'problem opening file' return }
 ;if OK, effectively push the "list images" button
 t3d_list_cb
 endsubr
 ;======================================================= 
subr t3d_pathlist_entry_cb
 ;path list entry callback
 ;iq = $list_item_position - 1
 path = xmtextfieldgetstring($t3dtext1)
 ;also effectively push the "hourly list" button
 $t3d_week_name = path+$list_item
 t3d_filelist_cb
 endsubr
 ;======================================================= 
subr t3d_filelist_cb
 ;make a list widget with all the hourly files for the week listed
 sf = getfiles($t3d_week_name, 2000)
 sf = sort(sf)
 nf = num_elem(sf)
 if (nf le 0) { errormess,'no files found in path\n'+$t3d_week_name  return }
 ;create widget if it doesn't exist yet
 if defined($t3filelistwidget) ne 1 then {
    compile_file, getenv('ANA_WLIB') + '/t3filelistwidgettool.ana'
 }
 ;loop over all files and put in list
 xtpopdown, $t3filelistwidget
 ;delete the old stuff (if any)
 xmlistdeleteall, $t3filelist
 for i= 0, nf-1 do {
 xmlistadditem, $t3filelist, removepath(sf(i))
 }
 xtpopup, $t3filelistwidget
 endsubr
 ;======================================================= 
func t3d_get_base_path(dummy)
 path = xmtextfieldgetstring($t3dtext1)
 ;while path(num_elem(path)-1) eq '/' path = path(0:(num_elem(path)-2))
 ;append a / if not one there
 if path(num_elem(path)-1) ne '/' then path = path + '/'
 ;path = getfilepath(path)
 return, path
 endfunc
 ;======================================================= 
subr doytodom(iyr, doy, imy, idm)
 ;converts day of year to month and day of month
 m=[31,28,31,30,31,30,31,31,30,31,30,31]
 if (iyr%4) eq 0 then m(1)=29
 ndt=0
 for i=0,11 do { ndt=ndt+m(i)    if ndt ge doy then break}
 imy=i+1          idm=doy-ndt+m(i)
 endsubr
 ;======================================================= 
func open_tri_file(fname)
 ;another way to open an hourly file, search all the paths and keep the last
 ;success
 ;first try with the last successful directory
 if defined($t3d_file_name) then {
 path = getfilepath($t3d_file_name)
 f_sans_path = removepath(fname)
 $t3d_file_name = path + f_sans_path
 if t3d_open_file() eq 1 then return, 1
 ;if that failed, a thorough search
 ;7/16/99 - make this less thorough since it is now taking a long time with
 ;years of data online. Check if we seem to be using weekly directories and
 ;try the appropiate one if we are
 iq = strpos(path, 'week')
 if iq ge 0 then {
  ;guess we are, proceed
  if iq gt 0 then path2 = path(0:(iq-1)) else path2 = ''
  ;now isolate the month/day part of the hourly
  s = strskp(f_sans_path,'tri')
  ty,'s =', s
  ;dump the hour part
  iq = strpos(s,'.')
  if iq eq 8 then {
   ;fussy here, it must be an 8 character field
   year = fix(s(0:3))
   ty,'year =', year
   dayofyear = doy(year, fix(s(4:5)), fix(s(6:7)))
   ;the weekly name should start with the previous Sunday (or the first
   ;day of the year) but we'll be slightly more general here and check for
   ;up to 7 potential weekly names. We still assume that there is a weekly at
   ;the start of the year however so this generality is mostly laziness.
   wq = 'week'+s(0:3)	;first part of weekly name
   ;try up to 7
   for jj = 0, 6 do {
    dq = dayofyear - jj
    if dq ge 1 then {
     doytodom, year, dq, im, idm
     save = $t3d_file_name
     $t3d_file_name = path2 + wq + sprintf('%02d%02d/', im, idm) + f_sans_path
     ;avoid mucking up $t3d_file_name if this is a bad name
     if t3d_open_file() eq 1 then return, 1 else $t3d_file_name = save
     }
    }
   ;OK, if we got here we didn't find it and we want to avoid the more
   ;thorough (time consuming) search - so give up!
   ty,'problem finding file: ', $t3d_file_name
   return, 0
   }
  
  }
 }
 ;if all that failed or $t3d_file_name was not defined, a thorough search
 base_path = t3d_get_base_path()
 fn = findfile(base_path, fname)
 if isscalar(fn) then {
 ty,'problem finding file in thorough search: '+fname
 return, 0 }

 ;found it
 $t3d_file_name = fn
 ty,'file name in open_tri_file:', fn
 if t3d_open_file() ne 1 then {
 	ty,'problem opening file: '+fname
	return, 0 }
 return, 1
 endfunc
 ;======================================================= 
subr t3d_popweeks_cb
 ;just pop up the weekly list which should exist
 if defined($t3pathlistwidget) ne 1 then {
 errormess,'no weekly list widget\nhow could this happen?'
 return
 }
 xtpopup, $t3pathlistwidget
 endsubr
 ;======================================================= 
subr t3d_pathlist_cb
 ;make a list widget with all the weekly paths listed
 ;get the path with the last subdirectory
 path = t3d_get_base_path()
 sf = getdirects(path, 2000)
 if isstrarr(sf) eq 0 then {
  ;try again (network hangup?) and then complain
  sf = getdirects(path, 2000)
  if isstrarr(sf) eq 0 then {
   errormess,'could not read\n'+path+'\nnetwork problem\nor path error?\n'
   return }}
 ;if this is the secondary, take out directories not named week... and
 ;those without any files
 if $primary eq 0 then {
  nf = num_elem(sf)
  for i=0,nf-1 do {
   if strpos(sf(i),'week') eq 0 then {
   sq = path + '/' + sf(i)
   sq = getfiles(sq,1000)
   if isstrarr(sq) eq 0  then sf(i) = ''
   } else sf(i) = ''
  }
 }
 sf = sort(sf)
 nf = num_elem(sf)
 if (nf le 0) { errormess,'no files found in path\n'+path  return }
 if defined($t3pathlistwidget) ne 1 then {
  $t3pathlistwidget = xmtoplevel_form(0,0, 'TRACE paths for '+path,0,0,5, 5)
  wq = topbuttonsetupsanslink_tl('$t3pathlist')

  sq = 't3d_pathlist_entry_cb'
  list = xmlist($t3pathlistwidget, sq, 10, $f8, 'white', 1)
  xmposition, xtparent(list), 0, 0, 150, 100
  sep = xmseparator($t3pathlistwidget, 0, 10, 0)
  xmposition, sep, 0, 0, 10, 10
  formvstack, wq, sep, xtparent(list)
  xmattach, xtparent(list), 0, 1,1,0,1
  $t3pathlistwidget = list	;use for global
  add_to_hideables, $t3pathlistwidget
 }
 ;delete the old stuff (if any)
 xmlistdeleteall, list
 ;loop over all files and put in list, if string isn't NULL
 xtpopdown, $t3pathlistwidget
 for i= 0, nf-1 do {
 if num_elem(sf(i)) gt 0 then xmlistadditem, list, sf(i)
 }
 ;;base_path = path	;added 7/6/98
 xtpopup, $t3pathlistwidget
 ;position to bottom and select last entry if primary source
 if $primary then { 
   xmlistselect,$t3pathlistwidget,nf,1
   xmlistselect,$t3pathlistwidget,(nf-5)>1,0
   }
 endsubr
 ;======================================================= 
subr mylist_save_cb
 name = xmtextfieldgetstring($mylistsavefile)
 s = xmtextgetstring($mylist_text)
 lun = get_lun()
 if lun lt 0 then { errormess,'no available LUN for file write!' return }
 stat = openw(lun, name)
 if stat ne 1 then {
 	errormess,'can''t write to file: ',name,'\ncheck name and permissions\n'
 	close, lun
	return }
 printf,lun,s
 close,lun
 endsubr
 ;======================================================= 
subr mylist_load_cb
 name = xmtextfieldgetstring($mylistsavefile)
 lun = get_lun_and_openr(name)
 if lun lt 0 then return, 0 
 s =''
 while ( readf(lun,s) ) {
 xmtextappend, $mylist_text, s, 1
 }
 close, lun
 endsubr
 ;======================================================= 
subr mylist_widget
 ;create a text widget for keeping names of favorite images
 if defined($mylistwidget) eq 0 then {
 $mylistwidget = xmtoplevel_form(0, 0, 'some favorite images',0,0,10,10)
 wq = topbuttonsetupsanslink_tl('$mylist')
 bh = 20        bw = 160        ;size of buttons
 s1 = 'save to file (below)'
 xmposition,xmbutton(wq, s1,'mylist_save_cb',$f4,'gray'), 150, 0, bw, bh
 s1 = 'load from file (below)'
 xmposition,xmbutton(wq, s1,'mylist_load_cb',$f4,'gray'), 320, 0, bw, bh

 ;a text field for the saved file name
 $mylistsavefile = xmtextfield(wq,'',256,'',$f3,'white')
 xmposition, $mylistsavefile, 150, 25, 330, 35
 xmtextfieldsetstring, $mylistsavefile, 'junk'

 $mylist_text = xmtext($mylistwidget, 20,80,$f3,'white')
 xmsize, $mylist_text, 450, 100
 tq = xtparent($mylist_text)
 xmattach, wq, 0, 1, 1, 1, 0
 xmattach, tq, wq, 0, 0, 1, 0
 xmattach, tq,0,1,1,0,1
 }
 xtpopup, $mylistwidget
 endsubr
 ;======================================================= 
subr mylist_cb, mode
 ;mode is used to distinguish between the several callers
 ;;ty, 'in mylist_cb', mode
 ncase mode
  { s = $t3d_list_file_name   iq = $t3d_list_file_image }
  { s = $t3d_select_file_name   iq = $t3d_select_file_image }
 endcase
 sq = sprintf('%s %d\n', s, iq)
 mylist_widget
 xmtextappend, $mylist_text, sq
 endsubr
 ;======================================================= 
func tai_from_list_file(dum)
 ;figure out the time for the list file name, return -1 if error
 name = removepath($t3d_list_file_name)
 ty,num_elem(name)
 ;just to be sure
 name = strloc(name, 'tri')
 name = strtrim(name)
 if num_elem(name) ne 16 then return, -1
 name = name(3:*)
 y1 = fix(name(0:3)
 mon1 = fix(name(4:5)
 dom1 = fix(name(6:7)
 d1 = doy(y1,mon1,dom1)
 ;;ty,'y1,mon1,dom1, d1 =', y1,mon1,dom1, d1
 h1 = fix(name(9:10)
 t1 = tai_from_date(y1, d1, h1, 0, 0)
 return, t1
 endfunc
 ;======================================================= 
subr t3dlistnext_cb, direction
 ;called from t3d_list_cb, finds the next or previous available hourly file
 tt = tai_from_list_file()
 if tt lt 0 then { errormess,'problem with current\ntrace hourly file\nname, this should not happen'  return }
 ntries = 3
 while (ntries) {
 tt= tt + direction*3600.
 fname = tri_name_from_tai(tt)
 if open_tri_file(fname) eq 1 then break
 ntries -= 1
 }
 ;did we succeed?
 if ntries then {
  t3d_list_cb	;yes, call the loader
 } else {
  errormess,'could not find\nthe next hourly file\nplease check manually'
 }
 endsubr
 ;======================================================= 
subr t3d_list_cb
 ;make a list widget with all the images listed
 ;could be lots
 if defined($t3listwidget) ne 1 then {
 $t3listwidget = xmtoplevel_form(0,0, 'TRACE Image List',0,0,5, 5)
 wq = topbuttonsetupsanslink_tl('$t3list')
 bb = xmbutton(wq,'put in list','mylist_cb,0',$f4,'gray') 
 xmposition, bb, 140, 0, 90, 30
 $t3listnext = xmbutton(wq, 'next', 't3dlistnext_cb, 1',$f4,  'gray')
 $t3listprev = xmbutton(wq, 'prev', 't3dlistnext_cb, -1',$f4, 'gray')
 ;;$t3listnext = xmarrow(wq, 2, 't3dlistnext_cb, 1',  'grey')
 ;;$t3listprev = xmarrow(wq, 3, 't3dlistnext_cb, -1', 'grey')
 xmposition, $t3listnext, 235, 0, 40, 30
 xmposition, $t3listprev, 278, 0, 40, 30
 lab1 = xmlabel(wq,'file: ',$f4,'', 1)
 xmposition, lab1, 325, 5
 sq = 't3d_list_entry_cb'
 list = xmlist($t3listwidget, sq, 40, $f8, 'white', 1)
 lparent = xtparent(list)
 shellw = xtparent(lparent)
 xmposition, lparent, 0, 0, 500, 300
 sep = xmseparator($t3listwidget, 0, 10, 0)
 xmposition, sep, 0, 0, 10, 10
 formvstack, wq, sep, lparent
 xmattach, xtparent(list), 0, 1,1,0,1
 $t3listwidget = list	;make the list widget the global
 add_to_hideables, $t3listwidget
 }
 ;some of the operations below can change the size, so save it here and then
 ;re-apply it
 xmgetwidgetsize, shellw, dx, dy
 ;also the position
 xmgetwidgetposition, shellw, xp, yp
 ;ty,'positions =', xp, yp
 ;delete the old stuff (if any)
 xmlistdeleteall, list
 if $t3d_file_open_flag ne 1 then {
  ;try to read the current name and open the file
  if t3d_open_file() eq 0 then { errormess,'no valid file to view' return }
 }
 ;save the file name in case we have a selection and the name got changed in
 ;the meantime
 $t3d_list_file_name = $t3d_file_name
 ;loop over all images and put in list
 t1 = !systime
 xmsetlabel, lab1, 'file: ' + removepath($t3d_file_name)
 ;pop down so that filling list takes less time
 xtpopdown, $t3listwidget
 for i= 0, $t3d_nimages-1 do {
 sq = ist(i,3)+' '+trace_oneliner(wmap($t3d_dp_header(*,i)))
 xmlistadditem, list, sq
 }
 t2 = !systime
 ty,'time to load list =', t2 - t1
 xmposition, shellw, xp, yp, dx, dy
 xtpopup, $t3listwidget
 xmgetwidgetposition, shellw, xp, yp
 endsubr
 ;======================================================= 
subr t3d_imagedn_cb
 $t3d_image_number = fix(xmtextfieldgetstring($t3d_image)) - 1
 if $t3d_image_number lt 0 then $t3d_image_number = 0
 xmtextfieldsetstring, $t3d_image, string($t3d_image_number)
 endsubr
 ;======================================================= 
subr t3d_auto_cb
 ty,'called t3d_auto_cb'
 ;only react if state is set on
 if $radio_state then {
 $t3d_view_flag = $radio_button }
 endsubr
 ;======================================================= 
subr t3d_imageup_cb
 $t3d_image_number = fix(xmtextfieldgetstring($t3d_image)) + 1
 if $t3d_image_number ge $t3d_nimages then $t3d_image_number = $t3d_nimages - 1
 xmtextfieldsetstring, $t3d_image, string($t3d_image_number)
 endsubr
 ;======================================================= 
func t3d_open_file(iq)
 ;open the file, name and path in the appropiate text fields
 ;assumes it really is a 3-D trace file or pops an error
 ;4/22/99 - modified to use new fits routines, probably not the final
 ;or best yet

 fname = $t3d_file_name
 fsize = filesize(fname)
 if fsize le 0 then return, 0
 ;;iq = fits_header(x2, fname, h, h2, xoff, '$T3D_')
 iq = fits_header(fname, h, h2, '$T3D_')
 if iq eq 0 then {
	errormess, 'TRACE 3-D file\nis not readable'
	return, 0 }
 if isscalar(h2) then {
	errormess, 'not really a\nTRACE 3-D file\ntry again'
	return, 0 }
 ;check if are already set up
 if defined($t3d_file_open_flag) eq 0 then {
 t3d_widget
 }
 if $t3d_file_open_flag then close, $trace_lun
 $trace_lun = get_lun()
 ;open the file for later reading of individual images, we should already
 ;have the various extension arrays; if not, then bad things will happen
 openr, $trace_lun, fname
 ;;get_trace_header, x2, h2, dp_head, starts, nbytes, xdim, ydim
 $t3d_file_open_flag = 1
 $little_endian = not(bigendian())
 ;;switch, dp_head, $t3d_dp_header
 ;;switch, starts, $t3d_start_byte
 ;;switch, nbytes, $t3d_n_bytes
 ;;switch, xdim, $t3d_nx_out
 ;;switch, ydim, $t3d_ny_out
 ;examine the types, looking for # of compressed vs uncompressed
 trace_type = $t3d_dp_header(2,*)
 ;the following is dumb, it undoes the swab done by the fits reader, the decoding
 ;further on assumes in natural byte order and should be changed eventually
 if $little_endian then swab, $t3d_dp_header
 $t3d_nimages = dimen($t3d_dp_header, 1)
 xmtextfieldsetstring, $t3d_range_textarr(1), '0'
 xmtextfieldsetstring, $t3d_range_textarr(2), string($t3d_nimages-1)
 ncomp = sieve(trace_type eq 1)
 if isarray(ncomp) then ncomp = num_elem(ncomp) else ncomp = 0
 sq=sprintf('file: %d bytes, %d images, %d compressed',fsize,$t3d_nimages,ncomp)
 xmsetlabel, $t3d_lab1, sq
 xmtextfieldsetstring, $t3d_image, '0'
 return, 1
 endfunc
 ;======================================================= 
subr t3d_pathdn_cb
 ty,'nothing happens'
 endsubr
 ;======================================================= 
subr t3d_pathup_cb
 ty,'nothing happens'
 endsubr
 ;======================================================= 
subr t3d_open_cb
 ;call back for the open button
 if t3d_open_file() ne 1 then errormess,'problem opening file'
 endsubr
 ;======================================================= 
subr t3d_close_cb
 ;this is obsolete ?
 ;call back for the close button
 if $t3d_file_open_flag then close, $trace_lun
 endsubr
 ;======================================================= 
subr t3d_route_changer
 ;read all of them for any CR
 n=num_elem($t3droutest1)-1
 for i=1,n do { $t3d_route_win(i-1) = fix(xmtextgetstring($t3droutest1(i)) }
 ty,'results:', $t3d_route_win
 endsubr
 ;======================================================= 
subr t3d_route_cb
 $t3d_routing_flag = $radio_state 
 endsubr
 ;======================================================= 
subr t3d_adjustroute_cb
 if defined($t3droutewidget) eq 0 then {
  ;the compile_file is supposed to operate at top level and hence the edb's
 ;are temporary and don't add to our accumulation
 compile_file, getenv('ANA_WLIB') + '/t3droutewidget.ana'
 }
 xtpopup, $t3droutewidget
 endsubr
 ;====================================================== 
subr t3d_view(i)
 ;the view routine, check if a file open and get current image #
 if $t3d_file_open_flag ne 1 then {
  ;try to read the current name and open the file
  if t3d_open_file() eq 0 then {
  	errormess,'no valid file to view'
	return
  }
 }
 x = get_trace_image(i)
 if isarray(x) eq 0 then {
   sq = sprintf('bad TRACE image\ncan''t decode\nimage %d in\n%s',i, $t3d_file_name)
   errormess,sq  return }
 ;for raw trace images, we orient them so that they have the normal solar
 ;directions, this depends on the amplifier
 xx = wmap($t3d_dp_header(*,i))
 if extract_bits(xx(102),12,1) eq 1 then {
  ;amp B case
  ;x = x(>1,>0)
  x = reorder(x,4)
 } else {
  ;amp A case
  ;x = reverse(x(>1,>0))		;should use a faster reorder
  x = reorder(x, 7)			;and we do but keep above for reference
 }
 
 nx = dimen(x, 0)		ny = dimen(x, 1)
 ;ty,' ready for view'
 ;which window ?
 labelq = trace_view_info(xx)	;getting the label also sets $trace_wave, etc
 if $t3d_routing_flag then {
  ;first by wavelength
  win = $t3d_route_win($t3d_routes($trace_wave))
  ;also check for little guys, they go into another place
  if $trace_nx le 256 and $trace_ny le 256 then win = $t3d_route_win(9)
 } else win = $current_window
 switch,x,eval('$data'+string(win))
 ;set some other window attached parameters
 $view_sun_pixel_scale(win) = $trace_pixel_size
 $view_sun_xc(win) = $trace_xc
 $view_sun_yc(win) = $trace_yc
 $view_tai(win) = $trace_tai
 ;11/23/98 - some selection parameters
 $view_data_type(win) = 1
 x = zero(fltarr(2))
 x(0) = $trace_et
 switch, x, eval('$view_trace_info_flt_'+string(win))
 x = zero(intarr(8))
 x(0) = $trace_nx  x(1) = $trace_ny  x(2) = $trace_wave
 x(3) = $trace_bm  x(4) = $trace_sai
 x(5) = $trace_ccdxbase  x(6) = $trace_ccdybase
 x(7) = $trace_sum
 switch, x, eval('$view_trace_info_int_'+string(win))
 
 x = 0

 ;do we want a despike ?
 if $viewdespikeflag(win) then viewdespike, win
 ;reduce emi ? this has the image already re-ordered
 if $viewemiflag(win) then viewemi, win

 if $view_scaletype(win) eq 5 then $view_scaletype(win) = 2
 view, win
 if $auto_size_flag then {
 ;try setting the zoom button according to nx size
 for zw=0,7 do xmtogglesetstate, $view_zoom_widgets(zw, win), 0, 0
 nxw = nx		nyw = ny	zmnew = 1   zw = 2
 if nx gt 768 then { zmnew = -2  nxw = nx/2  nyw = ny/2 }
 if nx lt 256 then { zmnew = 2	 nxw = nx*2  nyw = ny*2 }
 $view_zoom_fac(win) = zmnew
 if zmnew eq -2 then zw = 1 else if zmnew eq 2 then zw = 3
 xmtogglesetstate, $view_zoom_widgets(zw, win), 1, 0
 ;make the size about right and expose it, this makes the size fit
 xmsize, $view_draw(win), nxw, nyw
 xtloop,2
 view_expose_cb, win
 xtloop,2
 xmtogglesetstate, $view_zoom_widgets(zw, win), 1, 1
 }
 ;also put some basic info in the view next to the zoom buttons
 xmtextsetstring, $view_text_widget(win), labelq
 $view_text(win) = labelq
 endsubr
 ;======================================================= 
subr t3d_view_cb
 ;get the current count and call t3d_view
 $t3d_image_number = fix(xmtextfieldgetstring($t3d_image))
 i = $t3d_image_number
 t3d_view, i
 endsubr
 ;======================================================= 
subr t3d_viewup_cb
 ;get the current count, bump it up, call t3d_view
 $t3d_image_number = fix(xmtextfieldgetstring($t3d_image)) + 1
 if $t3d_image_number ge $t3d_nimages then $t3d_image_number = $t3d_nimages - 1
 xmtextfieldsetstring, $t3d_image, string($t3d_image_number)
 i = $t3d_image_number
 t3d_view, i
 endsubr
 ;======================================================= 
subr t3d_viewdn_cb
 ;get the current count, bump it down, call t3d_view
 $t3d_image_number = fix(xmtextfieldgetstring($t3d_image)) - 1
 if $t3d_image_number lt 0 then $t3d_image_number = 0
 xmtextfieldsetstring, $t3d_image, string($t3d_image_number)
 i = $t3d_image_number
 t3d_view, i
 endsubr
 ;======================================================= 
subr t3dinspec_erase_cb
 ;just erase it all
 xmtexterase, $t3dinspec_t2
 $t3d_nheaders = 0
 endsubr
 ;======================================================= 
subr t3dexamine_cb
 ;do something with the selection, depends on what it might be
 ty,'selection is: ', xmtextgetselection($t3dinspec_t2, i1,i2)
 ty,'at: ', i1, i2
 endsubr
 ;======================================================= 
subr trace3d_inspec_widget
 ;this creates the TRACE image inspector widget
 if defined($t3dinspecwidget) ne 1 then {
 $t3dinspecwidget = xmtoplevel_form(0,0, 'TRACE Image Inspector',0,0,5, 5)
 wq = topbuttonsetupsanslink_tl('$t3dinspec')

 ;an erase button
 bq=xmbutton(wq,'erase','t3dinspec_erase_cb', $f4,'gray')
 xmposition,bq, 144, 0, 60, 30

 ;how many to keep
 $t3dinspec_t1 = xmtextfield(wq,'5',6,'',$f3,'white')
 xmposition, $t3dinspec_t1, 210, 0, 50, 30
 xmposition, xmlabel(wq, '# to keep', $f4), 265, 4

 ;examine selection button
 bq=xmbutton(wq,'examine selection','t3dexamine_cb', $f4,'gray')
 xmposition, bq, 350, 0, 130, 30

 $t3dinspec_t2 = xmtext($t3dinspecwidget, 80, 10, $f3, 'white')
 xmposition, xtparent($t3dinspec_t2), 0, 0, 550, 500
 sep = xmseparator($t3dinspecwidget, 0, 10, 0)
 xmposition, sep, 0, 0, 10, 10
 formvstack, wq, sep, xtparent($t3dinspec_t2)
 xmattach, xtparent($t3dinspec_t2), 0, 1,1,0,1
 }
 xtpopup, $t3dinspecwidget
 endsubr
 ;======================================================= 
subr t3d_inspect(i)
 ;inspect the current choice
 if $t3d_file_open_flag ne 1 then {
  ;try to read the current name and open the file
  if t3d_open_file() eq 0 then {
  	errormess,'no valid file to view'
	return
  }
 }
 if defined($t3d_nheaders) eq 0 then {
 ;some setups
 $t3d_nheaders = 0
 maxheaders = 100
 last_positions = intarr(maxheaders)
 }
 trace3d_inspec_widget
 trace_header_decode, wmap($t3d_dp_header(*,i)), $t3d_n_bytes(i)
 ;get the cycle length
 nkeep = fix(xmtextfieldgetstring($t3dinspec_t1))
 if nkeep gt maxheaders then nkeep = maxheaders
 ;try the delete first
 if $t3d_nheaders ge nkeep then {
 iq = last_positions(0)
 xmtextreplace, $t3dinspec_t2, 0, iq, ''
 last_positions(0) = last_positions(1:*) - iq
 $t3d_nheaders -= 1
 }
 xmtextappend, $t3dinspec_t2, ist(i,3)+' '+$trace_frame_info
 xmtextappend, $t3dinspec_t2, smap(zero(bytarr(50))+byte(45))+'\n'
 last_positions($t3d_nheaders) = xmtextgetlastposition($t3dinspec_t2)
 $t3d_nheaders += 1
 endsubr
 ;======================================================= 
subr t3d_inspect_cb
 ;inspect call back
 $t3d_image_number = fix(xmtextfieldgetstring($t3d_image))
 i = $t3d_image_number
 t3d_inspect, i
 endsubr
 ;======================================================= 
subr t3d_inspectup_cb
 ;get the current count, bump it up, call t3d_inspect
 $t3d_image_number = fix(xmtextfieldgetstring($t3d_image)) + 1
 if $t3d_image_number ge $t3d_nimages then $t3d_image_number = $t3d_nimages - 1
 xmtextfieldsetstring, $t3d_image, string($t3d_image_number)
 i = $t3d_image_number
 t3d_inspect, i
 endsubr
 ;======================================================= 
subr t3d_inspectdn_cb
 ;get the current count, bump it down, call t3d_inspect
 $t3d_image_number = fix(xmtextfieldgetstring($t3d_image)) - 1
 if $t3d_image_number lt 0 then $t3d_image_number = 0
 xmtextfieldsetstring, $t3d_image, string($t3d_image_number)
 i = $t3d_image_number
 t3d_inspect, i
 endsubr
 ;======================================================= 
subr t3d_widget
 if defined($t3dwidget) eq 0 then {
 ;the compile_file is supposed to operate at top level and hence the edb's
 ;are temporary and don't add to our accumulation
 compile_file, getenv('ANA_WLIB') + '/trace3dwidgettool.ana'
 }
 xtpopup, $t3dwidget
 endsubr
 ;===============================================================================