;+ ; Name: spex_edit_summ ; ; Purpose: Use table widget to edit values in OSPEX spex_summ structure ; ; Calling sequence: ; spex_edit_summ, summ, item, xsize=xsize, ysize=ysize, status=status ; ; Arguments: ; summ - spex_summ structure from OSPEX ; item - name of item to edit (tag name from ospex structure, like 'spex_summ_params') - accepted ; items are those dimensioned nparam,ntime or ncomp,ntime. Exception is 'energy_range' - use spex_summ_emask ; and spex_summ_energy to find low/high energy for each time bin, and allow user to edit them. ; ; Input Keywords: ; xsize - number of columns to show ; ysize - number of rows to show ; ; Output Keywords: ; status - 0 means user cancelled out of edit widget so return original structure. 1 means ; user accepted changes in edit widget. ; ; Output: ; Returns spex_summ structure modified according to user. (Does not modify OSPEX object, doesn't even know about it) ; ; Written: Kim Tolbert 17-Sep-2012 ; Modifications: ; 04-Apr-2014, Kim. Make row_label an array even if only one value, so xedit_table doesn't crash. ; ;- function spex_edit_summ, summ, item, xsize=xsize, ysize=ysize, status=status s = summ if size(s.spex_summ_fit_done, /tname) eq 'POINTER' then begin message,/info,'No spex_summ parameters available. Aborting.' return, s endif tags = strlowcase(tag_names(s)) ntime = n_elements(s.spex_summ_time_interval[0,*]) item = strlowcase(item) case item of 'energy_range': begin ; For energy range, look at emask for each time interval, and find the lowest and ; highest energy selected (emask is 1 for that bin). Save index (into spex_summ_energy array) ; and value for lowest and highest energy. We'll let user edit low/high, and then reset the ; emask accordingly. Note that if there are energy bins unselected between lo and hi, those ; won't be affected by this - we're only changing the emask between the previous lo or hi and ; the new lo or hi. ; elo/ehi will be bottom/top of lowest/highest energy bin selected. ilo,ihi will be index corresponding ; to lowest/highest bin. message, 'Note: this allows you to set only the low or high end of energy range to fit.', /cont message, ' If you have excluded some energy intervals, they will still be excluded.', /cont message, ' If you want to set some energy intervals to exclude, edit the energy bin mask parameter.', /cont elo = fltarr(ntime) - 1. ehi = fltarr(ntime) - 1. ilo = intarr(ntime) - 1 ihi = intarr(ntime) - 1 for i=0,ntime-1 do begin q = where (s.spex_summ_emask[*,i], nq) if nq gt 0 then begin ilo[i] = q[0] ihi[i] = q[nq-1] elo[i] = s.spex_summ_energy[0,ilo[i]] ehi[i] = s.spex_summ_energy[1,ihi[i]] endif endfor start_vals = transpose([[elo],[ehi]]) nparams = 2 column_labels = ['Energy Range Low ', 'Energy Range High'] end 'spex_summ_emask': begin start_vals = s.spex_summ_emask nparams = n_elements(start_vals[*,0]) column_labels = format_intervals(s.spex_summ_energy) tag_num = where(tags eq item, count) end 'spex_summ_maxiter': begin start_vals = reform(s.spex_summ_maxiter, 1, ntime) ; time int has to be second dim nparams = 1 column_labels = ['Max Iter'] tag_num = where(tags eq item, count) end 'spex_summ_uncert': begin start_vals = reform(s.spex_summ_uncert, 1, ntime) ; time int has to be second dim nparams = 1 column_labels = ['Uncert'] tag_num = where(tags eq item, count) end else: begin tag_num = where(tags eq item, count) if count eq 0 then begin message, /info, 'Requested item not in spex_summ structure, aborting.' return,s endif start_vals = s.(tag_num) nparams = n_elements(start_vals[*,0]) comps = str2arr(s.spex_summ_fit_function, '+') ncomp = n_elements(comps) column_labels = nparams eq ncomp ? comps : fit_function_query(s.spex_summ_fit_function,/param_num) maxlen = max(strlen(column_labels)) column_labels[0] = strpad(column_labels[0],maxlen) end endcase device, get_screen_size=screen if ~keyword_set(xsize) then scr_xsize = screen[0]*.75 else xsize = xsize < nparams if ~keyword_set(ysize) then scr_ysize = screen[1]*.75 else ysize = ysize < ntime title = 'Edit ' + item + 'values' blue = [220,245,255] bk_col = bytarr(3,nparams) + 255 ; all white to start for i=0,nparams-1,2 do bk_col[*,i] = blue ; every other column blue row_label=['Int ' + trim(indgen(ntime))] ; brackets so will be array even if ntime=1 vals = xedit_table (start_vals, $ title=title, $ row_label=row_label, $ column_label=column_labels, $ scr_xsize=scr_xsize, scr_ysize=scr_ysize, $ x_scroll_size=xsize, y_scroll_size=ysize, $ background_color=bk_col, $ status=status ) ;message,/info,'status = ' + trim(status) if status then begin if item eq 'energy_range' then begin ; for energy range, change emask for each time interval based on low/high energy set by user. mids = get_edges(s.spex_summ_energy, /mean) mine = min(s.spex_summ_energy) maxe = max(s.spex_summ_energy) for i=0,ntime-1 do begin ; if only one limit is set, set other limit to min or max of energy edges if vals[0,i] gt 0. and vals[1,i] eq -1. then vals[1,i] = maxe if vals[0,i] eq -1. and vals[1,i] gt 0. then vals[0,i] = mine ; qlo,qhi are indices of energy bins containing new low and high value for this interval (use bin whose ; start (or end) is closest to start (or end) specified by user, NOT the bin that contains the value) q = where (mids ge vals[0,i] and mids lt vals[1,i], nq) qlo = q[0] qhi = last_item(q) if nq gt 0 then begin ; if range wasn't set, then just set all bins between qlo,qhi to 1. Otherwise, only add or remove bins at ; start or end so we don't change any settings for energies user wants to skip over. if ilo[i] eq -1 or ihi[i] eq -1 then for ibin=qlo,qhi do s.spex_summ_emask[ibin,i]=1 else begin if qlo lt ilo[i] then for ibin=qlo,ilo[i] do s.spex_summ_emask[ibin,i]=1 ; set additional bins at low end if qlo gt ilo[i] then for ibin=ilo[i],qlo-1 do s.spex_summ_emask[ibin,i]=0 ; unset some bins at low end if qhi gt ihi[i] then for ibin=ihi[i],qhi do s.spex_summ_emask[ibin,i]=1 ; set additional bins at high end if qhi lt ihi[i] then for ibin=qhi+1,ihi[i] do s.spex_summ_emask[ibin,i]=0 ; unset some bins at high end endelse endif else if total(vals[*,i]) ne -2 then message,/info,'New range is outside all energies for interval ' + trim(i) + '. Not setting.' ; ; q[0] is index of energy bin containing new high value for this interval ; q = where(vals[1,i] le s.spex_summ_energy[1,*],nq) ; q = where(s.spex_summ_energy[1,*]-vals[1,i] gt 1.e-6, nq) ; if nq gt 0 then begin ; if q[0] gt ihi[i] then for ibin=ihi[i],q[0] do s.spex_summ_emask[ibin,i]=1 ; set additional bins ; if q[0] lt ihi[i] then for ibin=q[0]+1,ihi[i] do s.spex_summ_emask[ibin,i]=0 ; unset some bins ; endif else message,/info,'New high end of range is lower than all energies for interval ' + trim(i) + '. Not setting.' endfor endif else s.(tag_num) = vals endif return,s end