;******************************************************************************
;* File name: ql_operation.pro                                                *
;*                                                                            *
;* Content  : 	ql_reset_selection                                            *
;*              ql_operation                                                  *
;*                                                                            *
;*                                                                            *
;* Date		Author		Comment                                       *
;* -------------------------------------------------------------------------- *
;* 22-01-94	E.PETIT		Creation                                      *
;* 16-03-94	E.PETIT		Remove Test on extrema                        *
;* 25-03-94	E.PETIT		Wavelen ref                                   *
;* 14-04-94	E.PETIT		remove discret format                         *
;* 22-04-94	E.PETIT		modify stat call                              *
;* 18-05-94	E.PETIT		Remove control before allowing operation(s)   *
;* 11-07-94	E.PETIT		Extrema Pb after operation                    *
;* 08-09-94	E.PETIT		Exp time Pb  after operation                  *
;* 11-01-95	E.PETIT		New header                                    *
;* 08-03-95	E.PETIT		Add multiplication                            *
;*                                                                            *
;******************************************************************************




;***
;##############################################################################
;#Function  name   : ql_reset_selection                                       #
;#LEVEL            :                                                          #
;#                                                                            #
;#Author           : Emmanuel PETIT                                           #
;#Language         : IDL                                                      #
;#Purpose          : reset stack selection button state                       #
;#Creation date    : 25-02-94                                                 #
;#External modules :                                                          #
;#                                                                            #
;#Call sequence    :                                                          #
;#                                                                            #
;#Arguments        : nb_button: number of button to reset                     #
;#                   index    : array of button indexes                       #
;#                   target   : IMAGE/PROFILE                                 #
;#                                                                            #
;#Description      :                                                          #
;#                                                                            #
;#                                                                            #
;##############################################################################
;*** 

PRO ql_reset_selection, nb_button, index, target

  ;============================================================================
  ;                       Common Block in use
  ;============================================================================
  COMMON stack_com
  COMMON button_id_com
  COMMON const_com

  ;============================================================================
  ;                       Initialization
  ;============================================================================

  ;============================================================================
  ;                       Processing 
  ;============================================================================
  WIDGET_CONTROL, /HOURGLASS 


    ; Update stack header, file and button state
    ; ------------------------------------------
    FOR i=0,nb_button-1 DO BEGIN
      IF (target EQ IMAGE) THEN stack_hd.i(index(i)).selected  = 0 $
      ELSE                      stack_hd.p(index(i)).selected  = 0
      WIDGET_CONTROL, button_id(target,index(i)), SET_BUTTON=0
    ENDFOR

    POINT_LUN, stack_unit, 0
    WRITEU   , stack_unit, stack_hd
END

;***
;##############################################################################
;#Function  name   : ql_operation                                             #
;#LEVEL            : 1                                                        #
;#                                                                            #
;#Author           : Emmanuel PETIT                                           #
;#Language         : IDL                                                      #
;#Purpose          : res = n1*I1 + n2*I2                                      #
;#Creation date    : Feb 94                                                   #
;#External modules :                                                          #
;#                                                                            #
;#Call sequence    : Called by Event Handler                                  #
;#                                                                            #
;#Arguments        : curr_header: curr_header_i or curr_header_p              #
;#                   curr_data: curr_data_i or curr_data_p                    #
;#                   curr_dctrl: curr_dctrl_i or curr_dctrl_p                 #
;#                   curr_banner: curr_banner_i or curr_banner_p              #
;#                   index_1: First operande index in stack                   #
;#                   index_2: Second operande index in stack                  #
;#                   mode   : ADDITION, SOUSTRACTION or AVERAGE               #
;#                   target : IMAGE or PROFILE                                #
;#                   err    : 0 if OK                                         #
;#                                                                            #
;#Description      :                                                          #
;#                                                                            #
;#                                                                            #
;##############################################################################
;*** 

