
PRO  plot_fov, xy, fov, LINESTYLE=linestyle, THICK=thick, COLOR=color
;plotting coordinates already established. All values in units of plotting coordinates.

  x0 = xy[0]
  y0 = xy[1]
  fovx2 = fov[0]/2.
  fovy2 = fov[1]/2.
  xlo = x0 - fovx2
  xhi = x0 + fovx2
  ylo = y0 - fovy2
  yhi = y0 + fovy2
  PLOTS,[xlo,xhi],[yhi,yhi],linestyle=linestyle,thick=thick,color=color
  PLOTS,[xhi,xhi],[yhi,ylo],linestyle=linestyle,thick=thick,color=color
  PLOTS,[xlo,xhi],[ylo,ylo],linestyle=linestyle,thick=thick,color=color
  PLOTS,[xlo,xlo],[ylo,yhi],linestyle=linestyle,thick=thick,color=color
  PLOTS,x0,y0,psym=1,symsize=0.75,color=color

RETURN
END


FUNCTION hinode_pointing_scan, date, BFI=bfi, NFI=NFI, SP=sp, SCAN=scan, OVERLAP=overlap, $
                            CCD=ccd, LATITUDE=latitude, NPOINT=npoint, LONGITUDE=longitude, $
                            HORIZONTAL=horizontal, MUVALUE=muvalue, MUARC=muarc, $
                            MUCIRCLES=MUCIRCLES, NOERASE=noerase, XS_WIN=xs_win, YS_WIN=ys_win, $
                            XPOS_WIN=xpos_win, YPOS_WIN=ypos_win, GRID_SPAC=grid_spac, $
                            COLOR=color, OUTFILE=outfile, ROUND=round, QUIET=quiet

