;------------------------------------------------------------------------------
;+
; NAME:
;   match_sample
;
; PURPOSE:
;   Starting with an input sample catalog matches to the redshifts.
;
; CALLING SEQUENCE:
;   match_sample,'catalog-file-name','output-file-name'
;
; OPTIONAL INPUTS:
;
; OUTPUTS:
;   A fits file containing the match.
;                                
; COMMENTS:
;   Fills in the "imatch" and "z" entries of the structure.
;     imatch==0:  Not matched to a redshift.
;     imatch==1:  Matched to a new BOSS redshift.
;     imatch==2:  Matched to an old SDSS redshift.
;     imatch==3:  Used later for fiber collision corrected. 
;     imatch==4:  Star (remove from target list when computing completeness).
;     imatch==5:  Used later for redshift failure corrected.
;     imatch==6:  Fiber collision, but we cannot find a galaxy*
;			redshift for it  NOT CURRENTLY USED (BR)!  
;                       perhaps useful in next generation fiber collisions.
;     imatch==7:  Redshift failure, but we cannot find a galaxy*
;			redshift for it
;     imatch==8:  had a good redshift, but disgarded a close pair containing a
;                 legacy galaxy to enforce close pair uniformity.
;
; Note imatch = 6 and 7 will be filled in here, but could become 3 or 5 once
;			fiberc_zfail is run.
;
;      comp is the sector completeness for the galaxy (where fiber collided/redshift failure
;      galaxies are counted as 'observed.'
;      cp_comp tells you the number of resolved fiber collisions in nplate > 1 regions.
;      cp_comp filled in by fiberc_zfail.pro
; EXAMPLES:
;
; REQUIREMENTS:
;   A bunch of stuff we should document here.
; 
; REVISION HISTORY:
;   16-May-2011 Written by Martin White (LBNL)
;   01-Jun-2011 Edited by Shirley Ho (LBNL) including the ingroup
;		flag which includes the information whether a galaxy
;		is fiber collided or not.
;   06-Jun-2011 Edited by Shirley Ho (LBNL) including Zcode redshift.
;   19-Jul-2011 Edited by Shirley Ho (LBNL) including possibility of
;		using a non-updated zcode file, while using the newer
;		spAll file.
;    6-Sep-2011 MJW: Tidy up
;    8-Sep-2011 Edited by Shirley Ho (LBNL): Keeping track of fiber
;		collided galaxies and redshift failure galaxies
;   22-Sep-2011 Edited by Shirley Ho (LBNL): Separating the part doing
;		simple matching, and the part doing fiber collided and
;		redshift failure corrections
;    3-Oct-2011 MJW: Remove zcode stuff
;   20-Apr-2012 SH: Added weight_fkp and weight_star fields.
;   20-Apr-2012 MJW: Tidied up.
;   21-Jun-2012 BR: added N (0) or S (1) only option.  For no split, choose -1.                              
;   23-May-2013 SH: Added and matched fiberid and mjd to match output files format to sas.                              
;   4-June-2013 SH: Added left right option (LRopt) [L-> -1, R -> 1,  no split: 0] so that we split the sample into left and right of RA= 180 to check for oddities in reconstruction that maybe created by weird dndz.                               
;-

pro match_sample,target_file,NSopt,LRopt,spall_file,output_file
  print,' '
  print,'Match sample starting with:'
  print,'  target_file=',target_file
  print,'  NSopt      =',NSopt
  print,'  LRopt      =',LRopt
  print,'  spall_file      =',spall_file
  print,'  output_file=',output_file

  ; Set up some useful paths for the code below.
  data_dir  = filepath(root=getenv("BOSSLSS_DIR"),"/data/")
  ;;; there is now an extra RUN1D file directory.
  ;; this is now a program input.
  ;spall_file = getenv("SPECTRO_DATA")+'/'+getenv("RUN1D")+'/spAll-'+getenv("RUN1D")+'.fits'

  ; Should this be part of the bosslss product, or should we fetch it
  ; from the server before running this code or what?
  ;known_file= filepath(root=getenv("BOSSLSS_DIR"),$
  ;              "/data/spAll_primary_good.fits")
  ;; this is the spAll file used for DR10/DR11 analysis; roundoff error in new file from Schlegel causes differences from DR10/DR11 catalogs.
  known_file = "inputfiles/spAll_primary_good_dr10dr11.fits"

  ; Start with the target list.
  print,'Opening target photometry file: ',target_file
  dd_targ = mrdfits(data_dir+target_file,1,hdr)

  ;; N/S split
  euler,dd_targ.ra,dd_targ.dec,glong,glat,1
  north = where(glat GT 0, cntnorth)
  south = where(glat LE 0, cntsouth)
  print,'NS target split: ',cntnorth,cntsouth
  if(NSopt EQ 0) then begin 
    dd_targ = dd_targ[north]
  endif
  if(NSopt EQ 1) then begin 
    dd_targ = dd_targ[south]
  endif
  ;; L/R split around RA=180 ; investigating dipole in reconstruction
  left = where(dd_targ.ra LE 180, cntleft)
  right = where(dd_targ.ra  GT 180, cntright)

  print,'LR  target split: ',cntleft,cntright
  if (LRopt EQ 0) then begin 
    dd_targ = dd_targ 
  endif 
  if(LRopt EQ -1) then begin 
    dd_targ = dd_targ[left]
  endif
  if(LRopt EQ 1) then begin 
    dd_targ = dd_targ[right]
  endif
  print,'keeping this many galaxies: ',n_elements(dd_targ)
  print,'keeping this many galaxies: ',n_elements(dd_targ)


  ;; new list of final fields to keep downstream.
  ;; Q1: is rerun a string or an integer?  I'm going string, which means
  ;; we still need to check this gives int -> string conversion of rerun field.
  ;;
  ee = {ra:0.D,dec:0.D,$
        ;; 
        run:0L,rerun:'',camcol:0L,field:0L,id:0L,$
        ichunk:0L,tchunk:0L,ipoly:0L,isect:0L,$
        fracpsf:fltarr(5),expflux:fltarr(5),devflux:fltarr(5),$
        psfflux:fltarr(5),modelflux:fltarr(5),fiber2flux:fltarr(5),$
        extinction:fltarr(5),$
        imatch:0L,z:0.0,$
        weight_fkp:1.0,weight_cp:1.0,weight_noz:1.0,weight_star:1.0,$
        weight_seeing:1.0, weight_systot:1.0,$
        nz:0.0,comp:0.0,cp_comp:1.0, plate:-10L,fiberid:1L,mjd:1L, ntiles:0,$
        ;new stuff from collated file
        finalN:0L,finalid:0L,nassigned:0L,whichfinal:0L,$
        tile:intarr(3),spectile:0L,$
        collateindx:0L,icollided:0L,$
        coll_group_finalid:lonarr(10),$
        coll_group_bosstarget1:lonarr(10),$
        ;; tmp addition?  not sure which is most useful
        ingroup:-1L,firstgroup:-1L,multgroup:-1L,nextgroup:-1L$
        }

  ee = replicate(ee,n_elements(dd_targ))
  struct_assign,dd_targ,ee  ; Copy fields in dd_targ to ee

  ; struct assign zeros any unfound field, so reassign them here.
  ee[*].weight_fkp = 1.0
  ee[*].weight_cp = 1.0
  ee[*].weight_noz = 1.0
  ee[*].weight_star= 1.0
  ee[*].weight_seeing= 1.0
  ee[*].weight_systot= 1.0
  ee[*].plate = -10L
  ee[*].fiberid = -10L
  ee[*].mjd = -10L
  ee[*].cp_comp = 1.0

  ; Add legacy redshifts first, since those should be overwritten by
  ; BOSS redshifts (in case they do overlap)
  print,'Reading known redshifts from ',known_file
  dd_spec = mrdfits(known_file,1,hdr)
  dd_spec = dd_spec[where( (dd_spec.zwarning EQ 0) AND $
                           (dd_spec.specprimary EQ 1) AND $
                           strmatch(dd_spec.class,"GALAX*") )]
  spherematch,dd_targ.ra,dd_targ.dec,$
              dd_spec.plug_ra,dd_spec.plug_dec,$
              2./3600.,dd_targ_match,dd_spec_match
  size_match  = n_elements(dd_targ_match)
  print,'Matched ',size_match,' elements to ',known_file
  ee[dd_targ_match].imatch = 2
  ee[dd_targ_match].z      = dd_spec[dd_spec_match].z
  ;; for reproducing DR10/DR11 with old primary file, these aren't available.
  ;; ee[dd_targ_match].plate = dd_spec[dd_spec_match].plate
  ;; ee[dd_targ_match].fiberid = dd_spec[dd_spec_match].fiberid
  ;; ee[dd_targ_match].mjd= dd_spec[dd_spec_match].mjd


  ; Get the BOSS redshifts.
  print,'Reading new redshifts from ',spall_file
  ;; changed this so reading in the fits file doesn't take up so much memory.
  ;; stupid mrdfits read takes 2x memory according to Schlegel.
  ;; reads it in in chunks
  dd_spec = hogg_mrdfits(spall_file,1,hdr,nchunk=10)
  ;; 
  print, 'read finished.'
  dd_spec = dd_spec[where(dd_spec.specprimary EQ 1)]
  print,'Have ',n_elements(dd_spec),' galaxy targets with specprimary==1.'

  spherematch,dd_targ.ra,dd_targ.dec,$
              dd_spec.ra,dd_spec.dec,$
              2./3600.,dd_targ_match_zpipe,dd_spec_match
  print,'Matched ',n_elements(dd_targ_match_zpipe),' elements to ',spall_file
  print,'Will use z_noqso redshifts.'
  ee[dd_targ_match_zpipe].z = dd_spec[dd_spec_match].z_noqso
  ee[dd_targ_match_zpipe].spectile = dd_spec[dd_spec_match].tile
  ;; necessary for sector-by-sector fiber collision corrections
  ;; based on how many plates were observed in each sector.
  ee[dd_targ_match_zpipe].plate = dd_spec[dd_spec_match].plate
  ee[dd_targ_match_zpipe].fiberid = dd_spec[dd_spec_match].fiberid
  ee[dd_targ_match_zpipe].mjd= dd_spec[dd_spec_match].mjd
  
  ; Set the flags, assuming everything is a good match.
  ; Below we change imatch to account for stars and redshift failures.
  ee[dd_targ_match_zpipe].imatch = 1

  ; Check for redshift failures -- don't change .z tag just imatch.
  dd_spec_matched = dd_spec[dd_spec_match]
  tmp_spec = where(dd_spec_matched.zwarning_noqso GT 0, count)
  dd_spec_matched = dd_spec_matched[tmp_spec]
  spherematch,dd_targ.ra,dd_targ.dec,$
              dd_spec_matched.ra, dd_spec_matched.dec,$
              2./3600.,dd_targ_match_badz,dd_spec_bad_match
  ee[dd_targ_match_badz].imatch = 7
  print,'Marked ',n_elements(dd_targ_match_badz),$
        ' redshift failures as imatch=7.'

  ; Mark stars -- don't change .z tag just imatch.
  ; David Schlegel said zwarning_noqso is correct!  Since we 
  ; know the object is a galaxy target, it's almost 100% 
  ; certain it's not a QSO.
  starindx = where((dd_spec.zwarning_noqso    EQ 0) AND $
                   (dd_spec.specprimary EQ 1) AND $
                   strmatch(dd_spec.class,"STAR*") )
  print,'Pipeline has ',n_elements(starindx),' stars.'
  ; spherematch the stars to targets
  dd_spec_stars = dd_spec[starindx]
  spherematch,dd_targ.ra,dd_targ.dec,$
              dd_spec_stars.ra,dd_spec_stars.dec,$
              2./3600.,dd_targ_match,dd_spec_stars_match
  ee[dd_targ_match].imatch = 4 
  ee[dd_targ_match].plate = dd_spec_stars[dd_spec_stars_match].plate
  ee[dd_targ_match].fiberid = dd_spec_stars[dd_spec_stars_match].fiberid
  ee[dd_targ_match].mjd = dd_spec_stars[dd_spec_stars_match].mjd
  print,'Marked ',n_elements(dd_targ_match),' stars as imatch=4.'

  ; Flag fiber collision objects.
  ;; BR: removing imatch = 6 since we don't use it in fiber collision corrections anymore.
  ;fiber_col = where( (ee.ingroup EQ 1) and (ee.imatch EQ 0)) 
  ;ee[fiber_col].imatch = 6   ; flagging the fiber collisions
  ;print,'Marked ',n_elements(fiber_col),$
  ;      ' collided but unmatched objects as imatch=6.'

  print,'Histogram of imatch values:'
  print,histogram(ee.imatch,min=0,max=8)

  ; Write out the data to a useful FITS file.
  print,'Writing:',output_file
  mwrfits,ee,data_dir+output_file,/create

end
