pro sel_dc_image, struct_in, file_use, dsets, imap, match_qual=match_qual, qstop=qstop, qdebug=qdebug, qmanual=qmanual, $
	times_input=times_input, res_input=res_input, dpe_input=dpe_input, temp_input=temp_input, $
	long=long, short=short, q2debug=q2debug, $
	mmdpe=mmdpe
;
;+
;NAME:
;	sel_dc_image
;PURPOSE:
;	Given an index or roadmap structure, match the closest dark 
;	current image for that exposure
;CALLING SEQUENCE:
;	sel_dc_image, index(3), dset, imap
;	sel_dc_image, roadmap, dset, imap
;
;	sel_dc_image, xxx, dset, times=times, res=res, dpe=dpe
;	sel_dc_image, xxx, dset, times='1-sep-92 1:00', res=0, dpe=15
;INPUT:
;	struct_in - An index or roadmap structure.  If the input
;		    is an array, then data will be a matrix and it
;		    is necessary to use the output variable "imap"
;		    to match up which dark frame goes with which input
;		    image.  This is done so that unnessary duplication
;		    of the same image is not done.
;
;		    If the image was taken when the CCD was warm, then
;		    the index should be passed in so that the routine
;		    can match the temperature also.
;OPTIONAL KEYWORD INPUT:
;	times	- MANUAL METHOD:  A list of input times (any of 3 standard
;		  formats)
;	res	- MANUAL METHOD: The resolution required (0=full res, 
;		  1=half res, 2=quarter res)
;	dpe	- MANUAL METHOD: The DPE level (exposure level)
;	temp	- MANUAL METHOD: The CCD temperature in degrees.  If not
;		  passed, it will use -21.0 C
;	long	- If set, then match any DPEs OVER the minimum DPE value
;		  for the input resolution (FR,HR,QR = 21, 23, 19)
;		  (not the DPE value closest to it)
;		 	TODO - this definition has changed
;	short	- If set, then match any DPEs UNDER the maximum DPE value
;		  for the input resolution (FR,HR,QR = 13, 13, 13)
;		  (not the DPE value closest to it)
;		 	TODO - this definition has changed
;	mmdpe	- An array with min or maximum DPE value to search for.
;		  Used in conjuction with the /LONG option
;OUTPUT:
;	file_use- The names of the SDC/SDW files that are to be used for
;		  the selected dark frames (subset of "dc_infil")
;	dset	- The MK_DSET_STR output listing the dataset and file
;		  number of the unique dark images.
;		  Use "imap" to figure which dark image to use for which
;		  input image.
;	imap	- A list of indicies telling which image in "data" to
;		  use for each "struct_in" image.  The output is an
;		  array the same length as "struct_in" with values that
;		  go from 0 to the number of dark images minus one.
;KEYWORD OUTPUT:
;	match_qual - The quality of the match.  It is a structure with
;		  the following fields.
;			.dpe  = # of seconds in exposure away from the actual
;				0 is perfect match, positive means DC
;				is longer exposure than requested.
;			.time = the number of days from the requested day.
;			        positive is for DC images taken past
;				the time of the input image
;			.temp = the number of degress that the match is off
;			.dpeval = the DPE value matched
;METHOD:
;	The program will try to make an exact match to the exposure
;	level passed.  If it cannot match, it will take the next exposure
;	larger which is available.  
;
;	GET_DC_IMAGE can be called manually by passing "times", "res"
;	and "dpe" using the keywords.  All three need to be passed, however
;	it is possible to pass an array of times, but have res or dpe
;	be a scalar.
;HISTORY:
;	Written 24-Aug-93 by M.Morrison (using GET_DC_IMAGE as starting point)
;	Differences from GET_DC_IMAGE:
;		* Combined GET_DC_WARM and GET_DC_IMAGE
;		* Match on exposure duration in seconds, not DPE value
;	25-Aug-93 (MDM) - Added "dc_filidx" to speed things up
;	 1-Sep-93 (MDM) - Corrected a typo "dc_filidx2"
;	16-Dec-93 (MDM) - Modified to break images into two categories
;			  Those taken before 13-Nov-92 and those taken 
;			  after.  Do not cross the line.
;	26-Jan-94 (MDM) - Corrected error when trying to get SDW files and
;			  they do not exist.
;			- Modified the logic so that manual passing of the
;			  temperature works properly
;	31-Jan-94 (MDM) - Corrected 26-Jan-94 patch - there are cases when
;			  the roadmap is passed in, which does not have the
;			  temperature
;       11-May-94 (SLF) - subscript protection for good(ss)
;	15-Aug-94 (MDM) - Try to add some protection in the case when
;			  the execution is interupted in the middle of
;			  reading the SDC roadmaps
;	29-Nov-94 (MDM) - Modified the logic so that the closest image
;			  above and below the desired exposure duration
;			  are used.  Previously, it used a short exposure
;			  and a medium or long exposure no matter what the
;			  input exposure duration was.
;	30-Nov-94 (MDM) - Fairly large change to the technique used to find
;			  a match.  It MUST be within +/- 30 days now, and 
;			  it still minimizes the DPE error and temperature
;			  error and finds the image closest in time with
;			  those minimum error.	
;	27-Feb-95 (MDM) - Modified to allow a large temperature error when
;			  no SDW data is available.
;	 1-Mar-95 (MDM) - Patched error which occured during warm CCD and
;			  when /INTERPOLATE is used.
;	15-May-95 (MDM) - Modified to be able to use PFI images as the
;			  input (slight modification to the 288 line number
;			  starting corner of FR images code).
;-
;
common sel_dc_image_blk, dc_infil, dc_roadmap, temp, dc_filidx
;
qdebug = keyword_set(qdebug)
q2debug = keyword_set(q2debug)
max_temperr = 3.0
dpe_lo_cutoffs = [13, 13, 13]       ;maximum DPE for the short exposure
dpe_hi_cutoffs = [21, 23, 19]       ;minimum DPE for the long expsoure
;
match_qual0 = {sel_dc_image3, dpe: 0., time: 0.0, temp: 0.0, dpeval: 0}
;
code = 0	;find closest exposure for the time
if (keyword_set(short)) then code = 1	;find the closest DPE under the input value
if (keyword_set(long)) then code = 2	;find the closest DPE over the input value
;
;------------------------------------------------------------------------------
;		Setup the input structures
;------------------------------------------------------------------------------
;
qmanual = 0
if (keyword_set(times_input)) then begin
    qmanual = 1
    tims = anytim2ints(times_input)
    n = max( [n_elements(tims), n_elements(res_input), n_elements(dpe_input), n_elements(temp_input)])
    ;^^ can mix scalars and array inputs
    struct_in = {sel_dc_struct_in, day: 0, time: 0L, dpe: 0, imgparam: 0b, temp: 0.0}
    struct_in = replicate(struct_in, n)
    struct_in.time = tims.time
    struct_in.day  = tims.day
    struct_in.dpe  = dpe_input
    struct_in.imgparam = res_input		;is low 2 bits
    if (n_elements(temp_input) eq 0) then temp_input = -21.0
    struct_in.temp = temp_input