;+
; NAME:
;	HINODE_POINTING_SCAN
; PURPOSE:
;       Calculate pointing positions for the N-S and E-W scans for
;       the HOP 79 irradiance program. Produces pointing values that are
;       symmetric around disk center for either type of scan. 
;       to relative alignment with the first image in the series.
;
; CALLING SEQUENCE:
;	
; INPUTS:
; 
;   DATE: the date the scan is to be run. In any SSW format.
;
; KEYWORD INPUTS:
;
;   BFI:          Use the BFI FOV when calculating positions and overlaps on the Sun.
;   NFI:          Use the NFI FOV when calculating positions and overlaps. 
;   SP:           Use the SP slit dimensions when calculating positions and overlaps.
;   OVERLAP:      The amount of overlap in consecutive pointings. In
;                   fraction of FOV. Default = 0.1.
;   CCD:          [x,y] array of number of pixels read out from the CCD. Used
;                   to calculate positions and overlaps in case of a sub-camera read
;                   out.
;   LATITUDE:     Calculate pointing coordinates for an E-W scan along a
;                   constant latitude given by this keyword. 
;   LONGITUDE:    Calculate pointing coordinates for a N-S scan along a
;                   constant longitude given by this value. Currently
;                   limited to LONGITUDE=0 (central meridian).
;   HORIZONTAL:   Calculate pointing coordinates for a scan along the E-W
;                   lateral through disk center. Note that this is not an
;                   "equatorial" scan along latitude = 0. 
;   NOCORRECT:    Set this keyword to NOT correct for the SOT pointing
;                   offset relative to the S/C. The default corrects
;                   for the pointing offset. Default behavior requires
;                   that machine on which code is run has the
;                   SBOPS_SC_XCORR and SBOPS_SC_YCORR environment
;                   variables set. If these are not set, the program
;                   warns that the pointing coordinates do not take
;                   into account the SOT offsets. If these are set,
;                   program prints the offsets. Operator should verify
;                   that the offsets are the correct current values
;                   and if not, update the machine's environment
;                   variables before running this program.  
;   NPOINT:       Number of pointings along an E-W. Can be used to specify a
;                   given number of non-overlapping pointing samples. Must be odd.
;   MUVALUE:      Scan along this constant value of mu = cos(theta). Not yet
;                   implemented.
;   MUARC:        Arclength in degrees of scan along constant mu. Not yet
;                   implemented. 
;   MUCIRCLES:    Set this keyword to plot constant mu-value circles on
;                   the output plots. 
;   NOERASE:      Set this keyword to overplot a second scan on an existing
;                   scan plot. Useful for plotting the +15 deg and -15 E-W scans
;                   together, for example. 
;   COLOR:        The color that the FOV boxes are plotted on the disk image.
;   OUTFILE:      The name of a file in which an EPS file of the scan plots
;                   is written to. 
;   ROUND:        Set this keyword to print out integer numbers for the
;                   pointing coordinates. 
;   QUIET:        Set this keyword to supress all PRINT and PLOT statements. 
;   XS_WIN:       X size of graphics window (default is 900).
;   YS_WIN:       X size of graphics window (default is 900).
;   XPOS_WIN:     Optional X position of graphics window.
;   YPOS_WIN:     Optional Y position of graphics window.
;   GRID_SPAC:    Optional helio grid spacing (default is 10 deg).
;
; OUTPUTS:
;
;   SC_POINTING_XY: [2,N] array of (x,y) Spacecraft pointing values in arcseconds
;                   relative to heliocentric disk center. 
; 
; USAGE:
;
;   For N-S scan:
;   xyns = hinode_pointing_scan('22-Oct-2008',/BFI, /long, overlap=0.1, color=253, /round)
;
;   For E-W scans:
;   xyp15 = hinode_pointing_scan('22-Oct-2008',/BFI, lat=15, overl=0.1, color=251, /round)
;  
;   xym15 = hinode_pointing_scan('22-Oct-2008',/BFI, lat=-15,overl=0.1, color=252, /noerase, /round)
;
;   For Horizontal scan:
;   xyh = hinode_pointing_scan('22-Oct-2008',/BFI,/horizontal,overl=0.1,color=252, /noerase, /round)
;
;
;As discussed in the monthly and weekly meetings, the HOP 79
;irradiance scan schedule has been altered to have a different E-W
;scan every other month. From now on, we will run the following pointings:
;
;	Month X
;
;		Day 1:  N-S scan (as usual)
;		Day 2:  E-W scan consisting of  +15 latitude scan and new "HORIZONTAL" scan through disk center
;
;	Month X+1
;
;		Day 1: N-S scan (as usual)
;		Day 2: E-W scan consisting of -15 latitude scan and new "HORIZONTAL" scan through disk center
;
;	repeat...
;
;The reason for the new horizontal scan through disk center is to help
;calibrate the N-S scan through disk center. This scan has possibly
;discovered a significant latitudinal temperature variation and a
;better calibration will help narrow the error bars.

; REVISION HISTORY:
;   v 1.0    Written by T. Berger, LMSAL, Jan. 2007. 
;   v 1.1    TEB, LMSAL, Oct. 2008. 
;   v 1.2    Added horizontal scan at DC. Also defaults to correct for
;            SOT pointing relative to S/C. Must have environment
;            variables set on machine on which code is run. TEB,
;            LMSAL, Oct. 2009
;   v 1.2.1  Program now returns S/C pointing coordinates but plots
;            SOT FOV boxes correctly on the disk. TEB, LMSAL 11/9/09.
;   v 1.2.2  Added optional keywords XS_WIN, YS_WIN, XPOS_WIN, YPOS_WIN to optionally control
;            size and position of graphics window GLS, LMSAL, Feb. 2010
;   v 1.2.3  Added off-limb image on southern end of Central meridian scan. This was requested by
;            Prof. Tsuneta for scattered light measurement.  TEB, LMSAL 19-Feb-2010.
;-

prognam = 'HINODE_POINTING_SCAN'
progver = 'V1.2.3'

if N_ELEMENTS(latitude) gt 0 then dolat = 1 else dolat = 0
if N_ELEMENTS(longitude) gt 0 then dolong = 1 else dolong = 0
if KEYWORD_SET(horizontal) then dohoriz = 1  else dohoriz = 0
if N_ELEMENTS(muvalue) gt 0 then domu = 1 else domu = 0
if KEYWORD_SET(overlap) then ov = overlap else ov = 0.1
if KEYWORD_SET(bfi) then platescale = 0.054    ;arcsec/pixel
if KEYWORD_SET(nfi) then platescale = 0.080    ;arcsec/pixel

