;+------------------------------------------------------------------------
; NAME: PLOT_TIMETEXT
; PURPOSE: To generate a time text plot given the anonymous structures
;          returned by the read_mycdf function.
; CALLING SEQUENCE:
;       out = plot_timetext(Xstruct,Ystruct)
; INPUTS:
;       Xstruct = structure containing the Epoch variable structure of the
;                 type returned by the read_mycdf structure.
;       Ystruct = structure containing the variable to be printed against
;                 the Epoch variable in the Xstruct parameter
; KEYWORD PARAMETERS:
;       TSTART   = Forces the time axis to begin at this Epoch time.
;       TSTOP    = Forces the time axis to end at this Epoch time.
;	NOTIME	 = time is not displayed by timeaxis_text
;	NOSUBTITLE=subtitle is not displayed 
;	PLABELOFFSET=Label offset in pixels
;	ONLYLABEL= only label will be displayed by timeaxis, no x-axis. 
;	ELEMENTS = if set, then only these elements of a dimensional variable
;                  will be plotted.
;       NONOISE  = if set, filter out values outside 3 sigma from mean
;	NOVALIDS = if set, ignore validmin and validmax from input structures
;	COMBINE = if set, need to add the dataset name to the y axis label
;		  added 10/24/2003 - TJK.	
;       DEBUG    = if set, turns on additional debug output.
; OUTPUTS:
;       out = status flag, 0=0k, -1 = problem occured.
; AUTHOR:
;       Created 11/99 by RCJ. Based on plot_timeseries.pro
; MODIFICATION HISTORY:
;       10/24/2003 - TJK added COMBINE keyword to add dataset name label
;
;-------------------------------------------------------------------------
FUNCTION plot_timetext, Xvar, Yvar, $
         TSTART=TSTART,TSTOP=TSTOP,NOTIME=NOTIME, NOSUBTITLE=NOSUBTITLE, $
         ONLYLABEL=ONLYLABEL,PLABELOFFSET=PLABELOFFSET, ELEMENTS=ELEMENTS,$
         NONOISE=NONOISE, NOVALIDS=NOVALIDS, COMBINE=COMBINE,$
         DEBUG=DEBUG,REPORT=REPORT,_EXTRA=EXTRAS, HELP=HELP

; Open report file if keyword is set
status = 0
nogood=0
if keyword_set(help) then begin
   print,'Plot_timetext. Example:'
   print,'IDL>s=plot_timeseries(xvar,yvar,/onlylabel,panel_height=100,/nosubtitle)'
   print,'where xvar and yvar are structures containing the Epoch variable'
   print,'as returned by read_myCDF, and the variable to be printed against the'
   print,'Epoch variable, respectively.'
   print,'IDL>s=plot_timetext(xvar,yvar,/notime, plabellofset=-40)'   
   status=-1
   goto, skipped
endif   
;

if keyword_set(REPORT) then begin & reportflag=1L
   a=size(REPORT) & if (a(n_elements(a)-2) eq 7) then $
   OPENW,1,REPORT,132,WIDTH=132
endif else reportflag=0L

; Verify that both Xvar and Yvar are present
if (n_params() ne 2) then begin
   print,'ERROR=Missing parameter to plot_timetext function' & return,-1
endif

; Verify the type of the first parameter and retrieve the data
a = size(Xvar)
if (a(n_elements(a)-2) ne 8) then begin
   print,'ERROR=1st parameter to plot_timetext not a structure' & return,-1
endif else begin
   a = tagindex('DAT',tag_names(Xvar))
   if (a(0) ne -1) then times = Xvar.DAT $
   else begin
      a = tagindex('HANDLE',tag_names(Xvar))
     if (a(0) ne -1) then handle_value,Xvar.HANDLE,times $
     else begin
        print,'ERROR=1st parameter does not have DAT or HANDLE tag' & return,-1
     endelse
     b = size(times)
     if (b(n_elements(b)-2) ne 5) then begin
        print,'ERROR=1st parameter datatype not CDF EPOCH' & return,-1
     endif
   endelse
endelse
szck=size(times)
if(szck(szck(0)+2) ne 1) then $ ; RTB added to prevent reform(scalar)
       times = reform(times) ; eliminate any redundant dimensions
       