PRO ql_operation, curr_header , $
                  curr_data   , $
                  curr_dctrl  , $
                  curr_banner , $
                  nb_op       , $
                  index       , $
                  mode        , $
                  target      , $
                  err

  ;============================================================================
  ;                       Common Block in use
  ;============================================================================
  COMMON stack_com
  COMMON curr_data_i_com
  COMMON curr_data_p_com
  COMMON button_id_com
  COMMON const_com
  COMMON load_flg_com
  COMMON flag_com
  COMMON const2_com

  ;============================================================================
  ;                       Initialization
  ;============================================================================
  err     = 0
  i       = 0 
  tmp_header = curr_header
  offset  = LONARR (STACK_SZ)
  xmin    = FLTARR (STACK_SZ)
  xmax    = FLTARR (STACK_SZ)
  ymin    = FLTARR (STACK_SZ)
  ymax    = FLTARR (STACK_SZ)
  xdetmin = FLTARR (STACK_SZ)
  ydetmin = FLTARR (STACK_SZ)
  type    = INTARR (STACK_SZ)
  comp    = INTARR (STACK_SZ)
  popnum  = INTARR (STACK_SZ)
  targ    = INTARR (STACK_SZ)
  vawe    = FLTARR (STACK_SZ)
  pix     = INTARR (STACK_SZ)
  exptime = FLTARR (STACK_SZ)
  xsz     = INTARR (STACK_SZ)
  ysz     = INTARR (STACK_SZ)
  fmt     = INTARR (STACK_SZ)

  ;============================================================================
  ;                       Processing 
  ;============================================================================
  WIDGET_CONTROL, /HOURGLASS 

  ; ---------------------------------------
  ; Get data used for compatibility control
  ; ---------------------------------------
  FOR i=0, nb_op-1 DO BEGIN
    IF (target EQ IMAGE) THEN BEGIN 
      offset(i) = stack_hd.i(index(i)).offset
      xmin(i)   = stack_hd.i(index(i)).display_ctrl.x.min
      xmax(i)   = stack_hd.i(index(i)).display_ctrl.x.max
      ymin(i)   = stack_hd.i(index(i)).display_ctrl.y.min
      ymax(i)   = stack_hd.i(index(i)).display_ctrl.y.max
      xdetmin(i)= stack_hd.i(index(i)).display_ctrl.x.det_min
      ydetmin(i)= stack_hd.i(index(i)).display_ctrl.y.det_min
      xsz (i)   = stack_hd.i(index(i)).display_ctrl.x.nb_dot
      ysz (i)   = stack_hd.i(index(i)).display_ctrl.y.nb_dot
    ENDIF ELSE BEGIN
      offset(i) = stack_hd.p(index(i)).offset
      xmin(i)   = stack_hd.p(index(i)).display_ctrl.x.min
      xmax(i)   = stack_hd.p(index(i)).display_ctrl.x.max
      xsz (i)   = 1
      ysz (i)   = stack_hd.p(index(i)).display_ctrl.x.nb_dot
    ENDELSE

    POINT_LUN, stack_unit, offset(i)
    READU    , stack_unit, tmp_header
    type(i)   = tmp_header.DATATYPE
    comp(i)   = tmp_header.SSCOMPRM
    popnum(i) = tmp_header.SSPOPUDP
    targ(i)   = tmp_header.SSTARGET
    vawe(i)   = tmp_header.SSWAVEL 
    pix(i)    = tmp_header.SSREFPIX
    exptime(i)= tmp_header.SSEXPTIM
    fmt (i)   = tmp_header.DATAFMT
  ENDFOR



  ; -------------------  
  ; Check compatibility
  ; -------------------  
  FOR i=1, nb_op-1 DO BEGIN
;    IF type(i)   NE type(0)   THEN err = 13	; same type
    IF xsz (i)   NE xsz(0)    THEN err = 13	; same size /X
    IF ysz (i)   NE ysz(0)    THEN err = 15	; same size /Y
