;;-----------------------------------------------------------------------------
;; PURPOSE:
;;	Retrieves a bias file from the database or using the serial overclock
;;	pixels
;;
;; CALLING SEQUENCE:
;;	RESULT = getBias(hdr, inst, date, mode, /OCLOCK, IMG=img)
;;
;; REQUIRED INPUTS:
;;	hdr - the fits header of the image. Will be modified with the bias
;;		frame used
;;	inst - string: the instrument for the dark needed (e.g. HRIVIS)
;;	date - string: the latest date in ISO format of the model to use
;;	mode - Image mode
;;	flags - image map specifying the flags for the image
;;
;; OUTPUTS:
;;	RETURN - the bias frame to subtract from the image
;;
;; OPTIONAL INPUT KEYWORDS:
;;	oclock - if specified than the bias frame is created from the serial overclock
;;		pixels
;;	img - the image we're creating a bias for. Needed if OCLOCK is specified.
;;
;; EXAMPLE:
;;      IDL> bias=getBias(hdr, inst, date, mode, /OCLOCK, IMG=img)
;;
;; PROCEDURES USED (i.e. called directly!):
;;	DI_sqlQuery - Query the SQL server
;;	getSQLServer - Retrives info on how to acess the SQL server
;;	getLocFn - Converts a remote filename into a local one
;;	getBiasCols - Determines where the bias columns are
;;
;; MODIFICATION HISTORY:
;;   2004-09-10  M. Desnoyer    Created
;;   2005-03-28  M. Desnoyer    Added OCLOCK feature
;;
;;-----------------------------------------------------------------------------
FUNCTION getBias, hdr, inst, date, mode, flags, OCLOCK=oclock, IMG=img

;; Determine method to get the bias file
IF keyword_set(OCLOCK) THEN BEGIN
	;; Create the bias from the overclock rows

	@dical_flags

	;; Make sure we have the image
	IF (size(img,/n_dimensions))[0] NE 2 THEN $
		message, 'Image required to create overclocked bias frame'

	;; Figure out where the bias cols are
	bcols = getBiasCols(hdr,COUNT=c)
	IF (c EQ 0) THEN message, 'Image has no serial overclock pixels'

	;; Identify the quadrants
	sz = size(img,/dimensions)
	quadOCols = [[bcols[0:c/2-1]],[bcols[0:c/2-1]],[bcols[c/2:*]],[bcols[c/2:*]]]
	quads = [[0,sz[0]/2-1,0,sz[1]/2-1],$
		[0,sz[0]/2-1,sz[1]/2,sz[1]-1],$
		[sz[0]/2,sz[0]-1,0,sz[1]/2-1],$
		[sz[0]/2,sz[0]-1,sz[1]/2,sz[1]-1]]

	;; Put the bias columns into the bias frame with NaNs filling the gaps (so they
	;; won't be a part of the calculation)
	bias = dblarr(sz[0],sz[1],/nozero)
	bias[bcols,*] = img[bcols,*]
	missLoc = where((flags AND FLAG_GAP) NE 0,missCnt)
	IF missCnt GT 0 THEN bias[missLoc] = !VALUES.D_NAN

	;; Generate the bias frame one quadrant at a time by taking the median of the
	;; valid serial overclock pixels
	FOR i=0, (size(quads,/dimensions))[1]-1 DO BEGIN
		bias[quads[0,i]:quads[1,i],quads[2,i]:quads[3,i]] = $
			median(bias[quadOCols[*,i],quads[2,i]:quads[3,i]],/even)

		;; **** This is for subtracting bias row by row ****
		;;FOR j=quads[2,i], quads[3,i] DO BEGIN
		;;	bias[quads[0,i]:quads[1,i],j] = $
		;;		median(bias[quadOCols[*,i],j],/even)+1
		;;ENDFOR
	ENDFOR

	;; Turn all the NaNs into zeros so the image doesn't get NaNs stuck in it.
	IF missCnt GT 0 THEN bias[missLoc] = 0

	;;  Update the FITS header
	fxaddpar, hdr, 'BIASFN', 'SERIAL OVERCLOCK'
ENDIF ELSE BEGIN
	;; Get the bias from the database

	;; Parameters to acess SQL database
	serv = getSQLServer()
	db = 'di_calib'

	;; Get the filename for the bias frame from the database
	sel = ['Filepath']
	cond = "(Instrument='" + inst + "') AND (Date<='" + date + $
	"') AND (Mode="+strtrim(mode,2)+") order by Date DESC, Version desc limit 1"
	tblNm = 'BIAS'
	fn = DI_sqlQuery(serv, db, tblNm, sel, cond, DIM=dim)
	IF max(dim) EQ 0 THEN $
	message, 'Database contained no valid bias frame',/NONAME

	;; Convert that filename into a local one
	fn = getLocFn(fn, subdir='BIAS')

	message, /reset
	bias = readfits(fn[0],calHdr,/silent)
	IF !error_state.code LT 0 THEN message, 'Invalid bias frame', /noname

	;; Rotate the bias image
	bias = dical_rotCalImg(bias,inst,calHdr)

	;; Update the fits header
	fxaddpar, hdr, 'BIASFN', $
		strupcase(strmid(fn[0], strpos(fn[0], path_sep(), /reverse_search)+1))
ENDELSE

RETURN, bias
END