; Verify the type of the second parameter and retrieve the data
a = size(Yvar)
if (a(n_elements(a)-2) ne 8) then begin
   print,'ERROR=2nd parameter to plot_timetext not a structure' & return,-1
endif else begin
   YTAGS = tag_names(Yvar) ; avoid multiple calls to tag_names

   if keyword_set(COMBINE) then begin
     a = tagindex('LOGICAL_SOURCE',YTAGS)
     if (a(0) ne -1) then yds = strupcase(Yvar.(a(0)))
   endif

   a = tagindex('DAT',YTAGS)
   if (a(0) ne -1) then THEDATA = Yvar.DAT $
   else begin
      a = tagindex('HANDLE',YTAGS)
      if (a(0) ne -1) then handle_value,Yvar.HANDLE,THEDATA $
      else begin
         print,'ERROR=2nd parameter does not have DAT or HANDLE tag' & return,-1
      endelse
   endelse
endelse

szck=size(thedata)
if(szck(szck(0)+2) ne 1) then $ ; RTB added to prevent reform(scalar)
      thedata = reform(thedata) ; eliminate any redundant dimensions
      
; Get size of data 
thedata_size = size(thedata)

; Verify type of data and determine the number of panels that will be plotted
; and which elements of the data array are to be plotted.
a = size(thedata) & b = a(n_elements(a)-2) & thedata_size = a
if ((b eq 0) OR (b gt 5)) then begin
  print,'STATUS=datatype indicates that data is not plottable' & return,-1
endif else begin
  case a(0) of
  0   : begin
        print,'STATUS=Re-select longer time interval. Single data points are not plottable' & return,-1
        end
  1   : begin
        elist=0
        end
  2   : begin ; #panels determined by dimensionality or by display type
        elist=indgen(a(1))
        ;if keyword_set(ELEMENTS) then begin
	; RCJ 11/13/2003 Line above is not a good way to check the keyword elements
	; because it could be =0 (ie, we want x component only) but it will
	; be understood by the program as 'elements keyword not set'. Better line below:
        if n_elements(ELEMENTS) ne 0 then begin
           elist = ELEMENTS
        endif else begin
          if NOT keyword_set(IGNORE_DISPLAY_TYPE) then begin
            b = tagindex('DISPLAY_TYPE',YTAGS)
            if (b(0) ne -1) then begin ; evaluate the display type
              c = strupcase(Yvar.(b(0))) & c = break_mystring(c,delimiter='>')
              if ((c(0) eq 'TIME_TEXT')AND(n_elements(c) gt 1)) then begin
                d = break_mystring(c(1),delimiter=',')
                elist = long(d) & elist = elist -1
              endif
            endif
          endif
        endelse
        end
  else: begin
        print,'ERROR=Cannot plot data with > 2 dimensions' & return,-1
        end
  endcase
endelse

if (thedata_size(0) eq 1) then mydata = thedata $
  else mydata=thedata(elist,*)
mydata=reform(mydata)
  
; Determine the proper start and stop times of the plot
tbegin = times(0) & tend = times(n_elements(times)-1) ; default to data
if keyword_set(TSTART) then begin ; set tbegin
   tbegin = TSTART & a = size(TSTART)
   if (a(n_elements(a)-2) eq 7) then tbegin = encode_CDFEPOCH(TSTART)
endif

if keyword_set(TSTOP) then begin ; set tend
   tend = TSTOP & a = size(TSTOP)
   if (a(n_elements(a)-2) eq 7) then tend = encode_CDFEPOCH(TSTOP)
endif
;
; Compare the range of the time data to the requested start and stop times
pad_front = 0L & pad_end = 0L
if (tbegin lt times(0)) then begin
   if keyword_set(DEBUG) then print,'Padding front of times...'
   times = [tbegin,times] & pad_front = 1L
endif
if (tend gt times(n_elements(times)-1)) then begin
   if keyword_set(DEBUG) then print,'Padding end of times...'
   times = [times,tend] & pad_end = 1L
