Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado
How do I create a plot which looks something like a Matrix Plot in IDL ?
Re: How do I create a plot which looks something like a Matrix Plot in IDL ?
On Saturday, January 2, 2016 at 9:51:16 PM UTC+1, Jim P wrote: > On Saturday, January 2, 2016 at 10:31:50 AM UTC-7, James wrote: >> I have two dataset scenarios. Each scenario is an output from a model and each scenario contains an array of values in the x (horizontal) axis and 10 arrays of values in the y (vertical) axis. I am trying to create a plot which looks like this http://www.mathworks.com/matlabcentral/answers/uploaded_file s/42412/3.png >> I have been looking for a plot function in ENVI IDL which can help make these plots but so far I did not find any. Can anybody help? Even better if someone can suggest a better graphical/visualization/plot option to display these two multivariate datasets so that the differences are conspicuous enough. With line graphs the visualization is not clear enough because the same values overlap on top of each other. >> >> Following are my scenarios. >> >> SCENARIO A >> >> x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >> y1= [0, 0, 0.02, 0.01, 0, 0, 0, 0, 0, 0, 0, 0] >> y2= [0.01, 0, 0.05, 0.1, 0.19, 0.6, 0.87, 1, 1, 1, 1, 1] >> y3= [0.02, 0.05, 0.2, 0.69, 0.99, 1, 1, 1, 1, 1, 1, 1] >> y4= [0.02, 0.12, 0.25, 0.97, 1, 1, 1, 1, 1, 1, 1, 1] >> y5= [0, 0.12, 0.68, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y6= [0, 0.2, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y7= [0.01, 0.49, 0.97, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y8= [0.01, 0.51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y9= [0.01, 0.82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y10= [0, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> >> SCENARIO B >> >> x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >> y1= [0.01, 0.03, 0.01, 0, 0.01, 0, 0, 0, 0, 0, 0, 0] >> y2= [0.01, 0.07, 0.04, 0.13, 0.23, 0.5, 0.92, 1, 1, 1, 1, 1] >> y3= [0.01, 0.03, 0.2, 0.61, 0.99, 1, 1, 1, 1, 1, 1, 1] >> y4= [0.02, 0.06, 0.4, 0.99, 1, 1, 1, 1, 1, 1, 1, 1] >> y5= [0, 0.24, 0.61, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y6= [0, 0.26, 0.88, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y7= [0, 0.51, 0.99, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y8= [0.02, 0.64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y9= [0.02, 0.87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> y10= [0.01, 0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] > > The simplest way may be to use a widget_table with cell colors, then take a screen capture. > > Jim P. ************************************************************ **************** Dear Jim, Thanks a lot for your helpful comments. I have never used WIDGET_TABLE function before since I am quite new to IDL Programming. The idea seems interesting and I want to try it. I am right now looking at the help page http://www.exelisvis.com/docs/WIDGET_TABLE.html Do you know whether this function allows automatic addition of cell colours based on the range of values present or do I need to manually assign cell colours to the values? Additionally, if I assign colours to the cells which hold the values, will the values be still visible or I can replace the values just with colours? Apologies if I am asking some basic questions which may be otherwise common knowledge among the IDL Programmers' community. It would be a great help if I can find an example. I will search the web for it. If you have any other suggestions they are welcome. James
On Saturday, January 2, 2016 at 2:30:29 PM UTC-7, James wrote: > On Saturday, January 2, 2016 at 9:51:16 PM UTC+1, Jim P wrote: >> On Saturday, January 2, 2016 at 10:31:50 AM UTC-7, James wrote: >>> I have two dataset scenarios. Each scenario is an output from a model and each scenario contains an array of values in the x (horizontal) axis and 10 arrays of values in the y (vertical) axis. I am trying to create a plot which looks like this http://www.mathworks.com/matlabcentral/answers/uploaded_file s/42412/3.png >>> I have been looking for a plot function in ENVI IDL which can help make these plots but so far I did not find any. Can anybody help? Even better if someone can suggest a better graphical/visualization/plot option to display these two multivariate datasets so that the differences are conspicuous enough. With line graphs the visualization is not clear enough because the same values overlap on top of each other. >>> >>> Following are my scenarios. >>> >>> SCENARIO A >>> >>> x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>> y1= [0, 0, 0.02, 0.01, 0, 0, 0, 0, 0, 0, 0, 0] >>> y2= [0.01, 0, 0.05, 0.1, 0.19, 0.6, 0.87, 1, 1, 1, 1, 1] >>> y3= [0.02, 0.05, 0.2, 0.69, 0.99, 1, 1, 1, 1, 1, 1, 1] >>> y4= [0.02, 0.12, 0.25, 0.97, 1, 1, 1, 1, 1, 1, 1, 1] >>> y5= [0, 0.12, 0.68, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y6= [0, 0.2, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y7= [0.01, 0.49, 0.97, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y8= [0.01, 0.51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y9= [0.01, 0.82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y10= [0, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> >>> SCENARIO B >>> >>> x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>> y1= [0.01, 0.03, 0.01, 0, 0.01, 0, 0, 0, 0, 0, 0, 0] >>> y2= [0.01, 0.07, 0.04, 0.13, 0.23, 0.5, 0.92, 1, 1, 1, 1, 1] >>> y3= [0.01, 0.03, 0.2, 0.61, 0.99, 1, 1, 1, 1, 1, 1, 1] >>> y4= [0.02, 0.06, 0.4, 0.99, 1, 1, 1, 1, 1, 1, 1, 1] >>> y5= [0, 0.24, 0.61, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y6= [0, 0.26, 0.88, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y7= [0, 0.51, 0.99, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y8= [0.02, 0.64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y9= [0.02, 0.87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> y10= [0.01, 0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >> >> The simplest way may be to use a widget_table with cell colors, then take a screen capture. >> >> Jim P. > ************************************************************ **************** > > Dear Jim, > > Thanks a lot for your helpful comments. I have never used WIDGET_TABLE function before since I am quite new to IDL Programming. The idea seems interesting and I want to try it. I am right now looking at the help page http://www.exelisvis.com/docs/WIDGET_TABLE.html > Do you know whether this function allows automatic addition of cell colours based on the range of values present or do I need to manually assign cell colours to the values? Additionally, if I assign colours to the cells which hold the values, will the values be still visible or I can replace the values just with colours? Apologies if I am asking some basic questions which may be otherwise common knowledge among the IDL Programmers' community. It would be a great help if I can find an example. I will search the web for it. If you have any other suggestions they are welcome. > > James Below is an example I wrote a number of years ago, with additional input from Dr. Mike Galloy. On the left is an image and on the right is a tabular form of the image with the cells colored according to the selected color table, using the same color table as the pixels in the image. You would be responsible for setting the color of each cell. "Showing" and "hiding" the text value in a cell is simply a matter of setting the foreground color to be the same as the background color. There are lots of comments that, along with the online help, should get you where you want to be. ;+ ; This procedure updates the image window display based ; on the current contents of the table widget, the ; selected cells (if any) and the current color table. ; ; @Param ; TLB {in}{required}{type=long} ; Set this parameter to the ID of the top-level base. ; ; @Hidden ; ; @Author ; JLP, RSI Global Services ; ; @History ; March 29, 2005 - Initial version ;- Pro ImageTable_62_UpdateImage, TLB Compile_Opt StrictArr On_Error, 2 ; ; Get the raw data values from the table. ; Table = Widget_Info(TLB, Find_by_UName='ValueTable') Widget_Control, Table, Get_Value = Values ; ; Get the color table number from the combobox. ; CTCombobox = Widget_Info(TLB, Find_by_UName = 'ColorTableCombobox') Current = Widget_Info(CTCombobox, /Combobox_GetText) Widget_Control, CTCombobox, Get_Value = AllValues CTIndex = (Where(AllValues eq Current))[0] ; ; Save the Direct Graphics state. ; WSave = !d.window Device, Get_Decomposed = WasDecomposed TVLCT, R, G, B, /Get ; ; Draw the table values to the image window using ; the current color table. ; Draw = Widget_Info(TLB, Find_by_UName = 'ImageDraw') Widget_Control, Draw, Get_Value = DrawID WSet, DrawID LoadCT, CTIndex, /Silent Device, Decomposed = 0 ; ; Remember that the table values are flipped in Y ; relative to our image so they orient the same way ; on the screen. ; TVScl, Reverse(Values, 2) ; ; Read the image buffer back from the window. ; Device, Decomposed = 1 Image = TVRd(True = 1) ; ; Restore the Direct Graphics state. ; Device, Decomposed = WasDecomposed If (WSave ne -1) then Begin Device, Window_State = WState If (WState[WSave]) then Begin WSet, WSave EndIf EndIf TVLCT, R, G, B ; ; Save the image data for the purpose of reapplying the ; selection box. ; Widget_Control, TLB, Set_UValue = Image ; ; Flip the image data about Y back into the orientation of the ; table. ; TableImage = Reverse(Temporary(Image), 3) ; ; The background color of each cell corresponds to each pixel ; value. We use "Update = 0" to prevent excessive flashing. ; Widget_Control, Table, $ Background_Color = TableImage, Update = 0 ; ; If we're "hiding" the text, this just means we draw the ; table values using the same color as the background. ; HideShow = Widget_Info(TLB, Find_by_UName = 'HideShowCombobox') If (Widget_Info(HideShow, /Combobox_GetText) eq 'Show') then Begin ; ; If we're showing table values, render the text in either black ; or white, depending on the better contrast with the background ; color in the cell. ; ImageTable_62_EnhanceText, TableImage EndIf Widget_Control, Table, $ Foreground_Color = TableImage, Update = 0 ; ; Update the base now with the accumulated changes. ; Widget_Control, TLB, /Update If (~Widget_Info(TLB, /Map)) then Begin Widget_Control, TLB, Map = 1 EndIf End ;+ ; This procedure converts an input array of table cell (image ; pixel) colors to an array of black and/or white colors to ; be used as the text color of each cell. The color black ; or white is chosen to increase contrast with the background ; color in each cell. ; ; @Param ; RGB {inout}{required}{type=BYTARR(3, N, M)} ; Set this parameter to the RGB colors of the pixels ; displayed in the image using the current color table. ; On output, the array will contain the color, either ; white or black, to be used for the foreground (text) ; color for the corresponding table cells. ; ; @Hidden ; ; @Author ; JLP, RSI Global Services ; ; @History ; March 29, 2005 - Initial version ;- Pro ImageTable_62_EnhanceText, RGB Compile_Opt StrictArr On_Error, 2 ; ; Convert the individual pixel colors from RGB space to ; hue, lightness and saturation space. ; Color_Convert, Reform(RGB[0, *, *]), Reform(RGB[1, *, *]), $ Reform(RGB[2, *, *]), H, L, S, /RGB_HLS ; ; We say that a pixel is "dark" if its lightness is less ; than 50%. ; Dark = Where(L lt .50, NDark) ; ; Light pixels will use black text. This is out initial ; default. ; RGB[*] = 0b ImageSize = Size(RGB, /Dimensions) If (NDark ne 0) then Begin ; ; Dark pixels will have white text. We use reform here ; to aid in addressing our 2-D image space with the 1-dimensional ; vectors returned by Color_Convert. We use Overwrite so ; we don't make extra copies of the data. ; RGB = Reform(RGB, 3, N_elements(RGB)/3, /Overwrite) RGB[*, Dark] = 255b RGB = Reform(RGB, 3, ImageSize[1], ImageSize[2], /Overwrite) EndIf End ;+ ; This procedure manages all events from the application's ; widgets. ; ; @Param ; Event {in}{required}{type=widget event structure} ; Set this parameter to the event structure to be ; acted upon. ; ; @Hidden ; ; @Author ; JLP, RSI Global Services ; ; @History ; March 29, 2005 - Initial version ;- Pro ImageTable_62_Event, Event Compile_Opt StrictArr On_Error, 2 ; ; What type of event is it? ; EventType = Tag_Names(Event, /Structure_Name) If (EventType eq 'WIDGET_BASE') then Begin ; ; This is a base resize event. We adjust the size of the ; table accordingly (and leave all the other widgets alone.) ; TLBGeom = Widget_Info(Event.Top, /Geometry) ; ; The base on the left hand side containing the image, comboboxes ; and spinner, remains fixed in size. ; Left = Widget_Info(Event.Top, Find_by_UName = 'LeftBase') LeftGeom = Widget_Info(Left, /Geometry) ; ; The table widget occupies "everything else". ; NewX = Event.X - 2*TLBGeom.XPad - LeftGeom.Scr_XSize > 10 NewY = Event.Y - 2*TLBGeom.YPad > 10 Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') ; ; Update the table size and return. ; Widget_Control, Table, Scr_XSize = NewX, Scr_YSize = NewY Return EndIf ; ; All other events are managed according to the UVALUE of the ; widget that produced the event. ; Widget_Control, Event.ID, Get_UValue = BranchCode Case BranchCode of 'ValueVisibility' : Begin ; ; Hide or show the values in the table. ; Widget_Control, Event.Top, Get_UValue = Image Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') Case Widget_Info(Event.ID, /Combobox_GetText) of 'Show' : Begin ; ; If we're showing the text in the table, make sure the text color ; contrasts well with the cell color. ; ImageTable_62_EnhanceText, Image ; ; Remember that the table values are "upside down" in Y to ; correspond to our image orientation, so we need to flip ; the data. ; Widget_Control, Table, $ Foreground_Color = Reverse(Temporary(Image), 3) End 'Hide' : Begin ; ; If we're hiding the text in the table, then we set the text ; color to be the same as the image color at that pixel. Again, ; we need to flip the data to match the image orientation. ; Widget_Control, Table, $ Foreground_Color = Reverse(Temporary(Image), 3) End EndCase End 'ColorTable' : Begin ; ; A change in color table means we must update the image as well ; as the cell colors in the table. ; ImageTable_62_UpdateImage, Event.Top End 'Table' : Begin EventType = Tag_Names(Event, /Structure_Name) If (EventType eq 'WIDGET_CONTEXT') then Begin ; ; If we have a right click, this is a context menu event ; request, so show it at the position of the clicked cell. ; (Note that we have previously received at least one and ; maybe two WIDGET_TABLE_CELL_SEL events as a result of ; the right-click selection, if the table was editable.) ; ContextMenu = Widget_Info(Event.ID, $ Find_by_UName = 'TableContextMenu') Widget_DisplayContextMenu, Event.ID, $ Event.X, Event.Y, ContextMenu Return EndIf ; ; The user has selected cells in the table. First, ; update the image window. ; Widget_Control, Event.Top, Get_UValue = Image Draw = Widget_Info(Event.Top, Find_by_UName = 'ImageDraw') Widget_Control, Draw, Get_Value = DrawID ; ; Save the Direct Graphics environment. ; WSave = !d.window Device, Get_Decomposed = WasDecomposed ; ; Display the image to the draw widget. This will erase any ; previously overplotted line. A cleverer solution might use ; a pixmap instead. ; WSet, DrawID Device, Decomposed = 1 TV, Image, True = 1 ; ; Overplot the bounds of the region selected in the table ; if it's more than 1 cell. ; Selected = Widget_Info(Event.ID, /Table_Select) MinX = Min(Selected[0, *], Max = MaxX) MinY = Min(Selected[1, *], Max = MaxY) dX = MaxX - MinX + 1 dY = MaxY - MinY + 1 If ((dX gt 0) && (dY gt 0)) then Begin ; ; We're going to plot the bounding box in the image in green. ; We need to remember that the cell numbers in the table ; are flipped top to bottom with respect to the image. ; PlotS, MinX + [0, 1, 1, 0, 0]*dX, $ (Size(Image, /Dimensions))[2] - 1 - $ (MinY + [0, 0, 1, 1, 0]*dY), $ /Device, Color = '00ff00'x EndIf ; ; Restore the Direct Graphics environment. ; If (WSave ne -1) then Begin Device, Window_State = WState If (WState[WSave]) then Begin WSet, WSave EndIf EndIf Device, Decomposed = WasDecomposed End 'PixelSize' : Begin ; ; Change the number of pixels square each cell in the table ; should occupy according to the value in the spinner. This number ; actually includes the dividers between cells. ; Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') ; ; There are no bounds on the spinner, so we need to manually clamp ; it to a reasonable range. ; Value = Long(Event.Value) Value >= 2 Value <= 256 ; ; In case we needed to clamp the value, update the spinner with ; the current value. ; Widget_Control, Event.ID, Set_Value = Value, Update = 0 ; ; Adjust the cell dimensions in the table, then update ; everything on the interface at one time. ; Widget_Control, Table, Row_Heights = Value, $ Column_Widths = Value, Update = 0 Widget_Control, Event.Top, /Update End 'Context_SelectedStatistics' : Begin ; ; This is an event from the table's context menu. ; Calculate statistics on the selected cells. ; ParentContextBase = Widget_Info(Event.ID, /Parent) Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') Selected = Widget_Info(Table, /Table_Select) Widget_Control, Table, Get_Value = TableValues If (N_elements(Selected)/2 gt 1) then Begin TableSize = Size(TableValues, /Dimensions) Selected = Reform(Selected[0, *] + Selected[1, *]*TableSize[0]) Stats = Moment(TableValues[Selected], MDev = MDev, SDev = SDev) MinValue = Min(TableValues[Selected], Max = MaxValue) Stats = StrTrim([MinValue, MaxValue, Stats, MDev, SDev], 2) StatsLabels = ['Minimum', 'Maximum', 'Mean', 'Variance', 'Skewness', $ 'Kurtosis', 'Mean Absolute Deviation', $ 'Standard Deviation'] StatsLabel = StatsLabels + ' : ' + Stats EndIf Else Begin StatsLabel = 'Pixel value = ' + $ StrTrim(TableValues[Selected[0, 0], Selected[1, 0]], 2) EndElse v = Dialog_Message(StatsLabel, /Information, $ Dialog_Parent = Event.Top, $ Title = 'ImageTable 6.2 ROI Statistics') End 'Context_SelectedArea' : Begin ; ; This is an event from the table's context menu. ; Calculate the area of the selected cells ; ParentContextBase = Widget_Info(Event.ID, /Parent) Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') Selected = Widget_Info(Table, /Table_Select) NPixels = Long(N_elements(Selected)/2) AreaLabel = 'Area = ' + $ StrTrim(NPixels, 2) + $ ' pixel' + (NPixels gt 1 ? 's' : '') v = Dialog_Message(AreaLabel, /Information, $ Dialog_Parent = Event.Top, $ Title = 'ImageTable 6.2 ROI Area') End Else : EndCase End ;+ ; This procedure creates a table widget whose cell values are ; displayed in colors according to a color look-up table, ; much like an image. ; ; @Param ; Val {in}{optional}{type=integer array dimensions n by m} ; Set this parameter to a 2-dimensional array of integral ; values between the values of -99 and 999. (This limitation ; is related to the format statement used to display the ; cell values; feel free to modify the code according to ; your data's needs.) The default value is a 64-by-64 shifted ; DIST image. ; ; @Examples ; IDL> ImageTable_62 ; ; @Categories ; Widget_Table, 6.2 ; ; @Author ; Jim Pendleton & MG, RSI Global Services ; ; @History ; March 31, 2005 - Initial version ; ; @File_Comments ; This procedure highlights some new features of WIDGET_TABLE ; in IDL 6.2, in particular the ability to set foreground ; and background colors in individual cells, and to display ; a context menu within a table. ; ;- Pro ImageTable_62, Val Compile_Opt StrictArr On_Error, 2 ; ; Create a copy of the input data or create the default "bulls-eye" ; image. ; iVal = N_Elements(Val) eq 0 ? Fix(Shift(Dist(512), 256, 256)) : Val ImageSize = Size(iVal, /Dimensions) ; ; Create our widget tree. We'll have some controls on the left ; and a table widget on the right. ; TLB = Widget_Base(/Row, /TLB_Size_Events, UName = 'Top', $ Title = 'ImageTable 6.2') Left = Widget_Base(TLB, /Column, UName = 'LeftBase') D = Widget_Draw(Left, XSize = ImageSize[0], YSize = ImageSize[1], $ UName = 'ImageDraw') ; ; By default, we use the "Hardcandy" color table. It shows good ; contrast in the upper corner that is initiall displayed in the ; table. ; CTBase = Widget_Base(Left, /Row, /Align_Left) CTLabel = Widget_Label(CTBase, Value = 'Color Table : ') LoadCT, /Silent, Get_Names = CTNames ColorTable = 28 CTCombobox = Widget_Combobox(CTBase, Value = CTNames,$ UName = 'ColorTableCombobox', UValue = 'ColorTable') Widget_Control, CTCombobox, Set_Combobox_Select = ColorTable VisibilityBase = Widget_Base(Left, /Row, /Align_Left) VisibilityLabel = Widget_Label(VisibilityBase, $ Value = 'Table Values : ') VisibilityCombobox = Widget_Combobox(VisibilityBase, $ Value = ['Show', 'Hide'], $ UValue = 'ValueVisibility', $ UName = 'HideShowCombobox') ; ; We'll initially display each cell as an 18x18 square. The ; spinner will allow the user to adjust this. See the ; idl62/lib/itools/ui_widgets directory for the source to ; cw_itupdownfield.pro, an undocumented, but highly useful ; compound widget. ; PixelSize = 18 Spinner = CW_itUpDownField(Left, Increment = 1, $ Label = 'Pixel Size : ', $ Value = pixelsize, $ UName = 'PixelSizeSpinner', $ UValue = 'PixelSize') ; ; Create a table with our data values. The default orientation ; places the cell [0, 0] at the upper left. But we want it ; to be oriented the same as our image, with [0, 0] in the ; lower left.. So we need to flip the data in Y. ; Table = Widget_Table(TLB, Value = Reverse(IVal, 2), $ X_Scroll = 25,$ Y_Scroll = 25, $ Row_Heights = PixelSize, Column_Widths = PixelSize, $ Format = '(i3)', $ UName = 'ValueTable', $ UValue = 'Table', $ ; ; We choose a font appropriate to Windows or Linux. We want it ; to be small so our cell sizes can be small, too. ; Font = !version.os_family eq 'Windows' ? $ 'Helvetica*8' : 'timr08', $ Alignment = 1, $ ; ; Label the rows to show that we flipped the image in Y. ; Row 0 is at the bottom. ; Row_Labels = StrTrim(Reverse(Lindgen(ImageSize[1])), 2), $ /All_Events, $ ; ; Also capture context menu events (i.e., right-clicks.) ; /Context_Events, $ /Disjoint) ; ; Create a context menu for the table. ; ContextBase = Widget_Base(Table, /Context_Menu, $ UName = 'TableContextMenu') ContextStatisticsButton = Widget_Button(ContextBase, $ Value = 'Show Selected Statistics', $ UValue = 'Context_SelectedStatistics') ContextStatisticsArea = Widget_Button(ContextBase, $ Value = 'Show Selected Area', $ UValue = 'Context_SelectedArea') ; ; We initially hide the TLB until after we update the colors ; in the table the first time. ; Widget_Control, TLB, Map = 0 Geom = Widget_Info(TLB, /Geometry) ScreenSize = Get_Screen_Size() Widget_Control, TLB, $ TLB_Set_XOffset = (ScreenSize[0] - Geom.Scr_XSize)/2., $ TLB_Set_YOffset = (ScreenSize[1] - Geom.Scr_YSize)/2. Widget_Control, TLB, /Realize ; ; Update the colors in the cells and start the event handler. ; ImageTable_62_UpdateImage, TLB XManager, 'ImageTable_62', TLB, /No_Block End
On Sunday, January 3, 2016 at 2:40:03 AM UTC+1, Jim P wrote: > On Saturday, January 2, 2016 at 2:30:29 PM UTC-7, James wrote: >> On Saturday, January 2, 2016 at 9:51:16 PM UTC+1, Jim P wrote: >>> On Saturday, January 2, 2016 at 10:31:50 AM UTC-7, James wrote: >>>> I have two dataset scenarios. Each scenario is an output from a model and each scenario contains an array of values in the x (horizontal) axis and 10 arrays of values in the y (vertical) axis. I am trying to create a plot which looks like this http://www.mathworks.com/matlabcentral/answers/uploaded_file s/42412/3.png >>>> I have been looking for a plot function in ENVI IDL which can help make these plots but so far I did not find any. Can anybody help? Even better if someone can suggest a better graphical/visualization/plot option to display these two multivariate datasets so that the differences are conspicuous enough. With line graphs the visualization is not clear enough because the same values overlap on top of each other. >>>> >>>> Following are my scenarios. >>>> >>>> SCENARIO A >>>> >>>> x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> y1= [0, 0, 0.02, 0.01, 0, 0, 0, 0, 0, 0, 0, 0] >>>> y2= [0.01, 0, 0.05, 0.1, 0.19, 0.6, 0.87, 1, 1, 1, 1, 1] >>>> y3= [0.02, 0.05, 0.2, 0.69, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> y4= [0.02, 0.12, 0.25, 0.97, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y5= [0, 0.12, 0.68, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y6= [0, 0.2, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y7= [0.01, 0.49, 0.97, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y8= [0.01, 0.51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y9= [0.01, 0.82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y10= [0, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> >>>> SCENARIO B >>>> >>>> x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> y1= [0.01, 0.03, 0.01, 0, 0.01, 0, 0, 0, 0, 0, 0, 0] >>>> y2= [0.01, 0.07, 0.04, 0.13, 0.23, 0.5, 0.92, 1, 1, 1, 1, 1] >>>> y3= [0.01, 0.03, 0.2, 0.61, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> y4= [0.02, 0.06, 0.4, 0.99, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y5= [0, 0.24, 0.61, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y6= [0, 0.26, 0.88, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y7= [0, 0.51, 0.99, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y8= [0.02, 0.64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y9= [0.02, 0.87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> y10= [0.01, 0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> >>> The simplest way may be to use a widget_table with cell colors, then take a screen capture. >>> >>> Jim P. >> ************************************************************ **************** >> >> Dear Jim, >> >> Thanks a lot for your helpful comments. I have never used WIDGET_TABLE function before since I am quite new to IDL Programming. The idea seems interesting and I want to try it. I am right now looking at the help page http://www.exelisvis.com/docs/WIDGET_TABLE.html >> Do you know whether this function allows automatic addition of cell colours based on the range of values present or do I need to manually assign cell colours to the values? Additionally, if I assign colours to the cells which hold the values, will the values be still visible or I can replace the values just with colours? Apologies if I am asking some basic questions which may be otherwise common knowledge among the IDL Programmers' community. It would be a great help if I can find an example. I will search the web for it. If you have any other suggestions they are welcome. >> >> James > > Below is an example I wrote a number of years ago, with additional input from Dr. Mike Galloy. On the left is an image and on the right is a tabular form of the image with the cells colored according to the selected color table, using the same color table as the pixels in the image. > > You would be responsible for setting the color of each cell. > > "Showing" and "hiding" the text value in a cell is simply a matter of setting the foreground color to be the same as the background color. > > There are lots of comments that, along with the online help, should get you where you want to be. > > ;+ > ; This procedure updates the image window display based > ; on the current contents of the table widget, the > ; selected cells (if any) and the current color table. > ; > ; @Param > ; TLB {in}{required}{type=long} > ; Set this parameter to the ID of the top-level base. > ; > ; @Hidden > ; > ; @Author > ; JLP, RSI Global Services > ; > ; @History > ; March 29, 2005 - Initial version > ;- > Pro ImageTable_62_UpdateImage, TLB > Compile_Opt StrictArr > On_Error, 2 > ; > ; Get the raw data values from the table. > ; > Table = Widget_Info(TLB, Find_by_UName='ValueTable') > Widget_Control, Table, Get_Value = Values > ; > ; Get the color table number from the combobox. > ; > CTCombobox = Widget_Info(TLB, Find_by_UName = 'ColorTableCombobox') > Current = Widget_Info(CTCombobox, /Combobox_GetText) > Widget_Control, CTCombobox, Get_Value = AllValues > CTIndex = (Where(AllValues eq Current))[0] > ; > ; Save the Direct Graphics state. > ; > WSave = !d.window > Device, Get_Decomposed = WasDecomposed > TVLCT, R, G, B, /Get > ; > ; Draw the table values to the image window using > ; the current color table. > ; > Draw = Widget_Info(TLB, Find_by_UName = 'ImageDraw') > Widget_Control, Draw, Get_Value = DrawID > WSet, DrawID > LoadCT, CTIndex, /Silent > Device, Decomposed = 0 > ; > ; Remember that the table values are flipped in Y > ; relative to our image so they orient the same way > ; on the screen. > ; > TVScl, Reverse(Values, 2) > ; > ; Read the image buffer back from the window. > ; > Device, Decomposed = 1 > Image = TVRd(True = 1) > ; > ; Restore the Direct Graphics state. > ; > Device, Decomposed = WasDecomposed > If (WSave ne -1) then Begin > Device, Window_State = WState > If (WState[WSave]) then Begin > WSet, WSave > EndIf > EndIf > TVLCT, R, G, B > ; > ; Save the image data for the purpose of reapplying the > ; selection box. > ; > Widget_Control, TLB, Set_UValue = Image > ; > ; Flip the image data about Y back into the orientation of the > ; table. > ; > TableImage = Reverse(Temporary(Image), 3) > ; > ; The background color of each cell corresponds to each pixel > ; value. We use "Update = 0" to prevent excessive flashing. > ; > Widget_Control, Table, $ > Background_Color = TableImage, Update = 0 > ; > ; If we're "hiding" the text, this just means we draw the > ; table values using the same color as the background. > ; > HideShow = Widget_Info(TLB, Find_by_UName = 'HideShowCombobox') > If (Widget_Info(HideShow, /Combobox_GetText) eq 'Show') then Begin > ; > ; If we're showing table values, render the text in either black > ; or white, depending on the better contrast with the background > ; color in the cell. > ; > ImageTable_62_EnhanceText, TableImage > EndIf > Widget_Control, Table, $ > Foreground_Color = TableImage, Update = 0 > ; > ; Update the base now with the accumulated changes. > ; > Widget_Control, TLB, /Update > If (~Widget_Info(TLB, /Map)) then Begin > Widget_Control, TLB, Map = 1 > EndIf > End > > > ;+ > ; This procedure converts an input array of table cell (image > ; pixel) colors to an array of black and/or white colors to > ; be used as the text color of each cell. The color black > ; or white is chosen to increase contrast with the background > ; color in each cell. > ; > ; @Param > ; RGB {inout}{required}{type=BYTARR(3, N, M)} > ; Set this parameter to the RGB colors of the pixels > ; displayed in the image using the current color table. > ; On output, the array will contain the color, either > ; white or black, to be used for the foreground (text) > ; color for the corresponding table cells. > ; > ; @Hidden > ; > ; @Author > ; JLP, RSI Global Services > ; > ; @History > ; March 29, 2005 - Initial version > ;- > Pro ImageTable_62_EnhanceText, RGB > Compile_Opt StrictArr > On_Error, 2 > ; > ; Convert the individual pixel colors from RGB space to > ; hue, lightness and saturation space. > ; > Color_Convert, Reform(RGB[0, *, *]), Reform(RGB[1, *, *]), $ > Reform(RGB[2, *, *]), H, L, S, /RGB_HLS > ; > ; We say that a pixel is "dark" if its lightness is less > ; than 50%. > ; > Dark = Where(L lt .50, NDark) > ; > ; Light pixels will use black text. This is out initial > ; default. > ; > RGB[*] = 0b > ImageSize = Size(RGB, /Dimensions) > If (NDark ne 0) then Begin > ; > ; Dark pixels will have white text. We use reform here > ; to aid in addressing our 2-D image space with the 1-dimensional > ; vectors returned by Color_Convert. We use Overwrite so > ; we don't make extra copies of the data. > ; > RGB = Reform(RGB, 3, N_elements(RGB)/3, /Overwrite) > RGB[*, Dark] = 255b > RGB = Reform(RGB, 3, ImageSize[1], ImageSize[2], /Overwrite) > EndIf > End > > > ;+ > ; This procedure manages all events from the application's > ; widgets. > ; > ; @Param > ; Event {in}{required}{type=widget event structure} > ; Set this parameter to the event structure to be > ; acted upon. > ; > ; @Hidden > ; > ; @Author > ; JLP, RSI Global Services > ; > ; @History > ; March 29, 2005 - Initial version > ;- > Pro ImageTable_62_Event, Event > Compile_Opt StrictArr > On_Error, 2 > ; > ; What type of event is it? > ; > EventType = Tag_Names(Event, /Structure_Name) > If (EventType eq 'WIDGET_BASE') then Begin > ; > ; This is a base resize event. We adjust the size of the > ; table accordingly (and leave all the other widgets alone.) > ; > TLBGeom = Widget_Info(Event.Top, /Geometry) > ; > ; The base on the left hand side containing the image, comboboxes > ; and spinner, remains fixed in size. > ; > Left = Widget_Info(Event.Top, Find_by_UName = 'LeftBase') > LeftGeom = Widget_Info(Left, /Geometry) > ; > ; The table widget occupies "everything else". > ; > NewX = Event.X - 2*TLBGeom.XPad - LeftGeom.Scr_XSize > 10 > NewY = Event.Y - 2*TLBGeom.YPad > 10 > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') > ; > ; Update the table size and return. > ; > Widget_Control, Table, Scr_XSize = NewX, Scr_YSize = NewY > Return > EndIf > ; > ; All other events are managed according to the UVALUE of the > ; widget that produced the event. > ; > Widget_Control, Event.ID, Get_UValue = BranchCode > Case BranchCode of > 'ValueVisibility' : Begin > ; > ; Hide or show the values in the table. > ; > Widget_Control, Event.Top, Get_UValue = Image > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') > Case Widget_Info(Event.ID, /Combobox_GetText) of > 'Show' : Begin > ; > ; If we're showing the text in the table, make sure the text color > ; contrasts well with the cell color. > ; > ImageTable_62_EnhanceText, Image > ; > ; Remember that the table values are "upside down" in Y to > ; correspond to our image orientation, so we need to flip > ; the data. > ; > Widget_Control, Table, $ > Foreground_Color = Reverse(Temporary(Image), 3) > End > 'Hide' : Begin > ; > ; If we're hiding the text in the table, then we set the text > ; color to be the same as the image color at that pixel. Again, > ; we need to flip the data to match the image orientation. > ; > Widget_Control, Table, $ > Foreground_Color = Reverse(Temporary(Image), 3) > End > EndCase > End > 'ColorTable' : Begin > ; > ; A change in color table means we must update the image as well > ; as the cell colors in the table. > ; > ImageTable_62_UpdateImage, Event.Top > End > 'Table' : Begin > EventType = Tag_Names(Event, /Structure_Name) > If (EventType eq 'WIDGET_CONTEXT') then Begin > ; > ; If we have a right click, this is a context menu event > ; request, so show it at the position of the clicked cell. > ; (Note that we have previously received at least one and > ; maybe two WIDGET_TABLE_CELL_SEL events as a result of > ; the right-click selection, if the table was editable.) > ; > ContextMenu = Widget_Info(Event.ID, $ > Find_by_UName = 'TableContextMenu') > Widget_DisplayContextMenu, Event.ID, $ > Event.X, Event.Y, ContextMenu > Return > EndIf > ; > ; The user has selected cells in the table. First, > ; update the image window. > ; > Widget_Control, Event.Top, Get_UValue = Image > Draw = Widget_Info(Event.Top, Find_by_UName = 'ImageDraw') > Widget_Control, Draw, Get_Value = DrawID > ; > ; Save the Direct Graphics environment. > ; > WSave = !d.window > Device, Get_Decomposed = WasDecomposed > ; > ; Display the image to the draw widget. This will erase any > ; previously overplotted line. A cleverer solution might use > ; a pixmap instead. > ; > WSet, DrawID > Device, Decomposed = 1 > TV, Image, True = 1 > ; > ; Overplot the bounds of the region selected in the table > ; if it's more than 1 cell. > ; > Selected = Widget_Info(Event.ID, /Table_Select) > MinX = Min(Selected[0, *], Max = MaxX) > MinY = Min(Selected[1, *], Max = MaxY) > dX = MaxX - MinX + 1 > dY = MaxY - MinY + 1 > If ((dX gt 0) && (dY gt 0)) then Begin > ; > ; We're going to plot the bounding box in the image in green. > ; We need to remember that the cell numbers in the table > ; are flipped top to bottom with respect to the image. > ; > PlotS, MinX + [0, 1, 1, 0, 0]*dX, $ > (Size(Image, /Dimensions))[2] - 1 - $ > (MinY + [0, 0, 1, 1, 0]*dY), $ > /Device, Color = '00ff00'x > EndIf > ; > ; Restore the Direct Graphics environment. > ; > If (WSave ne -1) then Begin > Device, Window_State = WState > If (WState[WSave]) then Begin > WSet, WSave > EndIf > EndIf > Device, Decomposed = WasDecomposed > End > 'PixelSize' : Begin > ; > ; Change the number of pixels square each cell in the table > ; should occupy according to the value in the spinner. This number > ; actually includes the dividers between cells. > ; > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') > ; > ; There are no bounds on the spinner, so we need to manually clamp > ; it to a reasonable range. > ; > Value = Long(Event.Value) > Value >= 2 > Value <= 256 > ; > ; In case we needed to clamp the value, update the spinner with > ; the current value. > ; > Widget_Control, Event.ID, Set_Value = Value, Update = 0 > ; > ; Adjust the cell dimensions in the table, then update > ; everything on the interface at one time. > ; > Widget_Control, Table, Row_Heights = Value, $ > Column_Widths = Value, Update = 0 > Widget_Control, Event.Top, /Update > End > 'Context_SelectedStatistics' : Begin > ; > ; This is an event from the table's context menu. > ; Calculate statistics on the selected cells. > ; > ParentContextBase = Widget_Info(Event.ID, /Parent) > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') > Selected = Widget_Info(Table, /Table_Select) > Widget_Control, Table, Get_Value = TableValues > If (N_elements(Selected)/2 gt 1) then Begin > TableSize = Size(TableValues, /Dimensions) > Selected = Reform(Selected[0, *] + Selected[1, *]*TableSize[0]) > Stats = Moment(TableValues[Selected], MDev = MDev, SDev = SDev) > MinValue = Min(TableValues[Selected], Max = MaxValue) > Stats = StrTrim([MinValue, MaxValue, Stats, MDev, SDev], 2) > StatsLabels = ['Minimum', 'Maximum', 'Mean', 'Variance', 'Skewness', $ > 'Kurtosis', 'Mean Absolute Deviation', $ > 'Standard Deviation'] > StatsLabel = StatsLabels + ' : ' + Stats > EndIf Else Begin > StatsLabel = 'Pixel value = ' + $ > StrTrim(TableValues[Selected[0, 0], Selected[1, 0]], 2) > EndElse > v = Dialog_Message(StatsLabel, /Information, $ > Dialog_Parent = Event.Top, $ > Title = 'ImageTable 6.2 ROI Statistics') > End > 'Context_SelectedArea' : Begin > ; > ; This is an event from the table's context menu. > ; Calculate the area of the selected cells > ; > ParentContextBase = Widget_Info(Event.ID, /Parent) > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') > Selected = Widget_Info(Table, /Table_Select) > NPixels = Long(N_elements(Selected)/2) > AreaLabel = 'Area = ' + $ > StrTrim(NPixels, 2) + $ > ' pixel' + (NPixels gt 1 ? 's' : '') > v = Dialog_Message(AreaLabel, /Information, $ > Dialog_Parent = Event.Top, $ > Title = 'ImageTable 6.2 ROI Area') > End > Else : > EndCase > End > > > ;+ > ; This procedure creates a table widget whose cell values are > ; displayed in colors according to a color look-up table, > ; much like an image. > ; > ; @Param > ; Val {in}{optional}{type=integer array dimensions n by m} > ; Set this parameter to a 2-dimensional array of integral > ; values between the values of -99 and 999. (This limitation > ; is related to the format statement used to display the > ; cell values; feel free to modify the code according to > ; your data's needs.) The default value is a 64-by-64 shifted > ; DIST image. > ; > ; @Examples > ; IDL> ImageTable_62 > ; > ; @Categories > ; Widget_Table, 6.2 > ; > ; @Author > ; Jim Pendleton & MG, RSI Global Services > ; > ; @History > ; March 31, 2005 - Initial version > ; > ; @File_Comments > ; This procedure highlights some new features of WIDGET_TABLE > ; in IDL 6.2, in particular the ability to set foreground > ; and background colors in individual cells, and to display > ; a context menu within a table. > ; > ;- > Pro ImageTable_62, Val > Compile_Opt StrictArr > On_Error, 2 > ; > ; Create a copy of the input data or create the default "bulls-eye" > ; image. > ; > iVal = N_Elements(Val) eq 0 ? Fix(Shift(Dist(512), 256, 256)) : Val > ImageSize = Size(iVal, /Dimensions) > ; > ; Create our widget tree. We'll have some controls on the left > ; and a table widget on the right. > ; > TLB = Widget_Base(/Row, /TLB_Size_Events, UName = 'Top', $ > Title = 'ImageTable 6.2') > Left = Widget_Base(TLB, /Column, UName = 'LeftBase') > D = Widget_Draw(Left, XSize = ImageSize[0], YSize = ImageSize[1], $ > UName = 'ImageDraw') > ; > ; By default, we use the "Hardcandy" color table. It shows good > ; contrast in the upper corner that is initiall displayed in the > ; table. > ; > CTBase = Widget_Base(Left, /Row, /Align_Left) > CTLabel = Widget_Label(CTBase, Value = 'Color Table : ') > LoadCT, /Silent, Get_Names = CTNames > ColorTable = 28 > CTCombobox = Widget_Combobox(CTBase, Value = CTNames,$ > UName = 'ColorTableCombobox', UValue = 'ColorTable') > Widget_Control, CTCombobox, Set_Combobox_Select = ColorTable > VisibilityBase = Widget_Base(Left, /Row, /Align_Left) > VisibilityLabel = Widget_Label(VisibilityBase, $ > Value = 'Table Values : ') > VisibilityCombobox = Widget_Combobox(VisibilityBase, $ > Value = ['Show', 'Hide'], $ > UValue = 'ValueVisibility', $ > UName = 'HideShowCombobox') > ; > ; We'll initially display each cell as an 18x18 square. The > ; spinner will allow the user to adjust this. See the > ; idl62/lib/itools/ui_widgets directory for the source to > ; cw_itupdownfield.pro, an undocumented, but highly useful > ; compound widget. > ; > PixelSize = 18 > Spinner = CW_itUpDownField(Left, Increment = 1, $ > Label = 'Pixel Size : ', $ > Value = pixelsize, $ > UName = 'PixelSizeSpinner', $ > UValue = 'PixelSize') > ; > ; Create a table with our data values. The default orientation > ; places the cell [0, 0] at the upper left. But we want it > ; to be oriented the same as our image, with [0, 0] in the > ; lower left.. So we need to flip the data in Y. > ; > Table = Widget_Table(TLB, Value = Reverse(IVal, 2), $ > X_Scroll = 25,$ > Y_Scroll = 25, $ > Row_Heights = PixelSize, Column_Widths = PixelSize, $ > Format = '(i3)', $ > UName = 'ValueTable', $ > UValue = 'Table', $ > ; > ; We choose a font appropriate to Windows or Linux. We want it > ; to be small so our cell sizes can be small, too. > ; > Font = !version.os_family eq 'Windows' ? $ > 'Helvetica*8' : 'timr08', $ > Alignment = 1, $ > ; > ; Label the rows to show that we flipped the image in Y. > ; Row 0 is at the bottom. > ; > Row_Labels = StrTrim(Reverse(Lindgen(ImageSize[1])), 2), $ > /All_Events, $ > ; > ; Also capture context menu events (i.e., right-clicks.) > ; > /Context_Events, $ > /Disjoint) > ; > ; Create a context menu for the table. > ; > ContextBase = Widget_Base(Table, /Context_Menu, $ > UName = 'TableContextMenu') > ContextStatisticsButton = Widget_Button(ContextBase, $ > Value = 'Show Selected Statistics', $ > UValue = 'Context_SelectedStatistics') > ContextStatisticsArea = Widget_Button(ContextBase, $ > Value = 'Show Selected Area', $ > UValue = 'Context_SelectedArea') > ; > ; We initially hide the TLB until after we update the colors > ; in the table the first time. > ; > Widget_Control, TLB, Map = 0 > Geom = Widget_Info(TLB, /Geometry) > ScreenSize = Get_Screen_Size() > Widget_Control, TLB, $ > TLB_Set_XOffset = (ScreenSize[0] - Geom.Scr_XSize)/2., $ > TLB_Set_YOffset = (ScreenSize[1] - Geom.Scr_YSize)/2. > Widget_Control, TLB, /Realize > ; > ; Update the colors in the cells and start the event handler. > ; > ImageTable_62_UpdateImage, TLB > XManager, 'ImageTable_62', TLB, /No_Block > End Dear Jim, Thank you very much for providing the code. If I finally use parts of the code for my research work, I will credit your name and Dr. Mike Galloy's. But before I implement it for my example, I have a question. If I have to set the color of each cell, do you think it is practical as I have more than 30 dataset scenarios. If there is an option of setting the cell colours automatically then there would be consistency of colour usage across all the 30 scenarios. By the way, I don't see any image on the left and neither do I see is a tabular form of the image on the right? -James
On Sunday, January 3, 2016 at 10:41:01 AM UTC+1, James wrote: > On Sunday, January 3, 2016 at 2:40:03 AM UTC+1, Jim P wrote: >> On Saturday, January 2, 2016 at 2:30:29 PM UTC-7, James wrote: >>> On Saturday, January 2, 2016 at 9:51:16 PM UTC+1, Jim P wrote: >>>> On Saturday, January 2, 2016 at 10:31:50 AM UTC-7, James wrote: >>>> > I have two dataset scenarios. Each scenario is an output from a model and each scenario contains an array of values in the x (horizontal) axis and 10 arrays of values in the y (vertical) axis. I am trying to create a plot which looks like this http://www.mathworks.com/matlabcentral/answers/uploaded_file s/42412/3.png >>>> > I have been looking for a plot function in ENVI IDL which can help make these plots but so far I did not find any. Can anybody help? Even better if someone can suggest a better graphical/visualization/plot option to display these two multivariate datasets so that the differences are conspicuous enough. With line graphs the visualization is not clear enough because the same values overlap on top of each other. >>>> > >>>> > Following are my scenarios. >>>> > >>>> > SCENARIO A >>>> > >>>> > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > y1= [0, 0, 0.02, 0.01, 0, 0, 0, 0, 0, 0, 0, 0] >>>> > y2= [0.01, 0, 0.05, 0.1, 0.19, 0.6, 0.87, 1, 1, 1, 1, 1] >>>> > y3= [0.02, 0.05, 0.2, 0.69, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > y4= [0.02, 0.12, 0.25, 0.97, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y5= [0, 0.12, 0.68, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y6= [0, 0.2, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y7= [0.01, 0.49, 0.97, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y8= [0.01, 0.51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y9= [0.01, 0.82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y10= [0, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > >>>> > SCENARIO B >>>> > >>>> > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > y1= [0.01, 0.03, 0.01, 0, 0.01, 0, 0, 0, 0, 0, 0, 0] >>>> > y2= [0.01, 0.07, 0.04, 0.13, 0.23, 0.5, 0.92, 1, 1, 1, 1, 1] >>>> > y3= [0.01, 0.03, 0.2, 0.61, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > y4= [0.02, 0.06, 0.4, 0.99, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y5= [0, 0.24, 0.61, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y6= [0, 0.26, 0.88, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y7= [0, 0.51, 0.99, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y8= [0.02, 0.64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y9= [0.02, 0.87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > y10= [0.01, 0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> >>>> The simplest way may be to use a widget_table with cell colors, then take a screen capture. >>>> >>>> Jim P. >>> ************************************************************ **************** >>> >>> Dear Jim, >>> >>> Thanks a lot for your helpful comments. I have never used WIDGET_TABLE function before since I am quite new to IDL Programming. The idea seems interesting and I want to try it. I am right now looking at the help page http://www.exelisvis.com/docs/WIDGET_TABLE.html >>> Do you know whether this function allows automatic addition of cell colours based on the range of values present or do I need to manually assign cell colours to the values? Additionally, if I assign colours to the cells which hold the values, will the values be still visible or I can replace the values just with colours? Apologies if I am asking some basic questions which may be otherwise common knowledge among the IDL Programmers' community. It would be a great help if I can find an example. I will search the web for it. If you have any other suggestions they are welcome. >>> >>> James >> >> Below is an example I wrote a number of years ago, with additional input from Dr. Mike Galloy. On the left is an image and on the right is a tabular form of the image with the cells colored according to the selected color table, using the same color table as the pixels in the image. >> >> You would be responsible for setting the color of each cell. >> >> "Showing" and "hiding" the text value in a cell is simply a matter of setting the foreground color to be the same as the background color. >> >> There are lots of comments that, along with the online help, should get you where you want to be. >> >> ;+ >> ; This procedure updates the image window display based >> ; on the current contents of the table widget, the >> ; selected cells (if any) and the current color table. >> ; >> ; @Param >> ; TLB {in}{required}{type=long} >> ; Set this parameter to the ID of the top-level base. >> ; >> ; @Hidden >> ; >> ; @Author >> ; JLP, RSI Global Services >> ; >> ; @History >> ; March 29, 2005 - Initial version >> ;- >> Pro ImageTable_62_UpdateImage, TLB >> Compile_Opt StrictArr >> On_Error, 2 >> ; >> ; Get the raw data values from the table. >> ; >> Table = Widget_Info(TLB, Find_by_UName='ValueTable') >> Widget_Control, Table, Get_Value = Values >> ; >> ; Get the color table number from the combobox. >> ; >> CTCombobox = Widget_Info(TLB, Find_by_UName = 'ColorTableCombobox') >> Current = Widget_Info(CTCombobox, /Combobox_GetText) >> Widget_Control, CTCombobox, Get_Value = AllValues >> CTIndex = (Where(AllValues eq Current))[0] >> ; >> ; Save the Direct Graphics state. >> ; >> WSave = !d.window >> Device, Get_Decomposed = WasDecomposed >> TVLCT, R, G, B, /Get >> ; >> ; Draw the table values to the image window using >> ; the current color table. >> ; >> Draw = Widget_Info(TLB, Find_by_UName = 'ImageDraw') >> Widget_Control, Draw, Get_Value = DrawID >> WSet, DrawID >> LoadCT, CTIndex, /Silent >> Device, Decomposed = 0 >> ; >> ; Remember that the table values are flipped in Y >> ; relative to our image so they orient the same way >> ; on the screen. >> ; >> TVScl, Reverse(Values, 2) >> ; >> ; Read the image buffer back from the window. >> ; >> Device, Decomposed = 1 >> Image = TVRd(True = 1) >> ; >> ; Restore the Direct Graphics state. >> ; >> Device, Decomposed = WasDecomposed >> If (WSave ne -1) then Begin >> Device, Window_State = WState >> If (WState[WSave]) then Begin >> WSet, WSave >> EndIf >> EndIf >> TVLCT, R, G, B >> ; >> ; Save the image data for the purpose of reapplying the >> ; selection box. >> ; >> Widget_Control, TLB, Set_UValue = Image >> ; >> ; Flip the image data about Y back into the orientation of the >> ; table. >> ; >> TableImage = Reverse(Temporary(Image), 3) >> ; >> ; The background color of each cell corresponds to each pixel >> ; value. We use "Update = 0" to prevent excessive flashing. >> ; >> Widget_Control, Table, $ >> Background_Color = TableImage, Update = 0 >> ; >> ; If we're "hiding" the text, this just means we draw the >> ; table values using the same color as the background. >> ; >> HideShow = Widget_Info(TLB, Find_by_UName = 'HideShowCombobox') >> If (Widget_Info(HideShow, /Combobox_GetText) eq 'Show') then Begin >> ; >> ; If we're showing table values, render the text in either black >> ; or white, depending on the better contrast with the background >> ; color in the cell. >> ; >> ImageTable_62_EnhanceText, TableImage >> EndIf >> Widget_Control, Table, $ >> Foreground_Color = TableImage, Update = 0 >> ; >> ; Update the base now with the accumulated changes. >> ; >> Widget_Control, TLB, /Update >> If (~Widget_Info(TLB, /Map)) then Begin >> Widget_Control, TLB, Map = 1 >> EndIf >> End >> >> >> ;+ >> ; This procedure converts an input array of table cell (image >> ; pixel) colors to an array of black and/or white colors to >> ; be used as the text color of each cell. The color black >> ; or white is chosen to increase contrast with the background >> ; color in each cell. >> ; >> ; @Param >> ; RGB {inout}{required}{type=BYTARR(3, N, M)} >> ; Set this parameter to the RGB colors of the pixels >> ; displayed in the image using the current color table. >> ; On output, the array will contain the color, either >> ; white or black, to be used for the foreground (text) >> ; color for the corresponding table cells. >> ; >> ; @Hidden >> ; >> ; @Author >> ; JLP, RSI Global Services >> ; >> ; @History >> ; March 29, 2005 - Initial version >> ;- >> Pro ImageTable_62_EnhanceText, RGB >> Compile_Opt StrictArr >> On_Error, 2 >> ; >> ; Convert the individual pixel colors from RGB space to >> ; hue, lightness and saturation space. >> ; >> Color_Convert, Reform(RGB[0, *, *]), Reform(RGB[1, *, *]), $ >> Reform(RGB[2, *, *]), H, L, S, /RGB_HLS >> ; >> ; We say that a pixel is "dark" if its lightness is less >> ; than 50%. >> ; >> Dark = Where(L lt .50, NDark) >> ; >> ; Light pixels will use black text. This is out initial >> ; default. >> ; >> RGB[*] = 0b >> ImageSize = Size(RGB, /Dimensions) >> If (NDark ne 0) then Begin >> ; >> ; Dark pixels will have white text. We use reform here >> ; to aid in addressing our 2-D image space with the 1-dimensional >> ; vectors returned by Color_Convert. We use Overwrite so >> ; we don't make extra copies of the data. >> ; >> RGB = Reform(RGB, 3, N_elements(RGB)/3, /Overwrite) >> RGB[*, Dark] = 255b >> RGB = Reform(RGB, 3, ImageSize[1], ImageSize[2], /Overwrite) >> EndIf >> End >> >> >> ;+ >> ; This procedure manages all events from the application's >> ; widgets. >> ; >> ; @Param >> ; Event {in}{required}{type=widget event structure} >> ; Set this parameter to the event structure to be >> ; acted upon. >> ; >> ; @Hidden >> ; >> ; @Author >> ; JLP, RSI Global Services >> ; >> ; @History >> ; March 29, 2005 - Initial version >> ;- >> Pro ImageTable_62_Event, Event >> Compile_Opt StrictArr >> On_Error, 2 >> ; >> ; What type of event is it? >> ; >> EventType = Tag_Names(Event, /Structure_Name) >> If (EventType eq 'WIDGET_BASE') then Begin >> ; >> ; This is a base resize event. We adjust the size of the >> ; table accordingly (and leave all the other widgets alone.) >> ; >> TLBGeom = Widget_Info(Event.Top, /Geometry) >> ; >> ; The base on the left hand side containing the image, comboboxes >> ; and spinner, remains fixed in size. >> ; >> Left = Widget_Info(Event.Top, Find_by_UName = 'LeftBase') >> LeftGeom = Widget_Info(Left, /Geometry) >> ; >> ; The table widget occupies "everything else". >> ; >> NewX = Event.X - 2*TLBGeom.XPad - LeftGeom.Scr_XSize > 10 >> NewY = Event.Y - 2*TLBGeom.YPad > 10 >> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >> ; >> ; Update the table size and return. >> ; >> Widget_Control, Table, Scr_XSize = NewX, Scr_YSize = NewY >> Return >> EndIf >> ; >> ; All other events are managed according to the UVALUE of the >> ; widget that produced the event. >> ; >> Widget_Control, Event.ID, Get_UValue = BranchCode >> Case BranchCode of >> 'ValueVisibility' : Begin >> ; >> ; Hide or show the values in the table. >> ; >> Widget_Control, Event.Top, Get_UValue = Image >> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >> Case Widget_Info(Event.ID, /Combobox_GetText) of >> 'Show' : Begin >> ; >> ; If we're showing the text in the table, make sure the text color >> ; contrasts well with the cell color. >> ; >> ImageTable_62_EnhanceText, Image >> ; >> ; Remember that the table values are "upside down" in Y to >> ; correspond to our image orientation, so we need to flip >> ; the data. >> ; >> Widget_Control, Table, $ >> Foreground_Color = Reverse(Temporary(Image), 3) >> End >> 'Hide' : Begin >> ; >> ; If we're hiding the text in the table, then we set the text >> ; color to be the same as the image color at that pixel. Again, >> ; we need to flip the data to match the image orientation. >> ; >> Widget_Control, Table, $ >> Foreground_Color = Reverse(Temporary(Image), 3) >> End >> EndCase >> End >> 'ColorTable' : Begin >> ; >> ; A change in color table means we must update the image as well >> ; as the cell colors in the table. >> ; >> ImageTable_62_UpdateImage, Event.Top >> End >> 'Table' : Begin >> EventType = Tag_Names(Event, /Structure_Name) >> If (EventType eq 'WIDGET_CONTEXT') then Begin >> ; >> ; If we have a right click, this is a context menu event >> ; request, so show it at the position of the clicked cell. >> ; (Note that we have previously received at least one and >> ; maybe two WIDGET_TABLE_CELL_SEL events as a result of >> ; the right-click selection, if the table was editable.) >> ; >> ContextMenu = Widget_Info(Event.ID, $ >> Find_by_UName = 'TableContextMenu') >> Widget_DisplayContextMenu, Event.ID, $ >> Event.X, Event.Y, ContextMenu >> Return >> EndIf >> ; >> ; The user has selected cells in the table. First, >> ; update the image window. >> ; >> Widget_Control, Event.Top, Get_UValue = Image >> Draw = Widget_Info(Event.Top, Find_by_UName = 'ImageDraw') >> Widget_Control, Draw, Get_Value = DrawID >> ; >> ; Save the Direct Graphics environment. >> ; >> WSave = !d.window >> Device, Get_Decomposed = WasDecomposed >> ; >> ; Display the image to the draw widget. This will erase any >> ; previously overplotted line. A cleverer solution might use >> ; a pixmap instead. >> ; >> WSet, DrawID >> Device, Decomposed = 1 >> TV, Image, True = 1 >> ; >> ; Overplot the bounds of the region selected in the table >> ; if it's more than 1 cell. >> ; >> Selected = Widget_Info(Event.ID, /Table_Select) >> MinX = Min(Selected[0, *], Max = MaxX) >> MinY = Min(Selected[1, *], Max = MaxY) >> dX = MaxX - MinX + 1 >> dY = MaxY - MinY + 1 >> If ((dX gt 0) && (dY gt 0)) then Begin >> ; >> ; We're going to plot the bounding box in the image in green. >> ; We need to remember that the cell numbers in the table >> ; are flipped top to bottom with respect to the image. >> ; >> PlotS, MinX + [0, 1, 1, 0, 0]*dX, $ >> (Size(Image, /Dimensions))[2] - 1 - $ >> (MinY + [0, 0, 1, 1, 0]*dY), $ >> /Device, Color = '00ff00'x >> EndIf >> ; >> ; Restore the Direct Graphics environment. >> ; >> If (WSave ne -1) then Begin >> Device, Window_State = WState >> If (WState[WSave]) then Begin >> WSet, WSave >> EndIf >> EndIf >> Device, Decomposed = WasDecomposed >> End >> 'PixelSize' : Begin >> ; >> ; Change the number of pixels square each cell in the table >> ; should occupy according to the value in the spinner. This number >> ; actually includes the dividers between cells. >> ; >> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >> ; >> ; There are no bounds on the spinner, so we need to manually clamp >> ; it to a reasonable range. >> ; >> Value = Long(Event.Value) >> Value >= 2 >> Value <= 256 >> ; >> ; In case we needed to clamp the value, update the spinner with >> ; the current value. >> ; >> Widget_Control, Event.ID, Set_Value = Value, Update = 0 >> ; >> ; Adjust the cell dimensions in the table, then update >> ; everything on the interface at one time. >> ; >> Widget_Control, Table, Row_Heights = Value, $ >> Column_Widths = Value, Update = 0 >> Widget_Control, Event.Top, /Update >> End >> 'Context_SelectedStatistics' : Begin >> ; >> ; This is an event from the table's context menu. >> ; Calculate statistics on the selected cells. >> ; >> ParentContextBase = Widget_Info(Event.ID, /Parent) >> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >> Selected = Widget_Info(Table, /Table_Select) >> Widget_Control, Table, Get_Value = TableValues >> If (N_elements(Selected)/2 gt 1) then Begin >> TableSize = Size(TableValues, /Dimensions) >> Selected = Reform(Selected[0, *] + Selected[1, *]*TableSize[0]) >> Stats = Moment(TableValues[Selected], MDev = MDev, SDev = SDev) >> MinValue = Min(TableValues[Selected], Max = MaxValue) >> Stats = StrTrim([MinValue, MaxValue, Stats, MDev, SDev], 2) >> StatsLabels = ['Minimum', 'Maximum', 'Mean', 'Variance', 'Skewness', $ >> 'Kurtosis', 'Mean Absolute Deviation', $ >> 'Standard Deviation'] >> StatsLabel = StatsLabels + ' : ' + Stats >> EndIf Else Begin >> StatsLabel = 'Pixel value = ' + $ >> StrTrim(TableValues[Selected[0, 0], Selected[1, 0]], 2) >> EndElse >> v = Dialog_Message(StatsLabel, /Information, $ >> Dialog_Parent = Event.Top, $ >> Title = 'ImageTable 6.2 ROI Statistics') >> End >> 'Context_SelectedArea' : Begin >> ; >> ; This is an event from the table's context menu. >> ; Calculate the area of the selected cells >> ; >> ParentContextBase = Widget_Info(Event.ID, /Parent) >> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >> Selected = Widget_Info(Table, /Table_Select) >> NPixels = Long(N_elements(Selected)/2) >> AreaLabel = 'Area = ' + $ >> StrTrim(NPixels, 2) + $ >> ' pixel' + (NPixels gt 1 ? 's' : '') >> v = Dialog_Message(AreaLabel, /Information, $ >> Dialog_Parent = Event.Top, $ >> Title = 'ImageTable 6.2 ROI Area') >> End >> Else : >> EndCase >> End >> >> >> ;+ >> ; This procedure creates a table widget whose cell values are >> ; displayed in colors according to a color look-up table, >> ; much like an image. >> ; >> ; @Param >> ; Val {in}{optional}{type=integer array dimensions n by m} >> ; Set this parameter to a 2-dimensional array of integral >> ; values between the values of -99 and 999. (This limitation >> ; is related to the format statement used to display the >> ; cell values; feel free to modify the code according to >> ; your data's needs.) The default value is a 64-by-64 shifted >> ; DIST image. >> ; >> ; @Examples >> ; IDL> ImageTable_62 >> ; >> ; @Categories >> ; Widget_Table, 6.2 >> ; >> ; @Author >> ; Jim Pendleton & MG, RSI Global Services >> ; >> ; @History >> ; March 31, 2005 - Initial version >> ; >> ; @File_Comments >> ; This procedure highlights some new features of WIDGET_TABLE >> ; in IDL 6.2, in particular the ability to set foreground >> ; and background colors in individual cells, and to display >> ; a context menu within a table. >> ; >> ;- >> Pro ImageTable_62, Val >> Compile_Opt StrictArr >> On_Error, 2 >> ; >> ; Create a copy of the input data or create the default "bulls-eye" >> ; image. >> ; >> iVal = N_Elements(Val) eq 0 ? Fix(Shift(Dist(512), 256, 256)) : Val >> ImageSize = Size(iVal, /Dimensions) >> ; >> ; Create our widget tree. We'll have some controls on the left >> ; and a table widget on the right. >> ; >> TLB = Widget_Base(/Row, /TLB_Size_Events, UName = 'Top', $ >> Title = 'ImageTable 6.2') >> Left = Widget_Base(TLB, /Column, UName = 'LeftBase') >> D = Widget_Draw(Left, XSize = ImageSize[0], YSize = ImageSize[1], $ >> UName = 'ImageDraw') >> ; >> ; By default, we use the "Hardcandy" color table. It shows good >> ; contrast in the upper corner that is initiall displayed in the >> ; table. >> ; >> CTBase = Widget_Base(Left, /Row, /Align_Left) >> CTLabel = Widget_Label(CTBase, Value = 'Color Table : ') >> LoadCT, /Silent, Get_Names = CTNames >> ColorTable = 28 >> CTCombobox = Widget_Combobox(CTBase, Value = CTNames,$ >> UName = 'ColorTableCombobox', UValue = 'ColorTable') >> Widget_Control, CTCombobox, Set_Combobox_Select = ColorTable >> VisibilityBase = Widget_Base(Left, /Row, /Align_Left) >> VisibilityLabel = Widget_Label(VisibilityBase, $ >> Value = 'Table Values : ') >> VisibilityCombobox = Widget_Combobox(VisibilityBase, $ >> Value = ['Show', 'Hide'], $ >> UValue = 'ValueVisibility', $ >> UName = 'HideShowCombobox') >> ; >> ; We'll initially display each cell as an 18x18 square. The >> ; spinner will allow the user to adjust this. See the >> ; idl62/lib/itools/ui_widgets directory for the source to >> ; cw_itupdownfield.pro, an undocumented, but highly useful >> ; compound widget. >> ; >> PixelSize = 18 >> Spinner = CW_itUpDownField(Left, Increment = 1, $ >> Label = 'Pixel Size : ', $ >> Value = pixelsize, $ >> UName = 'PixelSizeSpinner', $ >> UValue = 'PixelSize') >> ; >> ; Create a table with our data values. The default orientation >> ; places the cell [0, 0] at the upper left. But we want it >> ; to be oriented the same as our image, with [0, 0] in the >> ; lower left.. So we need to flip the data in Y. >> ; >> Table = Widget_Table(TLB, Value = Reverse(IVal, 2), $ >> X_Scroll = 25,$ >> Y_Scroll = 25, $ >> Row_Heights = PixelSize, Column_Widths = PixelSize, $ >> Format = '(i3)', $ >> UName = 'ValueTable', $ >> UValue = 'Table', $ >> ; >> ; We choose a font appropriate to Windows or Linux. We want it >> ; to be small so our cell sizes can be small, too. >> ; >> Font = !version.os_family eq 'Windows' ? $ >> 'Helvetica*8' : 'timr08', $ >> Alignment = 1, $ >> ; >> ; Label the rows to show that we flipped the image in Y. >> ; Row 0 is at the bottom. >> ; >> Row_Labels = StrTrim(Reverse(Lindgen(ImageSize[1])), 2), $ >> /All_Events, $ >> ; >> ; Also capture context menu events (i.e., right-clicks.) >> ; >> /Context_Events, $ >> /Disjoint) >> ; >> ; Create a context menu for the table. >> ; >> ContextBase = Widget_Base(Table, /Context_Menu, $ >> UName = 'TableContextMenu') >> ContextStatisticsButton = Widget_Button(ContextBase, $ >> Value = 'Show Selected Statistics', $ >> UValue = 'Context_SelectedStatistics') >> ContextStatisticsArea = Widget_Button(ContextBase, $ >> Value = 'Show Selected Area', $ >> UValue = 'Context_SelectedArea') >> ; >> ; We initially hide the TLB until after we update the colors >> ; in the table the first time. >> ; >> Widget_Control, TLB, Map = 0 >> Geom = Widget_Info(TLB, /Geometry) >> ScreenSize = Get_Screen_Size() >> Widget_Control, TLB, $ >> TLB_Set_XOffset = (ScreenSize[0] - Geom.Scr_XSize)/2., $ >> TLB_Set_YOffset = (ScreenSize[1] - Geom.Scr_YSize)/2. >> Widget_Control, TLB, /Realize >> ; >> ; Update the colors in the cells and start the event handler. >> ; >> ImageTable_62_UpdateImage, TLB >> XManager, 'ImageTable_62', TLB, /No_Block >> End > > > Dear Jim, > > > Thank you very much for providing the code. If I finally use parts of the code for my research work, I will credit your name and Dr. Mike Galloy's. But before I implement it for my example, I have a question. If I have to set the color of each cell, do you think it is practical as I have more than 30 dataset scenarios. If there is an option of setting the cell colours automatically then there would be consistency of colour usage across all the 30 scenarios. By the way, I don't see any image on the left and neither do I see is a tabular form of the image on the right? > > -James Dear Jim, I understood your last comments only after compiling and running the code in IDL. I can see what you mean now, with both the image and the table of values. The comments are also quite helpful. But I am stuggling to find out where to exactly insert my table of data values. If I want to save my datasets as an ASCII file or a text file and use the data values as input for running the code, can I do that somewhere in the code? In the first few lines of the code where the comment says, ;Get the raw data values from the table ; Which Table is this and how can I replace this table with my own data table from a text file or ASCII file? I think I will have to provide the path of the text file that I create with my dataset scenarios? -james
On Sunday, January 3, 2016 at 4:26:02 PM UTC-7, James wrote: > On Sunday, January 3, 2016 at 10:41:01 AM UTC+1, James wrote: >> On Sunday, January 3, 2016 at 2:40:03 AM UTC+1, Jim P wrote: >>> On Saturday, January 2, 2016 at 2:30:29 PM UTC-7, James wrote: >>>> On Saturday, January 2, 2016 at 9:51:16 PM UTC+1, Jim P wrote: >>>> > On Saturday, January 2, 2016 at 10:31:50 AM UTC-7, James wrote: >>>> > > I have two dataset scenarios. Each scenario is an output from a model and each scenario contains an array of values in the x (horizontal) axis and 10 arrays of values in the y (vertical) axis. I am trying to create a plot which looks like this http://www.mathworks.com/matlabcentral/answers/uploaded_file s/42412/3.png >>>> > > I have been looking for a plot function in ENVI IDL which can help make these plots but so far I did not find any. Can anybody help? Even better if someone can suggest a better graphical/visualization/plot option to display these two multivariate datasets so that the differences are conspicuous enough. With line graphs the visualization is not clear enough because the same values overlap on top of each other. >>>> > > >>>> > > Following are my scenarios. >>>> > > >>>> > > SCENARIO A >>>> > > >>>> > > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > > y1= [0, 0, 0.02, 0.01, 0, 0, 0, 0, 0, 0, 0, 0] >>>> > > y2= [0.01, 0, 0.05, 0.1, 0.19, 0.6, 0.87, 1, 1, 1, 1, 1] >>>> > > y3= [0.02, 0.05, 0.2, 0.69, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > > y4= [0.02, 0.12, 0.25, 0.97, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y5= [0, 0.12, 0.68, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y6= [0, 0.2, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y7= [0.01, 0.49, 0.97, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y8= [0.01, 0.51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y9= [0.01, 0.82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y10= [0, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > >>>> > > SCENARIO B >>>> > > >>>> > > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > > y1= [0.01, 0.03, 0.01, 0, 0.01, 0, 0, 0, 0, 0, 0, 0] >>>> > > y2= [0.01, 0.07, 0.04, 0.13, 0.23, 0.5, 0.92, 1, 1, 1, 1, 1] >>>> > > y3= [0.01, 0.03, 0.2, 0.61, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > > y4= [0.02, 0.06, 0.4, 0.99, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y5= [0, 0.24, 0.61, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y6= [0, 0.26, 0.88, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y7= [0, 0.51, 0.99, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y8= [0.02, 0.64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y9= [0.02, 0.87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > y10= [0.01, 0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > >>>> > The simplest way may be to use a widget_table with cell colors, then take a screen capture. >>>> > >>>> > Jim P. >>>> ************************************************************ **************** >>>> >>>> Dear Jim, >>>> >>>> Thanks a lot for your helpful comments. I have never used WIDGET_TABLE function before since I am quite new to IDL Programming. The idea seems interesting and I want to try it. I am right now looking at the help page http://www.exelisvis.com/docs/WIDGET_TABLE.html >>>> Do you know whether this function allows automatic addition of cell colours based on the range of values present or do I need to manually assign cell colours to the values? Additionally, if I assign colours to the cells which hold the values, will the values be still visible or I can replace the values just with colours? Apologies if I am asking some basic questions which may be otherwise common knowledge among the IDL Programmers' community. It would be a great help if I can find an example. I will search the web for it. If you have any other suggestions they are welcome. >>>> >>>> James >>> >>> Below is an example I wrote a number of years ago, with additional input from Dr. Mike Galloy. On the left is an image and on the right is a tabular form of the image with the cells colored according to the selected color table, using the same color table as the pixels in the image. >>> >>> You would be responsible for setting the color of each cell. >>> >>> "Showing" and "hiding" the text value in a cell is simply a matter of setting the foreground color to be the same as the background color. >>> >>> There are lots of comments that, along with the online help, should get you where you want to be. >>> >>> ;+ >>> ; This procedure updates the image window display based >>> ; on the current contents of the table widget, the >>> ; selected cells (if any) and the current color table. >>> ; >>> ; @Param >>> ; TLB {in}{required}{type=long} >>> ; Set this parameter to the ID of the top-level base. >>> ; >>> ; @Hidden >>> ; >>> ; @Author >>> ; JLP, RSI Global Services >>> ; >>> ; @History >>> ; March 29, 2005 - Initial version >>> ;- >>> Pro ImageTable_62_UpdateImage, TLB >>> Compile_Opt StrictArr >>> On_Error, 2 >>> ; >>> ; Get the raw data values from the table. >>> ; >>> Table = Widget_Info(TLB, Find_by_UName='ValueTable') >>> Widget_Control, Table, Get_Value = Values >>> ; >>> ; Get the color table number from the combobox. >>> ; >>> CTCombobox = Widget_Info(TLB, Find_by_UName = 'ColorTableCombobox') >>> Current = Widget_Info(CTCombobox, /Combobox_GetText) >>> Widget_Control, CTCombobox, Get_Value = AllValues >>> CTIndex = (Where(AllValues eq Current))[0] >>> ; >>> ; Save the Direct Graphics state. >>> ; >>> WSave = !d.window >>> Device, Get_Decomposed = WasDecomposed >>> TVLCT, R, G, B, /Get >>> ; >>> ; Draw the table values to the image window using >>> ; the current color table. >>> ; >>> Draw = Widget_Info(TLB, Find_by_UName = 'ImageDraw') >>> Widget_Control, Draw, Get_Value = DrawID >>> WSet, DrawID >>> LoadCT, CTIndex, /Silent >>> Device, Decomposed = 0 >>> ; >>> ; Remember that the table values are flipped in Y >>> ; relative to our image so they orient the same way >>> ; on the screen. >>> ; >>> TVScl, Reverse(Values, 2) >>> ; >>> ; Read the image buffer back from the window. >>> ; >>> Device, Decomposed = 1 >>> Image = TVRd(True = 1) >>> ; >>> ; Restore the Direct Graphics state. >>> ; >>> Device, Decomposed = WasDecomposed >>> If (WSave ne -1) then Begin >>> Device, Window_State = WState >>> If (WState[WSave]) then Begin >>> WSet, WSave >>> EndIf >>> EndIf >>> TVLCT, R, G, B >>> ; >>> ; Save the image data for the purpose of reapplying the >>> ; selection box. >>> ; >>> Widget_Control, TLB, Set_UValue = Image >>> ; >>> ; Flip the image data about Y back into the orientation of the >>> ; table. >>> ; >>> TableImage = Reverse(Temporary(Image), 3) >>> ; >>> ; The background color of each cell corresponds to each pixel >>> ; value. We use "Update = 0" to prevent excessive flashing. >>> ; >>> Widget_Control, Table, $ >>> Background_Color = TableImage, Update = 0 >>> ; >>> ; If we're "hiding" the text, this just means we draw the >>> ; table values using the same color as the background. >>> ; >>> HideShow = Widget_Info(TLB, Find_by_UName = 'HideShowCombobox') >>> If (Widget_Info(HideShow, /Combobox_GetText) eq 'Show') then Begin >>> ; >>> ; If we're showing table values, render the text in either black >>> ; or white, depending on the better contrast with the background >>> ; color in the cell. >>> ; >>> ImageTable_62_EnhanceText, TableImage >>> EndIf >>> Widget_Control, Table, $ >>> Foreground_Color = TableImage, Update = 0 >>> ; >>> ; Update the base now with the accumulated changes. >>> ; >>> Widget_Control, TLB, /Update >>> If (~Widget_Info(TLB, /Map)) then Begin >>> Widget_Control, TLB, Map = 1 >>> EndIf >>> End >>> >>> >>> ;+ >>> ; This procedure converts an input array of table cell (image >>> ; pixel) colors to an array of black and/or white colors to >>> ; be used as the text color of each cell. The color black >>> ; or white is chosen to increase contrast with the background >>> ; color in each cell. >>> ; >>> ; @Param >>> ; RGB {inout}{required}{type=BYTARR(3, N, M)} >>> ; Set this parameter to the RGB colors of the pixels >>> ; displayed in the image using the current color table. >>> ; On output, the array will contain the color, either >>> ; white or black, to be used for the foreground (text) >>> ; color for the corresponding table cells. >>> ; >>> ; @Hidden >>> ; >>> ; @Author >>> ; JLP, RSI Global Services >>> ; >>> ; @History >>> ; March 29, 2005 - Initial version >>> ;- >>> Pro ImageTable_62_EnhanceText, RGB >>> Compile_Opt StrictArr >>> On_Error, 2 >>> ; >>> ; Convert the individual pixel colors from RGB space to >>> ; hue, lightness and saturation space. >>> ; >>> Color_Convert, Reform(RGB[0, *, *]), Reform(RGB[1, *, *]), $ >>> Reform(RGB[2, *, *]), H, L, S, /RGB_HLS >>> ; >>> ; We say that a pixel is "dark" if its lightness is less >>> ; than 50%. >>> ; >>> Dark = Where(L lt .50, NDark) >>> ; >>> ; Light pixels will use black text. This is out initial >>> ; default. >>> ; >>> RGB[*] = 0b >>> ImageSize = Size(RGB, /Dimensions) >>> If (NDark ne 0) then Begin >>> ; >>> ; Dark pixels will have white text. We use reform here >>> ; to aid in addressing our 2-D image space with the 1-dimensional >>> ; vectors returned by Color_Convert. We use Overwrite so >>> ; we don't make extra copies of the data. >>> ; >>> RGB = Reform(RGB, 3, N_elements(RGB)/3, /Overwrite) >>> RGB[*, Dark] = 255b >>> RGB = Reform(RGB, 3, ImageSize[1], ImageSize[2], /Overwrite) >>> EndIf >>> End >>> >>> >>> ;+ >>> ; This procedure manages all events from the application's >>> ; widgets. >>> ; >>> ; @Param >>> ; Event {in}{required}{type=widget event structure} >>> ; Set this parameter to the event structure to be >>> ; acted upon. >>> ; >>> ; @Hidden >>> ; >>> ; @Author >>> ; JLP, RSI Global Services >>> ; >>> ; @History >>> ; March 29, 2005 - Initial version >>> ;- >>> Pro ImageTable_62_Event, Event >>> Compile_Opt StrictArr >>> On_Error, 2 >>> ; >>> ; What type of event is it? >>> ; >>> EventType = Tag_Names(Event, /Structure_Name) >>> If (EventType eq 'WIDGET_BASE') then Begin >>> ; >>> ; This is a base resize event. We adjust the size of the >>> ; table accordingly (and leave all the other widgets alone.) >>> ; >>> TLBGeom = Widget_Info(Event.Top, /Geometry) >>> ; >>> ; The base on the left hand side containing the image, comboboxes >>> ; and spinner, remains fixed in size. >>> ; >>> Left = Widget_Info(Event.Top, Find_by_UName = 'LeftBase') >>> LeftGeom = Widget_Info(Left, /Geometry) >>> ; >>> ; The table widget occupies "everything else". >>> ; >>> NewX = Event.X - 2*TLBGeom.XPad - LeftGeom.Scr_XSize > 10 >>> NewY = Event.Y - 2*TLBGeom.YPad > 10 >>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>> ; >>> ; Update the table size and return. >>> ; >>> Widget_Control, Table, Scr_XSize = NewX, Scr_YSize = NewY >>> Return >>> EndIf >>> ; >>> ; All other events are managed according to the UVALUE of the >>> ; widget that produced the event. >>> ; >>> Widget_Control, Event.ID, Get_UValue = BranchCode >>> Case BranchCode of >>> 'ValueVisibility' : Begin >>> ; >>> ; Hide or show the values in the table. >>> ; >>> Widget_Control, Event.Top, Get_UValue = Image >>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>> Case Widget_Info(Event.ID, /Combobox_GetText) of >>> 'Show' : Begin >>> ; >>> ; If we're showing the text in the table, make sure the text color >>> ; contrasts well with the cell color. >>> ; >>> ImageTable_62_EnhanceText, Image >>> ; >>> ; Remember that the table values are "upside down" in Y to >>> ; correspond to our image orientation, so we need to flip >>> ; the data. >>> ; >>> Widget_Control, Table, $ >>> Foreground_Color = Reverse(Temporary(Image), 3) >>> End >>> 'Hide' : Begin >>> ; >>> ; If we're hiding the text in the table, then we set the text >>> ; color to be the same as the image color at that pixel. Again, >>> ; we need to flip the data to match the image orientation. >>> ; >>> Widget_Control, Table, $ >>> Foreground_Color = Reverse(Temporary(Image), 3) >>> End >>> EndCase >>> End >>> 'ColorTable' : Begin >>> ; >>> ; A change in color table means we must update the image as well >>> ; as the cell colors in the table. >>> ; >>> ImageTable_62_UpdateImage, Event.Top >>> End >>> 'Table' : Begin >>> EventType = Tag_Names(Event, /Structure_Name) >>> If (EventType eq 'WIDGET_CONTEXT') then Begin >>> ; >>> ; If we have a right click, this is a context menu event >>> ; request, so show it at the position of the clicked cell. >>> ; (Note that we have previously received at least one and >>> ; maybe two WIDGET_TABLE_CELL_SEL events as a result of >>> ; the right-click selection, if the table was editable.) >>> ; >>> ContextMenu = Widget_Info(Event.ID, $ >>> Find_by_UName = 'TableContextMenu') >>> Widget_DisplayContextMenu, Event.ID, $ >>> Event.X, Event.Y, ContextMenu >>> Return >>> EndIf >>> ; >>> ; The user has selected cells in the table. First, >>> ; update the image window. >>> ; >>> Widget_Control, Event.Top, Get_UValue = Image >>> Draw = Widget_Info(Event.Top, Find_by_UName = 'ImageDraw') >>> Widget_Control, Draw, Get_Value = DrawID >>> ; >>> ; Save the Direct Graphics environment. >>> ; >>> WSave = !d.window >>> Device, Get_Decomposed = WasDecomposed >>> ; >>> ; Display the image to the draw widget. This will erase any >>> ; previously overplotted line. A cleverer solution might use >>> ; a pixmap instead. >>> ; >>> WSet, DrawID >>> Device, Decomposed = 1 >>> TV, Image, True = 1 >>> ; >>> ; Overplot the bounds of the region selected in the table >>> ; if it's more than 1 cell. >>> ; >>> Selected = Widget_Info(Event.ID, /Table_Select) >>> MinX = Min(Selected[0, *], Max = MaxX) >>> MinY = Min(Selected[1, *], Max = MaxY) >>> dX = MaxX - MinX + 1 >>> dY = MaxY - MinY + 1 >>> If ((dX gt 0) && (dY gt 0)) then Begin >>> ; >>> ; We're going to plot the bounding box in the image in green. >>> ; We need to remember that the cell numbers in the table >>> ; are flipped top to bottom with respect to the image. >>> ; >>> PlotS, MinX + [0, 1, 1, 0, 0]*dX, $ >>> (Size(Image, /Dimensions))[2] - 1 - $ >>> (MinY + [0, 0, 1, 1, 0]*dY), $ >>> /Device, Color = '00ff00'x >>> EndIf >>> ; >>> ; Restore the Direct Graphics environment. >>> ; >>> If (WSave ne -1) then Begin >>> Device, Window_State = WState >>> If (WState[WSave]) then Begin >>> WSet, WSave >>> EndIf >>> EndIf >>> Device, Decomposed = WasDecomposed >>> End >>> 'PixelSize' : Begin >>> ; >>> ; Change the number of pixels square each cell in the table >>> ; should occupy according to the value in the spinner. This number >>> ; actually includes the dividers between cells. >>> ; >>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>> ; >>> ; There are no bounds on the spinner, so we need to manually clamp >>> ; it to a reasonable range. >>> ; >>> Value = Long(Event.Value) >>> Value >= 2 >>> Value <= 256 >>> ; >>> ; In case we needed to clamp the value, update the spinner with >>> ; the current value. >>> ; >>> Widget_Control, Event.ID, Set_Value = Value, Update = 0 >>> ; >>> ; Adjust the cell dimensions in the table, then update >>> ; everything on the interface at one time. >>> ; >>> Widget_Control, Table, Row_Heights = Value, $ >>> Column_Widths = Value, Update = 0 >>> Widget_Control, Event.Top, /Update >>> End >>> 'Context_SelectedStatistics' : Begin >>> ; >>> ; This is an event from the table's context menu. >>> ; Calculate statistics on the selected cells. >>> ; >>> ParentContextBase = Widget_Info(Event.ID, /Parent) >>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>> Selected = Widget_Info(Table, /Table_Select) >>> Widget_Control, Table, Get_Value = TableValues >>> If (N_elements(Selected)/2 gt 1) then Begin >>> TableSize = Size(TableValues, /Dimensions) >>> Selected = Reform(Selected[0, *] + Selected[1, *]*TableSize[0]) >>> Stats = Moment(TableValues[Selected], MDev = MDev, SDev = SDev) >>> MinValue = Min(TableValues[Selected], Max = MaxValue) >>> Stats = StrTrim([MinValue, MaxValue, Stats, MDev, SDev], 2) >>> StatsLabels = ['Minimum', 'Maximum', 'Mean', 'Variance', 'Skewness', $ >>> 'Kurtosis', 'Mean Absolute Deviation', $ >>> 'Standard Deviation'] >>> StatsLabel = StatsLabels + ' : ' + Stats >>> EndIf Else Begin >>> StatsLabel = 'Pixel value = ' + $ >>> StrTrim(TableValues[Selected[0, 0], Selected[1, 0]], 2) >>> EndElse >>> v = Dialog_Message(StatsLabel, /Information, $ >>> Dialog_Parent = Event.Top, $ >>> Title = 'ImageTable 6.2 ROI Statistics') >>> End >>> 'Context_SelectedArea' : Begin >>> ; >>> ; This is an event from the table's context menu. >>> ; Calculate the area of the selected cells >>> ; >>> ParentContextBase = Widget_Info(Event.ID, /Parent) >>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>> Selected = Widget_Info(Table, /Table_Select) >>> NPixels = Long(N_elements(Selected)/2) >>> AreaLabel = 'Area = ' + $ >>> StrTrim(NPixels, 2) + $ >>> ' pixel' + (NPixels gt 1 ? 's' : '') >>> v = Dialog_Message(AreaLabel, /Information, $ >>> Dialog_Parent = Event.Top, $ >>> Title = 'ImageTable 6.2 ROI Area') >>> End >>> Else : >>> EndCase >>> End >>> >>> >>> ;+ >>> ; This procedure creates a table widget whose cell values are >>> ; displayed in colors according to a color look-up table, >>> ; much like an image. >>> ; >>> ; @Param >>> ; Val {in}{optional}{type=integer array dimensions n by m} >>> ; Set this parameter to a 2-dimensional array of integral >>> ; values between the values of -99 and 999. (This limitation >>> ; is related to the format statement used to display the >>> ; cell values; feel free to modify the code according to >>> ; your data's needs.) The default value is a 64-by-64 shifted >>> ; DIST image. >>> ; >>> ; @Examples >>> ; IDL> ImageTable_62 >>> ; >>> ; @Categories >>> ; Widget_Table, 6.2 >>> ; >>> ; @Author >>> ; Jim Pendleton & MG, RSI Global Services >>> ; >>> ; @History >>> ; March 31, 2005 - Initial version >>> ; >>> ; @File_Comments >>> ; This procedure highlights some new features of WIDGET_TABLE >>> ; in IDL 6.2, in particular the ability to set foreground >>> ; and background colors in individual cells, and to display >>> ; a context menu within a table. >>> ; >>> ;- >>> Pro ImageTable_62, Val >>> Compile_Opt StrictArr >>> On_Error, 2 >>> ; >>> ; Create a copy of the input data or create the default "bulls-eye" >>> ; image. >>> ; >>> iVal = N_Elements(Val) eq 0 ? Fix(Shift(Dist(512), 256, 256)) : Val >>> ImageSize = Size(iVal, /Dimensions) >>> ; >>> ; Create our widget tree. We'll have some controls on the left >>> ; and a table widget on the right. >>> ; >>> TLB = Widget_Base(/Row, /TLB_Size_Events, UName = 'Top', $ >>> Title = 'ImageTable 6.2') >>> Left = Widget_Base(TLB, /Column, UName = 'LeftBase') >>> D = Widget_Draw(Left, XSize = ImageSize[0], YSize = ImageSize[1], $ >>> UName = 'ImageDraw') >>> ; >>> ; By default, we use the "Hardcandy" color table. It shows good >>> ; contrast in the upper corner that is initiall displayed in the >>> ; table. >>> ; >>> CTBase = Widget_Base(Left, /Row, /Align_Left) >>> CTLabel = Widget_Label(CTBase, Value = 'Color Table : ') >>> LoadCT, /Silent, Get_Names = CTNames >>> ColorTable = 28 >>> CTCombobox = Widget_Combobox(CTBase, Value = CTNames,$ >>> UName = 'ColorTableCombobox', UValue = 'ColorTable') >>> Widget_Control, CTCombobox, Set_Combobox_Select = ColorTable >>> VisibilityBase = Widget_Base(Left, /Row, /Align_Left) >>> VisibilityLabel = Widget_Label(VisibilityBase, $ >>> Value = 'Table Values : ') >>> VisibilityCombobox = Widget_Combobox(VisibilityBase, $ >>> Value = ['Show', 'Hide'], $ >>> UValue = 'ValueVisibility', $ >>> UName = 'HideShowCombobox') >>> ; >>> ; We'll initially display each cell as an 18x18 square. The >>> ; spinner will allow the user to adjust this. See the >>> ; idl62/lib/itools/ui_widgets directory for the source to >>> ; cw_itupdownfield.pro, an undocumented, but highly useful >>> ; compound widget. >>> ; >>> PixelSize = 18 >>> Spinner = CW_itUpDownField(Left, Increment = 1, $ >>> Label = 'Pixel Size : ', $ >>> Value = pixelsize, $ >>> UName = 'PixelSizeSpinner', $ >>> UValue = 'PixelSize') >>> ; >>> ; Create a table with our data values. The default orientation >>> ; places the cell [0, 0] at the upper left. But we want it >>> ; to be oriented the same as our image, with [0, 0] in the >>> ; lower left.. So we need to flip the data in Y. >>> ; >>> Table = Widget_Table(TLB, Value = Reverse(IVal, 2), $ >>> X_Scroll = 25,$ >>> Y_Scroll = 25, $ >>> Row_Heights = PixelSize, Column_Widths = PixelSize, $ >>> Format = '(i3)', $ >>> UName = 'ValueTable', $ >>> UValue = 'Table', $ >>> ; >>> ; We choose a font appropriate to Windows or Linux. We want it >>> ; to be small so our cell sizes can be small, too. >>> ; >>> Font = !version.os_family eq 'Windows' ? $ >>> 'Helvetica*8' : 'timr08', $ >>> Alignment = 1, $ >>> ; >>> ; Label the rows to show that we flipped the image in Y. >>> ; Row 0 is at the bottom. >>> ; >>> Row_Labels = StrTrim(Reverse(Lindgen(ImageSize[1])), 2), $ >>> /All_Events, $ >>> ; >>> ; Also capture context menu events (i.e., right-clicks.) >>> ; >>> /Context_Events, $ >>> /Disjoint) >>> ; >>> ; Create a context menu for the table. >>> ; >>> ContextBase = Widget_Base(Table, /Context_Menu, $ >>> UName = 'TableContextMenu') >>> ContextStatisticsButton = Widget_Button(ContextBase, $ >>> Value = 'Show Selected Statistics', $ >>> UValue = 'Context_SelectedStatistics') >>> ContextStatisticsArea = Widget_Button(ContextBase, $ >>> Value = 'Show Selected Area', $ >>> UValue = 'Context_SelectedArea') >>> ; >>> ; We initially hide the TLB until after we update the colors >>> ; in the table the first time. >>> ; >>> Widget_Control, TLB, Map = 0 >>> Geom = Widget_Info(TLB, /Geometry) >>> ScreenSize = Get_Screen_Size() >>> Widget_Control, TLB, $ >>> TLB_Set_XOffset = (ScreenSize[0] - Geom.Scr_XSize)/2., $ >>> TLB_Set_YOffset = (ScreenSize[1] - Geom.Scr_YSize)/2. >>> Widget_Control, TLB, /Realize >>> ; >>> ; Update the colors in the cells and start the event handler. >>> ; >>> ImageTable_62_UpdateImage, TLB >>> XManager, 'ImageTable_62', TLB, /No_Block >>> End >> >> >> Dear Jim, >> >> >> Thank you very much for providing the code. If I finally use parts of the code for my research work, I will credit your name and Dr. Mike Galloy's. But before I implement it for my example, I have a question. If I have to set the color of each cell, do you think it is practical as I have more than 30 dataset scenarios. If there is an option of setting the cell colours automatically then there would be consistency of colour usage across all the 30 scenarios. By the way, I don't see any image on the left and neither do I see is a tabular form of the image on the right? >> >> -James > > Dear Jim, > > I understood your last comments only after compiling and running the code in IDL. I can see what you mean now, with both the image and the table of values. > The comments are also quite helpful. But I am stuggling to find out where to exactly insert my table of data values. If I want to save my datasets as an ASCII file or a text file and use the data values as input for running the code, can I do that somewhere in the code? In the first few lines of the code where the comment says, ;Get the raw data values from the table ; Which Table is this and how can I replace this table with my own data table from a text file or ASCII file? I think I will have to provide the path of the text file that I create with my dataset scenarios? > > -james James, I'm glad to see you're working through this... The next step would be to notice that the main routine takes as input an option argument, which is a 2-dimensional array of your own making. If you don't provide one, it creates the default 512x512 image. If your data set is small you could enter the values manually. IDL> imagetable_62, [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]] If it's larger than you'd like to enter manually, you might consider the function READ_ASCII for importing your data from file into an array. Or you could use slightly lower level routines OPENR, READF, and FREE_LUN. There are examples for each of these online, for example http://www.exelisvis.com/docs/READ.html Jim P.
On Monday, January 4, 2016 at 5:20:26 AM UTC+1, Jim P wrote: > On Sunday, January 3, 2016 at 4:26:02 PM UTC-7, James wrote: >> On Sunday, January 3, 2016 at 10:41:01 AM UTC+1, James wrote: >>> On Sunday, January 3, 2016 at 2:40:03 AM UTC+1, Jim P wrote: >>>> On Saturday, January 2, 2016 at 2:30:29 PM UTC-7, James wrote: >>>> > On Saturday, January 2, 2016 at 9:51:16 PM UTC+1, Jim P wrote: >>>> > > On Saturday, January 2, 2016 at 10:31:50 AM UTC-7, James wrote: >>>> > > > I have two dataset scenarios. Each scenario is an output from a model and each scenario contains an array of values in the x (horizontal) axis and 10 arrays of values in the y (vertical) axis. I am trying to create a plot which looks like this http://www.mathworks.com/matlabcentral/answers/uploaded_file s/42412/3.png >>>> > > > I have been looking for a plot function in ENVI IDL which can help make these plots but so far I did not find any. Can anybody help? Even better if someone can suggest a better graphical/visualization/plot option to display these two multivariate datasets so that the differences are conspicuous enough. With line graphs the visualization is not clear enough because the same values overlap on top of each other. >>>> > > > >>>> > > > Following are my scenarios. >>>> > > > >>>> > > > SCENARIO A >>>> > > > >>>> > > > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > > > y1= [0, 0, 0.02, 0.01, 0, 0, 0, 0, 0, 0, 0, 0] >>>> > > > y2= [0.01, 0, 0.05, 0.1, 0.19, 0.6, 0.87, 1, 1, 1, 1, 1] >>>> > > > y3= [0.02, 0.05, 0.2, 0.69, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y4= [0.02, 0.12, 0.25, 0.97, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y5= [0, 0.12, 0.68, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y6= [0, 0.2, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y7= [0.01, 0.49, 0.97, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y8= [0.01, 0.51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y9= [0.01, 0.82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y10= [0, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > >>>> > > > SCENARIO B >>>> > > > >>>> > > > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > > > y1= [0.01, 0.03, 0.01, 0, 0.01, 0, 0, 0, 0, 0, 0, 0] >>>> > > > y2= [0.01, 0.07, 0.04, 0.13, 0.23, 0.5, 0.92, 1, 1, 1, 1, 1] >>>> > > > y3= [0.01, 0.03, 0.2, 0.61, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y4= [0.02, 0.06, 0.4, 0.99, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y5= [0, 0.24, 0.61, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y6= [0, 0.26, 0.88, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y7= [0, 0.51, 0.99, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y8= [0.02, 0.64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y9= [0.02, 0.87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > y10= [0.01, 0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > >>>> > > The simplest way may be to use a widget_table with cell colors, then take a screen capture. >>>> > > >>>> > > Jim P. >>>> > ************************************************************ **************** >>>> > >>>> > Dear Jim, >>>> > >>>> > Thanks a lot for your helpful comments. I have never used WIDGET_TABLE function before since I am quite new to IDL Programming. The idea seems interesting and I want to try it. I am right now looking at the help page http://www.exelisvis.com/docs/WIDGET_TABLE.html >>>> > Do you know whether this function allows automatic addition of cell colours based on the range of values present or do I need to manually assign cell colours to the values? Additionally, if I assign colours to the cells which hold the values, will the values be still visible or I can replace the values just with colours? Apologies if I am asking some basic questions which may be otherwise common knowledge among the IDL Programmers' community. It would be a great help if I can find an example. I will search the web for it. If you have any other suggestions they are welcome. >>>> > >>>> > James >>>> >>>> Below is an example I wrote a number of years ago, with additional input from Dr. Mike Galloy. On the left is an image and on the right is a tabular form of the image with the cells colored according to the selected color table, using the same color table as the pixels in the image. >>>> >>>> You would be responsible for setting the color of each cell. >>>> >>>> "Showing" and "hiding" the text value in a cell is simply a matter of setting the foreground color to be the same as the background color. >>>> >>>> There are lots of comments that, along with the online help, should get you where you want to be. >>>> >>>> ;+ >>>> ; This procedure updates the image window display based >>>> ; on the current contents of the table widget, the >>>> ; selected cells (if any) and the current color table. >>>> ; >>>> ; @Param >>>> ; TLB {in}{required}{type=long} >>>> ; Set this parameter to the ID of the top-level base. >>>> ; >>>> ; @Hidden >>>> ; >>>> ; @Author >>>> ; JLP, RSI Global Services >>>> ; >>>> ; @History >>>> ; March 29, 2005 - Initial version >>>> ;- >>>> Pro ImageTable_62_UpdateImage, TLB >>>> Compile_Opt StrictArr >>>> On_Error, 2 >>>> ; >>>> ; Get the raw data values from the table. >>>> ; >>>> Table = Widget_Info(TLB, Find_by_UName='ValueTable') >>>> Widget_Control, Table, Get_Value = Values >>>> ; >>>> ; Get the color table number from the combobox. >>>> ; >>>> CTCombobox = Widget_Info(TLB, Find_by_UName = 'ColorTableCombobox') >>>> Current = Widget_Info(CTCombobox, /Combobox_GetText) >>>> Widget_Control, CTCombobox, Get_Value = AllValues >>>> CTIndex = (Where(AllValues eq Current))[0] >>>> ; >>>> ; Save the Direct Graphics state. >>>> ; >>>> WSave = !d.window >>>> Device, Get_Decomposed = WasDecomposed >>>> TVLCT, R, G, B, /Get >>>> ; >>>> ; Draw the table values to the image window using >>>> ; the current color table. >>>> ; >>>> Draw = Widget_Info(TLB, Find_by_UName = 'ImageDraw') >>>> Widget_Control, Draw, Get_Value = DrawID >>>> WSet, DrawID >>>> LoadCT, CTIndex, /Silent >>>> Device, Decomposed = 0 >>>> ; >>>> ; Remember that the table values are flipped in Y >>>> ; relative to our image so they orient the same way >>>> ; on the screen. >>>> ; >>>> TVScl, Reverse(Values, 2) >>>> ; >>>> ; Read the image buffer back from the window. >>>> ; >>>> Device, Decomposed = 1 >>>> Image = TVRd(True = 1) >>>> ; >>>> ; Restore the Direct Graphics state. >>>> ; >>>> Device, Decomposed = WasDecomposed >>>> If (WSave ne -1) then Begin >>>> Device, Window_State = WState >>>> If (WState[WSave]) then Begin >>>> WSet, WSave >>>> EndIf >>>> EndIf >>>> TVLCT, R, G, B >>>> ; >>>> ; Save the image data for the purpose of reapplying the >>>> ; selection box. >>>> ; >>>> Widget_Control, TLB, Set_UValue = Image >>>> ; >>>> ; Flip the image data about Y back into the orientation of the >>>> ; table. >>>> ; >>>> TableImage = Reverse(Temporary(Image), 3) >>>> ; >>>> ; The background color of each cell corresponds to each pixel >>>> ; value. We use "Update = 0" to prevent excessive flashing. >>>> ; >>>> Widget_Control, Table, $ >>>> Background_Color = TableImage, Update = 0 >>>> ; >>>> ; If we're "hiding" the text, this just means we draw the >>>> ; table values using the same color as the background. >>>> ; >>>> HideShow = Widget_Info(TLB, Find_by_UName = 'HideShowCombobox') >>>> If (Widget_Info(HideShow, /Combobox_GetText) eq 'Show') then Begin >>>> ; >>>> ; If we're showing table values, render the text in either black >>>> ; or white, depending on the better contrast with the background >>>> ; color in the cell. >>>> ; >>>> ImageTable_62_EnhanceText, TableImage >>>> EndIf >>>> Widget_Control, Table, $ >>>> Foreground_Color = TableImage, Update = 0 >>>> ; >>>> ; Update the base now with the accumulated changes. >>>> ; >>>> Widget_Control, TLB, /Update >>>> If (~Widget_Info(TLB, /Map)) then Begin >>>> Widget_Control, TLB, Map = 1 >>>> EndIf >>>> End >>>> >>>> >>>> ;+ >>>> ; This procedure converts an input array of table cell (image >>>> ; pixel) colors to an array of black and/or white colors to >>>> ; be used as the text color of each cell. The color black >>>> ; or white is chosen to increase contrast with the background >>>> ; color in each cell. >>>> ; >>>> ; @Param >>>> ; RGB {inout}{required}{type=BYTARR(3, N, M)} >>>> ; Set this parameter to the RGB colors of the pixels >>>> ; displayed in the image using the current color table. >>>> ; On output, the array will contain the color, either >>>> ; white or black, to be used for the foreground (text) >>>> ; color for the corresponding table cells. >>>> ; >>>> ; @Hidden >>>> ; >>>> ; @Author >>>> ; JLP, RSI Global Services >>>> ; >>>> ; @History >>>> ; March 29, 2005 - Initial version >>>> ;- >>>> Pro ImageTable_62_EnhanceText, RGB >>>> Compile_Opt StrictArr >>>> On_Error, 2 >>>> ; >>>> ; Convert the individual pixel colors from RGB space to >>>> ; hue, lightness and saturation space. >>>> ; >>>> Color_Convert, Reform(RGB[0, *, *]), Reform(RGB[1, *, *]), $ >>>> Reform(RGB[2, *, *]), H, L, S, /RGB_HLS >>>> ; >>>> ; We say that a pixel is "dark" if its lightness is less >>>> ; than 50%. >>>> ; >>>> Dark = Where(L lt .50, NDark) >>>> ; >>>> ; Light pixels will use black text. This is out initial >>>> ; default. >>>> ; >>>> RGB[*] = 0b >>>> ImageSize = Size(RGB, /Dimensions) >>>> If (NDark ne 0) then Begin >>>> ; >>>> ; Dark pixels will have white text. We use reform here >>>> ; to aid in addressing our 2-D image space with the 1-dimensional >>>> ; vectors returned by Color_Convert. We use Overwrite so >>>> ; we don't make extra copies of the data. >>>> ; >>>> RGB = Reform(RGB, 3, N_elements(RGB)/3, /Overwrite) >>>> RGB[*, Dark] = 255b >>>> RGB = Reform(RGB, 3, ImageSize[1], ImageSize[2], /Overwrite) >>>> EndIf >>>> End >>>> >>>> >>>> ;+ >>>> ; This procedure manages all events from the application's >>>> ; widgets. >>>> ; >>>> ; @Param >>>> ; Event {in}{required}{type=widget event structure} >>>> ; Set this parameter to the event structure to be >>>> ; acted upon. >>>> ; >>>> ; @Hidden >>>> ; >>>> ; @Author >>>> ; JLP, RSI Global Services >>>> ; >>>> ; @History >>>> ; March 29, 2005 - Initial version >>>> ;- >>>> Pro ImageTable_62_Event, Event >>>> Compile_Opt StrictArr >>>> On_Error, 2 >>>> ; >>>> ; What type of event is it? >>>> ; >>>> EventType = Tag_Names(Event, /Structure_Name) >>>> If (EventType eq 'WIDGET_BASE') then Begin >>>> ; >>>> ; This is a base resize event. We adjust the size of the >>>> ; table accordingly (and leave all the other widgets alone.) >>>> ; >>>> TLBGeom = Widget_Info(Event.Top, /Geometry) >>>> ; >>>> ; The base on the left hand side containing the image, comboboxes >>>> ; and spinner, remains fixed in size. >>>> ; >>>> Left = Widget_Info(Event.Top, Find_by_UName = 'LeftBase') >>>> LeftGeom = Widget_Info(Left, /Geometry) >>>> ; >>>> ; The table widget occupies "everything else". >>>> ; >>>> NewX = Event.X - 2*TLBGeom.XPad - LeftGeom.Scr_XSize > 10 >>>> NewY = Event.Y - 2*TLBGeom.YPad > 10 >>>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> ; >>>> ; Update the table size and return. >>>> ; >>>> Widget_Control, Table, Scr_XSize = NewX, Scr_YSize = NewY >>>> Return >>>> EndIf >>>> ; >>>> ; All other events are managed according to the UVALUE of the >>>> ; widget that produced the event. >>>> ; >>>> Widget_Control, Event.ID, Get_UValue = BranchCode >>>> Case BranchCode of >>>> 'ValueVisibility' : Begin >>>> ; >>>> ; Hide or show the values in the table. >>>> ; >>>> Widget_Control, Event.Top, Get_UValue = Image >>>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> Case Widget_Info(Event.ID, /Combobox_GetText) of >>>> 'Show' : Begin >>>> ; >>>> ; If we're showing the text in the table, make sure the text color >>>> ; contrasts well with the cell color. >>>> ; >>>> ImageTable_62_EnhanceText, Image >>>> ; >>>> ; Remember that the table values are "upside down" in Y to >>>> ; correspond to our image orientation, so we need to flip >>>> ; the data. >>>> ; >>>> Widget_Control, Table, $ >>>> Foreground_Color = Reverse(Temporary(Image), 3) >>>> End >>>> 'Hide' : Begin >>>> ; >>>> ; If we're hiding the text in the table, then we set the text >>>> ; color to be the same as the image color at that pixel. Again, >>>> ; we need to flip the data to match the image orientation. >>>> ; >>>> Widget_Control, Table, $ >>>> Foreground_Color = Reverse(Temporary(Image), 3) >>>> End >>>> EndCase >>>> End >>>> 'ColorTable' : Begin >>>> ; >>>> ; A change in color table means we must update the image as well >>>> ; as the cell colors in the table. >>>> ; >>>> ImageTable_62_UpdateImage, Event.Top >>>> End >>>> 'Table' : Begin >>>> EventType = Tag_Names(Event, /Structure_Name) >>>> If (EventType eq 'WIDGET_CONTEXT') then Begin >>>> ; >>>> ; If we have a right click, this is a context menu event >>>> ; request, so show it at the position of the clicked cell. >>>> ; (Note that we have previously received at least one and >>>> ; maybe two WIDGET_TABLE_CELL_SEL events as a result of >>>> ; the right-click selection, if the table was editable.) >>>> ; >>>> ContextMenu = Widget_Info(Event.ID, $ >>>> Find_by_UName = 'TableContextMenu') >>>> Widget_DisplayContextMenu, Event.ID, $ >>>> Event.X, Event.Y, ContextMenu >>>> Return >>>> EndIf >>>> ; >>>> ; The user has selected cells in the table. First, >>>> ; update the image window. >>>> ; >>>> Widget_Control, Event.Top, Get_UValue = Image >>>> Draw = Widget_Info(Event.Top, Find_by_UName = 'ImageDraw') >>>> Widget_Control, Draw, Get_Value = DrawID >>>> ; >>>> ; Save the Direct Graphics environment. >>>> ; >>>> WSave = !d.window >>>> Device, Get_Decomposed = WasDecomposed >>>> ; >>>> ; Display the image to the draw widget. This will erase any >>>> ; previously overplotted line. A cleverer solution might use >>>> ; a pixmap instead. >>>> ; >>>> WSet, DrawID >>>> Device, Decomposed = 1 >>>> TV, Image, True = 1 >>>> ; >>>> ; Overplot the bounds of the region selected in the table >>>> ; if it's more than 1 cell. >>>> ; >>>> Selected = Widget_Info(Event.ID, /Table_Select) >>>> MinX = Min(Selected[0, *], Max = MaxX) >>>> MinY = Min(Selected[1, *], Max = MaxY) >>>> dX = MaxX - MinX + 1 >>>> dY = MaxY - MinY + 1 >>>> If ((dX gt 0) && (dY gt 0)) then Begin >>>> ; >>>> ; We're going to plot the bounding box in the image in green. >>>> ; We need to remember that the cell numbers in the table >>>> ; are flipped top to bottom with respect to the image. >>>> ; >>>> PlotS, MinX + [0, 1, 1, 0, 0]*dX, $ >>>> (Size(Image, /Dimensions))[2] - 1 - $ >>>> (MinY + [0, 0, 1, 1, 0]*dY), $ >>>> /Device, Color = '00ff00'x >>>> EndIf >>>> ; >>>> ; Restore the Direct Graphics environment. >>>> ; >>>> If (WSave ne -1) then Begin >>>> Device, Window_State = WState >>>> If (WState[WSave]) then Begin >>>> WSet, WSave >>>> EndIf >>>> EndIf >>>> Device, Decomposed = WasDecomposed >>>> End >>>> 'PixelSize' : Begin >>>> ; >>>> ; Change the number of pixels square each cell in the table >>>> ; should occupy according to the value in the spinner. This number >>>> ; actually includes the dividers between cells. >>>> ; >>>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> ; >>>> ; There are no bounds on the spinner, so we need to manually clamp >>>> ; it to a reasonable range. >>>> ; >>>> Value = Long(Event.Value) >>>> Value >= 2 >>>> Value <= 256 >>>> ; >>>> ; In case we needed to clamp the value, update the spinner with >>>> ; the current value. >>>> ; >>>> Widget_Control, Event.ID, Set_Value = Value, Update = 0 >>>> ; >>>> ; Adjust the cell dimensions in the table, then update >>>> ; everything on the interface at one time. >>>> ; >>>> Widget_Control, Table, Row_Heights = Value, $ >>>> Column_Widths = Value, Update = 0 >>>> Widget_Control, Event.Top, /Update >>>> End >>>> 'Context_SelectedStatistics' : Begin >>>> ; >>>> ; This is an event from the table's context menu. >>>> ; Calculate statistics on the selected cells. >>>> ; >>>> ParentContextBase = Widget_Info(Event.ID, /Parent) >>>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> Selected = Widget_Info(Table, /Table_Select) >>>> Widget_Control, Table, Get_Value = TableValues >>>> If (N_elements(Selected)/2 gt 1) then Begin >>>> TableSize = Size(TableValues, /Dimensions) >>>> Selected = Reform(Selected[0, *] + Selected[1, *]*TableSize[0]) >>>> Stats = Moment(TableValues[Selected], MDev = MDev, SDev = SDev) >>>> MinValue = Min(TableValues[Selected], Max = MaxValue) >>>> Stats = StrTrim([MinValue, MaxValue, Stats, MDev, SDev], 2) >>>> StatsLabels = ['Minimum', 'Maximum', 'Mean', 'Variance', 'Skewness', $ >>>> 'Kurtosis', 'Mean Absolute Deviation', $ >>>> 'Standard Deviation'] >>>> StatsLabel = StatsLabels + ' : ' + Stats >>>> EndIf Else Begin >>>> StatsLabel = 'Pixel value = ' + $ >>>> StrTrim(TableValues[Selected[0, 0], Selected[1, 0]], 2) >>>> EndElse >>>> v = Dialog_Message(StatsLabel, /Information, $ >>>> Dialog_Parent = Event.Top, $ >>>> Title = 'ImageTable 6.2 ROI Statistics') >>>> End >>>> 'Context_SelectedArea' : Begin >>>> ; >>>> ; This is an event from the table's context menu. >>>> ; Calculate the area of the selected cells >>>> ; >>>> ParentContextBase = Widget_Info(Event.ID, /Parent) >>>> Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> Selected = Widget_Info(Table, /Table_Select) >>>> NPixels = Long(N_elements(Selected)/2) >>>> AreaLabel = 'Area = ' + $ >>>> StrTrim(NPixels, 2) + $ >>>> ' pixel' + (NPixels gt 1 ? 's' : '') >>>> v = Dialog_Message(AreaLabel, /Information, $ >>>> Dialog_Parent = Event.Top, $ >>>> Title = 'ImageTable 6.2 ROI Area') >>>> End >>>> Else : >>>> EndCase >>>> End >>>> >>>> >>>> ;+ >>>> ; This procedure creates a table widget whose cell values are >>>> ; displayed in colors according to a color look-up table, >>>> ; much like an image. >>>> ; >>>> ; @Param >>>> ; Val {in}{optional}{type=integer array dimensions n by m} >>>> ; Set this parameter to a 2-dimensional array of integral >>>> ; values between the values of -99 and 999. (This limitation >>>> ; is related to the format statement used to display the >>>> ; cell values; feel free to modify the code according to >>>> ; your data's needs.) The default value is a 64-by-64 shifted >>>> ; DIST image. >>>> ; >>>> ; @Examples >>>> ; IDL> ImageTable_62 >>>> ; >>>> ; @Categories >>>> ; Widget_Table, 6.2 >>>> ; >>>> ; @Author >>>> ; Jim Pendleton & MG, RSI Global Services >>>> ; >>>> ; @History >>>> ; March 31, 2005 - Initial version >>>> ; >>>> ; @File_Comments >>>> ; This procedure highlights some new features of WIDGET_TABLE >>>> ; in IDL 6.2, in particular the ability to set foreground >>>> ; and background colors in individual cells, and to display >>>> ; a context menu within a table. >>>> ; >>>> ;- >>>> Pro ImageTable_62, Val >>>> Compile_Opt StrictArr >>>> On_Error, 2 >>>> ; >>>> ; Create a copy of the input data or create the default "bulls-eye" >>>> ; image. >>>> ; >>>> iVal = N_Elements(Val) eq 0 ? Fix(Shift(Dist(512), 256, 256)) : Val >>>> ImageSize = Size(iVal, /Dimensions) >>>> ; >>>> ; Create our widget tree. We'll have some controls on the left >>>> ; and a table widget on the right. >>>> ; >>>> TLB = Widget_Base(/Row, /TLB_Size_Events, UName = 'Top', $ >>>> Title = 'ImageTable 6.2') >>>> Left = Widget_Base(TLB, /Column, UName = 'LeftBase') >>>> D = Widget_Draw(Left, XSize = ImageSize[0], YSize = ImageSize[1], $ >>>> UName = 'ImageDraw') >>>> ; >>>> ; By default, we use the "Hardcandy" color table. It shows good >>>> ; contrast in the upper corner that is initiall displayed in the >>>> ; table. >>>> ; >>>> CTBase = Widget_Base(Left, /Row, /Align_Left) >>>> CTLabel = Widget_Label(CTBase, Value = 'Color Table : ') >>>> LoadCT, /Silent, Get_Names = CTNames >>>> ColorTable = 28 >>>> CTCombobox = Widget_Combobox(CTBase, Value = CTNames,$ >>>> UName = 'ColorTableCombobox', UValue = 'ColorTable') >>>> Widget_Control, CTCombobox, Set_Combobox_Select = ColorTable >>>> VisibilityBase = Widget_Base(Left, /Row, /Align_Left) >>>> VisibilityLabel = Widget_Label(VisibilityBase, $ >>>> Value = 'Table Values : ') >>>> VisibilityCombobox = Widget_Combobox(VisibilityBase, $ >>>> Value = ['Show', 'Hide'], $ >>>> UValue = 'ValueVisibility', $ >>>> UName = 'HideShowCombobox') >>>> ; >>>> ; We'll initially display each cell as an 18x18 square. The >>>> ; spinner will allow the user to adjust this. See the >>>> ; idl62/lib/itools/ui_widgets directory for the source to >>>> ; cw_itupdownfield.pro, an undocumented, but highly useful >>>> ; compound widget. >>>> ; >>>> PixelSize = 18 >>>> Spinner = CW_itUpDownField(Left, Increment = 1, $ >>>> Label = 'Pixel Size : ', $ >>>> Value = pixelsize, $ >>>> UName = 'PixelSizeSpinner', $ >>>> UValue = 'PixelSize') >>>> ; >>>> ; Create a table with our data values. The default orientation >>>> ; places the cell [0, 0] at the upper left. But we want it >>>> ; to be oriented the same as our image, with [0, 0] in the >>>> ; lower left.. So we need to flip the data in Y. >>>> ; >>>> Table = Widget_Table(TLB, Value = Reverse(IVal, 2), $ >>>> X_Scroll = 25,$ >>>> Y_Scroll = 25, $ >>>> Row_Heights = PixelSize, Column_Widths = PixelSize, $ >>>> Format = '(i3)', $ >>>> UName = 'ValueTable', $ >>>> UValue = 'Table', $ >>>> ; >>>> ; We choose a font appropriate to Windows or Linux. We want it >>>> ; to be small so our cell sizes can be small, too. >>>> ; >>>> Font = !version.os_family eq 'Windows' ? $ >>>> 'Helvetica*8' : 'timr08', $ >>>> Alignment = 1, $ >>>> ; >>>> ; Label the rows to show that we flipped the image in Y. >>>> ; Row 0 is at the bottom. >>>> ; >>>> Row_Labels = StrTrim(Reverse(Lindgen(ImageSize[1])), 2), $ >>>> /All_Events, $ >>>> ; >>>> ; Also capture context menu events (i.e., right-clicks.) >>>> ; >>>> /Context_Events, $ >>>> /Disjoint) >>>> ; >>>> ; Create a context menu for the table. >>>> ; >>>> ContextBase = Widget_Base(Table, /Context_Menu, $ >>>> UName = 'TableContextMenu') >>>> ContextStatisticsButton = Widget_Button(ContextBase, $ >>>> Value = 'Show Selected Statistics', $ >>>> UValue = 'Context_SelectedStatistics') >>>> ContextStatisticsArea = Widget_Button(ContextBase, $ >>>> Value = 'Show Selected Area', $ >>>> UValue = 'Context_SelectedArea') >>>> ; >>>> ; We initially hide the TLB until after we update the colors >>>> ; in the table the first time. >>>> ; >>>> Widget_Control, TLB, Map = 0 >>>> Geom = Widget_Info(TLB, /Geometry) >>>> ScreenSize = Get_Screen_Size() >>>> Widget_Control, TLB, $ >>>> TLB_Set_XOffset = (ScreenSize[0] - Geom.Scr_XSize)/2., $ >>>> TLB_Set_YOffset = (ScreenSize[1] - Geom.Scr_YSize)/2. >>>> Widget_Control, TLB, /Realize >>>> ; >>>> ; Update the colors in the cells and start the event handler. >>>> ; >>>> ImageTable_62_UpdateImage, TLB >>>> XManager, 'ImageTable_62', TLB, /No_Block >>>> End >>> >>> >>> Dear Jim, >>> >>> >>> Thank you very much for providing the code. If I finally use parts of the code for my research work, I will credit your name and Dr. Mike Galloy's. But before I implement it for my example, I have a question. If I have to set the color of each cell, do you think it is practical as I have more than 30 dataset scenarios. If there is an option of setting the cell colours automatically then there would be consistency of colour usage across all the 30 scenarios. By the way, I don't see any image on the left and neither do I see is a tabular form of the image on the right? >>> >>> -James >> >> Dear Jim, >> >> I understood your last comments only after compiling and running the code in IDL. I can see what you mean now, with both the image and the table of values. >> The comments are also quite helpful. But I am stuggling to find out where to exactly insert my table of data values. If I want to save my datasets as an ASCII file or a text file and use the data values as input for running the code, can I do that somewhere in the code? In the first few lines of the code where the comment says, ;Get the raw data values from the table ; Which Table is this and how can I replace this table with my own data table from a text file or ASCII file? I think I will have to provide the path of the text file that I create with my dataset scenarios? >> >> -james > > James, > I'm glad to see you're working through this... The next step would be to notice that the main routine takes as input an option argument, which is a 2-dimensional array of your own making. If you don't provide one, it creates the default 512x512 image. > > If your data set is small you could enter the values manually. > > IDL> imagetable_62, [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]] > > If it's larger than you'd like to enter manually, you might consider the function READ_ASCII for importing your data from file into an array. Or you could use slightly lower level routines OPENR, READF, and FREE_LUN. > > There are examples for each of these online, for example > > http://www.exelisvis.com/docs/READ.html > > Jim P. Dear Jim, I did it finally :)I did not find any option to paste an image here, otherwise I would have shown what the output looks like. This is a brilliant code. I am grateful to the creators. Don't know how else to thank you other than crediting your name. It would have taken me months if not years to create this on my own from scratch. How long have you been working with IDL Programming? Just want to get an idea of the time it will take for me to get there. The code is working just fine with my manual addition of data values. I have to still figure it out how to do it via the ASCII file way through the examples. I have more than 30 such scenarios to create and I don't mind taking a screen capture each time and manually adding the x and y axis tick labels and the axis labels with legend, but just to make the task quicker, do you think there is way to add the labels directly during the execution of the code? So that I make only some manual edits after the screen capture? Once again, I am grateful for your help. -James
On Monday, January 4, 2016 at 2:21:04 AM UTC-7, James wrote: > On Monday, January 4, 2016 at 5:20:26 AM UTC+1, Jim P wrote: >> On Sunday, January 3, 2016 at 4:26:02 PM UTC-7, James wrote: >>> On Sunday, January 3, 2016 at 10:41:01 AM UTC+1, James wrote: >>>> On Sunday, January 3, 2016 at 2:40:03 AM UTC+1, Jim P wrote: >>>> > On Saturday, January 2, 2016 at 2:30:29 PM UTC-7, James wrote: >>>> > > On Saturday, January 2, 2016 at 9:51:16 PM UTC+1, Jim P wrote: >>>> > > > On Saturday, January 2, 2016 at 10:31:50 AM UTC-7, James wrote: >>>> > > > > I have two dataset scenarios. Each scenario is an output from a model and each scenario contains an array of values in the x (horizontal) axis and 10 arrays of values in the y (vertical) axis. I am trying to create a plot which looks like this http://www.mathworks.com/matlabcentral/answers/uploaded_file s/42412/3.png >>>> > > > > I have been looking for a plot function in ENVI IDL which can help make these plots but so far I did not find any. Can anybody help? Even better if someone can suggest a better graphical/visualization/plot option to display these two multivariate datasets so that the differences are conspicuous enough. With line graphs the visualization is not clear enough because the same values overlap on top of each other. >>>> > > > > >>>> > > > > Following are my scenarios. >>>> > > > > >>>> > > > > SCENARIO A >>>> > > > > >>>> > > > > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > > > > y1= [0, 0, 0.02, 0.01, 0, 0, 0, 0, 0, 0, 0, 0] >>>> > > > > y2= [0.01, 0, 0.05, 0.1, 0.19, 0.6, 0.87, 1, 1, 1, 1, 1] >>>> > > > > y3= [0.02, 0.05, 0.2, 0.69, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y4= [0.02, 0.12, 0.25, 0.97, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y5= [0, 0.12, 0.68, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y6= [0, 0.2, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y7= [0.01, 0.49, 0.97, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y8= [0.01, 0.51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y9= [0.01, 0.82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y10= [0, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > >>>> > > > > SCENARIO B >>>> > > > > >>>> > > > > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > > > > y1= [0.01, 0.03, 0.01, 0, 0.01, 0, 0, 0, 0, 0, 0, 0] >>>> > > > > y2= [0.01, 0.07, 0.04, 0.13, 0.23, 0.5, 0.92, 1, 1, 1, 1, 1] >>>> > > > > y3= [0.01, 0.03, 0.2, 0.61, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y4= [0.02, 0.06, 0.4, 0.99, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y5= [0, 0.24, 0.61, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y6= [0, 0.26, 0.88, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y7= [0, 0.51, 0.99, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y8= [0.02, 0.64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y9= [0.02, 0.87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > y10= [0.01, 0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > >>>> > > > The simplest way may be to use a widget_table with cell colors, then take a screen capture. >>>> > > > >>>> > > > Jim P. >>>> > > ************************************************************ **************** >>>> > > >>>> > > Dear Jim, >>>> > > >>>> > > Thanks a lot for your helpful comments. I have never used WIDGET_TABLE function before since I am quite new to IDL Programming. The idea seems interesting and I want to try it. I am right now looking at the help page http://www.exelisvis.com/docs/WIDGET_TABLE.html >>>> > > Do you know whether this function allows automatic addition of cell colours based on the range of values present or do I need to manually assign cell colours to the values? Additionally, if I assign colours to the cells which hold the values, will the values be still visible or I can replace the values just with colours? Apologies if I am asking some basic questions which may be otherwise common knowledge among the IDL Programmers' community. It would be a great help if I can find an example. I will search the web for it. If you have any other suggestions they are welcome. >>>> > > >>>> > > James >>>> > >>>> > Below is an example I wrote a number of years ago, with additional input from Dr. Mike Galloy. On the left is an image and on the right is a tabular form of the image with the cells colored according to the selected color table, using the same color table as the pixels in the image. >>>> > >>>> > You would be responsible for setting the color of each cell. >>>> > >>>> > "Showing" and "hiding" the text value in a cell is simply a matter of setting the foreground color to be the same as the background color. >>>> > >>>> > There are lots of comments that, along with the online help, should get you where you want to be. >>>> > >>>> > ;+ >>>> > ; This procedure updates the image window display based >>>> > ; on the current contents of the table widget, the >>>> > ; selected cells (if any) and the current color table. >>>> > ; >>>> > ; @Param >>>> > ; TLB {in}{required}{type=long} >>>> > ; Set this parameter to the ID of the top-level base. >>>> > ; >>>> > ; @Hidden >>>> > ; >>>> > ; @Author >>>> > ; JLP, RSI Global Services >>>> > ; >>>> > ; @History >>>> > ; March 29, 2005 - Initial version >>>> > ;- >>>> > Pro ImageTable_62_UpdateImage, TLB >>>> > Compile_Opt StrictArr >>>> > On_Error, 2 >>>> > ; >>>> > ; Get the raw data values from the table. >>>> > ; >>>> > Table = Widget_Info(TLB, Find_by_UName='ValueTable') >>>> > Widget_Control, Table, Get_Value = Values >>>> > ; >>>> > ; Get the color table number from the combobox. >>>> > ; >>>> > CTCombobox = Widget_Info(TLB, Find_by_UName = 'ColorTableCombobox') >>>> > Current = Widget_Info(CTCombobox, /Combobox_GetText) >>>> > Widget_Control, CTCombobox, Get_Value = AllValues >>>> > CTIndex = (Where(AllValues eq Current))[0] >>>> > ; >>>> > ; Save the Direct Graphics state. >>>> > ; >>>> > WSave = !d.window >>>> > Device, Get_Decomposed = WasDecomposed >>>> > TVLCT, R, G, B, /Get >>>> > ; >>>> > ; Draw the table values to the image window using >>>> > ; the current color table. >>>> > ; >>>> > Draw = Widget_Info(TLB, Find_by_UName = 'ImageDraw') >>>> > Widget_Control, Draw, Get_Value = DrawID >>>> > WSet, DrawID >>>> > LoadCT, CTIndex, /Silent >>>> > Device, Decomposed = 0 >>>> > ; >>>> > ; Remember that the table values are flipped in Y >>>> > ; relative to our image so they orient the same way >>>> > ; on the screen. >>>> > ; >>>> > TVScl, Reverse(Values, 2) >>>> > ; >>>> > ; Read the image buffer back from the window. >>>> > ; >>>> > Device, Decomposed = 1 >>>> > Image = TVRd(True = 1) >>>> > ; >>>> > ; Restore the Direct Graphics state. >>>> > ; >>>> > Device, Decomposed = WasDecomposed >>>> > If (WSave ne -1) then Begin >>>> > Device, Window_State = WState >>>> > If (WState[WSave]) then Begin >>>> > WSet, WSave >>>> > EndIf >>>> > EndIf >>>> > TVLCT, R, G, B >>>> > ; >>>> > ; Save the image data for the purpose of reapplying the >>>> > ; selection box. >>>> > ; >>>> > Widget_Control, TLB, Set_UValue = Image >>>> > ; >>>> > ; Flip the image data about Y back into the orientation of the >>>> > ; table. >>>> > ; >>>> > TableImage = Reverse(Temporary(Image), 3) >>>> > ; >>>> > ; The background color of each cell corresponds to each pixel >>>> > ; value. We use "Update = 0" to prevent excessive flashing. >>>> > ; >>>> > Widget_Control, Table, $ >>>> > Background_Color = TableImage, Update = 0 >>>> > ; >>>> > ; If we're "hiding" the text, this just means we draw the >>>> > ; table values using the same color as the background. >>>> > ; >>>> > HideShow = Widget_Info(TLB, Find_by_UName = 'HideShowCombobox') >>>> > If (Widget_Info(HideShow, /Combobox_GetText) eq 'Show') then Begin >>>> > ; >>>> > ; If we're showing table values, render the text in either black >>>> > ; or white, depending on the better contrast with the background >>>> > ; color in the cell. >>>> > ; >>>> > ImageTable_62_EnhanceText, TableImage >>>> > EndIf >>>> > Widget_Control, Table, $ >>>> > Foreground_Color = TableImage, Update = 0 >>>> > ; >>>> > ; Update the base now with the accumulated changes. >>>> > ; >>>> > Widget_Control, TLB, /Update >>>> > If (~Widget_Info(TLB, /Map)) then Begin >>>> > Widget_Control, TLB, Map = 1 >>>> > EndIf >>>> > End >>>> > >>>> > >>>> > ;+ >>>> > ; This procedure converts an input array of table cell (image >>>> > ; pixel) colors to an array of black and/or white colors to >>>> > ; be used as the text color of each cell. The color black >>>> > ; or white is chosen to increase contrast with the background >>>> > ; color in each cell. >>>> > ; >>>> > ; @Param >>>> > ; RGB {inout}{required}{type=BYTARR(3, N, M)} >>>> > ; Set this parameter to the RGB colors of the pixels >>>> > ; displayed in the image using the current color table. >>>> > ; On output, the array will contain the color, either >>>> > ; white or black, to be used for the foreground (text) >>>> > ; color for the corresponding table cells. >>>> > ; >>>> > ; @Hidden >>>> > ; >>>> > ; @Author >>>> > ; JLP, RSI Global Services >>>> > ; >>>> > ; @History >>>> > ; March 29, 2005 - Initial version >>>> > ;- >>>> > Pro ImageTable_62_EnhanceText, RGB >>>> > Compile_Opt StrictArr >>>> > On_Error, 2 >>>> > ; >>>> > ; Convert the individual pixel colors from RGB space to >>>> > ; hue, lightness and saturation space. >>>> > ; >>>> > Color_Convert, Reform(RGB[0, *, *]), Reform(RGB[1, *, *]), $ >>>> > Reform(RGB[2, *, *]), H, L, S, /RGB_HLS >>>> > ; >>>> > ; We say that a pixel is "dark" if its lightness is less >>>> > ; than 50%. >>>> > ; >>>> > Dark = Where(L lt .50, NDark) >>>> > ; >>>> > ; Light pixels will use black text. This is out initial >>>> > ; default. >>>> > ; >>>> > RGB[*] = 0b >>>> > ImageSize = Size(RGB, /Dimensions) >>>> > If (NDark ne 0) then Begin >>>> > ; >>>> > ; Dark pixels will have white text. We use reform here >>>> > ; to aid in addressing our 2-D image space with the 1-dimensional >>>> > ; vectors returned by Color_Convert. We use Overwrite so >>>> > ; we don't make extra copies of the data. >>>> > ; >>>> > RGB = Reform(RGB, 3, N_elements(RGB)/3, /Overwrite) >>>> > RGB[*, Dark] = 255b >>>> > RGB = Reform(RGB, 3, ImageSize[1], ImageSize[2], /Overwrite) >>>> > EndIf >>>> > End >>>> > >>>> > >>>> > ;+ >>>> > ; This procedure manages all events from the application's >>>> > ; widgets. >>>> > ; >>>> > ; @Param >>>> > ; Event {in}{required}{type=widget event structure} >>>> > ; Set this parameter to the event structure to be >>>> > ; acted upon. >>>> > ; >>>> > ; @Hidden >>>> > ; >>>> > ; @Author >>>> > ; JLP, RSI Global Services >>>> > ; >>>> > ; @History >>>> > ; March 29, 2005 - Initial version >>>> > ;- >>>> > Pro ImageTable_62_Event, Event >>>> > Compile_Opt StrictArr >>>> > On_Error, 2 >>>> > ; >>>> > ; What type of event is it? >>>> > ; >>>> > EventType = Tag_Names(Event, /Structure_Name) >>>> > If (EventType eq 'WIDGET_BASE') then Begin >>>> > ; >>>> > ; This is a base resize event. We adjust the size of the >>>> > ; table accordingly (and leave all the other widgets alone.) >>>> > ; >>>> > TLBGeom = Widget_Info(Event.Top, /Geometry) >>>> > ; >>>> > ; The base on the left hand side containing the image, comboboxes >>>> > ; and spinner, remains fixed in size. >>>> > ; >>>> > Left = Widget_Info(Event.Top, Find_by_UName = 'LeftBase') >>>> > LeftGeom = Widget_Info(Left, /Geometry) >>>> > ; >>>> > ; The table widget occupies "everything else". >>>> > ; >>>> > NewX = Event.X - 2*TLBGeom.XPad - LeftGeom.Scr_XSize > 10 >>>> > NewY = Event.Y - 2*TLBGeom.YPad > 10 >>>> > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > ; >>>> > ; Update the table size and return. >>>> > ; >>>> > Widget_Control, Table, Scr_XSize = NewX, Scr_YSize = NewY >>>> > Return >>>> > EndIf >>>> > ; >>>> > ; All other events are managed according to the UVALUE of the >>>> > ; widget that produced the event. >>>> > ; >>>> > Widget_Control, Event.ID, Get_UValue = BranchCode >>>> > Case BranchCode of >>>> > 'ValueVisibility' : Begin >>>> > ; >>>> > ; Hide or show the values in the table. >>>> > ; >>>> > Widget_Control, Event.Top, Get_UValue = Image >>>> > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > Case Widget_Info(Event.ID, /Combobox_GetText) of >>>> > 'Show' : Begin >>>> > ; >>>> > ; If we're showing the text in the table, make sure the text color >>>> > ; contrasts well with the cell color. >>>> > ; >>>> > ImageTable_62_EnhanceText, Image >>>> > ; >>>> > ; Remember that the table values are "upside down" in Y to >>>> > ; correspond to our image orientation, so we need to flip >>>> > ; the data. >>>> > ; >>>> > Widget_Control, Table, $ >>>> > Foreground_Color = Reverse(Temporary(Image), 3) >>>> > End >>>> > 'Hide' : Begin >>>> > ; >>>> > ; If we're hiding the text in the table, then we set the text >>>> > ; color to be the same as the image color at that pixel. Again, >>>> > ; we need to flip the data to match the image orientation. >>>> > ; >>>> > Widget_Control, Table, $ >>>> > Foreground_Color = Reverse(Temporary(Image), 3) >>>> > End >>>> > EndCase >>>> > End >>>> > 'ColorTable' : Begin >>>> > ; >>>> > ; A change in color table means we must update the image as well >>>> > ; as the cell colors in the table. >>>> > ; >>>> > ImageTable_62_UpdateImage, Event.Top >>>> > End >>>> > 'Table' : Begin >>>> > EventType = Tag_Names(Event, /Structure_Name) >>>> > If (EventType eq 'WIDGET_CONTEXT') then Begin >>>> > ; >>>> > ; If we have a right click, this is a context menu event >>>> > ; request, so show it at the position of the clicked cell. >>>> > ; (Note that we have previously received at least one and >>>> > ; maybe two WIDGET_TABLE_CELL_SEL events as a result of >>>> > ; the right-click selection, if the table was editable.) >>>> > ; >>>> > ContextMenu = Widget_Info(Event.ID, $ >>>> > Find_by_UName = 'TableContextMenu') >>>> > Widget_DisplayContextMenu, Event.ID, $ >>>> > Event.X, Event.Y, ContextMenu >>>> > Return >>>> > EndIf >>>> > ; >>>> > ; The user has selected cells in the table. First, >>>> > ; update the image window. >>>> > ; >>>> > Widget_Control, Event.Top, Get_UValue = Image >>>> > Draw = Widget_Info(Event.Top, Find_by_UName = 'ImageDraw') >>>> > Widget_Control, Draw, Get_Value = DrawID >>>> > ; >>>> > ; Save the Direct Graphics environment. >>>> > ; >>>> > WSave = !d.window >>>> > Device, Get_Decomposed = WasDecomposed >>>> > ; >>>> > ; Display the image to the draw widget. This will erase any >>>> > ; previously overplotted line. A cleverer solution might use >>>> > ; a pixmap instead. >>>> > ; >>>> > WSet, DrawID >>>> > Device, Decomposed = 1 >>>> > TV, Image, True = 1 >>>> > ; >>>> > ; Overplot the bounds of the region selected in the table >>>> > ; if it's more than 1 cell. >>>> > ; >>>> > Selected = Widget_Info(Event.ID, /Table_Select) >>>> > MinX = Min(Selected[0, *], Max = MaxX) >>>> > MinY = Min(Selected[1, *], Max = MaxY) >>>> > dX = MaxX - MinX + 1 >>>> > dY = MaxY - MinY + 1 >>>> > If ((dX gt 0) && (dY gt 0)) then Begin >>>> > ; >>>> > ; We're going to plot the bounding box in the image in green. >>>> > ; We need to remember that the cell numbers in the table >>>> > ; are flipped top to bottom with respect to the image. >>>> > ; >>>> > PlotS, MinX + [0, 1, 1, 0, 0]*dX, $ >>>> > (Size(Image, /Dimensions))[2] - 1 - $ >>>> > (MinY + [0, 0, 1, 1, 0]*dY), $ >>>> > /Device, Color = '00ff00'x >>>> > EndIf >>>> > ; >>>> > ; Restore the Direct Graphics environment. >>>> > ; >>>> > If (WSave ne -1) then Begin >>>> > Device, Window_State = WState >>>> > If (WState[WSave]) then Begin >>>> > WSet, WSave >>>> > EndIf >>>> > EndIf >>>> > Device, Decomposed = WasDecomposed >>>> > End >>>> > 'PixelSize' : Begin >>>> > ; >>>> > ; Change the number of pixels square each cell in the table >>>> > ; should occupy according to the value in the spinner. This number >>>> > ; actually includes the dividers between cells. >>>> > ; >>>> > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > ; >>>> > ; There are no bounds on the spinner, so we need to manually clamp >>>> > ; it to a reasonable range. >>>> > ; >>>> > Value = Long(Event.Value) >>>> > Value >= 2 >>>> > Value <= 256 >>>> > ; >>>> > ; In case we needed to clamp the value, update the spinner with >>>> > ; the current value. >>>> > ; >>>> > Widget_Control, Event.ID, Set_Value = Value, Update = 0 >>>> > ; >>>> > ; Adjust the cell dimensions in the table, then update >>>> > ; everything on the interface at one time. >>>> > ; >>>> > Widget_Control, Table, Row_Heights = Value, $ >>>> > Column_Widths = Value, Update = 0 >>>> > Widget_Control, Event.Top, /Update >>>> > End >>>> > 'Context_SelectedStatistics' : Begin >>>> > ; >>>> > ; This is an event from the table's context menu. >>>> > ; Calculate statistics on the selected cells. >>>> > ; >>>> > ParentContextBase = Widget_Info(Event.ID, /Parent) >>>> > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > Selected = Widget_Info(Table, /Table_Select) >>>> > Widget_Control, Table, Get_Value = TableValues >>>> > If (N_elements(Selected)/2 gt 1) then Begin >>>> > TableSize = Size(TableValues, /Dimensions) >>>> > Selected = Reform(Selected[0, *] + Selected[1, *]*TableSize[0]) >>>> > Stats = Moment(TableValues[Selected], MDev = MDev, SDev = SDev) >>>> > MinValue = Min(TableValues[Selected], Max = MaxValue) >>>> > Stats = StrTrim([MinValue, MaxValue, Stats, MDev, SDev], 2) >>>> > StatsLabels = ['Minimum', 'Maximum', 'Mean', 'Variance', 'Skewness', $ >>>> > 'Kurtosis', 'Mean Absolute Deviation', $ >>>> > 'Standard Deviation'] >>>> > StatsLabel = StatsLabels + ' : ' + Stats >>>> > EndIf Else Begin >>>> > StatsLabel = 'Pixel value = ' + $ >>>> > StrTrim(TableValues[Selected[0, 0], Selected[1, 0]], 2) >>>> > EndElse >>>> > v = Dialog_Message(StatsLabel, /Information, $ >>>> > Dialog_Parent = Event.Top, $ >>>> > Title = 'ImageTable 6.2 ROI Statistics') >>>> > End >>>> > 'Context_SelectedArea' : Begin >>>> > ; >>>> > ; This is an event from the table's context menu. >>>> > ; Calculate the area of the selected cells >>>> > ; >>>> > ParentContextBase = Widget_Info(Event.ID, /Parent) >>>> > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > Selected = Widget_Info(Table, /Table_Select) >>>> > NPixels = Long(N_elements(Selected)/2) >>>> > AreaLabel = 'Area = ' + $ >>>> > StrTrim(NPixels, 2) + $ >>>> > ' pixel' + (NPixels gt 1 ? 's' : '') >>>> > v = Dialog_Message(AreaLabel, /Information, $ >>>> > Dialog_Parent = Event.Top, $ >>>> > Title = 'ImageTable 6.2 ROI Area') >>>> > End >>>> > Else : >>>> > EndCase >>>> > End >>>> > >>>> > >>>> > ;+ >>>> > ; This procedure creates a table widget whose cell values are >>>> > ; displayed in colors according to a color look-up table, >>>> > ; much like an image. >>>> > ; >>>> > ; @Param >>>> > ; Val {in}{optional}{type=integer array dimensions n by m} >>>> > ; Set this parameter to a 2-dimensional array of integral >>>> > ; values between the values of -99 and 999. (This limitation >>>> > ; is related to the format statement used to display the >>>> > ; cell values; feel free to modify the code according to >>>> > ; your data's needs.) The default value is a 64-by-64 shifted >>>> > ; DIST image. >>>> > ; >>>> > ; @Examples >>>> > ; IDL> ImageTable_62 >>>> > ; >>>> > ; @Categories >>>> > ; Widget_Table, 6.2 >>>> > ; >>>> > ; @Author >>>> > ; Jim Pendleton & MG, RSI Global Services >>>> > ; >>>> > ; @History >>>> > ; March 31, 2005 - Initial version >>>> > ; >>>> > ; @File_Comments >>>> > ; This procedure highlights some new features of WIDGET_TABLE >>>> > ; in IDL 6.2, in particular the ability to set foreground >>>> > ; and background colors in individual cells, and to display >>>> > ; a context menu within a table. >>>> > ; >>>> > ;- >>>> > Pro ImageTable_62, Val >>>> > Compile_Opt StrictArr >>>> > On_Error, 2 >>>> > ; >>>> > ; Create a copy of the input data or create the default "bulls-eye" >>>> > ; image. >>>> > ; >>>> > iVal = N_Elements(Val) eq 0 ? Fix(Shift(Dist(512), 256, 256)) : Val >>>> > ImageSize = Size(iVal, /Dimensions) >>>> > ; >>>> > ; Create our widget tree. We'll have some controls on the left >>>> > ; and a table widget on the right. >>>> > ; >>>> > TLB = Widget_Base(/Row, /TLB_Size_Events, UName = 'Top', $ >>>> > Title = 'ImageTable 6.2') >>>> > Left = Widget_Base(TLB, /Column, UName = 'LeftBase') >>>> > D = Widget_Draw(Left, XSize = ImageSize[0], YSize = ImageSize[1], $ >>>> > UName = 'ImageDraw') >>>> > ; >>>> > ; By default, we use the "Hardcandy" color table. It shows good >>>> > ; contrast in the upper corner that is initiall displayed in the >>>> > ; table. >>>> > ; >>>> > CTBase = Widget_Base(Left, /Row, /Align_Left) >>>> > CTLabel = Widget_Label(CTBase, Value = 'Color Table : ') >>>> > LoadCT, /Silent, Get_Names = CTNames >>>> > ColorTable = 28 >>>> > CTCombobox = Widget_Combobox(CTBase, Value = CTNames,$ >>>> > UName = 'ColorTableCombobox', UValue = 'ColorTable') >>>> > Widget_Control, CTCombobox, Set_Combobox_Select = ColorTable >>>> > VisibilityBase = Widget_Base(Left, /Row, /Align_Left) >>>> > VisibilityLabel = Widget_Label(VisibilityBase, $ >>>> > Value = 'Table Values : ') >>>> > VisibilityCombobox = Widget_Combobox(VisibilityBase, $ >>>> > Value = ['Show', 'Hide'], $ >>>> > UValue = 'ValueVisibility', $ >>>> > UName = 'HideShowCombobox') >>>> > ; >>>> > ; We'll initially display each cell as an 18x18 square. The >>>> > ; spinner will allow the user to adjust this. See the >>>> > ; idl62/lib/itools/ui_widgets directory for the source to >>>> > ; cw_itupdownfield.pro, an undocumented, but highly useful >>>> > ; compound widget. >>>> > ; >>>> > PixelSize = 18 >>>> > Spinner = CW_itUpDownField(Left, Increment = 1, $ >>>> > Label = 'Pixel Size : ', $ >>>> > Value = pixelsize, $ >>>> > UName = 'PixelSizeSpinner', $ >>>> > UValue = 'PixelSize') >>>> > ; >>>> > ; Create a table with our data values. The default orientation >>>> > ; places the cell [0, 0] at the upper left. But we want it >>>> > ; to be oriented the same as our image, with [0, 0] in the >>>> > ; lower left.. So we need to flip the data in Y. >>>> > ; >>>> > Table = Widget_Table(TLB, Value = Reverse(IVal, 2), $ >>>> > X_Scroll = 25,$ >>>> > Y_Scroll = 25, $ >>>> > Row_Heights = PixelSize, Column_Widths = PixelSize, $ >>>> > Format = '(i3)', $ >>>> > UName = 'ValueTable', $ >>>> > UValue = 'Table', $ >>>> > ; >>>> > ; We choose a font appropriate to Windows or Linux. We want it >>>> > ; to be small so our cell sizes can be small, too. >>>> > ; >>>> > Font = !version.os_family eq 'Windows' ? $ >>>> > 'Helvetica*8' : 'timr08', $ >>>> > Alignment = 1, $ >>>> > ; >>>> > ; Label the rows to show that we flipped the image in Y. >>>> > ; Row 0 is at the bottom. >>>> > ; >>>> > Row_Labels = StrTrim(Reverse(Lindgen(ImageSize[1])), 2), $ >>>> > /All_Events, $ >>>> > ; >>>> > ; Also capture context menu events (i.e., right-clicks.) >>>> > ; >>>> > /Context_Events, $ >>>> > /Disjoint) >>>> > ; >>>> > ; Create a context menu for the table. >>>> > ; >>>> > ContextBase = Widget_Base(Table, /Context_Menu, $ >>>> > UName = 'TableContextMenu') >>>> > ContextStatisticsButton = Widget_Button(ContextBase, $ >>>> > Value = 'Show Selected Statistics', $ >>>> > UValue = 'Context_SelectedStatistics') >>>> > ContextStatisticsArea = Widget_Button(ContextBase, $ >>>> > Value = 'Show Selected Area', $ >>>> > UValue = 'Context_SelectedArea') >>>> > ; >>>> > ; We initially hide the TLB until after we update the colors >>>> > ; in the table the first time. >>>> > ; >>>> > Widget_Control, TLB, Map = 0 >>>> > Geom = Widget_Info(TLB, /Geometry) >>>> > ScreenSize = Get_Screen_Size() >>>> > Widget_Control, TLB, $ >>>> > TLB_Set_XOffset = (ScreenSize[0] - Geom.Scr_XSize)/2., $ >>>> > TLB_Set_YOffset = (ScreenSize[1] - Geom.Scr_YSize)/2. >>>> > Widget_Control, TLB, /Realize >>>> > ; >>>> > ; Update the colors in the cells and start the event handler. >>>> > ; >>>> > ImageTable_62_UpdateImage, TLB >>>> > XManager, 'ImageTable_62', TLB, /No_Block >>>> > End >>>> >>>> >>>> Dear Jim, >>>> >>>> >>>> Thank you very much for providing the code. If I finally use parts of the code for my research work, I will credit your name and Dr. Mike Galloy's. But before I implement it for my example, I have a question. If I have to set the color of each cell, do you think it is practical as I have more than 30 dataset scenarios. If there is an option of setting the cell colours automatically then there would be consistency of colour usage across all the 30 scenarios. By the way, I don't see any image on the left and neither do I see is a tabular form of the image on the right? >>>> >>>> -James >>> >>> Dear Jim, >>> >>> I understood your last comments only after compiling and running the code in IDL. I can see what you mean now, with both the image and the table of values. >>> The comments are also quite helpful. But I am stuggling to find out where to exactly insert my table of data values. If I want to save my datasets as an ASCII file or a text file and use the data values as input for running the code, can I do that somewhere in the code? In the first few lines of the code where the comment says, ;Get the raw data values from the table ; Which Table is this and how can I replace this table with my own data table from a text file or ASCII file? I think I will have to provide the path of the text file that I create with my dataset scenarios? >>> >>> -james >> >> James, >> I'm glad to see you're working through this... The next step would be to notice that the main routine takes as input an option argument, which is a 2-dimensional array of your own making. If you don't provide one, it creates the default 512x512 image. >> >> If your data set is small you could enter the values manually. >> >> IDL> imagetable_62, [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]] >> >> If it's larger than you'd like to enter manually, you might consider the function READ_ASCII for importing your data from file into an array. Or you could use slightly lower level routines OPENR, READF, and FREE_LUN. >> >> There are examples for each of these online, for example >> >> http://www.exelisvis.com/docs/READ.html >> >> Jim P. > > > Dear Jim, > > I did it finally :)I did not find any option to paste an image here, otherwise I would have shown what the output looks like. This is a brilliant code. I am grateful to the creators. Don't know how else to thank you other than crediting your name. It would have taken me months if not years to create this on my own from scratch. How long have you been working with IDL Programming? Just want to get an idea of the time it will take for me to get there. The code is working just fine with my manual addition of data values. I have to still figure it out how to do it via the ASCII file way through the examples. I have more than 30 such scenarios to create and I don't mind taking a screen capture each time and manually adding the x and y axis tick labels and the axis labels with legend, but just to make the task quicker, do you think there is way to add the labels directly during the execution of the code? So that I make only some manual edits after the screen capture? > > Once again, I am grateful for your help. > > -James No need to "credit" me. I wrote this code 11 years ago as a simple demo of a new feature that had come out with IDL 6.2. We're up to 8.5.1, now of course. At the time I'd only been solving science and engineering problems with IDL for about 20 years. However, the table widget cell coloring feature had been available for just a couple weeks, so I wasn't really ahead of the pack in that sense. I wrote an IDL Data Point blog post a few weeks ago on the topic of screen capturing IDL GUIs programmatically which may be of use to you eventually, if you want to turn your manual process into a reusable utility. http://www.exelisvis.com/Company/PressRoom/Blogs/BlogAuthorJ Pen/TabId/1342/PID/4876/authorid/289/AuthorName/JimPendleton /Default.aspx You might consider a scenario where you capture the table into an image file, call the image() function to read it back in as a bitmap, then apply text() annotations. As with most things, there's no single right way to accomplish your task. Jim P.
On Monday, January 4, 2016 at 4:15:32 PM UTC+1, Jim P wrote: > On Monday, January 4, 2016 at 2:21:04 AM UTC-7, James wrote: >> On Monday, January 4, 2016 at 5:20:26 AM UTC+1, Jim P wrote: >>> On Sunday, January 3, 2016 at 4:26:02 PM UTC-7, James wrote: >>>> On Sunday, January 3, 2016 at 10:41:01 AM UTC+1, James wrote: >>>> > On Sunday, January 3, 2016 at 2:40:03 AM UTC+1, Jim P wrote: >>>> > > On Saturday, January 2, 2016 at 2:30:29 PM UTC-7, James wrote: >>>> > > > On Saturday, January 2, 2016 at 9:51:16 PM UTC+1, Jim P wrote: >>>> > > > > On Saturday, January 2, 2016 at 10:31:50 AM UTC-7, James wrote: >>>> > > > > > I have two dataset scenarios. Each scenario is an output from a model and each scenario contains an array of values in the x (horizontal) axis and 10 arrays of values in the y (vertical) axis. I am trying to create a plot which looks like this http://www.mathworks.com/matlabcentral/answers/uploaded_file s/42412/3.png >>>> > > > > > I have been looking for a plot function in ENVI IDL which can help make these plots but so far I did not find any. Can anybody help? Even better if someone can suggest a better graphical/visualization/plot option to display these two multivariate datasets so that the differences are conspicuous enough. With line graphs the visualization is not clear enough because the same values overlap on top of each other. >>>> > > > > > >>>> > > > > > Following are my scenarios. >>>> > > > > > >>>> > > > > > SCENARIO A >>>> > > > > > >>>> > > > > > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > > > > > y1= [0, 0, 0.02, 0.01, 0, 0, 0, 0, 0, 0, 0, 0] >>>> > > > > > y2= [0.01, 0, 0.05, 0.1, 0.19, 0.6, 0.87, 1, 1, 1, 1, 1] >>>> > > > > > y3= [0.02, 0.05, 0.2, 0.69, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y4= [0.02, 0.12, 0.25, 0.97, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y5= [0, 0.12, 0.68, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y6= [0, 0.2, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y7= [0.01, 0.49, 0.97, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y8= [0.01, 0.51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y9= [0.01, 0.82, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y10= [0, 0.84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > >>>> > > > > > SCENARIO B >>>> > > > > > >>>> > > > > > x= [0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] >>>> > > > > > y1= [0.01, 0.03, 0.01, 0, 0.01, 0, 0, 0, 0, 0, 0, 0] >>>> > > > > > y2= [0.01, 0.07, 0.04, 0.13, 0.23, 0.5, 0.92, 1, 1, 1, 1, 1] >>>> > > > > > y3= [0.01, 0.03, 0.2, 0.61, 0.99, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y4= [0.02, 0.06, 0.4, 0.99, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y5= [0, 0.24, 0.61, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y6= [0, 0.26, 0.88, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y7= [0, 0.51, 0.99, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y8= [0.02, 0.64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y9= [0.02, 0.87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > > y10= [0.01, 0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>>> > > > > >>>> > > > > The simplest way may be to use a widget_table with cell colors, then take a screen capture. >>>> > > > > >>>> > > > > Jim P. >>>> > > > ************************************************************ **************** >>>> > > > >>>> > > > Dear Jim, >>>> > > > >>>> > > > Thanks a lot for your helpful comments. I have never used WIDGET_TABLE function before since I am quite new to IDL Programming. The idea seems interesting and I want to try it. I am right now looking at the help page http://www.exelisvis.com/docs/WIDGET_TABLE.html >>>> > > > Do you know whether this function allows automatic addition of cell colours based on the range of values present or do I need to manually assign cell colours to the values? Additionally, if I assign colours to the cells which hold the values, will the values be still visible or I can replace the values just with colours? Apologies if I am asking some basic questions which may be otherwise common knowledge among the IDL Programmers' community. It would be a great help if I can find an example. I will search the web for it. If you have any other suggestions they are welcome. >>>> > > > >>>> > > > James >>>> > > >>>> > > Below is an example I wrote a number of years ago, with additional input from Dr. Mike Galloy. On the left is an image and on the right is a tabular form of the image with the cells colored according to the selected color table, using the same color table as the pixels in the image. >>>> > > >>>> > > You would be responsible for setting the color of each cell. >>>> > > >>>> > > "Showing" and "hiding" the text value in a cell is simply a matter of setting the foreground color to be the same as the background color. >>>> > > >>>> > > There are lots of comments that, along with the online help, should get you where you want to be. >>>> > > >>>> > > ;+ >>>> > > ; This procedure updates the image window display based >>>> > > ; on the current contents of the table widget, the >>>> > > ; selected cells (if any) and the current color table. >>>> > > ; >>>> > > ; @Param >>>> > > ; TLB {in}{required}{type=long} >>>> > > ; Set this parameter to the ID of the top-level base. >>>> > > ; >>>> > > ; @Hidden >>>> > > ; >>>> > > ; @Author >>>> > > ; JLP, RSI Global Services >>>> > > ; >>>> > > ; @History >>>> > > ; March 29, 2005 - Initial version >>>> > > ;- >>>> > > Pro ImageTable_62_UpdateImage, TLB >>>> > > Compile_Opt StrictArr >>>> > > On_Error, 2 >>>> > > ; >>>> > > ; Get the raw data values from the table. >>>> > > ; >>>> > > Table = Widget_Info(TLB, Find_by_UName='ValueTable') >>>> > > Widget_Control, Table, Get_Value = Values >>>> > > ; >>>> > > ; Get the color table number from the combobox. >>>> > > ; >>>> > > CTCombobox = Widget_Info(TLB, Find_by_UName = 'ColorTableCombobox') >>>> > > Current = Widget_Info(CTCombobox, /Combobox_GetText) >>>> > > Widget_Control, CTCombobox, Get_Value = AllValues >>>> > > CTIndex = (Where(AllValues eq Current))[0] >>>> > > ; >>>> > > ; Save the Direct Graphics state. >>>> > > ; >>>> > > WSave = !d.window >>>> > > Device, Get_Decomposed = WasDecomposed >>>> > > TVLCT, R, G, B, /Get >>>> > > ; >>>> > > ; Draw the table values to the image window using >>>> > > ; the current color table. >>>> > > ; >>>> > > Draw = Widget_Info(TLB, Find_by_UName = 'ImageDraw') >>>> > > Widget_Control, Draw, Get_Value = DrawID >>>> > > WSet, DrawID >>>> > > LoadCT, CTIndex, /Silent >>>> > > Device, Decomposed = 0 >>>> > > ; >>>> > > ; Remember that the table values are flipped in Y >>>> > > ; relative to our image so they orient the same way >>>> > > ; on the screen. >>>> > > ; >>>> > > TVScl, Reverse(Values, 2) >>>> > > ; >>>> > > ; Read the image buffer back from the window. >>>> > > ; >>>> > > Device, Decomposed = 1 >>>> > > Image = TVRd(True = 1) >>>> > > ; >>>> > > ; Restore the Direct Graphics state. >>>> > > ; >>>> > > Device, Decomposed = WasDecomposed >>>> > > If (WSave ne -1) then Begin >>>> > > Device, Window_State = WState >>>> > > If (WState[WSave]) then Begin >>>> > > WSet, WSave >>>> > > EndIf >>>> > > EndIf >>>> > > TVLCT, R, G, B >>>> > > ; >>>> > > ; Save the image data for the purpose of reapplying the >>>> > > ; selection box. >>>> > > ; >>>> > > Widget_Control, TLB, Set_UValue = Image >>>> > > ; >>>> > > ; Flip the image data about Y back into the orientation of the >>>> > > ; table. >>>> > > ; >>>> > > TableImage = Reverse(Temporary(Image), 3) >>>> > > ; >>>> > > ; The background color of each cell corresponds to each pixel >>>> > > ; value. We use "Update = 0" to prevent excessive flashing. >>>> > > ; >>>> > > Widget_Control, Table, $ >>>> > > Background_Color = TableImage, Update = 0 >>>> > > ; >>>> > > ; If we're "hiding" the text, this just means we draw the >>>> > > ; table values using the same color as the background. >>>> > > ; >>>> > > HideShow = Widget_Info(TLB, Find_by_UName = 'HideShowCombobox') >>>> > > If (Widget_Info(HideShow, /Combobox_GetText) eq 'Show') then Begin >>>> > > ; >>>> > > ; If we're showing table values, render the text in either black >>>> > > ; or white, depending on the better contrast with the background >>>> > > ; color in the cell. >>>> > > ; >>>> > > ImageTable_62_EnhanceText, TableImage >>>> > > EndIf >>>> > > Widget_Control, Table, $ >>>> > > Foreground_Color = TableImage, Update = 0 >>>> > > ; >>>> > > ; Update the base now with the accumulated changes. >>>> > > ; >>>> > > Widget_Control, TLB, /Update >>>> > > If (~Widget_Info(TLB, /Map)) then Begin >>>> > > Widget_Control, TLB, Map = 1 >>>> > > EndIf >>>> > > End >>>> > > >>>> > > >>>> > > ;+ >>>> > > ; This procedure converts an input array of table cell (image >>>> > > ; pixel) colors to an array of black and/or white colors to >>>> > > ; be used as the text color of each cell. The color black >>>> > > ; or white is chosen to increase contrast with the background >>>> > > ; color in each cell. >>>> > > ; >>>> > > ; @Param >>>> > > ; RGB {inout}{required}{type=BYTARR(3, N, M)} >>>> > > ; Set this parameter to the RGB colors of the pixels >>>> > > ; displayed in the image using the current color table. >>>> > > ; On output, the array will contain the color, either >>>> > > ; white or black, to be used for the foreground (text) >>>> > > ; color for the corresponding table cells. >>>> > > ; >>>> > > ; @Hidden >>>> > > ; >>>> > > ; @Author >>>> > > ; JLP, RSI Global Services >>>> > > ; >>>> > > ; @History >>>> > > ; March 29, 2005 - Initial version >>>> > > ;- >>>> > > Pro ImageTable_62_EnhanceText, RGB >>>> > > Compile_Opt StrictArr >>>> > > On_Error, 2 >>>> > > ; >>>> > > ; Convert the individual pixel colors from RGB space to >>>> > > ; hue, lightness and saturation space. >>>> > > ; >>>> > > Color_Convert, Reform(RGB[0, *, *]), Reform(RGB[1, *, *]), $ >>>> > > Reform(RGB[2, *, *]), H, L, S, /RGB_HLS >>>> > > ; >>>> > > ; We say that a pixel is "dark" if its lightness is less >>>> > > ; than 50%. >>>> > > ; >>>> > > Dark = Where(L lt .50, NDark) >>>> > > ; >>>> > > ; Light pixels will use black text. This is out initial >>>> > > ; default. >>>> > > ; >>>> > > RGB[*] = 0b >>>> > > ImageSize = Size(RGB, /Dimensions) >>>> > > If (NDark ne 0) then Begin >>>> > > ; >>>> > > ; Dark pixels will have white text. We use reform here >>>> > > ; to aid in addressing our 2-D image space with the 1-dimensional >>>> > > ; vectors returned by Color_Convert. We use Overwrite so >>>> > > ; we don't make extra copies of the data. >>>> > > ; >>>> > > RGB = Reform(RGB, 3, N_elements(RGB)/3, /Overwrite) >>>> > > RGB[*, Dark] = 255b >>>> > > RGB = Reform(RGB, 3, ImageSize[1], ImageSize[2], /Overwrite) >>>> > > EndIf >>>> > > End >>>> > > >>>> > > >>>> > > ;+ >>>> > > ; This procedure manages all events from the application's >>>> > > ; widgets. >>>> > > ; >>>> > > ; @Param >>>> > > ; Event {in}{required}{type=widget event structure} >>>> > > ; Set this parameter to the event structure to be >>>> > > ; acted upon. >>>> > > ; >>>> > > ; @Hidden >>>> > > ; >>>> > > ; @Author >>>> > > ; JLP, RSI Global Services >>>> > > ; >>>> > > ; @History >>>> > > ; March 29, 2005 - Initial version >>>> > > ;- >>>> > > Pro ImageTable_62_Event, Event >>>> > > Compile_Opt StrictArr >>>> > > On_Error, 2 >>>> > > ; >>>> > > ; What type of event is it? >>>> > > ; >>>> > > EventType = Tag_Names(Event, /Structure_Name) >>>> > > If (EventType eq 'WIDGET_BASE') then Begin >>>> > > ; >>>> > > ; This is a base resize event. We adjust the size of the >>>> > > ; table accordingly (and leave all the other widgets alone.) >>>> > > ; >>>> > > TLBGeom = Widget_Info(Event.Top, /Geometry) >>>> > > ; >>>> > > ; The base on the left hand side containing the image, comboboxes >>>> > > ; and spinner, remains fixed in size. >>>> > > ; >>>> > > Left = Widget_Info(Event.Top, Find_by_UName = 'LeftBase') >>>> > > LeftGeom = Widget_Info(Left, /Geometry) >>>> > > ; >>>> > > ; The table widget occupies "everything else". >>>> > > ; >>>> > > NewX = Event.X - 2*TLBGeom.XPad - LeftGeom.Scr_XSize > 10 >>>> > > NewY = Event.Y - 2*TLBGeom.YPad > 10 >>>> > > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > > ; >>>> > > ; Update the table size and return. >>>> > > ; >>>> > > Widget_Control, Table, Scr_XSize = NewX, Scr_YSize = NewY >>>> > > Return >>>> > > EndIf >>>> > > ; >>>> > > ; All other events are managed according to the UVALUE of the >>>> > > ; widget that produced the event. >>>> > > ; >>>> > > Widget_Control, Event.ID, Get_UValue = BranchCode >>>> > > Case BranchCode of >>>> > > 'ValueVisibility' : Begin >>>> > > ; >>>> > > ; Hide or show the values in the table. >>>> > > ; >>>> > > Widget_Control, Event.Top, Get_UValue = Image >>>> > > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > > Case Widget_Info(Event.ID, /Combobox_GetText) of >>>> > > 'Show' : Begin >>>> > > ; >>>> > > ; If we're showing the text in the table, make sure the text color >>>> > > ; contrasts well with the cell color. >>>> > > ; >>>> > > ImageTable_62_EnhanceText, Image >>>> > > ; >>>> > > ; Remember that the table values are "upside down" in Y to >>>> > > ; correspond to our image orientation, so we need to flip >>>> > > ; the data. >>>> > > ; >>>> > > Widget_Control, Table, $ >>>> > > Foreground_Color = Reverse(Temporary(Image), 3) >>>> > > End >>>> > > 'Hide' : Begin >>>> > > ; >>>> > > ; If we're hiding the text in the table, then we set the text >>>> > > ; color to be the same as the image color at that pixel. Again, >>>> > > ; we need to flip the data to match the image orientation. >>>> > > ; >>>> > > Widget_Control, Table, $ >>>> > > Foreground_Color = Reverse(Temporary(Image), 3) >>>> > > End >>>> > > EndCase >>>> > > End >>>> > > 'ColorTable' : Begin >>>> > > ; >>>> > > ; A change in color table means we must update the image as well >>>> > > ; as the cell colors in the table. >>>> > > ; >>>> > > ImageTable_62_UpdateImage, Event.Top >>>> > > End >>>> > > 'Table' : Begin >>>> > > EventType = Tag_Names(Event, /Structure_Name) >>>> > > If (EventType eq 'WIDGET_CONTEXT') then Begin >>>> > > ; >>>> > > ; If we have a right click, this is a context menu event >>>> > > ; request, so show it at the position of the clicked cell. >>>> > > ; (Note that we have previously received at least one and >>>> > > ; maybe two WIDGET_TABLE_CELL_SEL events as a result of >>>> > > ; the right-click selection, if the table was editable.) >>>> > > ; >>>> > > ContextMenu = Widget_Info(Event.ID, $ >>>> > > Find_by_UName = 'TableContextMenu') >>>> > > Widget_DisplayContextMenu, Event.ID, $ >>>> > > Event.X, Event.Y, ContextMenu >>>> > > Return >>>> > > EndIf >>>> > > ; >>>> > > ; The user has selected cells in the table. First, >>>> > > ; update the image window. >>>> > > ; >>>> > > Widget_Control, Event.Top, Get_UValue = Image >>>> > > Draw = Widget_Info(Event.Top, Find_by_UName = 'ImageDraw') >>>> > > Widget_Control, Draw, Get_Value = DrawID >>>> > > ; >>>> > > ; Save the Direct Graphics environment. >>>> > > ; >>>> > > WSave = !d.window >>>> > > Device, Get_Decomposed = WasDecomposed >>>> > > ; >>>> > > ; Display the image to the draw widget. This will erase any >>>> > > ; previously overplotted line. A cleverer solution might use >>>> > > ; a pixmap instead. >>>> > > ; >>>> > > WSet, DrawID >>>> > > Device, Decomposed = 1 >>>> > > TV, Image, True = 1 >>>> > > ; >>>> > > ; Overplot the bounds of the region selected in the table >>>> > > ; if it's more than 1 cell. >>>> > > ; >>>> > > Selected = Widget_Info(Event.ID, /Table_Select) >>>> > > MinX = Min(Selected[0, *], Max = MaxX) >>>> > > MinY = Min(Selected[1, *], Max = MaxY) >>>> > > dX = MaxX - MinX + 1 >>>> > > dY = MaxY - MinY + 1 >>>> > > If ((dX gt 0) && (dY gt 0)) then Begin >>>> > > ; >>>> > > ; We're going to plot the bounding box in the image in green. >>>> > > ; We need to remember that the cell numbers in the table >>>> > > ; are flipped top to bottom with respect to the image. >>>> > > ; >>>> > > PlotS, MinX + [0, 1, 1, 0, 0]*dX, $ >>>> > > (Size(Image, /Dimensions))[2] - 1 - $ >>>> > > (MinY + [0, 0, 1, 1, 0]*dY), $ >>>> > > /Device, Color = '00ff00'x >>>> > > EndIf >>>> > > ; >>>> > > ; Restore the Direct Graphics environment. >>>> > > ; >>>> > > If (WSave ne -1) then Begin >>>> > > Device, Window_State = WState >>>> > > If (WState[WSave]) then Begin >>>> > > WSet, WSave >>>> > > EndIf >>>> > > EndIf >>>> > > Device, Decomposed = WasDecomposed >>>> > > End >>>> > > 'PixelSize' : Begin >>>> > > ; >>>> > > ; Change the number of pixels square each cell in the table >>>> > > ; should occupy according to the value in the spinner. This number >>>> > > ; actually includes the dividers between cells. >>>> > > ; >>>> > > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > > ; >>>> > > ; There are no bounds on the spinner, so we need to manually clamp >>>> > > ; it to a reasonable range. >>>> > > ; >>>> > > Value = Long(Event.Value) >>>> > > Value >= 2 >>>> > > Value <= 256 >>>> > > ; >>>> > > ; In case we needed to clamp the value, update the spinner with >>>> > > ; the current value. >>>> > > ; >>>> > > Widget_Control, Event.ID, Set_Value = Value, Update = 0 >>>> > > ; >>>> > > ; Adjust the cell dimensions in the table, then update >>>> > > ; everything on the interface at one time. >>>> > > ; >>>> > > Widget_Control, Table, Row_Heights = Value, $ >>>> > > Column_Widths = Value, Update = 0 >>>> > > Widget_Control, Event.Top, /Update >>>> > > End >>>> > > 'Context_SelectedStatistics' : Begin >>>> > > ; >>>> > > ; This is an event from the table's context menu. >>>> > > ; Calculate statistics on the selected cells. >>>> > > ; >>>> > > ParentContextBase = Widget_Info(Event.ID, /Parent) >>>> > > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > > Selected = Widget_Info(Table, /Table_Select) >>>> > > Widget_Control, Table, Get_Value = TableValues >>>> > > If (N_elements(Selected)/2 gt 1) then Begin >>>> > > TableSize = Size(TableValues, /Dimensions) >>>> > > Selected = Reform(Selected[0, *] + Selected[1, *]*TableSize[0]) >>>> > > Stats = Moment(TableValues[Selected], MDev = MDev, SDev = SDev) >>>> > > MinValue = Min(TableValues[Selected], Max = MaxValue) >>>> > > Stats = StrTrim([MinValue, MaxValue, Stats, MDev, SDev], 2) >>>> > > StatsLabels = ['Minimum', 'Maximum', 'Mean', 'Variance', 'Skewness', $ >>>> > > 'Kurtosis', 'Mean Absolute Deviation', $ >>>> > > 'Standard Deviation'] >>>> > > StatsLabel = StatsLabels + ' : ' + Stats >>>> > > EndIf Else Begin >>>> > > StatsLabel = 'Pixel value = ' + $ >>>> > > StrTrim(TableValues[Selected[0, 0], Selected[1, 0]], 2) >>>> > > EndElse >>>> > > v = Dialog_Message(StatsLabel, /Information, $ >>>> > > Dialog_Parent = Event.Top, $ >>>> > > Title = 'ImageTable 6.2 ROI Statistics') >>>> > > End >>>> > > 'Context_SelectedArea' : Begin >>>> > > ; >>>> > > ; This is an event from the table's context menu. >>>> > > ; Calculate the area of the selected cells >>>> > > ; >>>> > > ParentContextBase = Widget_Info(Event.ID, /Parent) >>>> > > Table = Widget_Info(Event.Top, Find_by_UName = 'ValueTable') >>>> > > Selected = Widget_Info(Table, /Table_Select) >>>> > > NPixels = Long(N_elements(Selected)/2) >>>> > > AreaLabel = 'Area = ' + $ >>>> > > StrTrim(NPixels, 2) + $ >>>> > > ' pixel' + (NPixels gt 1 ? 's' : '') >>>> > > v = Dialog_Message(AreaLabel, /Information, $ >>>> > > Dialog_Parent = Event.Top, $ >>>> > > Title = 'ImageTable 6.2 ROI Area') >>>> > > End >>>> > > Else : >>>> > > EndCase >>>> > > End >>>> > > >>>> > > >>>> > > ;+ >>>> > > ; This procedure creates a table widget whose cell values are >>>> > > ; displayed in colors according to a color look-up table, >>>> > > ; much like an image. >>>> > > ; >>>> > > ; @Param >>>> > > ; Val {in}{optional}{type=integer array dimensions n by m} >>>> > > ; Set this parameter to a 2-dimensional array of integral >>>> > > ; values between the values of -99 and 999. (This limitation >>>> > > ; is related to the format statement used to display the >>>> > > ; cell values; feel free to modify the code according to >>>> > > ; your data's needs.) The default value is a 64-by-64 shifted >>>> > > ; DIST image. >>>> > > ; >>>> > > ; @Examples >>>> > > ; IDL> ImageTable_62 >>>> > > ; >>>> > > ; @Categories >>>> > > ; Widget_Table, 6.2 >>>> > > ; >>>> > > ; @Author >>>> > > ; Jim Pendleton & MG, RSI Global Services >>>> > > ; >>>> > > ; @History >>>> > > ; March 31, 2005 - Initial version >>>> > > ; >>>> > > ; @File_Comments >>>> > > ; This procedure highlights some new features of WIDGET_TABLE >>>> > > ; in IDL 6.2, in particular the ability to set foreground >>>> > > ; and background colors in individual cells, and to display >>>> > > ; a context menu within a table. >>>> > > ; >>>> > > ;- >>>> > > Pro ImageTable_62, Val >>>> > > Compile_Opt StrictArr >>>> > > On_Error, 2 >>>> > > ; >>>> > > ; Create a copy of the input data or create the default "bulls-eye" >>>> > > ; image. >>>> > > ; >>>> > > iVal = N_Elements(Val) eq 0 ? Fix(Shift(Dist(512), 256, 256)) : Val >>>> > > ImageSize = Size(iVal, /Dimensions) >>>> > > ; >>>> > > ; Create our widget tree. We'll have some controls on the left >>>> > > ; and a table widget on the right. >>>> > > ; >>>> > > TLB = Widget_Base(/Row, /TLB_Size_Events, UName = 'Top', $ >>>> > > Title = 'ImageTable 6.2') >>>> > > Left = Widget_Base(TLB, /Column, UName = 'LeftBase') >>>> > > D = Widget_Draw(Left, XSize = ImageSize[0], YSize = ImageSize[1], $ >>>> > > UName = 'ImageDraw') >>>> > > ; >>>> > > ; By default, we use the "Hardcandy" color table. It shows good >>>> > > ; contrast in the upper corner that is initiall displayed in the >>>> > > ; table. >>>> > > ; >>>> > > CTBase = Widget_Base(Left, /Row, /Align_Left) >>>> > > CTLabel = Widget_Label(CTBase, Value = 'Color Table : ') >>>> > > LoadCT, /Silent, Get_Names = CTNames >>>> > > ColorTable = 28 >>>> > > CTCombobox = Widget_Combobox(CTBase, Value = CTNames,$ >>>> > > UName = 'ColorTableCombobox', UValue = 'ColorTable') >>>> > > Widget_Control, CTCombobox, Set_Combobox_Select = ColorTable >>>> > > VisibilityBase = Widget_Base(Left, /Row, /Align_Left) >>>> > > VisibilityLabel = Widget_Label(VisibilityBase, $ >>>> > > Value = 'Table Values : ') >>>> > > VisibilityCombobox = Widget_Combobox(VisibilityBase, $ >>>> > > Value = ['Show', 'Hide'], $ >>>> > > UValue = 'ValueVisibility', $ >>>> > > UName = 'HideShowCombobox') >>>> > > ; >>>> > > ; We'll initially display each cell as an 18x18 square. The >>>> > > ; spinner will allow the user to adjust this. See the >>>> > > ; idl62/lib/itools/ui_widgets directory for the source to >>>> > > ; cw_itupdownfield.pro, an undocumented, but highly useful >>>> > > ; compound widget. >>>> > > ; >>>> > > PixelSize = 18 >>>> > > Spinner = CW_itUpDownField(Left, Increment = 1, $ >>>> > > Label = 'Pixel Size : ', $ >>>> > > Value = pixelsize, $ >>>> > > UName = 'PixelSizeSpinner', $ >>>> > > UValue = 'PixelSize') >>>> > > ; >>>> > > ; Create a table with our data values. The default orientation >>>> > > ; places the cell [0, 0] at the upper left. But we want it >>>> > > ; to be oriented the same as our image, with [0, 0] in the >>>> > > ; lower left.. So we need to flip the data in Y. >>>> > > ; >>>> > > Table = Widget_Table(TLB, Value = Reverse(IVal, 2), $ >>>> > > X_Scroll = 25,$ >>>> > > Y_Scroll = 25, $ >>>> > > Row_Heights = PixelSize, Column_Widths = PixelSize, $ >>>> > > Format = '(i3)', $ >>>> > > UName = 'ValueTable', $ >>>> > > UValue = 'Table', $ >>>> > > ; >>>> > > ; We choose a font appropriate to Windows or Linux. We want it >>>> > > ; to be small so our cell sizes can be small, too. >>>> > > ; >>>> > > Font = !version.os_family eq 'Windows' ? $ >>>> > > 'Helvetica*8' : 'timr08', $ >>>> > > Alignment = 1, $ >>>> > > ; >>>> > > ; Label the rows to show that we flipped the image in Y. >>>> > > ; Row 0 is at the bottom. >>>> > > ; >>>> > > Row_Labels = StrTrim(Reverse(Lindgen(ImageSize[1])), 2), $ >>>> > > /All_Events, $ >>>> > > ; >>>> > > ; Also capture context menu events (i.e., right-clicks.) >>>> > > ; >>>> > > /Context_Events, $ >>>> > > /Disjoint) >>>> > > ; >>>> > > ; Create a context menu for the table. >>>> > > ; >>>> > > ContextBase = Widget_Base(Table, /Context_Menu, $ >>>> > > UName = 'TableContextMenu') >>>> > > ContextStatisticsButton = Widget_Button(ContextBase, $ >>>> > > Value = 'Show Selected Statistics', $ >>>> > > UValue = 'Context_SelectedStatistics') >>>> > > ContextStatisticsArea = Widget_Button(ContextBase, $ >>>> > > Value = 'Show Selected Area', $ >>>> > > UValue = 'Context_SelectedArea') >>>> > > ; >>>> > > ; We initially hide the TLB until after we update the colors >>>> > > ; in the table the first time. >>>> > > ; >>>> > > Widget_Control, TLB, Map = 0 >>>> > > Geom = Widget_Info(TLB, /Geometry) >>>> > > ScreenSize = Get_Screen_Size() >>>> > > Widget_Control, TLB, $ >>>> > > TLB_Set_XOffset = (ScreenSize[0] - Geom.Scr_XSize)/2., $ >>>> > > TLB_Set_YOffset = (ScreenSize[1] - Geom.Scr_YSize)/2. >>>> > > Widget_Control, TLB, /Realize >>>> > > ; >>>> > > ; Update the colors in the cells and start the event handler. >>>> > > ; >>>> > > ImageTable_62_UpdateImage, TLB >>>> > > XManager, 'ImageTable_62', TLB, /No_Block >>>> > > End >>>> > >>>> > >>>> > Dear Jim, >>>> > >>>> > >>>> > Thank you very much for providing the code. If I finally use parts of the code for my research work, I will credit your name and Dr. Mike Galloy's. But before I implement it for my example, I have a question. If I have to set the color of each cell, do you think it is practical as I have more than 30 dataset scenarios. If there is an option of setting the cell colours automatically then there would be consistency of colour usage across all the 30 scenarios. By the way, I don't see any image on the left and neither do I see is a tabular form of the image on the right? >>>> > >>>> > -James >>>> >>>> Dear Jim, >>>> >>>> I understood your last comments only after compiling and running the code in IDL. I can see what you mean now, with both the image and the table of values. >>>> The comments are also quite helpful. But I am stuggling to find out where to exactly insert my table of data values. If I want to save my datasets as an ASCII file or a text file and use the data values as input for running the code, can I do that somewhere in the code? In the first few lines of the code where the comment says, ;Get the raw data values from the table ; Which Table is this and how can I replace this table with my own data table from a text file or ASCII file? I think I will have to provide the path of the text file that I create with my dataset scenarios? >>>> >>>> -james >>> >>> James, >>> I'm glad to see you're working through this... The next step would be to notice that the main routine takes as input an option argument, which is a 2-dimensional array of your own making. If you don't provide one, it creates the default 512x512 image. >>> >>> If your data set is small you could enter the values manually. >>> >>> IDL> imagetable_62, [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]] >>> >>> If it's larger than you'd like to enter manually, you might consider the function READ_ASCII for importing your data from file into an array. Or you could use slightly lower level routines OPENR, READF, and FREE_LUN. >>> >>> There are examples for each of these online, for example >>> >>> http://www.exelisvis.com/docs/READ.html >>> >>> Jim P. >> >> >> Dear Jim, >> >> I did it finally :)I did not find any option to paste an image here, otherwise I would have shown what the output looks like. This is a brilliant code. I am grateful to the creators. Don't know how else to thank you other than crediting your name. It would have taken me months if not years to create this on my own from scratch. How long have you been working with IDL Programming? Just want to get an idea of the time it will take for me to get there. The code is working just fine with my manual addition of data values. I have to still figure it out how to do it via the ASCII file way through the examples. I have more than 30 such scenarios to create and I don't mind taking a screen capture each time and manually adding the x and y axis tick labels and the axis labels with legend, but just to make the task quicker, do you think there is way to add the labels directly during the execution of the code? So that I make only some manual edits after the screen capture? >> >> Once again, I am grateful for your help. >> >> -James > > No need to "credit" me. I wrote this code 11 years ago as a simple demo of a new feature that had come out with IDL 6.2. We're up to 8.5.1, now of course. At the time I'd only been solving science and engineering problems with IDL for about 20 years. However, the table widget cell coloring feature had been available for just a couple weeks, so I wasn't really ahead of the pack in that sense. > > I wrote an IDL Data Point blog post a few weeks ago on the topic of screen capturing IDL GUIs programmatically which may be of use to you eventually, if you want to turn your manual process into a reusable utility. http://www.exelisvis.com/Company/PressRoom/Blogs/BlogAuthorJ Pen/TabId/1342/PID/4876/authorid/289/AuthorName/JimPendleton /Default.aspx > > You might consider a scenario where you capture the table into an image file, call the image() function to read it back in as a bitmap, then apply text() annotations. > > As with most things, there's no single right way to accomplish your task. > > Jim P. Dear Jim, Thanks for your reply. I will look at the text() annotations and the image() functions. I have another question. How do I create the color bar for the legend? Is there any way? I feel if I crop a part of the entire image, it might somehow work as a color bar but do you have a better idea. I mean, if I can get the color bar representing each color table option, it would have been better rather than manually cropping. Exelis has got the right person for the job. All the best with your work. I will go through your blog in due time. -James