;+
;
; Project   : s3drs reconstruction software
;                   
; Name      : p_getmask
;               
; Purpose   : part of Pixon, part of the s3drs GUI
;               
; Explanation: part of the Pixon wrappers used to access and
; manipulate the various arcane Pixon structures and objects.
;               
; routine to return a mask for a SECCHI, SOHO or generic mission
;
; Use       : typically called from 's3drs.pro' 
;    
; Inputs    : (various)
;               
; Outputs   : (various)
;
; Keywords  : (various)
;               
; Common    : none
;               
; Restrictions: none
;               
; Side effects: none
;               
; Category    : reconstruction, pixon
;               
; Prev. Hist. : None.
;
; Written     : Sandy Antunes, NRC, March-April 2005-2009
;               
;-            
; requires the idl_libs/astron/images/dist_circle.pro routine.
;
; routine to return a mask for a SECCHI, SOHO or generic mission
;
; Includes optional parameter 'ratio' to increase or shrink
;   the inner mask radius to the desired ratio of the original,
;   e.g. 1.1 will increase make the mask 110% of original size,
;   while 0.9 will make a smaller mask.  Usually used to enlarge
;   the mask to enable fainter outer features to be visible, since
;   shrinking the mask means we are using a mask smaller than the
;   actual occulter and therefore using bad data.
;
; Optional /cor2horn will include a mask for Cor2B over the 'devils
; horn' misalignment region.  Note we do not check whether you are
; using cor2B, but simply create that mask if /cor2horn is set.
;
; If detector='corners', this will return a mask that removes the corners,
; resulting in a circular region.
; This is good for cleaning data that has non-detector stuff at corners.
;
;
; sample usage:
;  mask=p_getmask(sr.detector[i],sr.Ndata[i],p_getk0(sr,i),sr.L0tau[i],$
;    ratio=1.0)
; or more directly
;
;mask=p_getmask('COR1',hdr.NAXIS1,[hdr.CRPIX1,hdr.CRPIX2],HDR.cdelt1/HDR.rsun)
; or just mask=p_getmask(hdr=hdr)
;
; or mask=p_getmask(sr=pxwrapper.sr,iele=iele)
;
; If you specify 'rocc' and/or 'routside', they overwrite the
; instrument defaults.
;
; You can pass 'rpixels=rpixels' to return an array of the final
; inner and outer masks calculated, in pixels.
;

FUNCTION p_getmask,detector,N,k0,L0tau,ratio=ratio,hdr=hdr,cor2horn=cor2horn,$
                   rocc=rocc,routside=routside,rpixels=rpixels,$
                   iele=iele,corners=corners,sr=sr,offshift=offshift,ab=ab

  cor2horn=KEYWORD_SET(cor2horn)
  if (n_elements(ratio) eq 0) then ratio=1.0
  if (n_elements(offshift) eq 0) then offshift=0
  if (n_elements(ab) eq 0) then ab=''

  corners=KEYWORD_SET(corners)

  if (cor2horn and ratio lt 2.0) then begin
      ; best region for masking off Cor2B artifacts
      ratio=2.0; first, double the radius, though 1.9 is also fine
  end

  if (n_elements(sr) ne 0) then begin
      ; extract elements from wrapper

      ; note this special case of recursive calling for all elements!
      if (n_elements(iele) eq 0) then begin
          ; recursive call!  generate and return the entire set
          mset=fltarr(sr.Ndata[0],sr.Ndata[0])
          for i=0,sr.Nd-1 do begin
              m=p_getmask(detector,N,k0,L0tau,ratio=ratio,hdr=hdr,$
                cor2horn=cor2horn,rocc=rocc,routside=routside,sr=sr,iele=i)
              mset=[[[mset]],[[m]]]
          end
          return,mset[*,*,1:*]
      end

      ; note, we do not overwrite a user-specified 'detector' if given
      if (n_elements(detector) eq 0) then detector=sr.detector[iele]
      N=sr.Ndata[iele]
      k0=p_getk0(sr,iele)
      L0tau=sr.L0tau[iele]

      if (sr.sat_name[iele] eq 'STEREO_B') then ab='B'

  end


  if (n_elements(hdr) ne 0) then begin
      ; extract elements from header

      ; note, we do not overwrite a user-specified 'detector' if given
      if (n_elements(detector) eq 0) then detector=hdr.detector
      N=hdr.NAXIS1
      k0=[hdr.CRPIX1,hdr.CRPIX2]
      L0tau=HDR.cdelt1/HDR.rsun
      if (tag_exist(hdr,'obsvtry')) then begin
          if (hdr.obsvtry eq 'STEREO_B') then ab='B'
      end

  end

  if (n_elements(N) eq 0) then N=64; guess at default
  if (n_elements(k0) eq 0) then k0=[(N-1)/2.0,(N-1)/2.0]; use near center
  if (n_elements(L0tau) eq 0) then begin
      L0tau = p_instrspec('fov',detector) / double(N/2)
  end

  ; occulter sizes taken from the web pages, thus are approximate.
  ; use the 'ratio' keyword to adjust as needed.

  r_outside=p_instrspec('fov',detector)
  r_occ=p_instrspec('occulter',detector)

  if (strupcase(detector) eq 'CORNERS') then begin
      L0tau=1
      r_outside=N/2
      r_occ=0.0
  end

  r_occ=r_occ*1.05; always add a little margin to handle rounding

  ; special case, extended mask for B
  ;print,'ab is ',ab,' and detector is ',detector