endif
;
; Determine the first and last data time points to be plotted
rbegin = 0L & w = where(times ge tbegin,wc)
if (wc gt 0) then rbegin = w(0)
rend = n_elements(times)-1 & w = where(times le tend,wc)
if (wc gt 0) then rend = w(n_elements(w)-1)
if (rbegin ge rend) then begin
   print,'STATUS=No data within specified time range.' & return,-1
endif
;
if not keyword_set(nosubtitle) then begin
   ; Create a subtitle for the plots showing the data start and stop times
   CDF_EPOCH,tbegin,year,month,day,hour,minute,second,milli,/BREAK
   ical,year,doy,month,day,/idoy
   subtitle = 'TIME RANGE='+strtrim(string(year),2)+'/'+strtrim(string(month),2)
   subtitle = subtitle + '/' + strtrim(string(day),2)  
   subtitle = subtitle + ' (' + strtrim(string(doy),2) + ') to '
   CDF_EPOCH,tend,year,month,day,hour,minute,second,milli,/BREAK
   ical,year,doy,month,day,/idoy
   subtitle = subtitle + strtrim(string(year),2)+'/'+strtrim(string(month),2)
   subtitle = subtitle + '/' + strtrim(string(day),2)
   subtitle = subtitle + ' (' + strtrim(string(doy),2) + ')'
endif else subtitle=''
;
; Convert the time array into seconds since tbegin
CDF_EPOCH,tbegin,year,month,day,hour,minute,second,milli,/BREAK
CDF_EPOCH,a,year,month,day,0,0,0,0,/COMPUTE_EPOCH
times  = (times - a) / 1000
julday = ymd2jd(year,month,day)
;
; Determine label for time axis based on time range
xranger = lonarr(2)
xranger(0) = (tbegin-a)/1000
xranger(1) = (tend-a)/1000
trange = xranger(1) - xranger(0)
if (trange le 60.0) then tform='h$:m$:s$.f$@y$ n$ d$' $
else tform='h$:m$:s$@y$ n$ d$'
;
; Determine the fill value for the Y data and valid min and valid max values
a = tagindex('FILLVAL',YTAGS)
if (a(0) ne -1) then Yfillval = Yvar.FILLVAL else Yfillval = 1.0e31
;
mydata_size=size(mydata)
; pad the beginning and end of data if extra time points were added
;  if (pad_front) then mydata = [Yfillval,mydata] ; add fill point to front
if (pad_front) then begin
   if (mydata_size(0) eq 1) then begin
      mydata = [Yfillval,mydata]
   endif else begin
      for ii=0,mydata_size(1)-1 do begin
         command='mydata'+strtrim(string(ii),2)+ $
             '=[Yfillval,reform(mydata('+strtrim(string(ii),2)+',*))]'
         status=execute(command) 
      endfor
      mydata=[mydata0] ; there's always going to be a mydata0
      for ii=1,mydata_size(1)-1 do begin
         command='mydata=[[mydata],[mydata'+strtrim(string(ii),2)+']]'
         status=execute(command)
      endfor
      mydata=transpose(mydata)
   endelse   
endif
;  if (pad_end) then mydata = [mydata,Yfillval] ; add fill point to back
if (pad_end) then begin
   if (mydata_size(0) eq 1) then begin
      mydata = [mydata,Yfillval]
   endif else begin
      for ii=0,mydata_size(1)-1 do begin
         command='mydata'+strtrim(string(ii),2)+ $
             '=[reform(mydata('+strtrim(string(ii),2)+',*)),Yfillval]'
         status=execute(command) 
      endfor
      mydata=[mydata0] ; there's always going to be a mydata0
      for ii=1,mydata_size(1)-1 do begin
         command='mydata=[[mydata],[mydata'+strtrim(string(ii),2)+']]'
         status=execute(command)
      endfor
      mydata=transpose(mydata)
   endelse   
endif

if (mydata_size(0) eq 1) then mydata=mydata(rbegin:rend) else mydata=mydata(*,rbegin:rend)
mytimes = times(rbegin:rend)

addi=[mytimes]
size_mydata=size(mydata)
if size_mydata(0) ne 1 then begin ; 1 = array, more than 1 = matrix
   for ii=0,size_mydata(1)-1 do begin
      addi=[[addi],[reform(mydata[ii,*])]]
   endfor
endif else begin
   addi=[[addi],[mydata]]
