; $Id: dcs_choose_mask.pro,v 1.19 2005/02/14 17:50:14 azuah Exp $
; Written by J.R.D. Copley.
;************************************************************************************************
;###############################################################################
;
; LICENSE:
;  The software in this file is written by an employee of 
;  National Institute of Standards and Technology 
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used or if the code in this file is
;  included in another product.
;
;###############################################################################
pro	dcs_choose_mask_choose_file_event,event
;************************************************************************************************
;
compile_opt strictarr
;
widget_control,event.top,get_uvalue=state,/no_copy
;
if (event.id eq state.done) then begin
	*(state.ptr)=widget_info(state.list,/list_select)
	widget_control,event.top,/destroy
	return
endif
;
widget_control,event.top,set_uvalue=state,/no_copy
;
end


;************************************************************************************************
pro	dcs_choose_mask_choose_file,files_selected,nfiles_selected,conditions,$
	assignments,chosen,group_leader=group_leader
;************************************************************************************************
;
compile_opt strictarr
;
nfiles=fix(total(nfiles_selected))
type=strarr(nfiles)
type_of_file=[$
	"Sample",$
	"Container",$
	"Vanadium",$
	"Absorber",$
	"Background"]
;
for k=0,4 do begin
	n=nfiles_selected[k]
	start=total(nfiles_selected[0:k])-n
	for kk=0,n-1 do begin
		j=start+kk
		type[j]=files_selected[j]+"-   "+type_of_file[k]
		if (k eq 0) then type[j]=type[j]+" condition"+strcompress(assignments[j])+$
			": "+conditions[assignments[j]-1]
	endfor
endfor
;
repeat begin
	tlb=widget_base(title='Files to sum and plot',/col,$
		group_leader=group_leader,/modal)
	title=widget_label(tlb,value='Choose one or more files to sum and plot')
	list=widget_list(tlb,value=type,ysize=nfiles,/multiple)
	list=list[sort(list)]
	done=widget_button(tlb,value="PROCEED")
	widget_control,tlb,/realize
	ptr=ptr_new(/allocate_heap)
	state={list:list,done:done,ptr:ptr}
	widget_control,tlb,set_uvalue=state
	xmanager,'dcs_choose_mask_choose_file',tlb
	chosen=*(state.ptr)
	ptr_free,ptr
	if (chosen[0] eq -1) then $
		res=dialog_message("At least one dataset must be active.",/error)
endrep until (chosen[0] ne -1)
;
;
end


;************************************************************************************************
pro dcs_define_mask_handler,event
;************************************************************************************************
;
compile_opt strictarr
;
widget_control,event.top,get_uvalue=state
;
blist=*state.ptr
;
evid=event.id
;
if (evid eq state.help) then $
	res=dialog_message(state.helptext,dialog_parent=event.top,/information)
;
if (evid eq state.clear) then	begin
	state.nbtop=-1
	blist=intarr(state.nbmax)
endif
;
if (evid eq state.restoremask) then	begin
	file=!dcs_outp_directory+!dcs_rootname+".msk"
	if (not file_test(file)) then file=!dcs_default_root+".msk" $
		else file=!dcs_rootname+".msk"
	fullfilename=dialog_pickfile(filter="*.msk",/fix_filter,$
		path=!dcs_outp_directory,/must_exist,$
		file=file,get_path=file_path,$
		title="Select the file that contains the mask information.")
	cancel=fullfilename eq ""
	if (not cancel) then begin
		if (strlowcase(strmid(fullfilename,3,/reverse)) ne ".msk") then $
			fullfilename=fullfilename+".msk"
		restore,filename=fullfilename
		blist=intarr(state.nbmax)
		templist=where(mask eq 0,nblist)
		if (nblist gt 0) then blist[0:nblist-1]=templist+1
		state.nbtop=nblist-1
	endif
endif
;
if (evid eq state.savemask) then begin
	repeat begin
		file=!dcs_rootname+".msk"
		fullfilename=dialog_pickfile(filter="*.msk",/fix_filter,$
			path=!dcs_outp_directory,$
			file=file,get_path=file_path,$
			title="Define the file that will contain the mask.")
		cancel=fullfilename eq ""
		compok=strcmp(file_path,!dcs_outp_directory,/fold_case)
		if (not cancel and not compok) then res=dialog_message("You may not change the directory.")
	endrep until (cancel or compok)
	if (not cancel) then begin
		if (strlowcase(strmid(fullfilename,3,/reverse)) ne ".msk") then $
			fullfilename=fullfilename+".msk"
		nelem=state.nbtop+1
		mask=bytarr(state.nbmax)+1
		if (nelem ne state.nbmax) then mask[blist[0:state.nbtop]-1]=0
		save,filename=fullfilename,mask
	endif