end
;
if (n_elements(struct_in) eq 0) then begin
    message, 'No input passed.  Returning', /info
    return
end
;
;------------------------------------------------------------------------------
;		Read the SDC Datasets
;------------------------------------------------------------------------------
;
;if (n_elements(dc_roadmap) eq 0) then begin
if (n_elements(dc_roadmap) eq 0) or (n_elements(temp) eq 0) then begin	;MDM modified 15-Aug-94
    if (keyword_set(qdebug)) then print, 'Reading SDC Roadmap'
    dc_infil = file_list('$DIR_SXT_SDC', 'sdc*')
    if (dc_infil(0) ne '') then rd_roadmap, dc_infil, dc_roadmap, filidx=dc_filidx
    n = n_elements(dc_roadmap)
    if (n ne 0) then temp = fltarr(n) + (-21.00)	;they are all cool to set temperature of -21.0 C
end
if (dc_infil(0) eq '') then begin
    message, 'No SDC files found in $DIR_SXT_SDC', /info
    message, 'Returning with a value of zero', /info
    imap = -1
    dsets = -1
    file_use = ''
    match_qual = match_qual0
    match_qual.dpe = -99
    match_qual.time = 1e+6
    match_qual.dpeval = -1
    return
end
;
;------------------------------------------------------------------------------
;		Read the SDW datasets if necessary
;------------------------------------------------------------------------------
;
if (qmanual) then begin
    temps_in = struct_in.temp
