PRO trace_build_mosaic3, index, data, index_fs, fs_med, $ 
	xgrid = xgrid, ygrid = ygrid, tmrfilename=tmrfilename, version=version
;+
; NAME: trace_build_mosaic3
;
; PURPOSE: Assembles TRACE full disk mosaic
;
; CALLING SEQUENCE: trace_build_mosaic3, tmrfilename
;
; INPUT PARAMETERS:	tmrfilename - the tmr file contining the data
;	index, data - from tmrfile
;	xgrid, ygrid - grid parameters for rotation shift (default 8,8)	
;
; OUTPUTS:  tma_tmrfilename 
;	mindex, mdata - mosaic 'index,data'
;	
; EXAMPLE: trace_build_mosaic, tmrindex, tmrdata, mindex, mdata
;	                           IN     IN       OUT     OUT
; HISTORY:
;	Written		McMullen/Northup	June, 1998 for TRACE data
;	(largely from DeLuca fs_mosaic.pro)
;	Modified to do 4 rotation shifts/image July 6, 1998
;       13-July-1998 - S.L.Freeland - made it a memory operation routine
;	15-July-1998 - T.Northup - rotation shifts/image as variable
;       23-Sep -1998 - S.L.Freeland - Boost output size to maximum for new (larger) mosaics
;	25-Nov -1998 - T. Tarbell - Remove despiking from here and put in make_tma instead
;       30-Nov-1998  - S.L.Freeland - add a history (update_history.pro)
;                                     change 'boost it' logic to use
;                                     index2fov.pro
;
; CALLS: read_trace, anytim2tai, rot_xy, tracedespike, write_trace
;	 trace_struct2filename
;
; RESTRICTIONS:
;-
version=1.0                         ; UPDATE IF MAJOR/ALGORITHM change

;Restore header information from tmr file.
if not data_chk(index,/struct) and data_chk(tmrfilename,/string) then $
   read_trace, tmrfilename, -1, index,/all

;Useful variables and tests.
 imsize = index(0).naxis1	; image size is 1024, extracted from data
 fs_size = imsize*5		; dimensions of full sun mosaic
 boostit=n_elements(index) gt 24 ; keep up with moving target...
 if boostit then begin
   ;   S.L.Freeland - boost size to maximum  (multiple of 64)
     index2fov,index,e,w,n,s,center_fov=cfov, size_fov=sfov,/extreme
     fs_size=round(max(sfov/min(index.cdelt1)))
     fs_size=((fs_size/64)*64) + (64* ((fs_size mod 64) ne 0))
    box_message,'Large Mosaic - Boosting size to: ' + strtrim(fs_size,2)
 endif   
 fs = intarr(fs_size,fs_size)             ; defining the mosaic array
 fs(*)=min(data)
 nimg = n_elements(index)	          ; number of images, check:

 pix_size = index(0).cdelt1	; define pixel size, check square pixels:
  IF (index(0).cdelt2 ne index(0).cdelt1) THEN BEGIN
   PRINT,'Non-square pixels! Check idx array' ;tr_head_info,index(110)
   RETURN
  ENDIF

;Grid variables.
 IF keyword_set (xgrid) THEN xgrid = float(xgrid) ELSE xgrid = 8
 IF keyword_set (ygrid) THEN ygrid = float(ygrid) ELSE ygrid = 8
				; x and y dimensions of grid to be
				; differentially rotated	
 IF imsize-(imsize/xgrid)*xgrid ne 0 or $ 
	imsize-(imsize/ygrid)*ygrid ne 0 THEN BEGIN
		print, 'grid dimensions must be divisors of image size'
		RETURN
 ENDIF				; grid divides image into similar rectangles
 ngrid = xgrid*ygrid		; number of rotation shifts/image 
 xsize = imsize/xgrid		; x and y dimensions of rectangle
 ysize = imsize/ygrid		
 x_pt = 0.5 + findgen(xgrid)
 y_pt = 0.5 + findgen(ygrid)

;Time arrays.
 date_obs = strarr(nimg)	; find times associated with images
 date_obs = index.date_obs
 dday=anytim2tai(date_obs)	; convert associated times
 daysort = sort(dday)		; sort associated times
 middate= date_obs(daysort(nimg/2))	; find middle time (needed for rot_xy)