endif
;
if (evid eq state.savelist) then begin
	numbers=strarr(1)
	widget_control,state.savelist,get_value=numbers
	if (stregex(numbers[0],'[[:alpha:]]') ne -1) then $
		widget_control,state.savelist,$
			set_value="Alphabetic characters are not allowed." $
	else begin
		numbers=strsplit(numbers[0],"[, ]+",/extract)
		n_numbers=n_elements(numbers)
		for i=0,n_numbers-1 do begin
			if (stregex(numbers[i],'[0-9]+-[0-9]+') ne -1) then begin
				limits=strsplit(numbers[i],"-",/extract)
				if (fix(limits[0]) gt 0 and fix(limits[0]) le state.nbmax and $
						fix(limits[1]) gt 0 and fix(limits[1]) le state.nbmax) then begin
					for j=fix(limits[0]),fix(limits[1]) do begin
						wb=where(blist eq j)
						if (wb[0] eq -1) then begin
							state.nbtop=state.nbtop+1
							blist[state.nbtop]=j
						endif
					endfor
					widget_control,state.removelist,set_value=""
				endif else widget_control,state.removelist,$
					set_value="Unacceptable detector number range: "$
					+limits[0]+" - "+limits[1]
			endif else begin
				wb=where(blist eq numbers[i])
				if (wb[0] eq -1) then begin
					if (fix(numbers[i]) gt 0 and numbers[i] le state.nbmax) then begin
						state.nbtop=state.nbtop+1
						blist[state.nbtop]=numbers[i]
						widget_control,state.removelist,set_value=""
					endif else widget_control,state.removelist,$
						set_value="Unacceptable detector number:"$
						+strcompress(numbers[i])
				endif
			endelse
		endfor
		widget_control,state.savelist,set_value=""
	endelse
endif
;
if (evid eq state.removelist) then begin
	numbers=strarr(1)
	widget_control,state.removelist,get_value=numbers
	if (stregex(numbers[0],'[[:alpha:]]') ne -1) then $
		widget_control,state.removelist,$
			set_value="Alphabetic characters are not allowed." $
	else begin
		numbers=strsplit(numbers[0],"[, ]+",/extract)
		n_numbers=n_elements(numbers)
		for i=0,n_numbers-1 do begin
			if (stregex(numbers[i],'[0-9]+-[0-9]+') ne -1) then begin
				limits=strsplit(numbers[i],"-",/extract)
				for j=fix(limits[0]),fix(limits[1]) do begin
					wb=where(blist eq j)
					wb0=wb[0]
					if (wb0 eq 0) then begin
						state.nbtop=state.nbtop-1
						b2=blist[1:state.nbmax-1]
						b0=0
						blist=[b2,b0]
					endif
					if (wb0 gt 0) then begin
						state.nbtop=state.nbtop-1
						b1=blist[0:wb0-1]
						b2=blist[wb0+1:state.nbmax-1]
						b0=0
						blist=[b1,b2,b0]
					endif
				endfor
			endif else begin
				wb=where(blist eq numbers[i])
				wb0=wb[0]
				if (wb0 eq 0) then begin
					state.nbtop=state.nbtop-1
					b2=blist[1:state.nbmax-1]
					b0=0
					blist=[b2,b0]
				endif
				if (wb0 gt 0) then begin
					state.nbtop=state.nbtop-1
					b1=blist[0:wb0-1]
					b2=blist[wb0+1:state.nbmax-1]
					b0=0
					blist=[b1,b2,b0]
				endif
			endelse
		endfor
		widget_control,state.removelist,set_value=""
	endelse
endif
;
if (evid eq state.plotsums) then begin
;	Determine which file(s) to sum and plot.
	if (n_elements(state.files_selected) gt 1) then $
		dcs_choose_mask_choose_file,state.files_selected,$
			state.nfiles_selected,state.conditions,state.assignments,$
			chosen,group_leader=event.top $
		else chosen=0