endelse 
;
; correction for bad or missing data at the beginning, end, and middle of addi array  
;
szaddi=size(addi)
; this part will fix the beginning of the array, row by row.
; example: if the array starts with  99  99  99  5  7  3 ... it will become
; 5  5  5  5  7  3 .... the bad values will be replaced with the first good value.
; Addendum (07/00): Only replace values within 'delta' from first good value,
; where delta is 1% of number of points. Remaining bad values will become 0's. RCJ
for i=1,szaddi(2)-1 do begin ; i starts at 1 because row 0 is time
   delta=round(n_elements(addi(*,i))*0.01) ; 1% of total number of elements in that row
   if keyword_set(DEBUG) then print,'DELTA = ',strtrim(delta,2), ', 1% of ',strtrim(n_elements(addi(*,i)),2)
   q=where(addi(*,i) ne yfillval)
   if q(0) ne -1 then begin
      j=0
      counter=0
      value=addi(0,i)
      while (value eq yfillval) do begin
         counter=j
         j=j+1
         value=addi(j,i)
      endwhile
      ;if keyword_set(DEBUG) then print,'Replacing array positions (',$
      ;      '0:',strtrim(counter,2),$
      ;      ',',strtrim(i,2),') with ',strtrim(value,2)
      if (counter-delta lt 0) then begin
         if keyword_set(DEBUG) then print,'Replacing array positions (',$
            '0:',strtrim(counter,2),$
            ',',strtrim(i,2),'), value(s) =  ',strtrim(addi[0:counter,i],2),' with ',strtrim(value,2)
         addi[0:counter,i]=value 
      endif else begin
         if keyword_set(DEBUG) then print,'Replacing array positions (',$
            strtrim(counter-delta,2),':',strtrim(counter,2),$
            ',',strtrim(i,2),'), value(s) =  ',strtrim(addi[counter-delta:counter,i],2),' with ',strtrim(value,2)
         addi[counter-delta:counter,i]=value
      endelse   
      ;
      ; similarly for the end of the array.....
      j=n_elements(addi(*,i))-1
      counter=n_elements(addi(*,i))-1
      value=addi(j,i)
      while (value eq yfillval) do begin
         counter=j
         j=j-1
         value=addi(j,i)
      endwhile
      ;if keyword_set(DEBUG) then print,'Replacing array positions (',$
      ;      strtrim(counter,2),':', $
      ;      strtrim(n_elements(addi(*,i))-1,2),$
      ;      ',',strtrim(i,2),') with ',strtrim(value,2)
      if (counter+delta gt n_elements(addi(*,i))-1) then begin
         if keyword_set(DEBUG) then print,'Replacing array positions (',$
            strtrim(counter,2),':',strtrim(n_elements(addi(*,i))-1,2),$
            ',',strtrim(i,2),'), value(s) =  ',strtrim(addi[counter:n_elements(addi(*,i))-1,i],2),' with ',strtrim(value,2)
         addi[counter:n_elements(addi(*,i))-1,i]=value
      endif else begin
         if keyword_set(DEBUG) then print,'Replacing array positions (',$
            strtrim(counter,2),':',strtrim(counter+delta,2),$
            ',',strtrim(i,2),'), value(s) =  ',strtrim(addi[counter:counter+delta,i],2),' with ',strtrim(value,2)
         addi[counter:counter+delta,i]=value
      endelse   
      ;
      ; now for gaps in the data. Take an average of the closest non-bad values to the
      ; left and to the right of the gap. In other words, interpolate the data.
      for j=1L,n_elements(addi(*,i))-2 do begin
         if addi(j,i) eq yfillval then begin
            prev=addi(j-1,i)
            pos_prev=j-1
            next=addi(j+1,i)
            pos_next=j+1
            for k=pos_next,n_elements(addi(*,i))-1 do begin
               if addi(k,i) ne yfillval then begin
                  next=addi(k,i)
                  pos_next=k
                  goto, fill_gap
               endif    
            endfor
            fill_gap:
            ;if keyword_set(DEBUG) then print,'Replacing array positions (',$
            ;	strtrim(pos_prev+1,2),':', $
            ;	strtrim(pos_next-1,2),$
            ;	',',strtrim(i,2),') with ',strtrim((prev+next)/2.,2)
            ;addi[pos_prev+1:pos_next-1,i]=(prev+next)/2.   ; gap is filled with average 
            if (pos_next-pos_prev le delta) then begin
               if keyword_set(DEBUG) then print,'Replacing array positions (',$
            	  strtrim(pos_prev+1,2),':', $
            	  strtrim(pos_next-1,2),$
            	  ',',strtrim(i,2),'), value(s) =  ',strtrim(addi[pos_prev+1:pos_next-1,i],2),' with ',strtrim(prev,2)
               addi[pos_prev+1:pos_next-1,i]=prev
            endif else begin
	       ; The condition below is for the case when we are at the beginning of the array
	       ; and we could have pos_prev=0 and delta=0 (small number of points, 1% of
	       ; it would be =0). In this case we would be doing:
	       ; addi[1:0,i]=prev which results in error.
	       ; RCJ 10/15/02
	       if (pos_prev+1 le pos_prev+delta) then $
               addi[pos_prev+1:pos_prev+delta,i]=prev
               w=where(addi[pos_prev+delta:pos_next-1,i] eq yfillval)
               if w(0) ne -1 then begin
                  if (n_elements(w) gt delta) then begin
                     if keyword_set(DEBUG) then print,'Replacing array positions (',$
            	        strtrim(pos_next-1-delta,2),':', $
            	        strtrim(pos_next-1,2),$
            	        ',',strtrim(i,2),'), value(s) =  ',strtrim(addi[pos_next-1-delta:pos_next-1,i],2),' with ',strtrim(next,2)
                     addi[pos_next-1-delta:pos_next-1,i]=next
                  endif else begin
                     if keyword_set(DEBUG) then print,'Replacing array positions (',$
            	        strtrim(w(0),2),':', $
            	        strtrim(w(n_elements(w)-1),2),$
            	        ',',strtrim(i,2),'), value(s) =  ',strtrim(addi[w,i],2),' with ',strtrim(next,2)
                     addi[w,i]=next
                  endelse
               endif   
            endelse  
            j=k
         endif  ; end if element is yfillval
      endfor ; done all the gaps
   endif   ; end if there are yfillvals 
   qq=where(addi(*,i) eq yfillval) 
   ; if after all we've done there are still yfillvals in this row, make them = 0
   if qq(0) ne -1 then begin
      addi(qq,i) = 0
      if keyword_set(debug) then print,'Array position(s) set to 0: ',qq
   endif   