if NOT EXIST(xs_win) then xs_win = 900
if NOT EXIST(ys_win) then ys_win = 900
if NOT EXIST(xpos_win) then xpos_win = 0
if NOT EXIST(ypos_win) then ypos_win = 0
if NOT EXIST(grid_spac) then grid_spac = 10

ccdread = [4096,2048]     ;Full FOV, pixels
;SCAN = width of SP scan in pixels
if KEYWORD_SET(sp) then begin
   if not KEYWORD_SET(scan) then scan = 1000 ;164" scan
   platescale = 0.1585          ;arcsec/pixel
   ccdread = [scan,1024]
end
if KEYWORD_SET(ccd) then begin
   sz = SIZE(ccd, /dimen)
   if sz[0] ne 2 then begin
      MESSAGE,'CCD keyword must be a 1-D array of two elements: X and Y pixels readout'
      RETURN,-1
   end else ccdread = ccd
end 
fov = ccdread*platescale
if KEYWORD_SET(outfile) then ps = 1 else ps = 0
if KEYWORD_SET(quiet) then loud=0 else loud=1
;if no date supplied, take today's date:
err = ''
tdate=anytim2utc(date,err=err)
if err ne '' then get_utc,tdate

;Get radius and B0 angle:
pvec = FLOAT(pb0r(tdate,/arcsec))
radius = pvec[2]
if (loud) then PRINT,'Solar radius = ',radius,' arcseconds'
if (1 - is_number(b0)) then b0 = pvec[1]
if (loud) then PRINT,'Solar B0 angle = ',b0,' degrees'
saferad = 945   ;maximum arcseconds from DC that Hinode can point.

;Pointing correction
xoff = GETENV('SBOPS_SC_XCORR')
yoff = GETENV('SBOPS_SC_YCORR')
if xoff eq '' or yoff eq '' then begin
   MESSAGE,/cont,'One or both of the SBOPS_SC_*CORR environment variables is not set. Pointing coordinates will NOT have SOT offsets taken into account.'
   xoff = 0
   yoff = 0
end else if (loud) then begin
   PRINT,'Current SOT offsets relative to S/C pointing:'
   PRINT,'    dX = ', xoff,' arcsec'
   PRINT,'    dY = ', yoff,' arcsec'
end
xyoff = FIX([xoff,yoff])

;Branch on type of scan: constant latitude, constant latitude, or constant mu. These are 
; currently mutually exclusive.
case 1 of 

   dolong: begin
      if longitude lt -90 or longitude gt +90 then begin
         MESSAGE,'Longitude must be > -90 and < +90'
         RETURN, -1
      end
      ;Only central meridian for now...
      if longitude ne 0 then begin
         MESSAGE,/info,'Only central meridian scans are implemented at this point...'
         longitude=0
      end
;      xy0 = [0,-radius+fov[1]*(0.5-ov)] > (-saferad)
      xy0 = [0,-saferad]   ; Tsuneta requests off-limb images for scattered light calibration. 
      pointing_xy = xy0
     dely = fov[1]*(1-ov)