;  if (strupcase(detector) eq 'COR2' and ab eq 'B') then r_occ=r_occ*1.5

  if (n_elements(rocc) ne 0) then r_occ=rocc
  if (n_elements(routside) ne 0) then r_outside=routside

;  if (detector eq 'C2' or detector eq 'C3') then begin
;      occ = t_param(detector,'OCCENTER')
;      if (datascaling ne 1) then occ=occ/datascaling
;      r_occ = t_param(detector,'OCCULTER')
;      if (datascaling ne 1) then r_occ=r_occ/datascaling
;      r_outside = r_outside/L0tau
;  end else begin
      ; non-SOHO, assume occulter center is sun-center

; Assumes all images give the optical center as the occulter center

  ;print,r_occ,r_outside,L0tau,k0
  r_occ = r_occ/L0tau
  r_outside = r_outside/L0tau
;  end

  r_occ = r_occ * ratio; apply any additional scaling

  mask=make_array(N,N,/byte,value=1) ; # initially, no mask needed

  ;print,L0tau,r_occ,r_outside,k0

  if (r_occ ne 0 or r_outside ne 0) then begin
      ; first make r scales
      rmask=fltarr(N,N)
      dist_circle,rmask,N,k0[0],k0[1]
;      rmask=rmask*sr.l0tau[0] ; no need for this, we already scale r_o values
      ie=where(rmask le r_occ or rmask ge r_outside)
      if (ie[0] ne -1) then mask[ie]=0
  end else begin
      print,'(data says no mask needed, proceeding)'
  end

;  print,'Mask center is ',k0[0],k0[1]


  if (cor2horn) then begin
      ; best region for masking off Cor2B artifacts
      ; note we already doubled the radius
      ; then add the extra 'horns'
      xlow=  N * 20.5/56.0
      xhigh= N * 36.0/56.0
      ylow=  N * 21.5/52.0
      yhigh= N * 23.0/52.0
      mask[xlow:xhigh,ylow:yhigh]=0
  end

  rpixels=[r_occ,r_outside]

  if (offshift ne 0) then begin
      mask2=mask*0
      N2=(N/2)
      case offshift of
          1: mask2[0:N2-1,*]=mask[N2:*,*] ; Left open
          2: mask2[N2:*,*]=mask[0:N2-1,*] ; Right open
          3: mask2[*,0:N2-1]=mask[*,N2:*] ; Down open
          4: mask2[*,N2:*]=mask[*,0:N2-1] ; Up open
      endcase
      mask=mask2
  end

  ;tv_multi,mask,header=detector

  return,mask

END
