
PRO  EIS_PIXEL_MASK, IMAGE, MASK, WVL, SLIT, COLOR=COLOR, XSC=XSC, $
	YSC=YSC, MAXIMAGE=MAXIMAGE, xrange=xrange, yrange=yrange, $
                     velocity=velocity,velmax=velmax, ct=ct

;+
; PROJECT:  Hinode/EIS
;
; NAME: EIS_PIXEL_MASK()
;       
; PURPOSE:
;
;       To take an image and select portions of the image for further study.
;
; CATEGORY:
;
;       Scientific analysis
;
; EXPLANATION:
;
;	This is a mouse-based routine that requires for input an image 
;	array. The image is displayed and a `menu' will appear in the 
;	IDL window. The options are:
;
;	LEFT:	Go into `polygon' mode
;	MIDDLE:	Go into `painting' mode
;	RIGHT:	Exit
;
;	In `polygon' mode the mouse is used to select polygon vertices on 
;	the image using the LEFT mouse button. With each vertex chosen, a 
;	line will be drawn connecting it to the previous vertex. It is not 
;	necessary to `complete' the polygon - clicking on either the MIDDLE 
;	or RIGHT buttons will complete the polygon and exit to the 
;	top-level `menu'. When this done the selected points are over-laid 
;	on the image. This type of pixel selection is useful when you are 
;	interested in large regions of the data-set.
;
;	In `painting' mode it is possible to paint pixels on the image. By 
;	clicking-and-holding the LEFT button pixels are `set'. By 
;	clicking-and-holding the MIDDLE button pixels are `un-set'. Clicking 
;	on the RIGHT button will exit to the top-level `menu' and redraw the 
;	image with the selected pixels over-laid.
;
;	When exiting out of the program, the selected pixels are stored in 
;	the array MASK which has the same size as IMAGE. The selected 
;	pixels are stored as `1's  in this array, while the remaining pixels 
;	are stored as `0's. By calling EIS_PIXEL_MASK again with 
;	MASK, it is possible to make further adjustments to the 
;	selected pixels.
;
;	MASK can be used in the routine EIS_MASK_SPECTRUM to provide 
;	spectra averaged over the selected region.
;
; CALLING SEQUENCE:
;
;       EIS_PIXEL_MASK, IMAGE, MASK, WVL, SLIT
;
; EXAMPLES:
;
;	EIS_PIXEL_MASK, IMAGE, MASK, WVL, SLIT
;
;	EIS_PIXEL_MASK, IMAGE, MASK, WVL, SLIT, COL=255, MAXIMAGE=0.5
;
; INPUTS:
;
;	IMAGE:		A 2D image derived using the routine
;	                EIS_MAKE_IMAGE
;	MASK:	        A structure containing the pixel mask and
;	                associated information. The tags are:
;                       .image  A byte array of same size as IMAGE,
;                               with 1's indicating that the
;                               pixel has been selected. 
;                       .wvl    The value of WVL.
;                       .slit   The value of SLIT.
;       WVL             The wavelength corresponding to the input
;                       image.
;       SLIT            The size of the slit in arcsec.
;
; OPTIONAL INPUTS:
;
;	COLOR:	The colour of the plotted pixels. The default is black 
;		(COL=0). COL=255 gives white.
;       XRANGE: 2 element array specifying X coordinates of a
;               sub-region of the image to plot.
;       YRANGE: 2 element array specifying Y coordinates of a
;               sub-region of the image to plot.
;	XSC:	Allows a different x-scale to be input. This is
;	        obsolete - please use XRANGE=.
;	YSC:	Allows a different y-scale to be input. This is
;	        obsolete - please use YRANGE=.
;       MAXIMAGE: Sometimes it's necessary to saturate the
;                 image to bring out weak features. Setting MAXIMAGE
;                 to a fraction means that all pixels with intensity
;                 greater than MAXIMAGE*MAX(IMAGE) will be saturated.
;       VELMAX: If /velocity is set, then velmax controls the scaling
;               of the image such that only velocities between +/-
;               velmax are shown. Default is 20 km/s.
;
; KEYWORDS:
;
;       VELOCITY: If set, then the image is interpreted as a velocity
;                 image and plot_vel_image is used to plot it. Use
;                 VELMAX= to control the scaling of the image.
;
; CALLS:
;
;	PLOT_IMAGE, GET_IJ
;
; HISTORY:
;
;       Version 1, 27-OCT-2008, Peter Young
;          Adapted from the routine sub_image_select.pro for
;          SOHO/CDS. 
;       Version 2, 17-MAR-2010, Peter Young
;          Changed for loop to long integers for case when polygon
;          area is large.
;       Version 3, 7-Oct-2013, Peter Young
;          Added XRANGE= and YRANGE= keywords.
;       Version 4, 10-Oct-2013, Peter Young
;          Modified so that the X-axis always gives pixel numbers even
;          for the 2" slit; added /velocity and /velmax
;          keywords for displaying velocity maps.
;       Version 5, 18-Oct-2013, Peter Young
;          If polygon mode is exited before polygon completed, then
;          routine no longer crashes.
;       Version 6, 12-Dec-2014, Peter Young
;          Added CT= keyword for specifying color table.
;       Version 7, 9-Feb-2015, Peter Young
;          The routine started crashing for me (something to do with
;          IDL 8.4?) so I've changed !err to !mouse.button, and
;          also removed the /down keyword from the call to
;          cursor. These changes seem to have fixed the problem. 
;-