endfor ; end i, for each row 
;
if (yvar.lablaxis ne '') then begin
   if keyword_set(notime) then addl=[yvar.lablaxis] else addl=['UT','',yvar.lablaxis]
endif else begin ; if lablaxis is not present, labl_ptr_1 must be
    if keyword_set(notime) then addl=[yvar.labl_ptr_1] else addl=['UT','',yvar.labl_ptr_1]
endelse    
 
;addf=['(e10.2)','(e10.2)','(e10.2)','(e10.2)'] format accepted by timeaxis_text. RCJ
;
; timeaxis_text will only accept addf with same number of rows as addi
; so the first element of addf = '' (that would be the time format).  RCJ
addf=strarr(szaddi(2))
addf(0)='' 
 if (yvar.format ne '') then $
      addf(1:*)='('+yvar.format+')' else addf(1:*)='('+yvar.form_ptr(elist)+')'
 addl=[addl(elist)]
; RCJ attempt to align all labels:
for ii=0,n_elements(addl)-1 do begin
   if strlen(addl(ii)) lt 10 then begin
      for iii=strlen(addl(ii))+1,10 do addl(ii)=addl(ii)+' ' 
   endif
endfor

add_dataset='' ; initialize dataset label
if (keyword_set(COMBINE) and n_elements(yds) gt 0)then begin
  add_dataset = make_array(szaddi(2),/string,value=' ')
  add_dataset(0) = yds
endif

;

 timeaxis_text,FORM=tform,JD=julday,title=subtitle,CHARSIZE=0.9, /notime, $
         addinfo=addi,addlabel=addl,addformat=addf, add_ds=add_dataset, $
	 plabeloffset=plabeloffset, onlylabel=onlylabel, _extra=extras   
;

skipped:
return,status
end