end else begin
    qindex = 0
    tags = tag_names(struct_in)
    if (tags(0) eq 'GEN') then begin
	qindex = 1
	temps_in = gt_temp_ccd(struct_in)
    end else begin
	temps_in = fltarr(n_elements(struct_in)) - 21.0	;if passing in roadmap, assume all cooled
    end
end
;
if ((max(temps_in) gt -20) and (max(temp) lt -20)) then begin	;there are warm images requested, 
									;and SDW have not been read yet
	if (keyword_set(qdebug)) then print, 'Reading SDW Index'
	dc_infil2 = file_list('$DIR_SXT_SDW', 'sdw*')
	if (dc_infil2(0) ne '') then begin
	    rd_xda, dc_infil2, -1, index, data, roadmap, /nodata
	    rd_roadmap, dc_infil2, roadmap, filidx=filidx2
	    ;
	    n0 = n_elements(dc_infil)
	    dc_infil = [dc_infil, dc_infil2]
	    dc_roadmap = [dc_roadmap, roadmap]
	    temp = [temp, gt_temp_ccd(index)]
	    dc_filidx = [dc_filidx, filidx2+n0]
	end else begin
	    tbeep, 3
	    message, 'No SDW files found in $DIR_SXT_SDW', /info
	    message, 'You have requested dark images for images where CCD is warm', /info
	    message, 'and there are no SDW files on-line.  Will use cooled images...', /info
	     max_temperr = 20.0		;MDM added 27-Feb-95
	end
end
;
;------------------------------------------------------------------------------
;		Do the search
;------------------------------------------------------------------------------
;
;temp is done up above
dpe = gt_dpe(dc_roadmap, /conv)		;convert to seconds
res = gt_res(dc_roadmap)
dc_y0 = gt_corner(dc_roadmap, /y)
;
ndc = n_elements(dc_roadmap)
nin = n_elements(struct_in)
imap = intarr(nin)-1
dset_arr = intarr(nin)-1
match_qual = replicate(match_qual0, nin)
qafter_oct92 = int2secarr(struct_in(0), '13-oct-92') gt 0
qpfi_dc = min(gt_pfi_ffi(dc_roadmap)) eq 0		;SDC input set is PFI
;
for iin=0,nin-1 do begin
    struct_in0 = struct_in(iin)
    x = int2secarr(dc_roadmap, struct_in0)/86400	;# of days the xray/optical image was taken from each DC image
    good = bytarr(ndc)
    res0 = gt_res(struct_in0)
    ss = where(res eq res0)

    ;for older SDC data, there were only strips in the middle of the ccd.  
    if ((res0 eq 0) and (qafter_oct92) and (not qmanual) and (not qpfi_dc)) then begin	;full resolution
	;y0 = gt_corner(struct_in0, /y)
	y0 = gt_corner(struct_in0, /y) + gt_shape(struct_in0, /y)/2.	;MDM modified 30-Nov-94
	if (y0 ge 512) then ss = where( (res eq res0) and (dc_y0 gt 200) ) $	;start lin are either 288 or 512
			else ss = where( (res eq res0) and (dc_y0 lt 200) )	;start lin is 0 for FFI
    end