IF N_PARAMS() LT 2 THEN BEGIN
  PRINT,'Use:  IDL> eis_pixel_mask, image, mask, wvl, slit [, xrange=, yrange=, maximage=, /velocity, velmax=, ct= ]'
  print,''
  print,'    maximage - a factor by which scale intensity of image, e.g. 0.5 -> 50%'
  print,'    xrange - plot sub-range in X'
  print,'    yrange - plot sub-range in Y'
  print,'    /velocity - use this to display velocity images'
  print,'    ct     - IDL color table index (default=5)'
  RETURN
ENDIF


IF NOT KEYWORD_SET(color) THEN color=0
IF NOT KEYWORD_SET(xsc) THEN xsc=[0,0]
IF NOT KEYWORD_SET(ysc) THEN ysc=[0,0]
IF n_elements(ct) EQ 0 THEN ct=5

siz=size(image)
nx=siz(1)
ny=siz(2)


;
; Check the mask input for compatibility
;
IF n_tags(mask) NE 0 THEN BEGIN
  siz=size(mask.image,/dim)
  IF siz[0] NE nx OR siz[1] NE ny THEN BEGIN
    print,''
    print,'%EIS_PIXEL_MASK: the input mask image has a different size to IMAGE.'
    print,'                 Please delete MASK and restart this routine.'
    print,''
  return
  ENDIF 
ENDIF 

IF n_elements(xrange) EQ 0 THEN xrange=[0,nx-1]
IF n_elements(yrange) EQ 0 THEN yrange=[0,ny-1]

p_image=image[xrange[0]:xrange[1],yrange[0]:yrange[1]]
siz2=size(p_image,/dim)
nx2=siz2[0]
ny2=siz2[1]
x=indgen(nx2)+xrange[0]

IF slit EQ 2 THEN scale=[2,1] ELSE scale=[1,1]

IF n_elements(velmax) EQ 0 THEN velmax=20.0

IF n_elements(maximage) NE 0 THEN max=max(p_image)*maximage

;--------------+
; Plot the image and get dimensions of image
;
IF keyword_set(velocity) THEN BEGIN
   plot_vel_image,p_image,scale=scale,/_extra, $
             xticklen=-0.01,yticklen=-0.01, $
             xsty=5,ytitle='Y-pixel',velmax=velmax, $
                  black_val=-100.
  axis,xaxis=0,xra=[min(x)-0.5,max(x)+0.5],xsty=1,xtitle='X-pixel'
  axis,xaxis=1,xra=[min(x)-0.5,max(x)+0.5],xsty=1 
ENDIF ELSE BEGIN 
  loadct,ct
  plot_image,p_image,scale=scale,/_extra, $
             xticklen=-0.01,yticklen=-0.01, max=max, $
             xsty=5,ytitle='Y-pixel'
  axis,xaxis=0,xra=[min(x)-0.5,max(x)+0.5],xsty=1,xtitle='X-pixel'
  axis,xaxis=1,xra=[min(x)-0.5,max(x)+0.5],xsty=1
ENDELSE 
;--------------+

;------------------------<
; Use a filled-in square for over-plotting sub_image
;
usersym,[-1,1,1,-1],[-1,-1,1,1],/fill
;------------------------<


IF n_tags(mask) EQ 0 THEN BEGIN
  im_mask=byte(p_image-p_image) 
