; ; Leighton Barnden 26 Aug 2007 ; ; Compute Brain Perfusion Index and Absolute Cerebral BloodFlow using ; method of Matsuda et al, 1994, EJNM 19:195-200 ; ; Display projections and pick range for aortic arch and brain image ; generation. Draw regions. ; Query auto-peak selection OK. If not, operator to select. ; Compute parameter using peak offset ; Plot & get user to select line limits ; Compute Brain Perfusion Index & CBF ; ; Contents ; pro flash_multi_roi, mstat, t ; pro cellect_ev, event ; FUNCTION cell_display, img, xcells, ycells, home, title ; pro save_abs_cbf_results, links ; FUNCTION nearest_point, xarr, yarr, x, y ; pro brain_perfusion_index, links, b ; PRO adjust_curve_ev, event ; PRO setup_adjust_curve, event ; PRO get_adjust_peaks, links ; pro abs_cbf_process, links ; pro abs_cbf_ev, event ; pro abs_cbf ;_____________________________________________________________________________ @lblib.pro ;_____________________________________________________________________________ pro flash_multi_roi, mstat, t, LOCALSCALE=localscale IF NOT KEYWORD_SET(LOCALSCALE) THEN localscale = 0 img = *mstat.data first = mstat.first last = (first + mstat.nx * mstat.ny - 1) < mstat.nimg bimg = BYTE(img) IF localscale THEN BEGIN ; for scaling of low count (max < 100) projections use average ; of maxima of 5 adjacent projections ; create 1D array of same type as img to hold maxima localmax = img(0,0,0:mstat.nimg-1) FOR i=0,mstat.nimg-1 DO BEGIN localmax[i] = MAX(img[*,*,i]) > 1 EndFOR lowmax = WHERE(localmax LT 100) ; indices of low max projns smax = SMOOTH(localmax, 5) localmax[lowmax] = smax[lowmax] FOR i=0,last DO BEGIN im2d = img[*,*,i] b = BYTSCL(im2d, MAX=localmax[i]) bimg[*,*,i] = b EndFOR EndIF FOR i=first, last DO TV, bimg[*,*,i], i-first END ;_____________________________________________________________________________ pro cell_display_ev, event END ;_____________________________________________________________________________ pro cellect_ev, event WIDGET_CONTROL, event.id, GET_UVALUE = eventval d_source = event.handler WIDGET_CONTROL, d_source, GET_UVALUE = mstat CASE eventval OF "multidraw": IF event.type EQ 0 THEN BEGIN ; Respond to button press (event.type = 0) CASE event.press OF 1: BEGIN ; LEFT click cell_x = event.X / mstat.xdim ; cursor X cell_y = event.Y / mstat.ydim ; cursor Y cellnum = (mstat.ny - cell_y -1 ) * mstat.nx + cell_x index = mstat.nsel (*mstat.ptr).imnum[index] = cellnum IF mstat.nsel EQ 3 THEN BEGIN PTR_FREE, mstat.data WIDGET_CONTROL, event.handler, /DESTROY RETURN EndIF ELSE BEGIN x0 = cell_x * mstat.xdim & x1 = x0 + mstat.xdim -1 y0 = cell_y * mstat.ydim & y1 = y0+mstat.ydim-1 WIDGET_CONTROL, mstat.draw, GET_VALUE=index WSET, index PLOTS,[x0,x0,x1,x1,x0],[y1,y0,y0,y1,y1], /DEVICE, $ COLOR=(!d.table_size-1) mstat.nsel += 1 EndELSE END ; RIGHT click 4: WIDGET_DISPLAYCONTEXTMENU, event.ID, event.X, $ event.Y, mstat.popupBase EndCASE END 'popInvert': BEGIN !order = 1 - !order flash_multi_roi, mstat, 0, LOCALSCALE = mstat.localscale END 'popLocalScale': BEGIN mstat.localscale = 1 flash_multi_roi, mstat, 0, LOCALSCALE = mstat.localscale END 'popGlobalScale': BEGIN mstat.localscale = 0 flash_multi_roi, mstat, 0, LOCALSCALE = mstat.localscale END EndCASE WIDGET_CONTROL, d_source, SET_UVALUE = mstat END ;_____________________________________________________________________________ FUNCTION cell_display, img, xcells, ycells, home, title dim = SIZE(img) IF dim[0] LT 3 THEN RETURN, 0L zoom = 1 screen = GET_SCREEN_SIZE() xcells = xcells < (screen[1]/dim[1]) ; avoid need for X scroll multibase = WIDGET_BASE( TITLE = title, COLUMN=1, $ /MODAL, /FLOATING, GROUP_LEADER=home ) panel_x = xcells*dim[1]*zoom panel_y = ycells*dim[2]*zoom IF ycells * dim[2] LT screen[1] THEN $ multidraw = WIDGET_DRAW( multibase, $ XSIZE=panel_x, YSIZE=panel_y, $ UVALUE="multidraw", /BUTTON_EVENTS ) $ ELSE $ multidraw = WIDGET_DRAW( multibase, $ XSIZE=panel_x, YSIZE=panel_y, $ UVALUE="multidraw", /BUTTON_EVENTS, /SCROLL, $ X_SCROLL_SIZE=panel_x, Y_SCROLL_SIZE=FIX(screen[1]*0.9) ) popupBase = WIDGET_BASE(multidraw, /CONTEXT_MENU) button1 = WIDGET_BUTTON(popupBase, $ VALUE='Invert images', UVALUE='popInvert') button2 = WIDGET_BUTTON(popupBase, $ VALUE='Scale to Local Max', UVALUE='popLocalScale') button3 = WIDGET_BUTTON(popupBase, $ VALUE='Scale to Global Max', UVALUE='popGlobalScale') ptr = PTR_NEW({imnum:INTARR(4), Cancel:1}) mstat = { $ l_home:home, multibase:multibase, popupBase:popupBase, $ draw:multidraw, index:0, $ nx:xcells, ny:ycells, nimg:dim[3], xdim:dim[1], ydim:dim[2], $ nsel:0, ptr:ptr, $ data:Ptr_New(/ALLOCATE_HEAP), $ first:0, r_drop_action:0, localscale:1 } *mstat.data = img WIDGET_CONTROL, multibase, /REALIZE WIDGET_CONTROL, multidraw, GET_VALUE=index mstat.index = index WIDGET_CONTROL, multibase, SET_UVALUE = mstat flash_multi_roi, mstat, 0, /L XManager, "cell_display", multibase, EVENT_HANDLER = "cellect_ev" ; CLEANUP = "tidy_display_kill" choices = *ptr PTR_FREE, ptr, mstat.data RETURN, choices END ;_____________________________________________________________________________ pro save_abs_cbf_results, links hdr = *links.hdr file_path = links.out_path outfile = DIALOG_PICKFILE( PATH=file_path, $ FILTER='*.txt',GET_PATH=file_path,$ TITLE = "Enter or Pick Result file" ) IF file_path NE '' THEN BEGIN links.out_path = file_path OPENW, lun, outfile, /GET_LUN, /APPEND timedat = STRSPLIT(SYSTIME(0),' ',/EXTRACT) tday = timedat[2]+' '+timedat[1]+' '+timedat[4] resultext = STRING(FORMAT='(",",F5.2,",",F6.1, 2(1H,,I5), 6(1H,,I3))', $ links.bpi, links.cbf, links.nel_a, links.nel_b, $ links.del, links.pt1, links.pt2, links.aoval1, links.apk, links.bpk) printf, lun, FORMAT='(A,1H,,A,1H,,2A)', tday, $ STRING(hdr.db_name),STRING(hdr.date), resultext FREE_LUN,lun EndIF END ;_____________________________________________________________________________ FUNCTION nearest_point, xarr, yarr, x, y ; find index of nearest point in [xarr, yarr] to [x, y] d = SQRT((xarr-x)*(xarr-x) + (yarr-y)*(yarr-y)) tmp = MIN(d, index) RETURN, index END ;_____________________________________________________________________________ pro brain_perfusion_index, links, b ; disable GUI buttons WIDGET_CONTROL, links.all_again, SENSITIVE=0 WIDGET_CONTROL, links.plot1_again, SENSITIVE=0 WIDGET_CONTROL, links.plot2_again, SENSITIVE=0 WIDGET_CONTROL, links.save_result, SENSITIVE=0 hdr = *links.hdr patient = STRING(hdr.db_name)+' '+STRING(hdr.date) a = *links.saorta b_ov_a = (b/a) < 15.0 ; <15 to avoid pre-bolus extreme values integral = a * 0.0 integral[0] = a[0] nn = 60 < hdr.z_dim FOR i=1,nn-1 DO integral += a[i] int_ov_a = (integral/a) < 200.0 agent = (links.ecd) ? ' ECD' : ' HMPAO' WINDOW, /Free, XSIZE=600, YSIZE=300, XPOS=350, YPOS=440, $ TITLE=patient+agent+' Select RANGE for LINEAR FIT' links.intplot = !D.WINDOW PLOT, int_ov_a[0:nn-1], b_ov_a[0:nn-1], PSYM=1, SYMSIZE=0.5, $ XTITLE='!9i!XA/A(t)', YTITLE='B(t)/A(t)' ;tmp = DIALOG_MESSAGE( $ ; "Select first and last points for linear fit", DIALOG_PARENT=links.top) WSET, links.intplot ; make current plot draw widget right = 0 CURSOR, x1, y1, /DATA, /DOWN IF (!Err EQ 4) THEN right = 1 indx1 = nearest_point(int_ov_a, b_ov_a, x1, y1) OPLOT, int_ov_a[indx1:indx1], b_ov_a[indx1:indx1], PSYM=4, SYMSIZE=1.5 CURSOR, x2, y2, /DATA, /DOWN IF (!Err EQ 4) THEN right = 1 IF right THEN BEGIN y = DIALOG_MESSAGE( $ "Click Left, not Right. Try again.", $ DIALOG_PARENT=links.top, /I) RETURN EndIF indx2 = nearest_point(int_ov_a, b_ov_a, x2, y2) i1 = MIN([indx1, indx2]) i2 = MAX([indx1, indx2]) print, FORMAT='("a ", 12F7.1)', a[9:20] print, FORMAT='("b ", 12F7.1)', b[9:20] OPLOT, int_ov_a[i1:i2], b_ov_a[i1:i2], PSYM=4, SYMSIZE=1.5 F = LINFIT(int_ov_a[i1:i2], b_ov_a[i1:i2]) ;print,'fit is',F y0 = F[0] & slope = F[1] ymx = MAX(b_ov_a) & x2 = (ymx - y0)/slope OPLOT, [0.0,x2], [y0,ymx], LINESTYLE=1 bpi = 100.0 * slope * 10.0 * FLOAT(links.nel_a)/FLOAT(links.nel_b) CASE links.ecd OF 0: cbf = 2.75 * bpi + 17.7 ; HMPAO 1: cbf = 2.60 * bpi + 19.8 ; ECD EndCASE cbftext = STRING(FORMAT='("Cerebral BloodFlow =",F5.1," ml/100g/min")', cbf) XYOUTS, 0.16, 0.85, '!17'+cbftext+'!X', /NORMAL, SIZE=1.5 bpitext = STRING(FORMAT='("BPI =",F5.2)', bpi) XYOUTS, 0.16, 0.77, '!17'+bpitext+'!X', /NORMAL, SIZE=1.2 WSET, links.t_series ; make bolus plot draw widget !P = links.PsysV & !X = links.XsysV & !Y = links.YsysV x = FINDGEN(60) OPLOT, x[i1:i2], a[i1:i2], PSYM=4, SYMSIZE=1.5, COLOR=!d.table_size-1 links.bpi = bpi links.cbf = cbf links.pt1 = i1 links.pt2 = i2 WIDGET_CONTROL, links.all_again, /SENSITIVE WIDGET_CONTROL, links.plot1_again, /SENSITIVE WIDGET_CONTROL, links.plot2_again, /SENSITIVE WIDGET_CONTROL, links.save_result, /SENSITIVE END ;_____________________________________________________________________________ PRO adjust_curve_ev, event WIDGET_CONTROL, event.id, GET_UVALUE = eventval WIDGET_CONTROL, event.handler, GET_UVALUE = l_home WIDGET_CONTROL, l_home, GET_UVALUE = links WSET, links.t_series ; make current plot draw widget !P = links.PsysV & !X = links.XsysV & !Y = links.YsysV saorta = *links.saortaroi sbrain = *links.sbrain CASE eventval OF 'AortaPeak': BEGIN CURSOR, xloc, yloc, /DATA, /DOWN x1=FIX(xloc+0.5) OPLOT,[x1,x1],[0,saorta[x1]], LINESTYLE=2 del = ABS(links.bpk - x1) links.apk = x1 & links.del = del last = (*links.hdr).z_dim - del - 1 ofsbrain = (*links.sbrain)[del:last] OPLOT, ofsbrain, PSYM=-7, SYMSIZE=0.5, COLOR=(!d.table_size-1)*2/3 END 'BrainPeak': BEGIN CURSOR, xloc, yloc, /DATA, /DOWN x1=FIX(xloc+0.5) OPLOT,[x1,x1],[0,sbrain[x1]], LINESTYLE=2 del = ABS(x1 - links.apk) links.bpk = x1 & links.del = del last = (*links.hdr).z_dim - del - 1 ofsbrain = (*links.sbrain)[del:last] OPLOT, ofsbrain, PSYM=-7, SYMSIZE=0.5, COLOR=(!d.table_size-1)*2/3 END '1stValidAorta': BEGIN CURSOR, xloc, yloc, /DATA, /DOWN x1=FIX(xloc+0.5) OPLOT,[x1,x1],[0,saorta[x1+1]], LINESTYLE=3 links.aoval1 = x1 del = links.bpk - links.apk saorta[0:x1-1] = sbrain[del:del+x1-1] * (saorta[x1] / sbrain[x1+del]) ; print,'x1, saorta[x1-1]',x1, saorta[x1-1] OPLOT, saorta[0:x1-1], PSYM=-6, SYMSIZE=0.6, LINESTYLE=1 *links.saorta = saorta END 'AdjustDone': WIDGET_CONTROL, event.handler, /DESTROY ELSE: EndCASE WIDGET_CONTROL, l_home, SET_UVALUE = links END ;_____________________________________________________________________________ PRO setup_adjust_curve, links ; update links in memory. event handler reads it from there. WIDGET_CONTROL, links.home, SET_UVALUE = links adjust_curve_limits_base = WIDGET_BASE(GROUP_LEADER=links.top, $ EVENT_PRO='adjust_curve_ev', /COL, /MODAL) ;, $ ; XOFFSET=350, YOFFSET=100) adjust_aorta_peak = WIDGET_BUTTON(adjust_curve_limits_base, $ VALUE='New Aorta Peak', UVALUE='AortaPeak') adjust_aorta_peak = WIDGET_BUTTON(adjust_curve_limits_base, $ VALUE='New Brain Peak', UVALUE='BrainPeak') adjust_aorta_peak = WIDGET_BUTTON(adjust_curve_limits_base, $ VALUE='1st Valid Aorta Point', UVALUE='1stValidAorta') done_adjust = WIDGET_BUTTON(adjust_curve_limits_base, $ VALUE='DONE', UVALUE='AdjustDone') WIDGET_CONTROL, adjust_curve_limits_base, SET_UVALUE = links.home, /NO_COPY WIDGET_CONTROL, adjust_curve_limits_base, /REALIZE XMANAGER, 'setup_adjust_curve', adjust_curve_limits_base, $ EVENT_HANDLER = 'adjust_curve_ev', /NO_BLOCK END ;_____________________________________________________________________________ PRO get_adjust_peaks, links WIDGET_CONTROL, links.all_again, SENSITIVE=0 WIDGET_CONTROL, links.plot1_again, SENSITIVE=0 WIDGET_CONTROL, links.plot2_again, SENSITIVE=0 WIDGET_CONTROL, links.save_result, SENSITIVE=0 saorta = *links.saortaroi *links.saorta = *links.saortaroi sbrain = *links.sbrain links.aoval1 = 0 ; for re-entry pxtxt = STRING(FORMAT='(" (",I2,";",I4," pixels)")', $ links.nel_a, links.nel_b) maxval = MAX([saorta, sbrain]) WINDOW, /Free, XSIZE=600, YSIZE=300, XPOS=350, YPOS=140, $ TITLE='aortic-arch and brain'+pxtxt links.t_series = !D.WINDOW nn = 60 < (*links.hdr).z_dim ; plot first 60 points only PLOT, saorta[0:nn-1], YRANGE=[0.0,maxval], $ PSYM=-4, SYMSIZE=0.5 links.PsysV = !P & links.XsysV = !X & links.YsysV = !Y OPLOT, sbrain, PSYM=7, SYMSIZE=0.5 ; find first maximum mxa = MAX(saorta, imxa)/5.0 mxb = MAX(sbrain, imxb)/5.0 over = WHERE(saorta GT mxa/2.0) ia = over[2] WHILE saorta[ia] LT saorta[ia+1] AND ia LT imxa OR saorta[ia] LT mxa DO ia=ia+1 over = WHERE(sbrain GT mxb/3.0) ib = over[0] WHILE sbrain[ib] LT sbrain[ib+1] AND ib LT imxb OR sbrain[ib] LT mxb DO ib=ib+1 OPLOT,[ia,ia],[0,maxval], LINESTYLE=1 OPLOT,[ib,ib],[0,maxval], LINESTYLE=1 links.apk = ia links.bpk = ib setup_adjust_curve, links WIDGET_CONTROL, links.home, GET_UVALUE = links print,'links.apk, links.bpk',links.apk, links.bpk ;OPLOT, *links.saorta, PSYM=-7, SYMSIZE=0.5, COLOR=(!d.table_size-1)*2/3 END ;_____________________________________________________________________________ pro abs_cbf_process, links if links.loaded EQ 0 THEN BEGIN x = DIALOG_MESSAGE("Please File:Load image A") RETURN END WIDGET_CONTROL, links.all_again, SENSITIVE=0 ; for pass #2+ WIDGET_CONTROL, links.plot1_again, SENSITIVE=0 WIDGET_CONTROL, links.plot2_again, SENSITIVE=0 WIDGET_CONTROL, links.save_result, SENSITIVE=0 hdr = *links.hdr img = *links.img last = hdr.z_dim - 1 aorta = FLTARR(hdr.z_dim) ; array for aorta curve brain = aorta ; array for brain curve ;nd = hdr.x_dim / 64 & e = hdr.x_dim MOD 64 ;IF e EQ 0 AND nd GT 1 THEN BEGIN ; xd2 = hdr.x_dim/nd & yd2 = hdr.y_dim/nd ; dimg = REBIN(img, xd2, yd2, hdr.z_dim) ;EndIF ;nx=12 & ny=(hdr.z_dim+1)/nx ; re-display scaled to local maximum ;WIDGET_CONTROL, links.current_display, GET_UVALUE = disdat ;disdat.max_flag = 0 ; scale to local max ;flash_image_roi, disdat, 1 dimg = BYTE(img) nx = 7 & ny = 10 hint = $ 'Left click on first and last AORTIC-ARCH and first and last BRAIN images' cellect = cell_display(dimg, nx, ny, links.top, hint) i1 = MIN(cellect.imnum[0:1]) & i2 = MAX(cellect.imnum[0:1]) temp = img[*,*,i1:i2] fimg = TOTAL(temp, 3) ; sum aorta projections links.roi1 = imgset_display( fimg, zoom, hdr.x_dim, hdr.y_dim, 1, $ 'AORTIC ARCH ROI', links.top, XSIZE = 384 ) WIDGET_CONTROL, links.roi1, XOFFSET=70, YOFFSET = 170 WIDGET_CONTROL, links.roi1, GET_UVALUE = disdat ; from imgset_display WAIT, 1 make_roi, disdat.draw, disdat.zoom, Q1 ; lblib nel_a = N_ELEMENTS(Q1) IF nel_a LE 1 THEN RETURN ; no ROI drawn = 1 show_edge_on_display, Q1, links.roi1, 1 i1 = MIN(cellect.imnum[2:3]) & i2 = MAX(cellect.imnum[2:3]) ; if last image in cell display selected, interpret as last image in study IF i2 EQ nx*ny - 1 THEN i2 = hdr.z_dim - 1 temp = img[*,*,i1:i2] fimg = TOTAL(temp, 3) ; sum brain projections links.roi2 = imgset_display( fimg, zoom, hdr.x_dim, hdr.y_dim, 1, $ 'BRAIN ROI', links.top, XSIZE = 384 ) WIDGET_CONTROL, links.roi2, GET_UVALUE = disdat ; from imgset_display ; re-display scaled to brain maximum y2 = hdr.y_dim/3 *disdat.peak = MAX(fimg(*,0:y2)) disdat.max_flag = 1 ; scale to *disdat.peak flash_image_roi, disdat, 0 show_edge_on_display, Q1, links.roi2, 1, /PLURAL, /COLORS WIDGET_CONTROL, links.roi2, XOFFSET=70, YOFFSET = 190 WAIT, 1 make_roi, disdat.draw, disdat.zoom, Q2 ; lblib nel_b = N_ELEMENTS(Q2) IF nel_b LE 1 THEN RETURN ; no ROI drawn = 1 show_edge_on_display, Q2, links.roi2, 1, /PLURAL, COLORS=-1 ; generate curves of totals in ROIs FOR i=0,last DO BEGIN im2D = img[*,*,i] aorta[i] = TOTAL(im2D[Q1]) brain[i] = TOTAL(im2D[Q2]) EndFOR ; display regions on smoothed projections - need to convert 2D ROIs to 3D img = SMOOTH(img, [3,3,1], /EDGE_TRUNCATE, /NAN) mx = MAX(img) FOR i=0,hdr.z_dim-1 DO $ img[*,*,i] = img[*,*,i] * (mx / (MAX(img[*,*,i]) > 1)) pdis = imgset_display( img, zoom, hdr.x_dim, hdr.y_dim, hdr.z_dim, $ 'ROI review', links.top, XSIZE=384) roiplane = BYTARR(hdr.x_dim, hdr.y_dim) roiplane[Q1] = 1B & roiplane[Q2] = 1B FOR i=0,hdr.z_dim-1 DO dimg[*,*,i]=roiplane show_edge_on_display, dimg, pdis, 0, COLORS=-1 WIDGET_CONTROL, pdis, XOFFSET=70, YOFFSET = 210 *links.saortaroi = SMOOTH(aorta, 5) *links.saorta = *links.saortaroi *links.sbrain = SMOOTH(brain, 5) links.nel_a = nel_a links.nel_b = nel_b get_adjust_peaks, links del = links.bpk - links.apk print,'del, links.(apk,bpk)', del, links.apk, links.bpk IF del LT 0 THEN RETURN ofsbrain = (*links.sbrain)[del:hdr.z_dim-1] brain_perfusion_index, links, ofsbrain END ;____________________________________________________________________ pro abs_cbf_ev, event WIDGET_CONTROL, event.id, GET_UVALUE = eventval child = WIDGET_INFO(event.handler, /CHILD) ; first child WIDGET_CONTROL, child, GET_UVALUE = links ; Do not use /NO_COPY above. links becomes unavailable in get_filter ; cater for agent button event before any image loaded IF N_ELEMENTS(*links.hdr) GT 0 THEN hdr = *links.hdr CASE eventval OF "File": BEGIN op = STR_SEP(event.value,'|') ; decompose menu selection CASE op[0] OF "Save as ANALYZE": save_convert_imageset, links, event.value "Save as INTERFILE": save_convert_imageset, links, event.value "Preferences": CASE op[1] OF "New File:Load Filter": BEGIN get_filter, links.top, links.filter ; WIDGET_CONTROL, child, GET_UVALUE = links END "Printer Setup": $ ; result = DIALOG_PRINTJOB(DIALOG_PARENT=links.top) ; result = DIALOG_PRINTERSETUP(DIALOG_PARENT=links.top) print, DIALOG_PRINTERSETUP(DIALOG_PARENT=links.top) EndCASE "Quit": BEGIN PTR_FREE, links.hdr, links.img PTR_FREE, links.saortaroi, links.saorta, links.sbrain WIDGET_CONTROL, event.top, /DESTROY RETURN END ENDcase END "View": CASE event.value OF "Header": IF links.loaded THEN hdr_show_edit, $ links.hdr, links.top, links.filename "Colours": XloadCT, GROUP=links.top ENDcase "Agent": links.ecd = event.value "ReProcess": abs_cbf_process, links "Plot1": BEGIN get_adjust_peaks, links del = links.bpk - links.apk print,'del, links.del', del, links.apk, links.bpk IF del LT 0 THEN RETURN ofsbrain = (*links.sbrain)[del:hdr.z_dim-1] brain_perfusion_index, links, ofsbrain END "Plot2": BEGIN del = links.del ofsbrain = (*links.sbrain)[del:hdr.z_dim-1] brain_perfusion_index, links, ofsbrain END "SaveToFile": save_abs_cbf_results, links EndCASE ; update state variable WIDGET_CONTROL, child, SET_UVALUE = links END ;____________________________________________________________________ PRO abs_cbf platform_specific, S, need_to_swap, widget_font WIDGET_CONTROL, DEFAULT_FONT=widget_font loadct,3 ; red heat color table main_base = widget_base( Title = "Absolute CBF", GROUP=group, $ XOFFSET=230, YOFFSET=0, MBAR=bar, /COLUMN) ;_________________ define widgets of menu bar file_options = ['0\Save as ANALYZE', $ '1\Save as INTERFILE', $ '0\.hdr .dat', $ '0\.s .sb', $ '0\.r .rb', $ '2\.a00 .rb', $ '1\Preferences', $ '0\New File:Load Filter', $ '2\Printer Setup', $ '0\Quit' ] file_button = WIDGET_BUTTON( bar, VALUE='File', /MENU ) file_menu = CW_PDMENU(file_button, file_options, $ /MBAR, UVALUE='File', /RETURN_FULL_NAME, DELIMITER='|') view_button = WIDGET_BUTTON( bar, VALUE='View', /MENU ) view_menu = CW_PDMENU(view_button, $ ['0\Header','0\Colours'], /MBAR, UVALUE='View', /RETURN_NAME) ;________________ end of menu bar definition ; 'Load' button and image-format droplist pre_fmt = 0 ; 0:DICOM 1:Analyze 2:Interfile 3:Odyssey load_format_line, main_base, pre_fmt, image_formats, $ LOAD_BUTTON_TEXT="Load image A" agent_button = CW_BGROUP(main_base, ['HMPAO','ECD'], /ROW, $ /EXCLUSIVE, LABEL_LEFT='Agent', UVALUE='Agent', /NO_RELEASE) all_again = WIDGET_BUTTON( main_base, VALUE="Repeat all", $ UVALUE="ReProcess", SENSITIVE=0) plot1_again = WIDGET_BUTTON( main_base, VALUE="Re-Select on Aorta/Brain Plot", $ UVALUE="Plot1", SENSITIVE=0) plot2_again = WIDGET_BUTTON( main_base, VALUE="Re-Select on Linear Fit Plot", $ UVALUE="Plot2", SENSITIVE=0) save_result = WIDGET_BUTTON( main_base, VALUE="Save Results to File", $ UVALUE="SaveToFile", SENSITIVE=0) ; Create structure 'links' for access to user variables throughout procedures. ; It is stored in the UVALUE of the first child of main_base, as recommended in ; Building IDL Applications, chapt 15, Managing Widget Application State. ; (MBAR=bar is declared in main_base definition, so the first child is 'bar'.) ; Usage of pointers (heap variables) for hdr and img allows painless ; changes to the header (hdr) and/or 3D image array (img) type or size. ; Their contents are assigned in 'read_[type]', e.g. read_analyze in lblib.pro. ; links.comm is used in read_marconi in lblib.pro child = WIDGET_INFO(main_base, /CHILD) ; first child = bar links = { top:main_base, home:child, comm:0L, $ all_again:all_again, plot1_again:plot1_again, plot2_again:plot2_again, $ save_result:save_result, agent_button:agent_button, ecd:0, $ current_display:0L, roi1:0L, roi2:0L, mul_display:0L, $ t_series:0L, intplot:0L, img_fmt:image_formats[pre_fmt], $ previous:'abs_cbf_path', new_img_pro:'abs_cbf_process', $ S:S, swap:need_to_swap, loaded:0, show:0, zoom:1, $ data_path:GETENV('HOME'), filter:'*.img', out_path:GETENV('HOME'), $ PkTtle:'Select Image', filename:'', $ nel_a:0, nel_b:0, del:0, pt1:0, pt2:0, $ apk:0, bpk:0, aoval1:0, bpi:0.0, cbf:0.0, $ PsysV:!P, XsysV:!X, YsysV:!Y, $ ; plot system values saortaroi:Ptr_New(/ALLOCATE_HEAP), saorta:Ptr_New(/ALLOCATE_HEAP), $ sbrain:Ptr_New(/ALLOCATE_HEAP), $ hdr:Ptr_New(/ALLOCATE_HEAP), img:Ptr_New(/ALLOCATE_HEAP) } WIDGET_CONTROL, links.agent_button, SET_VALUE=links.ecd WIDGET_CONTROL, child, SET_UVALUE = links, /NO_COPY WIDGET_CONTROL, main_base, /REALIZE XMANAGER, 'abs_cbf', main_base , EVENT_HANDLER = 'abs_cbf_ev', /NO_BLOCK END