; Read the file header.
	printinfo=0
	omithisto=2
	filetype="binary"
	nf=n_elements(chosen)
	totsum=lonarr(state.nhedet)
	lines=["Evaluating summed detector sums.",$
	"Please be patient..."]
	dcs_message_display,lines,base,group_leader=event.top,alignment=0
	for j=0,nf-1 do begin
		index=chosen[j]
		file_path=state.files_selected[index]
		dcs_readdatafile,file_path,omithisto,printinfo,filetype,davePtr=state.davePtr
		detsum=(*(*(*state.davePtr).dataStrPtr).specificPtr).detsum[0:state.nhedet-1]
; Correct for bit flips.
		for k=0,state.maxbitflips-1 do begin
			if (state.bitflips[1,k,index] lt 1000) then begin
				bfdet=state.bitflips[1,k,index]
				bfamt=state.bitflips[2,k,index]
				if (bfdet lt state.nhedet) then begin
					detsum[bfdet]=detsum[bfdet]-bfamt
				endif
			endif
		endfor
		totsum=totsum+detsum
	endfor
	widget_control,base,/destroy
;
; Plot detector sum and obtain masking information.
	if (nf eq 1) then begin
		filetitle="file "+state.files_selected[0]
	endif else begin
		sorted=sort(state.files_selected[chosen])
		filetitle="files "
		for j=0,nf-1 do $
			filetitle=filetitle+state.files_selected[sorted[j]]
	endelse
	pblist=ptr_new(blist)
	dcs_plotdetmask,event.top,filetitle,totsum,pblist,state.helptext2
	blist=*pblist
	ptr_free,pblist
	templist=where(blist gt 0,nblist)
	state.nbtop=nblist-1
endif
;
if (state.nbtop ge 0) then begin
	olist=blist[sort(blist[0:state.nbtop])]
	str=strcompress(strjoin(olist,","))
endif else str=""
short_str=dcs_str_shorthand(str)
widget_control,state.text,set_value=short_str
widget_control,state.info1,$
	set_value=strcompress(string(state.nbtop+1));+" MASKED"
widget_control,state.info2,$
	set_value=strcompress(string(state.nbmax-state.nbtop-1));+" UNMASKED"
;
if (evid eq state.done) then begin
	if (state.nbtop ge 0) then	*state.ptr=blist[sort(blist[0:state.nbtop])]
	widget_control,event.top,/destroy
	return
endif
;
if (evid eq state.cancel) then begin
	(*state.ptr)[0]=999
	widget_control,event.top,/destroy
	return
endif
;
*state.ptr=blist
widget_control,event.top,set_uvalue=state
end


;************************************************************************************************
pro dcs_define_mask,dcs_base,mask,nhedet=nhedet,files_selected,nfiles_selected,$
	davePtr=davePtr,logentry=logentry,bitflips,maxbitflips,conditions,assignments
;************************************************************************************************
;
compile_opt strictarr
;
;dcs_sysdep,fonts=fonts
;
title="Define"+strcompress(nhedet)+"-element mask."
tlb=widget_base(title=title,/col,group_leader=dcs_base,/modal)
	text=widget_text(tlb,xsize=75,ysize=4,/scroll,/wrap)
	below=widget_base(tlb,/row)
		help=widget_button(below,value='Help')
		clear=widget_button(below,value='Clear')
		restoremask=widget_button(below,value='Restore')
		savemask=widget_button(below,value='Save')
		plotsums=widget_button(below,value='Plot sums')
		done=widget_button(below,value='PROCEED')
		cancel=widget_button(below,value='Main menu')
saveline=widget_base(tlb,/row)
	savelabel=widget_label(saveline,value="     MASK DETECTORS ")
	savelist=widget_text(saveline,xsize=60,/editable,/sensitive)
	info1=widget_text(saveline,xsize=3,value="  0",/editable)
removeline=widget_base(tlb,/row)
	removelabel=widget_label(removeline,value="UNMASK DETECTORS ")
	removelist=widget_text(removeline,xsize=60,/editable,/sensitive)
	info2=widget_text(removeline,xsize=3,$
		value=strcompress(string(nhedet))+"",/editable)
;
dave_position_tlb,tlb
widget_control,tlb,/realize
;
nbmax=nhedet
blist=intarr(nbmax); a set of 913 0's
;
templist=where(mask eq 0,nblist); initially -1 and nblist=0
if (nblist gt 0) then blist[0:nblist-1]=templist+1; no change in blist
nbtop=nblist-1; -1
;
if (nbtop ge 0) then begin
	olist=blist[sort(blist[0:nbtop])]
	str=strcompress(strjoin(olist,","))
