;+ ; $Header$ ; ; Laboratory for Atmospheric and Space Physics ; University of Colorado, Boulder, Colorado, USA ; ; FILENAME: ; view_diagnostics.pro ; ; AUTHOR: ; James Everton ; ; DATE: March 29, 2007 ; ; PURPOSE: ; The main procedure, view_diagnostic, created here provides a ; way to view multiple images at the same time. Sometimes, when ; images are being corrected, things can go wrong during the ; process, and this application provides a way to view the ; separate cleaning stages all at once to see when problems ; occurred. ; Added in March 2007 are plots of the middle column and middle ; rows of each of the images. This allows for a further analysis ; of how the images change through each cleaning stage. ; ; BACKGROUND: ; ; ALGORITHM: ; This program was written using IDL widgets. ; ; REFERENCES: ; ; NOTES: ; ; CONSTRAINTS: ; ; OTHER SERVERS/MODULES USED: ; ; RELATED MODULES / CLASSES: ; ; SUPPORTING DATABASE TABLES OR FILES: ; ; USAGE EXAMPLE: ; view_diagnostics, image_set ; ; VERSION: ; $Revision: 3.3 $ $Date: 2007-6-5 $ ; ; -------------------------------------------------------------------------- ; PROCEDURE view_diagnostics_event ; -------------------------------------------------------------------------- ; PURPOSE: ; The event handler for the view_diagnostics procedure ; ; INPUT PARAMETERS: ; event - ; A parameter automatically supplied by XMANAGER that holds the status ; of the event, along with ways to access the widget hierarchy. ; PRO VIEW_DIAGNOSTICS_EVENT, event ; Get the UVALUE for the triggered widget WIDGET_CONTROL, event.id, GET_UVALUE=uvalue ; Get the UVALUE for the base widget WIDGET_CONTROL, event.handler, GET_UVALUE=base_uvalue ; Get the variables out of the base_uvalue Images = base_uvalue.images COL_PLOT_TV = base_uvalue.col_plot_tv ROW_PLOT_TV = base_uvalue.row_plot_tv CASE WIDGET_INFO(event.id, /UNAME) OF 'COLCLEAR': BEGIN ;-- This is where we handle the clearing of the middle-column plot x_dim = (WIDGET_INFO(base_uvalue.col_plot, /geom, units=0)).scr_xsize y_dim = (WIDGET_INFO(base_uvalue.col_plot, /geom, units=0)).scr_ysize blank = replicate(0L, x_dim, y_dim) WSET, base_uvalue.col_plot_tv & TV, blank base_uvalue.col_plots = replicate(0B,n_elements(Images.viewer_images)) WIDGET_CONTROL, event.handler, SET_UVALUE=base_uvalue END 'COLSTEP': BEGIN ;-- This is where we step through the middle-column plots WIDGET_CONTROL, base_uvalue.col_step_num, GET_VALUE=in_value if ~isnumeric(in_value) then begin void = dialog_message('Can only use digits for step number') return endif if (in_value lt 0) then begin void = dialog_message('Value too low for step number') WIDGET_CONTROL, base_uvalue.col_step_num, set_value='0' return endif if (in_value ge n_elements(Images.viewer_images)) then begin void = dialog_message('Value too high for step number') WIDGET_CONTROL, base_uvalue.col_step_num, set_value=strtrim(n_elements(Images.viewer_images)-1,2) return endif base_uvalue.col_step = in_value WSET, base_uvalue.col_plot_tv plot, (*Images.viewer_images[base_uvalue.col_step].image_ptr)[base_uvalue.x_dim/2, *], $ COLOR=((float(base_uvalue.col_step+1)/float(n_elements(Images.viewer_images)))*255), $ YRANGE=[base_uvalue.col_min,base_uvalue.col_max], /NOERASE WIDGET_CONTROL, base_uvalue.col_step_num, $ set_value=strtrim(((in_value+1) MOD n_elements(Images.viewer_images)),2) base_uvalue.col_plots[base_uvalue.col_step] = 1 base_uvalue.col_step = ((base_uvalue.col_step+1) MOD n_elements(Images.viewer_images)) WIDGET_CONTROL, event.handler, SET_UVALUE=base_uvalue END 'COLMAXSCALE': BEGIN base_uvalue.col_max = $ ; (event.value/100.0)*(base_uvalue.col_high-base_uvalue.col_low)+base_uvalue.col_low exp((event.value/100.0) * alog(base_uvalue.col_high-base_uvalue.col_low))+base_uvalue.col_low if (base_uvalue.col_max eq base_uvalue.col_min) then base_uvalue.col_max += 1 WIDGET_CONTROL, uvalue, set_value=strtrim(string(base_uvalue.col_max, format='(f7.1)'),1) WIDGET_CONTROL, event.handler, SET_UVALUE=base_uvalue ; Re-plot x_dim = (WIDGET_INFO(base_uvalue.col_plot, /geom, units=0)).scr_xsize y_dim = (WIDGET_INFO(base_uvalue.col_plot, /geom, units=0)).scr_ysize blank = replicate(0L, x_dim, y_dim) WSET, base_uvalue.col_plot_tv & TV, blank for i=0, n_elements(base_uvalue.col_plots)-1 do begin if (base_uvalue.col_plots[i] eq 0) then continue plot, (*Images.viewer_images[i].image_ptr)[base_uvalue.x_dim/2,*], $ COLOR=((float(i+1)/float(n_elements(Images.viewer_images)))*255), $ YRANGE=[base_uvalue.col_min,base_uvalue.col_max], /NOERASE endfor END 'COLMINSCALE': BEGIN base_uvalue.col_min = $ ; (event.value/100.0)*(base_uvalue.col_high-base_uvalue.col_low)+base_uvalue.col_low exp((event.value/100.0) * alog(base_uvalue.col_high-base_uvalue.col_low))+base_uvalue.col_low if (base_uvalue.col_min eq base_uvalue.col_max) then base_uvalue.col_min -= 1 WIDGET_CONTROL, uvalue, set_value=strtrim(string(base_uvalue.col_min, format='(f7.1)'),1) WIDGET_CONTROL, event.handler, SET_UVALUE=base_uvalue ; Re-plot x_dim = (WIDGET_INFO(base_uvalue.col_plot, /geom, units=0)).scr_xsize y_dim = (WIDGET_INFO(base_uvalue.col_plot, /geom, units=0)).scr_ysize blank = replicate(0L, x_dim, y_dim) WSET, base_uvalue.col_plot_tv & TV, blank for i=0, n_elements(base_uvalue.col_plots)-1 do begin if (base_uvalue.col_plots[i] eq 0) then continue plot, (*Images.viewer_images[i].image_ptr)[base_uvalue.x_dim/2,*], $ COLOR=((float(i+1)/float(n_elements(Images.viewer_images)))*255), $ YRANGE=[base_uvalue.col_min,base_uvalue.col_max], /NOERASE endfor END 'ROWCLEAR': BEGIN ;-- This is where we handle the clearing of the middle-row plot x_dim = (WIDGET_INFO(base_uvalue.row_plot, /geom, units=0)).scr_xsize y_dim = (WIDGET_INFO(base_uvalue.row_plot, /geom, units=0)).scr_ysize blank = replicate(0L, x_dim, y_dim) WSET, base_uvalue.row_plot_tv & TV, blank base_uvalue.row_plots = replicate(0B,n_elements(Images.viewer_images)) WIDGET_CONTROL, event.handler, SET_UVALUE=base_uvalue END 'ROWSTEP': BEGIN ;-- This is where we step through the middle-row plots WIDGET_CONTROL, base_uvalue.row_step_num, GET_VALUE=in_value if ~isnumeric(in_value) then begin void = dialog_message('Can only use digits for step number') return endif if (in_value lt 0) then begin void = dialog_message('Value too low for step number') WIDGET_CONTROL, base_uvalue.row_step_num, set_value='0' return endif if (in_value ge n_elements(Images.viewer_images)) then begin void = dialog_message('Value too high for step number') WIDGET_CONTROL, base_uvalue.row_step_num, set_value=strtrim(n_elements(Images.viewer_images)-1,2) return endif base_uvalue.row_step = in_value WSET, base_uvalue.row_plot_tv plot, (*Images.viewer_images[base_uvalue.row_step].image_ptr)[*, base_uvalue.y_dim/2], $ COLOR=((float(base_uvalue.row_step+1)/float(n_elements(Images.viewer_images)))*255), $ YRANGE=[base_uvalue.row_min,base_uvalue.row_max], /NOERASE WIDGET_CONTROL, base_uvalue.row_step_num, $ set_value=strtrim(((in_value+1) MOD n_elements(Images.viewer_images)),2) base_uvalue.row_plots[base_uvalue.row_step] = 1 base_uvalue.row_step = ((base_uvalue.row_step+1) MOD n_elements(Images.viewer_images)) WIDGET_CONTROL, event.handler, SET_UVALUE=base_uvalue END 'ROWMAXSCALE': BEGIN base_uvalue.row_max = $ ; (event.value/100.0)*(base_uvalue.row_high-base_uvalue.row_low)+base_uvalue.row_low exp((event.value/100.0) * alog(base_uvalue.row_high-base_uvalue.row_low))+base_uvalue.row_low if (base_uvalue.row_max eq base_uvalue.row_min) then base_uvalue.row_max += 1 WIDGET_CONTROL, uvalue, set_value=strtrim(string(base_uvalue.row_max, format='(f7.1)'),1) WIDGET_CONTROL, event.handler, SET_UVALUE=base_uvalue ; Re-plot x_dim = (WIDGET_INFO(base_uvalue.row_plot, /geom, units=0)).scr_xsize y_dim = (WIDGET_INFO(base_uvalue.row_plot, /geom, units=0)).scr_ysize blank = replicate(0L, x_dim, y_dim) WSET, base_uvalue.row_plot_tv & TV, blank for i=0, n_elements(base_uvalue.row_plots)-1 do begin if (base_uvalue.row_plots[i] eq 0) then continue plot, (*Images.viewer_images[i].image_ptr)[*,base_uvalue.y_dim/2], $ COLOR=((float(i+1)/float(n_elements(Images.viewer_images)))*255), $ YRANGE=[base_uvalue.row_min,base_uvalue.row_max], /NOERASE endfor END 'ROWMINSCALE': BEGIN base_uvalue.row_min = $ ; (event.value/100.0)*(base_uvalue.row_high-base_uvalue.row_low)+base_uvalue.row_low exp((event.value/100.0) * alog(base_uvalue.row_high-base_uvalue.row_low))+base_uvalue.row_low if (base_uvalue.row_min eq base_uvalue.row_max) then base_uvalue.row_min -= 1 WIDGET_CONTROL, uvalue, set_value=strtrim(string(base_uvalue.row_min, format='(f7.1)'),1) WIDGET_CONTROL, event.handler, SET_UVALUE=base_uvalue ; Re-plot x_dim = (WIDGET_INFO(base_uvalue.row_plot, /geom, units=0)).scr_xsize y_dim = (WIDGET_INFO(base_uvalue.row_plot, /geom, units=0)).scr_ysize blank = replicate(0L, x_dim, y_dim) WSET, base_uvalue.row_plot_tv & TV, blank for i=0, n_elements(base_uvalue.row_plots)-1 do begin if (base_uvalue.row_plots[i] eq 0) then continue plot, (*Images.viewer_images[i].image_ptr)[*,base_uvalue.y_dim/2], $ COLOR=((float(i+1)/float(n_elements(Images.viewer_images)))*255), $ YRANGE=[base_uvalue.row_min,base_uvalue.row_max], /NOERASE endfor END 'DRAW': BEGIN if (event.type eq 0) && (event.clicks eq 2) then begin loadct, 39 colors = make_array(3, 256) tvlct, colors, /get iImage, *uvalue.image_ptr, RGB_TABLE=COLORS endif END ELSE: ENDCASE end ; -------------------------------------------------------------------------- ; PROCEDURE view_diagnostics ; -------------------------------------------------------------------------- ; PURPOSE: ; This procedure takes in Images and displays them all at once. ; If you want to take a closer look at one of the images, simply ; click on the image and it will open up in iImage. ; ; INPUT PARAMETERS: ; Images - ; An array of 1 element that contains a structure set up as: ; { viewer_images, - An array of image structures to be displayed ; viewer_caption } - A caption that's specific to each viewer ; ; The 'viewer_images' field will be an array of a structure set up as: ; { image_ptr, - A pointer to an image array ; image_caption } - A Caption specific to each image ; ; OUTPUT PARAMETERS: ; NONE ; ; RETURN VALUE: ; NONE ; ; KEYWORD ARGUMENTS: ; NONE ; ; NOTES: ; PRO VIEW_DIAGNOSTICS, Images ;-- Input checking: if ~KEYWORD_SET(Images) then begin print, "ERROR: No images supplied." return endif else begin if N_ELEMENTS(Images[0].viewer_images) gt 12 then begin print, "ERROR: Too many images for a single view." return endif else begin if N_ELEMENTS(Images[0].viewer_images) lt 1 then begin print, "ERROR: No images to display." return endif endelse endelse ;-- Set up variables based on input data num_of_windows = N_ELEMENTS(Images[0].viewer_images) dimensions = size(*Images[0].viewer_images[0].image_ptr, /DIMENSIONS) x_dim = dimensions[0] y_dim = dimensions[1] high_val=0 & col_high=0 & row_high=0 col_low=min((*Images.viewer_images[0].image_ptr)[x_dim/2,*]) row_low=min((*Images.viewer_images[0].image_ptr)[*,y_dim/2]) for i=0, n_elements(Images.viewer_images.image_ptr)-1 do begin high_val = (max(*Images.viewer_images[i].image_ptr) gt high_val ?$ max(*Images.viewer_images[i].image_ptr) : high_val ) col_high = (max((*Images.viewer_images[i].image_ptr)[x_dim/2,*]) gt col_high ?$ max((*Images.viewer_images[i].image_ptr)[x_dim/2,*]) : col_high ) col_low = (min((*Images.viewer_images[i].image_ptr)[x_dim/2,*]) lt col_low ?$ min((*Images.viewer_images[i].image_ptr)[x_dim/2,*]) : col_low ) row_high = (max((*Images.viewer_images[i].image_ptr)[*,y_dim/2]) gt row_high ?$ max((*Images.viewer_images[i].image_ptr)[*,y_dim/2]) : row_high ) row_low = (min((*Images.viewer_images[i].image_ptr)[*,y_dim/2]) lt row_low ?$ min((*Images.viewer_images[i].image_ptr)[*,y_dim/2]) : row_low ) endfor ;print, 'Column plot -- Hi:',col_high,' - Lo:',col_low ;print, ' Row plot -- Hi:',row_high,' - Lo:',row_low row_plots = replicate(1B, num_of_windows) col_plots = replicate(1B, num_of_windows) draw_widgets_arr = replicate(0L, num_of_windows) colorline_arr = replicate(0L, num_of_windows) screen_dim = GET_SCREEN_SIZE() scr_x = screen_dim[0]-10 & scr_y = screen_dim[1]-80 win_width = (x_dim+10)*num_of_windows horiz_scroll = (win_width gt scr_x ? 1 : 0) ;plot_size = ((scr_y lt 768 ? scr_y : 768) - (y_dim+100) ) x_plot_size = (scr_x - 452)/2 y_plot_size = ((scr_y - (y_dim+100+(horiz_scroll*40))) lt 200 ? 200 : scr_y-(y_dim+100+(horiz_scroll*40))) plot_size = (x_plot_size lt y_plot_size ? x_plot_size : y_plot_size) ;-- Load in the color tables loadct, 39 colors = make_array(3, 256) tvlct, colors, /get ;-- Create base widget and menu if(horiz_scroll) then $ base = widget_base(TITLE=Images[0].viewer_caption, /COLUMN, /BASE_ALIGN_CENTER, $ XSIZE=scr_x, YSIZE=scr_y) $ else base = widget_base(TITLE=Images[0].viewer_caption, /COLUMN, /BASE_ALIGN_CENTER) ;-- Create the base widgets for the image windows and the image plots if (win_width gt scr_x) then $ topbase = widget_base(base, /ROW, X_SCROLL_SIZE=scr_x-20, Y_SCROLL_SIZE=y_dim+40) $ else topbase = widget_base(base, /ROW) botbase = widget_base(base, /ROW, /BASE_ALIGN_CENTER) ;-- Create the image windows for i=0, num_of_windows-1 do begin new_base = widget_base(topbase, /COLUMN, /BASE_ALIGN_CENTER) draw_widgets_arr[i] = widget_draw(new_base, XSIZE=x_dim, YSIZE=y_dim, $ /BUTTON_EVENTS, RETAIN=2, UNAME='DRAW', $ UVALUE={id:'DRAW', image_ptr:Images[0].viewer_images[i].image_ptr}) ; the last 2 steps are scaled to themselves via tvscl... indicate that ; here or the colorbar is confusing curr_label = Images[0].viewer_images[i].image_caption if i gt 5 then curr_label = curr_label + ' (TVSCL)' text = widget_label(new_base, XSIZE=x_dim, VALUE=curr_label) colorline_arr[i] = widget_draw(new_base, XSIZE=x_dim, YSIZE=5, RETAIN=2) endfor ;-- Create the lower half of the UI (plots, buttons and colorbar) ; Center column plot options col_btn_base = widget_base(botbase, XSIZE=194, /COLUMN, /BASE_ALIGN_LEFT, /FRAME) label = widget_label(col_btn_base, value='--- Middle column (vert) ---') col_clear_btn = widget_button(col_btn_base, value=' Clear Plot ', UNAME='COLCLEAR') col_step_btn = widget_button(col_btn_base, value=' Step ', UNAME='COLSTEP') horiz_base = widget_base(col_btn_base, /ROW) label = widget_label(horiz_base, value='Step #') col_step_num = widget_text(horiz_base, value='0', xsize=3, $ /EDITABLE, /ALL_EVENTS, UNAME='COLNUM') space = widget_base(col_btn_base, ysize=20) ; Column plot - scaling options horiz_base = widget_base(col_btn_base, /ROW) label = widget_label(horiz_base, value='Max: ') max_scaling_slider = widget_slider(horiz_base, /SUPPRESS_VALUE, minimum=0, maximum=100, uname='COLMAXSCALE', value=100) max_value_label = widget_label(horiz_base, value=strtrim(string(col_high,format='(f7.1)'),2), xsize=60, /ALIGN_LEFT) WIDGET_CONTROL, max_scaling_slider, SET_UVALUE=max_value_label horiz_base = widget_base(col_btn_base, /ROW) label = widget_label(horiz_base, value='Min: ') min_scaling_slider = widget_slider(horiz_base, /SUPPRESS_VALUE, minimum=0, maximum=100, uname='COLMINSCALE', value=0) min_value_label = widget_label(horiz_base, value=strtrim(string(col_low,format='(f7.1)'),2), xsize=60, /ALIGN_LEFT) WIDGET_CONTROL, min_scaling_slider, SET_UVALUE=min_value_label ; Colorbar and plot areas center_base = widget_base(botbase, /COLUMN, /BASE_ALIGN_CENTER) colorbar_base = widget_base(center_base, /COLUMN, /BASE_ALIGN_CENTER) colorbar = widget_draw(colorbar_base, xsize=256, ysize=20, RETAIN=2) row_base = widget_base(colorbar_base, /ROW) left_lbl_base = widget_base(row_base, /BASE_ALIGN_LEFT, /COLUMN, xsize=130) label = widget_label(left_lbl_base, value='0') right_lbl_base = widget_base(row_base, /BASE_ALIGN_RIGHT, /COLUMN, xsize=130) label = widget_label(right_lbl_base, value=string(high_val, format='(f0.2)')) ;value=strtrim(high_val,2)) plot_base = widget_base(center_base, /ROW, /BASE_ALIGN_CENTER) vert_base = widget_base(plot_base, /COLUMN, /BASE_ALIGN_CENTER) col_plot = widget_draw(vert_base, RETAIN=2, XSIZE=plot_size, YSIZE=plot_size) space = widget_base(plot_base, xsize=10) vert_base = widget_base(plot_base, /COLUMN, /BASE_ALIGN_CENTER) row_plot = widget_draw(vert_base, RETAIN=2, XSIZE=plot_size, YSIZE=plot_size) ; Center row plot options row_btn_base = widget_base(botbase, XSIZE=194, /COLUMN, /BASE_ALIGN_LEFT, /FRAME) label = widget_label(row_btn_base, value='--- Middle row (horiz) ---') row_clear_btn = widget_button(row_btn_base, value=' Clear Plot ', UNAME='ROWCLEAR') row_step_btn = widget_button(row_btn_base, value=' Step ', UNAME='ROWSTEP') horiz_base = widget_base(row_btn_base, /ROW) label = widget_label(horiz_base, value='Step #') row_step_num = widget_text(horiz_base, value='0', xsize=3, $ /EDITABLE, /ALL_EVENTS, UNAME='ROWNUM') space = widget_base(row_btn_base, ysize=20) ; Row plot - scaling options horiz_base = widget_base(row_btn_base, /ROW) label = widget_label(horiz_base, value='Max: ') max_scaling_slider = widget_slider(horiz_base, /SUPPRESS_VALUE, minimum=0, maximum=100, uname='ROWMAXSCALE', value=100) max_value_label = widget_label(horiz_base, value=strtrim(string(row_high,format='(f7.1)'),2), xsize=60, /ALIGN_LEFT) WIDGET_CONTROL, max_scaling_slider, SET_UVALUE=max_value_label horiz_base = widget_base(row_btn_base, /ROW) label = widget_label(horiz_base, value='Min: ') min_scaling_slider = widget_slider(horiz_base, /SUPPRESS_VALUE, minimum=0, maximum=100, uname='ROWMINSCALE', value=0) min_value_label = widget_label(horiz_base, value=strtrim(string(row_low,format='(f7.1)'),2), xsize=60, /ALIGN_LEFT) WIDGET_CONTROL, min_scaling_slider, SET_UVALUE=min_value_label ;print, 'Base dimensions: ',(widget_info(base,/geom,units=0)).xsize, (widget_info(base,/geom,units=0)).ysize ;-- Realize the base widget WIDGET_CONTROL, base, /REALIZE WIDGET_CONTROL, col_plot, GET_VALUE=col_plot_tv WIDGET_CONTROL, row_plot, GET_VALUE=row_plot_tv WIDGET_CONTROL, base, SET_UVALUE={ IMAGES: images ,$ X_DIM: x_dim ,$ Y_DIM: y_dim ,$ ROW_PLOTS: row_plots ,$ COL_PLOTS: col_plots ,$ COL_HIGH: col_high ,$ COL_LOW: col_low ,$ COL_MAX: col_high ,$ COL_MIN: col_low ,$ ROW_HIGH: row_high ,$ ROW_LOW: row_low ,$ ROW_MAX: row_high ,$ ROW_MIN: row_low ,$ COL_STEP: 0 ,$ ROW_STEP: 0 ,$ COL_STEP_NUM: col_step_num,$ ROW_STEP_NUM: row_step_num,$ COL_PLOT: col_plot ,$ COL_PLOT_TV: col_plot_tv ,$ ROW_PLOT: row_plot ,$ ROW_PLOT_TV: row_plot_tv } ;-- Output the images to the windows along with color bars FOR i=0, num_of_windows-1 DO BEGIN WIDGET_CONTROL, draw_widgets_arr[i], GET_VALUE=wTV & WSET, wTV ;if ((MOMENT(*Images.viewer_images[i].image_ptr))[0] lt (high_val/255)) then begin if i gt 5 then begin TVSCL, *Images[0].viewer_images[i].image_ptr endif else TV, ((*Images[0].viewer_images[i].image_ptr)*255.0)/high_val WIDGET_CONTROL, colorline_arr[i], GET_VALUE=wTV WSET, wTV & TV, replicate((float(i+1)/float(num_of_windows))*255, x_dim, 5) END ;-- Fill in the colorbar WIDGET_CONTROL, colorbar, GET_VALUE=wTV WSET, wTV & TV, BINDGEN(256) # REPLICATE(1B, 30) ;-- Fill in the plots WSET, COL_PLOT_TV for i=0, (n_elements(Images.viewer_images)-1) do begin plot, (*Images.viewer_images[i].image_ptr)[x_dim/2, *], $ COLOR=((float(i+1)/float(num_of_windows))*255), YRANGE=[0,col_high], /NOERASE endfor WSET, ROW_PLOT_TV for i=0, (n_elements(Images.viewer_images)-1) do begin plot, (*Images.viewer_images[i].image_ptr)[*, y_dim/2], $ COLOR=((float(i+1)/float(num_of_windows))*255), YRANGE=[0,row_high], /NOERASE endfor ; Run the event manager xmanager, 'view_diagnostics', base, /no_block end