ENDIF ELSE BEGIN
  im_mask=mask.image[xrange[0]:xrange[1],yrange[0]:yrange[1]]
ENDELSE 

;---------------------------------------[
; Check if sub_image already exists. If it does, then make sure it has the 
; correct format. Overplot sub_image on the image.
;
;; IF n_elements(im_mask) NE n_elements(image) THEN BEGIN
;;   print,''
;;   print,'%EIS_PIXEL_MASK: the input mask image has a different size to IMAGE.'
;;   print,'                 Please delete MASK and restart this routine.'
;;   print,''
;;   return
;; ;  im_mask=byte(p_image-p_image)
;; ENDIF ELSE BEGIN
  IF (MIN(im_mask) EQ 0) AND (MAX(im_mask) EQ 1) THEN BEGIN
   ;
    ind=WHERE(im_mask EQ 1)
    IF ind(0) NE -1 THEN BEGIN
      FOR k=0,n_elements(ind)-1 DO BEGIN
        ij=get_ij(ind(k),nx2)
        x_plot=ij(0)*scale(0) & y_plot=ij(1)*scale(1)
        plots,x_plot,y_plot,PSYM=8,SYMSIZ=.7,COLOR=color
      ENDFOR
    ENDIF
  ENDIF ELSE BEGIN
    im_mask=byte(p_image-p_image)
  ENDELSE
;ENDELSE
;---------------------------------------[

; The main part of the program. There's a 'switch' which controls which menu 
; we're in
;
tst1=0
WHILE tst1 LT 2 DO BEGIN
  print,''
  print,'  *** CHOOSE A MODE ***'
  print,'   left:   polygon mode'
  print,'   middle: painting mode'
  print,'   right:  exit'
  print,''
  CURSOR,x_plot,y_plot
;
;---------------------------------------------------------0
  CASE !mouse.button of

  1: BEGIN          ;  <---------  GO INTO POLYGON MODE
;
       PRINT,'  *** IN POLYGON MODE ***'
       PRINT,'    left:    add a vertex'
       PRINT,'    middle:  complete polygon and exit'
       PRINT,'    right:   complete polygon and exit'
       cursor,x,y
;
       xp_pix=FIX(x/scale(0)+.5) & yp_pix=FIX(y/scale(1)+.5)
       xp_plot=scale(0)*xp_pix & yp_plot=scale(1)*yp_pix
;
;   The following takes the selected pixels and converts them into array 
;   pixel units (xp_pix,yp_pix) and plot pixel units (xp_plot,yp_plot). 
;
       i=0
       REPEAT BEGIN
         CURSOR,x_plot,y_plot
         IF !mouse.button EQ 1 THEN BEGIN
           i=i+1
           x_pix=FIX(x_plot/scale(0)+.5) & y_pix=FIX(y_plot/scale(1)+.5)
           x_plot=scale(0)*x_pix & y_plot=scale(1)*y_pix
           OPLOT,[x_plot,x_plot],[y_plot,y_plot],psym=8
           xp_pix=[xp_pix,x_pix] & yp_pix=[yp_pix,y_pix]
           xp_plot=[xp_plot,x_plot] & yp_plot=[yp_plot,y_plot]
           OPLOT,[xp_plot(i-1),xp_plot(i)],[yp_plot(i-1),yp_plot(i)],th=2
         ENDIF
       ENDREP UNTIL !mouse.button NE 1
;
;   The final line that completes the polygon is over-plotted, and the IDL 
;   routine POLYFILLV is used to work which pixels lie inside the polygon. 
;   The `wait' is necessary to show the final polygon side being drawn.
;
       IF n_elements(xp_plot) GT 1 THEN BEGIN 
         OPLOT,[xp_plot(i),xp_plot(0)],[yp_plot(i),yp_plot(0)],th=2
         WAIT,.5
         ind=POLYFILLV(xp_pix,yp_pix,nx2,ny2)
         im_mask(ind)=1
       ENDIF 
;
       tst1=1

     END

  2: BEGIN          ;   <-------  GO INTO PAINTING MODE
;
       PRINT,'  *** IN PAINTING MODE ***'
       PRINT,'    left:    add points'
       PRINT,'    middle:  remove points'
       PRINT,'    right:   exit'
       tst1=0
       REPEAT BEGIN
         CURSOR,x_plot,y_plot

;-------------------------------------------------------<
         CASE !mouse.button of

         1: BEGIN        ;   <------ left button down - add points
;
;  Giving `2' to CURSOR returns the co-ordinates when any change occurs with 
;  the mouse. This allows the `painting' to work.
;
             REPEAT BEGIN
               x_pix=FIX(x_plot/scale(0)+.5) & y_pix=FIX(y_plot/scale(1)+.5)
               x_plot=scale(0)*x_pix & y_plot=scale(1)*y_pix
               IF ((x_pix lt nx2) AND (x_pix ge 0) AND (y_pix lt ny2) AND $
	               (y_pix ge 0)) THEN BEGIN
                im_mask(x_pix,y_pix)=1
                OPLOT,[x_plot,x_plot],[y_plot,y_plot],PSYM=8,SYMSIZ=.7, $
                       COLOR=color
               ENDIF
               CURSOR,x_plot,y_plot,2
             ENDREP UNTIL !mouse.button eq 0
             tst1=0
            END

         2: BEGIN         ;   <------ middle button down - delete points
;
             REPEAT BEGIN
              x_pix=FIX(x_plot/scale(0)+.5) & y_pix=FIX(y_plot/scale(1)+.5)
              x_plot=scale(0)*x_pix & y_plot=scale(1)*y_pix
              IF ((x_pix lt nx2) AND (x_pix ge 0) AND (y_pix lt ny2) AND $
	             (y_pix ge 0)) THEN BEGIN
               im_mask(x_pix,y_pix)=0
               OPLOT,[x_plot,x_plot],[y_plot,y_plot],PSYM=8,SYMSIZ=.7, $
		     COLOR=255-color
              ENDIF
              CURSOR,x_plot,y_plot,2
             ENDREP UNTIL !mouse.button eq 0
             tst1=0
            END

        4: tst1=1        ;   <------ exit to main menu

        ENDCASE
;-------------------------------------------------------<

       ENDREP UNTIL tst1 EQ 1
 
     END

  4: tst1=2             ; exit
 
  ENDCASE
;---------------------------------------------------------0

;-------------------[]
; Replot the image and over-lay SUB_IMAGE. Have used GET_IJ.PRO to convert 
; the vector of indices into array elements. This seems to make the 
; over-plotting a little slow.
;
  IF tst1 EQ 1 THEN BEGIN
    IF keyword_set(velocity) THEN BEGIN
      plot_vel_image,p_image,scale=scale,/_extra, $
                     xticklen=-0.01,yticklen=-0.01, $
                     xsty=5,ytitle='Y-pixel',velmax=velmax, $
                  black_val=-100.
      axis,xaxis=0,xra=[min(x)-0.5,max(x)+0.5],xsty=1,xtitle='X-pixel'
      axis,xaxis=1,xra=[min(x)-0.5,max(x)+0.5],xsty=1 
    ENDIF ELSE BEGIN 
      plot_image,p_image,scale=scale,/_extra,xra=xsc,yra=ysc, $
                 xticklen=-0.01,yticklen=-0.01, max=max, $
                 xsty=5, $
                 ytitle='Y-pixel'
      axis,xaxis=0,xra=[min(x)-0.5,max(x)+0.5],xsty=1,xtitle='X-pixel'
      axis,xaxis=1,xra=[min(x)-0.5,max(x)+0.5],xsty=1
    ENDELSE 
    ind=WHERE(im_mask EQ 1,n_ind)
    IF ind(0) NE -1 THEN BEGIN
      FOR k=0l,n_ind-1l DO BEGIN
        ij=get_ij(ind(k),nx2)
        x_plot=ij(0)*scale(0) & y_plot=ij(1)*scale(1)
        OPLOT,[x_plot,x_plot],[y_plot,y_plot],PSYM=8,SYMSIZ=.7,COLOR=color
      ENDFOR
    ENDIF
  ENDIF
;-------------------[]

ENDWHILE

IF n_tags(mask) EQ 0 THEN BEGIN
  mask={image: bytarr(nx,ny), $
        wvl: wvl, $
        slit: slit}
  mask.image[xrange[0]:xrange[1],yrange[0]:yrange[1]]=im_mask
ENDIF ELSE BEGIN
  mask.image[xrange[0]:xrange[1],yrange[0]:yrange[1]]=im_mask
  mask.wvl=wvl
  mask.slit=slit
ENDELSE


END
