{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Interactive Tables and their API\n",
"\n",
"The table UI allows column drag/drop, hide, sorting, formatting, searching, selecting/export as CSV. This makes it easy to paste into a spreadsheet like Excel.\n",
"\n",
"There is a menu in the top-left for the whole table, and each column has a menu that appears on hover.\n",
"\n",
"There are also keyboard commands: digits change the precision of all columns, shift-digit changes the precision of the current column. Arrow keys navigate, and the page up/down keys work too."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"new TableDisplay( new CSV().read(\"../resources/data/interest-rates.csv\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Formatting and Alignment"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import com.twosigma.beakerx.table.*\n",
"import com.twosigma.beakerx.table.format.TableDisplayStringFormat\n",
"\n",
"display = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n",
"//show all time columns in days\n",
"display.setStringFormatForTimes(TimeUnit.DAYS)\n",
"//min 4, max 6 decimal places for all doubles\n",
"display.setStringFormatForType(ColumnType.Double, TableDisplayStringFormat.getDecimalFormat(4,6))\n",
"//setting for a column takes precidence over the type\n",
"display.setStringFormatForColumn(\"m3\", TableDisplayStringFormat.getDecimalFormat(0, 0))\n",
"//set the alignment\n",
"display.setAlignmentProviderForType(ColumnType.Double, TableDisplayAlignmentProvider.RIGHT_ALIGNMENT)\n",
"display.setAlignmentProviderForColumn('m3', TableDisplayAlignmentProvider.CENTER_ALIGNMENT)\n",
"\n",
"//using a closure\n",
"display.setStringFormatForColumn(\"y3\") { value, row, col, tableDisplay ->\n",
" if(value < 8) {\n",
" \":(\"\n",
" } else {\n",
" \":)\"\n",
" } \n",
"}\n",
"\n",
"display"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This changes the format of the table above in the previous output cell. It's updated because the object is synchronized between the kernel and the client."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"display.setStringFormatForTimes(TimeUnit.HOURS)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Bar Charts Renderer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import com.twosigma.beakerx.table.*\n",
"import com.twosigma.beakerx.table.renderer.TableDisplayCellRenderer\n",
"\n",
"def display2 = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n",
"//right now, the only renderer option is for data bars\n",
"display2.setRendererForType(ColumnType.Double, TableDisplayCellRenderer.getDataBarsRenderer())\n",
"//use the false parameter to hide the String value\n",
"display2.setRendererForColumn(\"y10\", TableDisplayCellRenderer.getDataBarsRenderer(false))\n",
"display2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Column Visibility and Placement"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import com.twosigma.beakerx.table.*\n",
"import com.twosigma.beakerx.fileloader.CSV\n",
"import com.twosigma.beakerx.table.format.TableDisplayStringFormat\n",
"\n",
"def display3 = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n",
"display3.setStringFormatForType(ColumnType.Double, TableDisplayStringFormat.getDecimalFormat(9,9))\n",
"//freeze a column\n",
"display3.setColumnFrozen(\"y1\", true)\n",
"//hide a column\n",
"display3.setColumnVisible(\"y30\", false)\n",
"\n",
"//explicitly set column order/visiblity\n",
"display3.setColumnOrder([\"m3\", \"y1\", \"y5\", \"time\", \"y2\"]) //Columns in the list will be shown in the provided order. Columns not in the list will be hidden.\n",
"display3"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Heatmaps"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import com.twosigma.beakerx.table.*\n",
"import com.twosigma.beakerx.table.highlight.TableDisplayCellHighlighter\n",
"\n",
"def display4 = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n",
"display4.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"m3\", TableDisplayCellHighlighter.FULL_ROW))\n",
"\n",
"//the following two overloads should also be supported\n",
"//set the min and max used for calculating the color\n",
"//display4.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"y1\", TableDisplayCellHighlighter.FULL_ROW, 0, 5))\n",
"//set the colors used for the min and max\n",
"//display4.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"m6\", TableDisplayCellHighlighter.SINGLE_COLUMN, null, null, Color.YELLOW, Color.BLUE))\n",
"\n",
"display4"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Cell Background Color"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def map = [\n",
" [a:1, b:2, c:3],\n",
" [a:4, b:5, c:6],\n",
" [a:7, b:8, c:5]\n",
"]\n",
"def display5 = new TableDisplay(map)\n",
"display5.addCellHighlighter { row, column, tableDisplay ->\n",
" if (column == 2) {\n",
" display5.values[row][column] < 5 ? Color.RED : Color.GREEN\n",
" }\n",
"}\n",
"display5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Heatmaps per Column"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import com.twosigma.beakerx.table.*\n",
"import com.twosigma.beakerx.table.highlight.*\n",
"\n",
"display6 = new TableDisplay(new CSV().read(\"../resources/data/interest-rates.csv\"))\n",
"display6.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"m3\", 0, 8, Color.ORANGE, Color.PINK))\n",
"display6.addCellHighlighter(TableDisplayCellHighlighter.getHeatmapHighlighter(\"m6\", TableDisplayCellHighlighter.SINGLE_COLUMN, 6, 8, Color.BLACK, Color.PINK))\n",
"\n",
"display6.addCellHighlighter(new ThreeColorHeatmapHighlighter(\"y1\", TableDisplayCellHighlighter.SINGLE_COLUMN, 4, 6, 8, new Color(247,106,106), new Color(239,218,82), new Color(100,189,122)))\n",
"\n",
"display6"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"display6.removeAllCellHighlighters()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Color Unique Entries"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import com.twosigma.beakerx.table.highlight.*\n",
"\n",
"def table = new TableDisplay([[1,2,3], \n",
" [3,4,5], \n",
" [6,2,8], \n",
" [6,2,8], \n",
" [6,2,8], \n",
" [6,4,8], \n",
" [6,2,8], \n",
" [6,2,8], \n",
" [6,5,8]], \n",
" ['a', 'b', 'c'], \n",
" ['double', 'double', 'double'])\n",
"table.addCellHighlighter(TableDisplayCellHighlighter.getUniqueEntriesHighlighter(\"b\", TableDisplayCellHighlighter.FULL_ROW))\n",
"table"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Font Size, Color, and Vertical Headers"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def mapList5 = [\n",
" [firstCol:1, secondCol:2, thirdCol:3],\n",
" [firstCol:4, secondCol:5, thirdCol:6],\n",
" [firstCol:9, secondCol:8, thirdCol:9]\n",
"]\n",
"def td4 = new TableDisplay(mapList5)\n",
"\n",
"//tool tip can be set with a closure\n",
"td4.setToolTip { row, col, display ->\n",
" \"The value is: \" + display.values[row][col]\n",
"}\n",
"td4\n",
"\n",
"//set the font size and color\n",
"td4.dataFontSize = 35\n",
"td4.headerFontSize = 30\n",
"\n",
"def colors = [[Color.LIGHT_GRAY, Color.GRAY, Color.RED],\n",
" [Color.DARK_GREEN, Color.ORANGE, Color.RED],\n",
" [Color.MAGENTA, Color.BLUE, Color.BLACK]]\n",
"\n",
"td4.setFontColorProvider { row, col, td ->\n",
" colors[row][col]\n",
"}\n",
"\n",
"//try different filter options\n",
"td4.setRowFilter { row, model ->\n",
" //model[row][1] == 8\n",
" true\n",
" //false\n",
" //model[row][0] == model[row][2]\n",
"}\n",
"\n",
"//set vertical headers\n",
"//you can also do this in the right-click menu\n",
"td4.setHeadersVertical(true)\n",
"\n",
"td4"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Programmable Actions\n",
"\n",
"Bind a closure or running a cell to the context menu or double click action on the table."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"abc = 0; // test variable\n",
"mapList = [\n",
" [a:1, b:2, c:3],\n",
" [a:4, b:5, c:6],\n",
" [a:7, b:8, c:5]\n",
"]\n",
"OutputCell.HIDDEN"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def display1 = new TableDisplay(mapList)\n",
"//set what happens on a double click\n",
"display1.setDoubleClickAction { row, col, tableDisplay ->\n",
" tableDisplay.values[row][col] = tableDisplay.values[row].sum()\n",
"}\n",
"\n",
"//add a context menu item\n",
"display1.addContextMenuItem(\"negate\") { row, col, tableDisplay ->\n",
" tableDisplay.values[row][col] = -tableDisplay.values[row][col]\n",
"}\n",
"\n",
"display1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def display2 = new TableDisplay(mapList)\n",
"\n",
"//run tagged cell on action\n",
"display2.addContextMenuItem(\"run print cell\", \"print_cell\");\n",
"display2.setDoubleClickAction(\"print_cell\");\n",
"\n",
"display2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"print_cell"
]
},
"outputs": [],
"source": [
"abc++\n",
"println abc"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"display4 = new TableDisplay(mapList)\n",
"\n",
"//run tagged cell on action\n",
"display4.addContextMenuItem(\"run tagged_cell cell\", \"tagged_cell\");\n",
"display4.setDoubleClickAction(\"tagged_cell\");\n",
"\n",
"display4"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"tagged_cell"
]
},
"outputs": [],
"source": [
"def details = display4.details\n",
"\n",
"if(details != null){\n",
" switch(details.actionType){\n",
" case 'DOUBLE_CLICK':\n",
" print (\"You clicked on the cell [\" + details.row + \", \" + details.col + \"]\")\n",
" break;\n",
" case 'CONTEXT_MENU_CLICK':\n",
" print (\"You selected context menu '\" + details.contextMenuItem + \"' on the cell [\" + details.row + \", \" + details.col + \"]\")\n",
" break;\n",
" }\n",
"}else{\n",
" println \"no table tag action performed.\"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## HTML format\n",
"\n",
"HTML format allows markup and styling of the cell's content. Interactive JavaScript and images are not supported however. See below for image support."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tbl = new TableDisplay([x: 'italic red',\n",
" y: 'bold blue',\n",
" z: 'multiline strings
work fine too']);\n",
"tbl.setStringFormatForColumn(\"Value\", TableDisplayStringFormat.getHTMLFormat())\n",
"tbl"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Image format\n",
"\n",
"Image format allows loading any image supported by the web browser, including PNG, JPG, and SVG formats. It can be a relative URL served from the same directories as the notebook itself, an absolute URL to anywhere on the web, or a data URL with encoded data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tbl = new TableDisplay(['Peacock': '../resources/img/butterfly1.jpg',\n",
" 'Morpho': '../resources/img/butterfly2.jpg',\n",
" 'Swallowtail': '../resources/img/butterfly3.jpg']);\n",
"tbl.setStringFormatForColumn(\"Value\", TableDisplayStringFormat.getImageFormat())\n",
"tbl"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tbl = new TableDisplay(['https://en.wikipedia.org/wiki/IPython': 'http://jupyter.org/assets/nav_logo.svg',\n",
" 'https://en.wikipedia.org/wiki/Two_Sigma': 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/2_sigma_logo.png/150px-2_sigma_logo.png']);\n",
"tbl.setStringFormatForColumn(\"Value\", TableDisplayStringFormat.getImageFormat())\n",
"tbl"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tbl = new TableDisplay(['up': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgaGVpZ2h0PSI2NCIgd2lkdGg9IjY0IiB2aWV3Qm94PSIwIDAgNjQgNjQiPg0KICA8cG9seWdvbiBmaWxsPSIjNmJhMmM3IiBwb2ludHM9IjMwLDQgNCw2MCA2MCw2MCI+PC9wb2x5Z29uPg0KPC9zdmc+DQo=',\n",
" 'down': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIGhlaWdodD0iNjQiIHdpZHRoPSI2NCIgdmlld0JveD0iMCAwIDY0IDY0Ij4KICA8cG9seWdvbiBmaWxsPSIjNmJhMmM3IiBwb2ludHM9IjMwLDYwIDYwLDQgNCw0Ij48L3BvbHlnb24+Cjwvc3ZnPgo=']);\n",
"tbl.setStringFormatForColumn(\"Value\", TableDisplayStringFormat.getImageFormat())\n",
"tbl"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Auto linking of URLs\n",
"\n",
"The normal string format automatically detects URLs and links them. An underline appears when the mouse hovers over such a string, and when you click it opens in a new window."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"new TableDisplay(['Two Sigma': 'http://twosigma.com', 'BeakerX': 'surrounding text http://BeakerX.com works fine'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Seamless Update"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def mapListToUpdate = [\n",
" [a:1, b:2, c:3],\n",
" [a:4, b:5, c:6],\n",
" [a:7, b:8, c:9]\n",
"]\n",
"tableToUpdate = new TableDisplay(mapListToUpdate)\n",
"\n",
"tableToUpdate"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tableToUpdate.values[0][0] = 99\n",
"tableToUpdate.sendModel()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tableToUpdate.updateCell(2,\"c\",121)\n",
"tableToUpdate.sendModel()"
]
}
],
"metadata": {
"anaconda-cloud": {},
"beakerx_kernel_parameters": {},
"celltoolbar": "Tags",
"kernelspec": {
"display_name": "Groovy",
"language": "groovy",
"name": "groovy"
},
"language_info": {
"codemirror_mode": "groovy",
"file_extension": ".groovy",
"mimetype": "",
"name": "Groovy",
"nbconverter_exporter": "",
"version": "2.4.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": false,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
},
"widgets": {
"state": {
"f7d30807-6d2d-414d-b604-fcb0ed748612": {
"views": [
{
"cell_index": 0
},
{
"cell_index": 1
}
]
}
},
"version": "1.2.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}