;     print,dely
;     while ((xy0[1] + fov[1]/2.) lt radius) do begin
     while (xy0[1] lt 0) do begin
	xy0[1] += dely
	if ABS(xy0[1]) gt saferad then xy0[1] = SGN(xy0[1])*saferad
        pointing_xy = [[pointing_xy],[xy0]]
     end
     npts = (SIZE(pointing_xy,/dim))[1]
     pointing_xy = pointing_xy[*,0:npts-2]
     pointing_xy=[[pointing_xy],[ROTATE(abs(pointing_xy),7)]]
  end


   dolat: begin
      if latitude lt -90 or latitude gt +90 then begin
         MESSAGE,'Latitude must be > -90 and < +90'
         RETURN, -1
      end
      ;need to step in x and calculate approximate latitude since FOV is in arcsec:
      xy0 = hel2arcmin(latitude,-90.,date=tdate,b0=b0)*60.
      r0 = sqrt(xy0[0]^2.+xy0[1]^2.)
      while r0 gt saferad do begin
         xy0 += (latitude gt 0 ? [5,-5] : [5,5] )
         r0 = SQRT(xy0[0]^2.+xy0[1]^2.)
      end
      if (loud) then PRINT,'starting radius: ',r0
      p_xy = xy0
      npt = 1
      if N_ELEMENTS(npoint) ne 0 then begin   ;evenly spaced NPOINTS along latitude
         if npoint mod 2 eq 0 then npoint -= 1  ;must be odd
         delx = 2*saferad/(npoint-1)
         for i=1,npoint-1 do begin
            xy = xy0 + [delx, 0]
            lon = (xy2lonlat(xy,tdate))[0]
            xy0 = hel2arcmin(latitude,lon,date=tdate,b0=b0)*60.
            r0 = SQRT(xy0[0]^2. + xy0[1]^2.) 
           while r0 gt saferad do begin
               xy0 += [-5,5]
               r0 = SQRT(xy0[0]^2. + xy0[1]^2.) 
               if (loud) then PRINT,r0
            end
            p_xy = [[p_xy],[xy0]]
            if (loud) then PRINT,xy0;, r0
            npt += 1
         end
         pointing_xy=p_xy
      end else begin   ;overlapped segments stepped along a latitude
         lon=-90
;         while (xy0[0] + fov[0]/2.) lt 0 do begin        
         while (xy0[0] lt -fov[0]*(0.5-ov)) do begin
            ovfac = (1.0 + ABS(SIN(lon*!DTOR))) ;adjust overlap to be more at limb.
            ovfac *= ov
            xy = xy0 + [fov[0]*(1-ovfac),0]
            lon = (xy2lonlat(xy,tdate))[0]
            xy0 = hel2arcmin(latitude,lon,date=tdate,b0=b0)*60.
            ;r0 = SQRT(xy0[0]^2. + xy0[1]^2.) 
            p_xy = [[p_xy],[xy0]]
            npt += 1
         end 
         if xy0[0] gt 0 then begin
            pointing_xy = FLTARR(2,2*npt-1)
            pointing_xy[*,0:npt-1]=p_xy
            pointing_xy[0,npt:2*npt-2]=REVERSE(REFORM(ABS(p_xy[0,0:npt-2])))
            pointing_xy[1,npt:2*npt-2]=REVERSE(REFORM(p_xy[1,0:npt-2]))
         end else begin
            pointing_xy = FLTARR(2,2*npt)
            pointing_xy[*,0:npt-1]=p_xy
            pointing_xy[0,npt:2*npt-1]=REVERSE(REFORM(ABS(p_xy[0,0:npt-1])))
            pointing_xy[1,npt:2*npt-1]=REVERSE(REFORM(p_xy[1,0:npt-1]))
         end
      end
   end

   dohoriz: begin
      xy0 = [-radius+fov[0]*(0.4-ov),0] > (-saferad)
      pointing_xy = xy0
      delx = fov[0]*(1-ov)
      while (xy0[0]+fov[0]/2 lt radius) do begin
         xy0[0] += delx
         if ABS(xy0[0]) gt saferad then xy0[0] = SGN(xy0[0])*saferad
         pointing_xy = [[pointing_xy],[xy0]]
      end
      npts = (SIZE(pointing_xy,/dim))[1]
   end

   else: begin
      MESSAGE,'Type of scan not defined. Please enter a value for LONGITUDE or LATITUDE or MUVALUE keyword'
      RETURN,-1
   end

endcase
npoint = (SIZE(pointing_xy))[2]
if KEYWORD_SET(round) then pointing_xy = ROUND(pointing_xy)

;correct for SOT offset: note that here split spacecraft pointing from
;SOT pointing. The program returns SPACECRAFT pointing coordinates.
sc_pointing_xy = pointing_xy
for i=0,npoint-1 do sc_pointing_xy[*,i] -= xyoff