endif else str=""
widget_control,text,set_value=str; initially a null string
;
ptr=ptr_new(blist); a set of 913 0's
helpstring=$
	"The list of masked detectors, in the gray box immediately below, "+$
		"is initially empty."+$
		"To add to the list of masked detectors type a list "+$
		"such as ''1-12,17,231-232'' in the ''MASK DETECTORS'' box."+$
		"To remove detectors from the list type a list such as "+$
		"''4-7,9'' in the ''UNMASK DETECTORS'' box."+$
		"Be sure to hit the <Enter> key."+$
		"To clear the list hit ''Clear''. To save hit ''Save''. "+$
		"To restore hit ''Restore''."+$
		"It may be helpful to use one or more plots of total detector counts "+$
		"in order to identify detectors to be masked. In that case hit "+$
		"''Plot sums'' and follow the directions."+$
		"The detectors are numbered from 1-"+strcompress(nhedet,/remove_all)+"."
maxlen=80
dcs_superstring_wrap,helpstring,maxlen,helptext,err
helpstring2=$
	"Use the mouse left button to zoom, the right button to mask/unmask. "+$
		"If ''XZOOM'' is displayed on a button in the top row, zooming only "+$
		"occurs in x. If ''XYZOOM'' is displayed zooming occurs in x and y. "+$
		"Click on the ''XZOOM/XYZOOM'' button to toggle between these states. "+$
		"If ''MASK'' is displayed on the other button in the top row, the right "+$
		"button is used to mask one or more detectors. If ''UNMASK'' is displayed "+$
		"the right button unmasks detectors. "+$
		"Click on the ''MASK/UNMASK'' button to toggle between these states. "+$
		"The sliders may also be used to define the displayed detector range. "+$
		"The most recent zoom may be ''undone'' using the ''Undo zoom'' button. "+$
		"To return to the previous user interface click the ''PROCEED'' button."
maxlen=80
dcs_superstring_wrap,helpstring2,maxlen,helptext2,err
state={$
	help:help,$
	clear:clear,$
	done:done,$
	cancel:cancel,$
	restoremask:restoremask,$
	savemask:savemask,$
	plotsums:plotsums,$
	text:text,$
	savelist:savelist,$
	removelist:removelist,$
	ptr:ptr,$
	nbtop:nbtop,$
	files_selected:files_selected,$
	nfiles_selected:nfiles_selected,$
	nbmax:nbmax,$
	newb:0,$
	but1:0,$
	davePtr:davePtr,$
	nhedet:nhedet,$
	bitflips:bitflips,$
	maxbitflips:maxbitflips,$
	conditions:conditions,$
	assignments:assignments,$
	info1:info1,$
	info2:info2,$
	helptext:helptext,$
	helptext2:helptext2}
;
widget_control,tlb,set_uvalue=state
xmanager,'dcs_define_mask',tlb,event_handler='dcs_define_mask_handler'
;
blist=*state.ptr
ptr_free,ptr
;
if (blist[0] eq 999) then begin
	mask[0]=999
	return
endif
;
nelem=n_elements(blist)
mask=bytarr(nhedet)+1
if (nelem eq nbmax) then return
mask[blist-1]=0
;
logentry=logentry+string(10B)+"A detector mask has been generated."
list=where(mask eq 0,count)+1
if (count gt 0) then begin
	logentry=logentry+string(10B)+"The masked detectors are as follows:"
	shortlist=dcs_str_shorthand(strjoin(strcompress(list),','))
	logentry=logentry+string(10B)+shortlist
endif
;
end


;************************************************************************************************
pro dcs_choose_mask,dcs_base,mask,nruns,nhedet,ichoice,files_selected,nfiles_selected,$
	davePtr=davePtr,logentry=logentry,bitflips,maxbitflips,conditions,assignments
;************************************************************************************************
;
compile_opt strictarr
;
; ichoice=0 if there is no mask.
; ichoice=1 if a single mask is to be restored and/or generated.
;
; mask is initially a set of nhedet 1's.
mask=bytarr(nhedet)+1
if (ichoice eq 0) then logentry=logentry+string(10B)+"There is no detector mask." $
	else $
	dcs_define_mask,dcs_base,mask,nhedet=nhedet,files_selected,nfiles_selected,$
		davePtr=davePtr,logentry=logentry,bitflips,maxbitflips,conditions,assignments
;
; Next line creates matrix with dimensions [nhedet,nruns].
mask=mask#(bytarr(nruns)+1); generate identical masks for each run
;
end