;Image center arrays.
 xy = intarr(nimg,2) 
 xy_pt = intarr(1,2,ngrid) 
 xy_grid = make_array(nimg,2,ngrid)
 xy=[[index.xcen], [index.ycen]]; center of each image (nimg x 2 array)
 FOR j = 0, ngrid-1 DO BEGIN 
  remainder = j-(j/xgrid)*xgrid
  xy_pt(0,*,j) = [[pix_size*(xsize*x_pt(remainder)-imsize/2)], $
		 [pix_size*(ysize*y_pt(j/xgrid)-imsize/2)]]  
 ENDFOR
 FOR i = 0, nimg-1 DO BEGIN
  FOR j = 0, ngrid-1 DO BEGIN
   xy_grid(i,*,j) = xy(i,*)+xy_pt(0,*,j)
  ENDFOR			; centers of all rectangles in arcseconds
 ENDFOR				; (from left to right, bottom to top)
				; (integer division logic)
 
;Set UV flag (if UV, then no despike is needed).
; IF(index(0).msquad eq 'UV') THEN uvflag = 1 ELSE uvflag = 0

;Apply differential rotation correction.
 dr_c = intarr (nimg,2,ngrid)	; create temporary index
  FOR i = 0, nimg-1 DO BEGIN
   FOR j = 0, ngrid-1 DO BEGIN
    dr_c(i,*,j) = rot_xy(xy_grid(i,0,j),xy_grid(i,1,j),tstart=date_obs(i),$
                      tend=middate)
    IF (dr_c(i,0,j) eq -9999 or dr_c(i,1,j) eq -9999) THEN $
       dr_c(i,*,j) = xy_grid(i,*,j)
   ENDFOR	
  ENDFOR
 im_cent = make_array(2,nimg,ngrid)
 FOR j = 0, ngrid-1 DO  im_cent(*,*,j)  = transpose(dr_c(*,*,j))	
				; center of each rectangle after DR

;Find the location (in ") of the lower left corner of each rectangle..
 offset_x = pix_size*(xsize/2)
 offset_y = pix_size*(ysize/2)
 im_cr = im_cent
 im_cr(0,*,*) = im_cr(0,*,*) - offset_x
 im_cr(1,*,*) = im_cr(1,*,*) - offset_y 	 

;Defining locations on full sun mosaic.
 fscenter = fs_size * 0.5
 pix_arcsec = pix_size*(findgen(fs_size)-fscenter)
				; location in arcseconds from sun-center 
				; of each pixel in the full sun mosaic
 test_x = Make_array(fs_size,ngrid)
 test_y = make_array(fs_size,ngrid)
 tmpx = make_array(ngrid)
 tmpy = make_array(ngrid)
 fsx = intarr(nimg,ngrid)	; finding min/max rectangle positions
 fsy = intarr(nimg,ngrid)	; on fs mosaic
  FOR i=0,nimg-1 DO BEGIN
   FOR j=0,ngrid-1 DO BEGIN
    test_x(*,j) = abs(pix_arcsec - im_cr(0,i,j))
    test_y(*,j) = abs(pix_arcsec - im_cr(1,i,j))	
    tmpx(j) = where(test_x(*,j) eq min(test_x(*,j))) 
				; temporary x and y indices
    tmpy(j) = where(test_y(*,j) eq min(test_y(*,j)))
     fsx(i,j) = tmpx(j)		; x and y pixel locations on fs
     fsy(i,j) = tmpy(j)
   ENDFOR
  ENDFOR

;Assemble the data for the full sun mosaic.
 FOR i=0,nimg-1 DO BEGIN
  tdata=data(*,*,i)
  iindex=index(i)
  print,'before i=',i
;   TDT  25-Nov-98  remove despiking from here and put it into make_tma instead
;   IF not uvflag THEN tdata = tracedespike(tdata)
   dat_array = intarr (xsize,ysize,ngrid)
   FOR j=0,ngrid-1 DO BEGIN
	remainder = j-(j/xgrid)*xgrid
	dat_array(*,*,j)=tdata(xsize*remainder:xsize*(remainder+1)-1, $
		ysize*(j/xgrid):ysize*((j/xgrid)+1)-1)
			; extract the existing data,
			; overwrite with "newer" data,
			; and ignore the bad data
   fs_ext = fs(fsx(i,j):fsx(i,j)+(xsize-1), $
	  fsy(i,j):fsy(i,j)+(ysize-1)) > min(dat_array(*,*,j))
   fs(fsx(i,j):fsx(i,j)+(xsize-1), $
	  fsy(i,j):fsy(i,j)+(ysize-1)) = fs_ext > $ 
   dat_array(*,*,j)
  ENDFOR
 print, 'after'	
 ENDFOR			; fs is the final product

;Apply median function in order to smooth fs.
 med_width = 4
 fs_med = median (fs, med_width)

;Adjust index to full sun mosaic.
 index_fs = index(0)
 index_fs.naxis1 = fs_size
 index_fs.naxis2 = fs_size
 index_fs.xcen = 0
 index_fs.ycen = 0

; add a history record
update_history, index_fs, version=version,/caller
		
RETURN
END