;check for safe radius violations caused by offset:
dr0 = saferad - SQRT(sc_pointing_xy[0,0]^2.+sc_pointing_xy[1,0]^2.)
if dr0 lt 0 then begin
   sc_pointing_xy[*,0] += xyoff
   MESSAGE,/cont,'Unsafe initial pointing due to SOT offset; removing SOT offset from first spacecraft pointing.'
end
dr1 = saferad - SQRT(sc_pointing_xy[0,npoint-1]^2.+sc_pointing_xy[1,npoint-1]^2.)
if dr1 lt 0 then begin
   sc_pointing_xy[*,npoint-1] += xyoff
   MESSAGE,/cont,'Unsafe final pointing due to SOT offset; removing SOT offset from final spacecraft pointing.'
end


if (loud) then begin 
   red = [[255],[0],[0]]
   cyan = [[0],[255],[255]]
   orange = [[255],[165],[0]]
   blue = [[0],[10],[255]]
   LOADCT,0
   TVLCT,r,g,b,/get
   if (1-ps) then r = REVERSE(r) & g=REVERSE(g) & b=REVERSE(b)
   TVLCT,r,g,b
   TVLCT,red,!d.table_size-2
   TVLCT,cyan,!d.table_size-3
   TVLCT,orange,!d.table_size-4
   TVLCT,blue,!d.table_size-5
;PLOT the solar grid and the SOT FOVs on top. Note that the FOVs shown
;correct for the SOT offset from S/C pointing.
   if KEYWORD_SET(color) then color = color else color = 252
   if ps then begin
                                ;Note: colors not working properly in PS on Mac G5.
      SET_PLOT,'ps'
      LOADCT,0
      TVLCT,red,!d.table_size-2
      TVLCT,cyan,!d.table_size-3
      TVLCT,orange,!d.table_size-4
      TVLCT,blue,!d.table_size-5
      DEVICE,/color, bits=8, /landscape,/inches,xsize=6,ysize=6
      DEVICE,file=outfile,font_size=10,/helvetica
   end
   if not KEYWORD_SET(noerase) and (1-ps) then $
      WINDOW, xs=xs_win, ys=ys_win, /free

;Plot the solar disk with Lat/Lon grid:
   if not KEYWORD_SET(noerase) then plot_helio, tdate, gstyle=3, grid_spacing=grid_spac, color=!d.table_size-1

;Plot the SOT CCD FOV boxes (note the removal of S/C pointing correction to show the SOT FOV on the Sun):
   for i=0, npoint-1 do plot_fov, pointing_xy[*,i]-xyoff, fov, linestyle=0, thick=2, color=color

;If requested, plot circles of constant mu values from 0.9 to 0.1:
   if KEYWORD_SET(mucircles) then begin
      theta = FINDGEN(181)*2*!DTOR
      for j=0,8 do begin
         mu = (j+1.0)/10
         PLOTS, radius*(1-mu^2.)*COS(theta), radius*(1-mu^2.)*SIN(theta)
      end
   end
   if not KEYWORD_SET(noerase) then ys = 1200 else ys = -1200
   deltay = 100
   XYOUTS,-1400,ys,'S/C X:', COLOR=color
   XYOUTS,-1400,ys-deltay,'S/C Y:', COLOR=color
   for i=0, npoint-1 do begin
      xs = -1250 + i*200
      xstr = STRTRIM(ROUND(sc_pointing_xy[0,i]),2)
;      xstr = STRSPLIT(xstr,'.',/extract)
;      xstr = xstr[0] + '.'+ STRMID(xstr[1],0,1)
      ystr = STRTRIM(ROUND(sc_pointing_xy[1,i]),2)
;      ystr = STRSPLIT(ystr,'.',/extract)
;      ystr = ystr[0] + '.' + STRMID(ystr[1],0,1)
      XYOUTS,xs, ys, xstr
      XYOUTS,xs, ys-deltay, ystr
   end

   if ps then begin
      DEVICE,/close
      SET_PLOT,'x'
   end
end

RETURN, sc_pointing_xy
END