;    IF comp(i)   NE comp(0)   THEN err = 14	; same method of compression
;    IF popnum(i) NE popnum(0) THEN err = 16	; same pop number
;    IF targ(i)   NE targ(0)   THEN err = 17	; same target
;    IF vawe(i)   NE vawe(0)   THEN err = 18	; same wavelength index
;    IF pix(i)    NE pix(0)    THEN err = 19	; same reference pixel
;    IF xmin(i)   NE xmin(0)   THEN err = xx	; same xmin
;    IF xmax(i)   NE xmax(0)   THEN err = xx	; same xmax
;    IF (target EQ IMAGE) THEN BEGIN
;      IF ymin(i) NE ymin(0) THEN err = xx	; same ymin for image only
;      IF ymax(i) NE ymax(0) THEN err = xx	; same ymax for image only
;    ENDIF
  ENDFOR  

  ; ----------------------------
  ; Special Check for Flat Field
  ; ----------------------------
  subflg = 0
  ffidx = -1
  FOR i=0,nb_op-1 DO IF (comp(i) EQ FF_ID) THEN ffidx = i
  IF (ffidx NE -1) THEN BEGIN 
    err = 0
    subflg = 0
    FOR i=0, nb_op-1 DO IF (xsz(i) GT xsz(ffidx)) OR (ysz(i) GT ysz(ffidx)) THEN err = 13  
    FOR i=0, nb_op-1 DO IF (xsz(i) NE xsz(ffidx)) OR (ysz(i) NE ysz(ffidx)) THEN subflg = 1
  ENDIF


  IF (err NE 0) THEN BEGIN 		; Error -> exit
    ql_reset_selection, nb_op, index, target
    RETURN
  ENDIF

  ; ---------------------------
  ; Compute Requested operation
  ; ---------------------------
  curr_header.SSEXPTIM = 0.0
  sz_x      = xsz(0)
  sz_y      = ysz(0)
  curr_data = DOUBLE(FLTARR(sz_x, sz_y)); computation in double format


  FOR i=0,nb_op-1 DO BEGIN
    ; load current operande
    ; ---------------------
    IF (fmt(i) EQ 1) THEN tampon = BYTARR (xsz(i), ysz(i))
    IF (fmt(i) EQ 2) THEN tampon = INTARR (xsz(i), ysz(i))
    IF (fmt(i) EQ 3) THEN tampon = LONARR (xsz(i), ysz(i))
    IF (fmt(i) EQ 4) THEN tampon = FLTARR (xsz(i), ysz(i))

    IF (target EQ IMAGE) THEN POINT_LUN,stack_unit,stack_hd.i(index(i)).offset+RRD_HD_SZ $
    ELSE                      POINT_LUN,stack_unit,stack_hd.p(index(i)).offset+RRD_HD_SZ 
    READU, stack_unit, tampon
    
    ; Compute operation- result in a float array
    ; ------------------------------------------
    IF (exptime(i) EQ 0) THEN exptime(i) = 1.0		; no 0 divide !
    CASE mode OF
       ADDITION    : BEGIN
         curr_data  = TEMPORARY(curr_data) + DOUBLE(tampon)
         curr_header.SSEXPTIM = curr_header.SSEXPTIM + exptime(i)
       END

       SOUSTRACTION: BEGIN
         IF exptime(0) NE exptime(1) THEN BEGIN	; normalize result
           IF (i EQ 0) THEN curr_data = DOUBLE (tampon)/exptime(i) $
           ELSE             curr_data = TEMPORARY(curr_data) - DOUBLE(tampon)/exptime(i)
           curr_header.SSEXPTIM = 1.0
         ENDIF ELSE BEGIN
           IF (i EQ 0) THEN curr_data = DOUBLE (tampon)$
           ELSE             curr_data = TEMPORARY(curr_data) - DOUBLE(tampon)
           curr_header.SSEXPTIM = exptime(0)
         ENDELSE
       END

       AVERAGE      : BEGIN
         IF exptime(i) EQ 0 THEN exptime(i)=1	; no 0 divide !
         curr_data  = TEMPORARY(curr_data) + DOUBLE(tampon)/exptime(i)
         curr_header.SSEXPTIM = 1.0
       END

      MULTIPLICATION: BEGIN
         IF (i EQ 0) THEN BEGIN
           curr_data = DOUBLE(tampon)
           curr_header.SSEXPTIM = exptime(i)
         ENDIF ELSE BEGIN
           curr_data  = TEMPORARY(curr_data) * DOUBLE(tampon)
           curr_header.SSEXPTIM = curr_header.SSEXPTIM * exptime(i)
         ENDELSE
      END

      DIVISION: BEGIN
         IF (exptime(0) NE exptime(1))  THEN BEGIN	; normalize result
           IF (i EQ 0) THEN curr_data = DOUBLE (tampon)/exptime(i) $
           ELSE             curr_data = TEMPORARY(curr_data) / (DOUBLE(tampon)/exptime(i))
           curr_header.SSEXPTIM = 1.0
         ENDIF ELSE BEGIN
           IF (i EQ 0) THEN curr_data = DOUBLE (tampon)$
           ELSE             curr_data = TEMPORARY(curr_data) / DOUBLE(tampon)
           curr_header.SSEXPTIM = exptime(0)
         ENDELSE
      END

      FLAT_FIELD: BEGIN
        IF (i EQ 0) THEN BEGIN
          IF (comp(i) EQ FF_ID) THEN BEGIN
            IF (subflg EQ 1) THEN BEGIN
              ; extract sub image from flat field
              ; prior to division
              tampon = DOUBLE(tampon(xdetmin(1):xdetmin(1)+xsz(1)-1,ydetmin(1):ydetmin(1)+ysz(1)-1))
              FOR kk=0,xsz(1)-1 DO FOR ll=0, ysz(1)-1 DO IF (tampon(kk,ll) EQ 0) THEN tampon(kk,ll) =1.0
              tampon = 1.0/tampon
              curr_data = tampon
            ENDIF  ELSE BEGIN 
              FOR kk=0,xsz(1)-1 DO FOR ll=0, ysz(1)-1 DO IF (tampon(kk,ll) EQ 0) THEN tampon(kk,ll) =1.0
              curr_data = 1.0/tampon
            ENDELSE
          ENDIF ELSE BEGIN
            curr_data = DOUBLE(tampon)
            curr_header.SSEXPTIM = exptime(i)
            curr_header.DATATYPE = type(i)
            curr_header.SSWAVEL  = vawe(i)
            curr_header.SSREFPIX = pix(i)
            curr_header.SSCOMPRM = comp(i)
          ENDELSE
        ENDIF ELSE BEGIN
          IF (comp(i) EQ FF_ID) THEN BEGIN
            IF (subflg EQ 1) THEN BEGIN
              ; extract sub image from flat field
              ; prior to division
              tampon = DOUBLE(tampon(xdetmin(0):xdetmin(0)+xsz(0)-1,ydetmin(0):ydetmin(0)+ysz(0)-1))
              FOR kk=0,xsz(0)-1 DO FOR ll=0, ysz(0)-1 DO IF (tampon(kk,ll) EQ 0) THEN tampon(kk,ll) =1.0
              tampon = 1.0/tampon
              curr_data = TEMPORARY(curr_data) * tampon
            ENDIF ELSE BEGIN
              FOR kk=0,xsz(0)-1 DO FOR ll=0, ysz(0)-1 DO IF (tampon(kk,ll) EQ 0) THEN tampon(kk,ll) =1.0
              curr_data = TEMPORARY(curr_data) / tampon
            ENDELSE
          ENDIF ELSE BEGIN
            curr_data = TEMPORARY(curr_data) * DOUBLE(tampon) 
            curr_header.SSEXPTIM = exptime(i)
            curr_header.DATATYPE = type(i)
            curr_header.SSWAVEL  = vawe(i)
            curr_header.SSREFPIX = pix(i)
            curr_header.SSCOMPRM = comp(i)
          ENDELSE
        ENDELSE
        curr_header.SSSTAT = curr_header.SSSTAT OR '40'X
      END
    ENDCASE
  ENDFOR

  ; Back to float after computation
  ; -------------------------------
  curr_data = FLOAT(curr_data)
  curr_header.DATAFMT = 4		; Final expression in float
  curr_header.SSTYPIMG = -1

  ; ------------------
  ; Update curr_header
  ; ------------------
  ql_init_banner, curr_data, target , err
  curr_header.SSBPADDY = maxpix MOD sz_x
  curr_header.SSBPADDZ = maxpix/sz_x

  curr_header.SSIMGTOT = LONG(TOTAL(curr_data))
  curr_header.SSBPCNTS = LONG(curr_banner.max)

  IF (ffidx EQ -1) THEN BEGIN
    curr_header.SSWAVEL  = vawe(0)
    curr_header.SSREFPIX = pix(0)
    curr_header.DATATYPE = type(0)
  ENDIF 


  ; ------------------------------
  ; Update  curr_dctrl/curr_header
  ; ------------------------------
  IF (target EQ IMAGE) THEN BEGIN
    IF (subflg EQ 1) AND (ffidx EQ 0)THEN $
      curr_dctrl = stack_hd.i(index(1)).display_ctrl  $
    ELSE $
      curr_dctrl = stack_hd.i(index(0)).display_ctrl
  ENDIF ELSE BEGIN
    curr_dctrl = stack_hd.p(index(0)).display_ctrl
  ENDELSE


  IF (target EQ PROFILE) AND (curr_banner.min NE curr_banner.max) THEN BEGIN
    curr_dctrl.y.min = MIN (curr_data)
    curr_dctrl.y.max = MAX (curr_data)
    curr_dctrl.y.plot_min = curr_dctrl.y.min
    curr_dctrl.y.plot_max = curr_dctrl.y.max
  ENDIF

  CASE mode OF
    ADDITION       :res = ql_manage_proc(curr_dctrl, PUSH, 5)
    SOUSTRACTION   :res = ql_manage_proc(curr_dctrl, PUSH, 6)
    AVERAGE        :res = ql_manage_proc(curr_dctrl, PUSH, 7)
    MULTIPLICATION :res = ql_manage_proc(curr_dctrl, PUSH, 22)
    DIVISION       :res = ql_manage_proc(curr_dctrl, PUSH, 23)
    FLAT_FIELD     :res = ql_manage_proc(curr_dctrl, PUSH, 04)
  ENDCASE

  ; -------------------------------------------
  ; Update stack header, stack and button state
  ; -------------------------------------------
  ql_reset_selection, nb_op, index, target
END  