;   slf 11-May-94 - subscript protection
    if ss(0) ne -1 then good(ss) = 1

    ;------------- Code to check for which side of 13-Nov-92 was taken was added 16-Dec-93

    ref_date = '13-Nov-92 17:06'
    qafter_nov92 = sel_timrange(struct_in0, ref_date, '31-dec-99', /between, /boolean)
    if (qafter_nov92) then begin
	ss = sel_timrange(dc_roadmap, '1-jan-91', ref_date, /between)
	if (ss(0) ne -1) then good(ss) = 0		;do not use any images before 13-Nov-92
    end else begin
	ss = sel_timrange(dc_roadmap, ref_date, '31-dec-99', /between)
	if (ss(0) ne -1) then good(ss) = 0		;do not use any images after 13-Nov-92
    end

    if (qmanual) then begin
	dpe0 = gt_dpe(struct_in0.dpe, /conv)
	temp0 = struct_in0.temp
    end else begin
	dpe0 = gt_dpe(struct_in0, /conv)
	if (qindex) then temp0 = gt_temp_ccd(struct_in0) $
		    else temp0 = -21.0
    end
    if ((code eq 1) and keyword_set(mmdpe)) then dpe0 = gt_dpe( mmdpe(iin<(n_elements(mmdpe)-1))+1, /conv)

    ;if (keyword_set(short)) then dpe0 = gt_dpe( dpe_lo_cutoffs(res0), /conv)	;maximum DPE for the short exposure
    ;if (keyword_set(long))  then dpe0 = gt_dpe( dpe_hi_cutoffs(res0), /conv)	;minimum DPE for the long expsoure

    dpe_err_arr = (dpe-dpe0)/1000.	;convert to seconds
    ;^^^ see below - it is redefined for code=2
    temp_err_arr = temp-temp0

    ;---- 30-Nov-94 (MDM) - further reduce the "good" array - must be within temperature range
    ss = where(abs(temp_err_arr) gt max_temperr, count)		& if (count ne 0) then good(ss) = 0

    itry = 1
    qdone = 0
    code0 = code
    if (temp0 lt -20) then timerrstep = 7. else timerrstep = 30.		;check +/- 7 days if cold
    while (not qdone) do begin
	timerr = timerrstep*itry
	if (keyword_set(qdebug)) then print, 'Try #', itry, ' Time window = ', timerr		;MDM added 29-Nov-94

	case code0 of
	    0: 	ss = where(good and (abs(x) le timerr),                   count)
	    1:	ss = where(good and (abs(x) le timerr) and (dpe le dpe0), count)	;short case
	    2:	ss = where(good and (abs(x) le timerr) and (dpe ge dpe0), count)	;long case
	endcase

	if (count ne 0) then begin
	    ;-------- First select the subset which has the smallest temperature error (should be all for cold case)
            sss = where(abs(temp_err_arr(ss)) eq min(abs(temp_err_arr(ss))))    
            ss = ss(sss)

	    ;-------- Second, select the subset which has the smallest exposure error
            sss = where(abs(dpe_err_arr(ss)) eq min(abs(dpe_err_arr(ss))))    
            ss = ss(sss)

	    ;-------- Third, select the image closest in time
	    xoff = x(ss)
	    imin = min(abs(xoff), isub)
	    idset = ss(isub)
	    if (qdebug) then print, 'Found a match.  Time offset = ', imin, ' days'
	    if (q2debug) then aaa=get_info2(dc_roadmap(idset))
	    qdone = 1
	    dset_arr(iin) = idset
	    match_qual(iin).dpe		= dpe_err_arr(idset)
	    match_qual(iin).time	= imin
	    match_qual(iin).temp	= temp_err_arr(idset)
	    match_qual(iin).dpeval	= gt_dpe(dc_roadmap(idset))	;MDM added 30-Nov-94
	end else begin
	    itry = itry + 1
	end

	if (timerr gt 180) then begin	;don't look outside of +/- 6 months
	    case code0 of
		0: begin
			qdone = 1
			message, 'No match for image - all DPEs searched', /info
		   end
		1: begin
			if (qdebug) then print, 'Cannot find shorter, find the closest
			itry = 1
			code0 = 0
		   end
		2: begin
			if (qdebug) then print, 'Cannot find longer than input, so find shorter than short exposure
			itry = 1
			code0 = 1
			if (keyword_set(mmdpe)) then dpe0 = gt_dpe( mmdpe(iin<(n_elements(mmdpe)-1))-1, /conv)
			dpe_err_arr = (dpe-dpe0)/1000.	;convert to seconds
		   end
	    endcase
	end
    end		;while
end
;
ss_dsets = uniq(dset_arr, sort(dset_arr))
dsetsi = dset_arr(ss_dsets)
if (dsetsi(0) eq -1) then begin
    if (n_elements(dsetsi) eq 1) then begin
	message, 'No matches made for all inputs', /info
	if (keyword_set(qstop)) then stop
	dsets = -1
	return
    end else begin
	dsetsi = dsetsi(1:*)		;drop off first value (-1)
    end
end
;
for i=0,n_elements(dsetsi)-1 do imap(where(dset_arr eq dsetsi(i))) = i	;gotta be a better way
;
dsets = mk_dset_str(dc_filidx, dsetsi)	;convert to the structure
if (n_elements(dsets) eq 1) then ss = 0 else ss = uniq( dsets.ifil, sort(dsets.ifil) )	;uniq DC files used
ufiles = dsets(ss).ifil
file_use = dc_infil(ufiles)
for i=0,n_elements(ss)-1 do dsets(where(dsets.ifil eq ufiles(i))).ifil = i	;gotta be a better way
;
if (keyword_set(qstop)) then stop
end
