  
  [1X7 [33X[0;0YFunction reference[133X[101X
  
  
  [1X7.1 [33X[0;0YHigh-Level Public API[133X[101X
  
  [1X7.1-1 Plot[101X
  
  [33X[1;0Y[29X[2XPlot[102X( [3Xvarious[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Yone of two things, documented below[133X
  
  [33X[0;0YIf  evaluated  in  a  Jupyter  Notebook,  the  result of this function, when
  rendered by that notebook, will run JavaScript code that generates and shows
  a  plot  in  the  output  cell, which could be any of a wide variety of data
  visualizations,  including  bar  charts,  pie charts, scatterplots, etc. (To
  draw a vertex-and-edge graph, see [2XPlotGraph[102X ([14X7.1-3[114X) instead.)[133X
  
  [33X[0;0YIf  evaluated  outside of a Jupyter Notebook, the result of this function is
  the  name  of  a temporary file stored on disk in which HTML code for such a
  visualization  has  been  written,  and on which [5XGAP[105X has already invoked the
  user's  default web browser. The user should see the visualization appear in
  the browser immediately before the return value is shown.[133X
  
  [33X[0;0YThis  function can take data in a wide variety of input formats. Here is the
  current list of acceptable formats:[133X
  
  [30X    [33X[0;6YIf  [10XX[110X is a list of [23Xx[123X values and [10XY[110X is a list of [23Xy[123X values then [10XPlot(X,Y)[110X
        plots them as ordered pairs.[133X
  
  [30X    [33X[0;6YIf [10XX[110X is a list of [23Xx[123X values and [10Xf[110X is a [5XGAP[105X function that can be applied
        to  each  [23Xx[123X  to yield a corresponding [23Xy[123X, then [10XPlot(X,f)[110X computes those
        corresponding [23Xy[123X values and plots everything as ordered pairs.[133X
  
  [30X    [33X[0;6YIf [10XP[110X is a list of [23X(x,y)[123X pairs then [10XPlot(P)[110X plots those ordered pairs.[133X
  
  [30X    [33X[0;6YIf  [10XY[110X  is  a list of [23Xy[123X values then [10XPlot(Y)[110X assumes the corresponding [23Xx[123X
        values are 1, 2, 3, and so on up to the length of [10XY[110X. It then plots the
        corresponding set of ordered pairs.[133X
  
  [30X    [33X[0;6YIf  [10Xf[110X  is  a [5XGAP[105X function then [10XPlot(f)[110X assumes that [10Xf[110X requiers integer
        inputs  and  evaluates  it on a small domain (1 through 5) of [23Xx[123X values
        and plots the resulting [23X(x,y)[123X pairs.[133X
  
  [30X    [33X[0;6YIn any of the cases above, a new, last argument may be added that is a
        [5XGAP[105X  record  (call  it [10XR[110X) containing options for how to draw the plot,
        including the plot type, title, axes options, and more. Thus the forms
        [10XPlot(X,Y,R)[110X,  [10XPlot(X,f,R)[110X, [10XPlot(P,R)[110X, [10XPlot(Y,R)[110X, and [10XPlot(f,R)[110X are all
        acceptable. (For details, see [2XConvertDataSeriesForTool[102X ([14X7.1-2[114X).)[133X
  
  [30X    [33X[0;6YIf [10XA1[110X is a list of arguments fitting any of the cases documented above
        (such  as  [10X[X,f][110X)  and  [10XA2[110X  is  as  well,  and  so on through [10XAn[110X, then
        [10XPlot(A1,A2,...,An)[110X  creates  a  combination  plot with all of the data
        from  each  of the arguments treated as a separate data series. If the
        arguments contain conflicting plot options (e.g., the first requests a
        line  plot  and  the  second  a  bar  chart)  then the earliest option
        specified takes precedence.[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28X# Plot the number of small groups of order n, from n=1 to n=50:[128X[104X
    [4X[28XPlot( [1..50], NrSmallGroups );[128X[104X
  [4X[32X[104X
  
  [33X[0;0YResulting image not shown here.[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28X# Plot how much Andrea has been jogging lately:[128X[104X
    [4X[28XPlot( ["Jan","Feb","Mar"], [46,59,61],[128X[104X
    [4X[28X      rec( title := "Andrea's Jogging", yaxis := "miles per month" ) );[128X[104X
  [4X[32X[104X
  
  [33X[0;0YResulting image not shown here.[133X
  
  [1X7.1-2 ConvertDataSeriesForTool[101X
  
  [33X[1;0Y[29X[2XConvertDataSeriesForTool[102X [32X global variable[133X
  
  [33X[0;0YThe  [5XJupyterViz[105X  Package  has  a  high-level  API  and  a low-level API. The
  high-level API involves functions like [10XPlot[110X, which take data in a variety of
  convenient  formats, and produce visualizations from them. The low-level API
  can  be  used to pass JSON data structures to JavaScript visualization tools
  in  their  own  native formats for rendering. The high-level API is built on
  the low-level API, using key functions to do the conversion.[133X
  
  [33X[0;0YThe conversion functions for plots are stored in a global dictionary in this
  variable.  It  is  a  [5XGAP[105X  record  mapping visualization tool names (such as
  plotly, etc., a complete list of which appears in Section [14X1.1[114X) to conversion
  functions.  Only those tools that support plotting data in the form of [23X(x,y)[123X
  pairs  should  be  included.  (For example, tools that specialize in drawing
  vertex-and-edge graphs are not relevant here.)[133X
  
  [33X[0;0YEach conversion function must behave as follows. It expects its input object
  to be a single data series, which will be a [5XGAP[105X record with three fields:[133X
  
  [30X    [33X[0;6Y[10Xx[110X - a list of [23Xx[123X values for the plot[133X
  
  [30X    [33X[0;6Y[10Xy[110X - the corresponding list of [23Xy[123X values for the same plot[133X
  
  [30X    [33X[0;6Y[10Xoptions[110X  -  another  (inner)  [5XGAP[105X record containing any of the options
        documented in Section [14X2.2[114X.[133X
  
  [33X[0;0YThe  output  of  the  conversion function should be a [5XGAP[105X record amenable to
  conversion  (using  [10XGapToJsonString[110X  from  the  [5Xjson[105X package) into JSON. The
  format  of  the  JSON  is governed entirely by the tool that will be used to
  visualize it, each of which has a different data format it expects.[133X
  
  [33X[0;0YThose who wish to install new visualization tools for plots (as discussed in
  Chapter  [14X5[114X) will want to install a new function in this object corresponding
  to  the  new  tool.  If  you plan to do so, consider the source code for the
  existing  conversion  functions,  which  makes  use of two useful convenince
  methods,  [2XJUPVIZFetchWithDefault[102X ([14X7.3-12[114X) and [2XJUPVIZFetchIfPresent[102X ([14X7.3-13[114X).
  Following  those  examples will help keep your code consistent with existing
  code and as concise as possible.[133X
  
  [1X7.1-3 PlotGraph[101X
  
  [33X[1;0Y[29X[2XPlotGraph[102X( [3Xvarious[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Yone of two things, documented below[133X
  
  [33X[0;0YIf  evaluated  in  a  Jupyter  Notebook,  the  result of this function, when
  rendered by that notebook, will run JavaScript code that generates and shows
  a  graph in the output cell, not in the sense of coordinate axes, but in the
  sense  of vertices and edges. (To graph a function or data set on coordinate
  axes, use [2XPlot[102X ([14X7.1-1[114X) instead.)[133X
  
  [33X[0;0YIf  evaluated  outside of a Jupyter Notebook, the result of this function is
  the  name  of  a temporary file stored on disk in which HTML code for such a
  visualization  has  been  written,  and on which [5XGAP[105X has already invoked the
  user's  default web browser. The user should see the visualization appear in
  the browser immediately before the return value is shown.[133X
  
  [33X[0;0YThis  function can take data in a wide variety of input formats. Here is the
  current list of acceptable formats:[133X
  
  [30X    [33X[0;6YIf  [10XV[110X  is  a  list  and  [10XE[110X  is  a  list  of pairs of items from [10XV[110X then
        [10XPlotGraph(V,E)[110X treats them as vertex and edge sets, respectively.[133X
  
  [30X    [33X[0;6YIf [10XV[110X is a list and [10XR[110X is a [5XGAP[105X function then [10XPlotGraph(V,R)[110X treats [10XV[110X as
        the  vertex set and calls [10XR(v1,v2)[110X for every pair of vertices (in both
        orders) to test whether there is an edge between them. It exepcts [10XR[110X to
        return boolean values.[133X
  
  [30X    [33X[0;6YIf [10XE[110X is a list of pairs then [10XPlotGraph(E)[110X treats [10XE[110X as a list of edges,
        inferring  the  vertex  set  to  be any vertex mentioned in any of the
        edges.[133X
  
  [30X    [33X[0;6YIf  [10XM[110X  is  a  square matrix then [10XPlotGraph(M)[110X treats [10XM[110X as an adjacency
        matrix  whose vertices are the integers 1 through [23Xn[123X (the height of the
        matrix) and where two vertices are connected by an edge if and only if
        that matrix entry is positive.[133X
  
  [30X    [33X[0;6YIn any of the cases above, a new, last argument may be added that is a
        [5XGAP[105X  record  containing options for how to draw the graph, such as the
        tool   to   use.   For   details   on   the   supported  options,  see
        [2XConvertGraphForTool[102X ([14X7.1-4[114X).[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28X# Plot the subgroup lattice for a small group:[128X[104X
    [4X[28XG := Group((1,2),(2,3));[128X[104X
    [4X[28XPlotGraph( AllSubgroups(G), IsSubgroup );[128X[104X
  [4X[32X[104X
  
  [33X[0;0YResulting image not shown here.[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28X# Plot a random graph on 5 vertices:[128X[104X
    [4X[28X# (The results change from one run to the next, of course.)[128X[104X
    [4X[28XPlotGraph( RandomMat(5,5) );[128X[104X
  [4X[32X[104X
  
  [33X[0;0YResulting image not shown here.[133X
  
  [1X7.1-4 ConvertGraphForTool[101X
  
  [33X[1;0Y[29X[2XConvertGraphForTool[102X [32X global variable[133X
  
  [33X[0;0YThe  [5XJupyterViz[105X  Package  has  a  high-level  API  and  a low-level API. The
  high-level  API  involves  functions  like  [10XPlotGraph[110X,  which take data in a
  variety  of  convenient  formats,  and produce visualizations from them. The
  low-level  API  can  be  used  to  pass  JSON  data structures to JavaScript
  visualization   tools  in  their  own  native  formats  for  rendering.  The
  high-level  API is built on the low-level API, using key functions to do the
  conversion.[133X
  
  [33X[0;0YThe  conversion  functions  for  graphs are stored in a global dictionary in
  this  variable. It is a [5XGAP[105X record mapping visualization tool names (such as
  cytoscape,  a  complete  list of which appears in Section [14X1.1[114X) to conversion
  functions.  Only  those  tools  that  support  graphing vertex and edge sets
  should  be included. (For example, tools that specialize in drawing plots of
  data stored as [23X(x,y)[123X pairs are not relevant here.)[133X
  
  [33X[0;0YEach conversion function must behave as follows. It expects its input object
  to be a single graph, which will be a [5XGAP[105X record with three fields:[133X
  
  [30X    [33X[0;6Y[10Xvertices[110X  - a list of vertex names for the graph. These can be any [5XGAP[105X
        data structure and they will be converted to strings with [10XPrintString[110X.
        The  one  exception  is  that  you  can give each vertex a position by
        making  it  a  record with three entries: [10Xname[110X, [10Xx[110X, and [10Xy[110X. In this way,
        you can manually lay out a graph.[133X
  
  [30X    [33X[0;6Y[10Xedges[110X  -  a  list  of  pairs  from  the  [10Xvertices[110X  list, each of which
        represents an edge[133X
  
  [30X    [33X[0;6Y[10Xoptions[110X  -  a  [5XGAP[105X  record containing any of the options documented in
        Section [14X2.4[114X.[133X
  
  [33X[0;0YThe  output  of  the  conversion function should be a [5XGAP[105X record amenable to
  conversion  (using  [10XGapToJsonString[110X  from  the  [5Xjson[105X package) into JSON. The
  format  of  the  JSON  is governed entirely by the tool that will be used to
  visualize it, each of which has a different data format it expects.[133X
  
  [33X[0;0YThose  who  wish to install new visualization tools for graphs (as discussed
  in  Chapter  [14X5[114X)  will  want  to  install  a  new  function  in  this  object
  corresponding  to  the  new  tool. If you plan to do so, consider the source
  code  for  the  existing conversion functions, which makes use of two useful
  convenince methods, [2XJUPVIZFetchWithDefault[102X ([14X7.3-12[114X) and [2XJUPVIZFetchIfPresent[102X
  ([14X7.3-13[114X).  Following those examples will help keep your code consistent with
  existing code and as concise as possible.[133X
  
  [1X7.1-5 PlotDisplayMethod[101X
  
  [33X[1;0Y[29X[2XPlotDisplayMethod[102X [32X global variable[133X
  
  [33X[0;0YThe  [5XJupyterViz[105X  Package can display visualizations in three different ways,
  and this global variable is used to switch among those ways.[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28XPlotDisplayMethod := PlotDisplayMethod_HTML;[128X[104X
  [4X[32X[104X
  
  [33X[0;0YUsers  of this package almost never need to alter the value of this variable
  because  a  sensible  default  is  chosen  at  package  loading time. If the
  [5XJupyterViz[105X Package is loaded after the [5XJupyterKernel[105X Package, it notices the
  presence  of  that  package  and  leverage  its  tools to set up support for
  plotting   in   a  Jupyter  environment.  Furthermore,  it  will  initialize
  [2XPlotDisplayMethod[102X  to  [2XPlotDisplayMethod_Jupyter[102X  ([14X7.1-6[114X), which is probably
  what  the user wants. Note that if one calls [10XLoadPackage("JupyterViz");[110X from
  a cell in a Jupyter notebook, this is the case that applies, because clearly
  in such a case, the [5XJupyterKernel[105X Package was already loaded.[133X
  
  [33X[0;0YIf  the  [5XJupyterViz[105X  Package  is  loaded  without  the [5XJupyterKernel[105X Package
  already    loaded,    then   it   will   initialize   [2XPlotDisplayMethod[102X   to
  [2XPlotDisplayMethod_HTML[102X  ([14X7.1-8[114X),  which  is  what the user probably wants if
  using   [5XGAP[105X   from   a   terminal,   for   example.  You  may  later  assign
  [2XPlotDisplayMethod[102X to another value, but doing so has little purpose from the
  REPL. You would need to first load the [5XJupyterKernel[105X Package, and even then,
  all  that  would  be  produced by this package would be data structures that
  would, if evaluated in a Jupyter notebook, produce visualizations.[133X
  
  [1X7.1-6 PlotDisplayMethod_Jupyter[101X
  
  [33X[1;0Y[29X[2XPlotDisplayMethod_Jupyter[102X [32X global variable[133X
  
  [33X[0;0YThis   global   constant   can   be   assigned   to   the   global  variable
  [2XPlotDisplayMethod[102X  ([14X7.1-5[114X)  as  documented  above.  Doing  so  produces  the
  following results.[133X
  
  [30X    [33X[0;6YFunctions    such    as   [2XPlot[102X   ([14X7.1-1[114X),   [2XPlotGraph[102X   ([14X7.1-3[114X),   and
        [2XCreateVisualization[102X    ([14X7.2-5[114X)    will    return   objects   of   type
        [10XJupyterRenderable[110X, which is defined in the [5XJupyterKernel[105X Package.[133X
  
  [30X    [33X[0;6YSuch  objects,  when  rendered  in a Jupyter cell, will run a block of
        JavaScript  contained  within  them,  which  will  create  the desired
        visualization.[133X
  
  [30X    [33X[0;6YSuch  scripts  tend to request additional information from [5XGAP[105X as they
        are   running,   by   using   calls   to   the   JavaScript   function
        [10XJupyter.kernel.execute[110X   defined  in  the  notebook.  Such  calls  are
        typically to fetch JavaScript libraries needed to create the requested
        visualization.[133X
  
  [30X    [33X[0;6YVisualizations  produced  this  way  will  not be visible if one later
        closes and then reopens the Jupyter notebook in which they are stored.
        To  see  the visualizations again, one must re-evaluate the cells that
        created  them,  so that the required libraries are re-fetched from the
        [5XGAP[105X Jupyter kernel.[133X
  
  [1X7.1-7 PlotDisplayMethod_JupyterSimple[101X
  
  [33X[1;0Y[29X[2XPlotDisplayMethod_JupyterSimple[102X [32X global variable[133X
  
  [33X[0;0YThis   global   constant   can   be   assigned   to   the   global  variable
  [2XPlotDisplayMethod[102X  ([14X7.1-5[114X)  as  documented  above.  Doing  so  produces  the
  following results.[133X
  
  [30X    [33X[0;6YFunctions    such    as   [2XPlot[102X   ([14X7.1-1[114X),   [2XPlotGraph[102X   ([14X7.1-3[114X),   and
        [2XCreateVisualization[102X    ([14X7.2-5[114X)    will    return   objects   of   type
        [10XJupyterRenderable[110X, which is defined in the [5XJupyterKernel[105X Package.[133X
  
  [30X    [33X[0;6YSuch  objects,  when  rendered  in a Jupyter cell, will run a block of
        JavaScript  contained  within  them,  which  will  create  the desired
        visualization.[133X
  
  [30X    [33X[0;6YSuch  scripts  will be entirely self-contained, and thus will not make
        any  additional  requests from the [5XGAP[105X Jupyter kernel. This makes such
        objects  larger  because they must contain all the required JavaScript
        visualization  libraries,  rather  than  being able to request them as
        needed later.[133X
  
  [30X    [33X[0;6YVisualizations  produced  this  way  will be visible even if one later
        closes and then reopens the Jupyter notebook in which they are stored,
        because  all  the code needed to create them is included in the output
        cell itself, and is re-run upon re-opening the notebook.[133X
  
  [1X7.1-8 PlotDisplayMethod_HTML[101X
  
  [33X[1;0Y[29X[2XPlotDisplayMethod_HTML[102X [32X global variable[133X
  
  [33X[0;0YThis   global   constant   can   be   assigned   to   the   global  variable
  [2XPlotDisplayMethod[102X  ([14X7.1-5[114X)  as  documented  above.  Doing  so  produces  the
  following results.[133X
  
  [30X    [33X[0;6YFunctions    such    as   [2XPlot[102X   ([14X7.1-1[114X),   [2XPlotGraph[102X   ([14X7.1-3[114X),   and
        [2XCreateVisualization[102X  ([14X7.2-5[114X)  will  return  no value, but will instead
        store  HTML (and JavaScript) code for the visualization in a temporary
        file on the filesystem, then launch the operating system's default web
        browser to view that file.[133X
  
  [30X    [33X[0;6YSuch  files are entirely self-contained, and require no [5XGAP[105X session to
        be  running  to  continue viewing them. They can be saved anywhere the
        user likes for later viewing, printing, or sharing without [5XGAP[105X.[133X
  
  [30X    [33X[0;6YVisualizations  produced  this  way  will  not be visible if one later
        closes and then reopens the Jupyter notebook in which they are stored.
        To  see  the visualizations again, one must re-evaluate the cells that
        created  them,  so that the required libraries are re-fetched from the
        [5XGAP[105X Jupyter kernel.[133X
  
  
  [1X7.2 [33X[0;0YLow-Level Public API[133X[101X
  
  [1X7.2-1 RunJavaScript[101X
  
  [33X[1;0Y[29X[2XRunJavaScript[102X( [3Xscript[103X[, [3XreturnHTML[103X] ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Yone of two things, documented below[133X
  
  [33X[0;0YIf  run  in  a  Jupyter Notebook, this function returns an object that, when
  rendered by that notebook, will run the JavaScript code given in [3Xscript[103X.[133X
  
  [33X[0;0YIf  run  outside  of  a Jupyter Notebook, this function creates an HTML page
  containing  the  given [3Xscript[103X, an HTML element on which that script can act,
  and  the  RequireJS  library for importing other script tools. It then opens
  the  page  in  the  system default web browser (thus running the script) and
  returns the path to the temporary file in which the script is stored.[133X
  
  [33X[0;0YIn  this  second case only, the optional second parameter (which defaults to
  false) can be set to true if the caller does not wish the function to open a
  web  browser, but just wants the HTML content that would have been displayed
  in such a browser returned as a string instead.[133X
  
  [33X[0;0YWhen  the  given  code  is  run,  the varible [10Xelement[110X will be defined in its
  environment,  and  will  contain  either  the  output element in the Jupyter
  notebook  corresponding  to the code that was just evaluated or, in the case
  outside  of Jupyter, the HTML element mentioned above. The script is free to
  write to that element in both cases.[133X
  
  [1X7.2-2 LoadJavaScriptFile[101X
  
  [33X[1;0Y[29X[2XLoadJavaScriptFile[102X( [3Xfilename[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe string contents of the file whose name is given[133X
  
  [33X[0;0YInterprets the given [3Xfilename[103X relative to the [11Xlib/js/[111X path in the [5XJupyterViz[105X
  package's installation folder, because that is where this package stores its
  JavaScript  libraries. A [11X.js[111X extension will be added to [3Xfilename[103X iff needed.
  A  [11X.min.js[111X  extension  will  be  added iff such a file exists, to prioritize
  minified versions of files.[133X
  
  [33X[0;0YIf  the  file  has  been  loaded  before in this [5XGAP[105X session, it will not be
  reloaded, but will be returned from a cache in memory, for efficiency.[133X
  
  [33X[0;0YIf no such file exists, returns [9Xfail[109X and caches nothing.[133X
  
  [1X7.2-3 InstallVisualizationTool[101X
  
  [33X[1;0Y[29X[2XInstallVisualizationTool[102X( [3XtoolName[103X, [3Xscript[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Yboolean indicating success (true) or failure (false)[133X
  
  [33X[0;0YThis   function  permits  extending,  at  runtime,  the  set  of  JavaScript
  visualization tools beyond those that are built into the [5XJupyterViz[105X package.[133X
  
  [33X[0;0YThe  first  argument  must  be the name of the visualization tool (a string,
  which  you will later use in the [10Xtool[110X field when calling [2XCreateVisualization[102X
  ([14X7.2-5[114X)).  The second must be a string of JavaScript code that installs into
  [10Xwindow.VisualizationTools.TOOL_NAME_HERE[110X    the    function   for   creating
  visualizations using that tool. It can also define other helper functions or
  make  calls  to  [10Xwindow.requirejs.config[110X.  For examples of how to write such
  JavaScript code, see the chapter on extending this package in its manual.[133X
  
  [33X[0;0YThis  function  returns  false  and  does nothing if a tool of that name has
  already been installed. Otherwise, it installs the tool and returns true.[133X
  
  [33X[0;0YThere  is  also a convenience method that calls this one on your behalf; see
  [2XInstallVisualizationToolFromTemplate[102X ([14X7.2-4[114X).[133X
  
  [1X7.2-4 InstallVisualizationToolFromTemplate[101X
  
  [33X[1;0Y[29X[2XInstallVisualizationToolFromTemplate[102X( [3XtoolName[103X, [3XfunctionBody[103X[, [3XCDNURL[103X] ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Yboolean indicating success (true) or failure (false)[133X
  
  [33X[0;0YThis  function  is  a  convenience  function  that  makes  it  easier to use
  [2XInstallVisualizationTool[102X  ([14X7.2-3[114X);  see the documentation for that function,
  then read on below for how this function makes it easier.[133X
  
  [33X[0;0YMost  visualization  tools do two things: First, they install a CDN URL into
  [10Xwindow.requirejs.config[110X  for  some  external JavaScript library that must be
  loaded  in  the  client  to support the given type of visualization. Second,
  they   install   a   function   as  [10Xwindow.VisualizationTools.TOOL_NAME_HERE[110X
  accepting  parameters  [10Xelement[110X, [10Xjson[110X, and [10Xcallback[110X, and building the desired
  visualization  inside  the  given DOM element. Such code often begins with a
  call to [10Xrequire(['...'],function(library}{/*...*/}))[110X, but not always.[133X
  
  [33X[0;0YThis  function  will  write  for  you  the  boiler  plate  code  for calling
  [10Xwindow.requirejs.config[110X  and  the declaration and installation of a function
  into [10Xwindow.VisualizationTools.TOOL_NAME_HERE[110X. You provide the function body
  and optionally the CDN URL. (If you provide no CDN URL, then no external CDN
  will be installed into [10Xrequirejs[110X.)[133X
  
  [1X7.2-5 CreateVisualization[101X
  
  [33X[1;0Y[29X[2XCreateVisualization[102X( [3Xdata[103X[, [3Xcode[103X] ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Yone of two things, documented below[133X
  
  [33X[0;0YIf  run  in  a  Jupyter Notebook, this function returns an object that, when
  rendered  by that notebook, will produce the visualization specified by [3Xdata[103X
  in  the  corresponding output cell, and will also run any given [3Xcode[103X on that
  visualization.[133X
  
  [33X[0;0YIf  run  outside  of  a Jupyter Notebook, this function creates an HTML page
  containing  the  visualization  specified by [3Xdata[103X and then opens the page in
  the  system  default web browser. It will also run any given [3Xcode[103X as soon as
  the  page  opens.  The  [3Xdata[103X must be a record that will be converted to JSON
  using [5XGAP[105X's [5Xjson[105X package.[133X
  
  [33X[0;0YThe  second argument is optional, a string containing JavaScript [3Xcode[103X to run
  once  the  visualization  has  been  created.  When  that  code  is run, the
  variables  [10Xelement[110X  and [10Xvisualization[110X will be in its environment, the former
  holding the output element in the notebook containing the visualization, and
  the latter holding the visualization element itself.[133X
  
  [33X[0;0YThe [3Xdata[103X should have the following attributes.[133X
  
  [30X    [33X[0;6Y[10Xtool[110X (required) - the name of the visualization tool to use. Currently
        supported  tools  are  listed  in  Section  [14X1.2[114X  and  links  to  their
        documentation are given in Section [14X3.4[114X.[133X
  
  [30X    [33X[0;6Y[10Xdata[110X  (required)  -  subobject  containing all options specific to the
        content  of  the  visualization,  often  passed intact to the external
        JavaScript  visualization library. You should prepare this data in the
        format  required by the library specified in the [10Xtool[110X field, following
        the documentation for that library, linked to in Section [14X3.4[114X.[133X
  
  [30X    [33X[0;6Y[10Xwidth[110X (optional) - width to set on the output element being created[133X
  
  [30X    [33X[0;6Y[10Xheight[110X (optional) - similar, but height[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28XCreateVisualization( rec([128X[104X
    [4X[28X    tool := "html",[128X[104X
    [4X[28X    data := rec( html := "I am <i>SO</i> excited about this." )[128X[104X
    [4X[28X), "console.log( 'Visualization created.' );" );[128X[104X
  [4X[32X[104X
  
  
  [1X7.3 [33X[0;0YInternal methods[133X[101X
  
  [33X[0;0YUsing  the  convention  common  to  [5XGAP[105X  packages, we prefix all methods not
  intended  for  public  use  with  a sequence of characters that indicate our
  particular  package.  In this case, we use the [10XJUPVIZ[110X prefix. This is a sort
  of "poor man's namespacing."[133X
  
  [33X[0;0Y[13XNone  of these methods should need to be called by a client of this package.
  We provide this documentation here for completeness, not out of necessity.[113X[133X
  
  [1X7.3-1 JUPVIZAbsoluteJavaScriptFilename[101X
  
  [33X[1;0Y[29X[2XJUPVIZAbsoluteJavaScriptFilename[102X( [3Xfilename[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya JavaScript filename to an absolute path in the package dir[133X
  
  [33X[0;0YGiven  a  relative  [3Xfilename[103X,  convert  it  into  an  absolute  filename  by
  prepending  the  path  to the [11Xlib/js/[111X folder within the [5XJupyterViz[105X package's
  installation  folder. This is used by functions that need to find JavaScript
  files stored there.[133X
  
  [33X[0;0YA [11X.js[111X extension is appended if none is included in the given [3Xfilename[103X.[133X
  
  [1X7.3-2 JUPVIZLoadedJavaScriptCache[101X
  
  [33X[1;0Y[29X[2XJUPVIZLoadedJavaScriptCache[102X [32X global variable[133X
  
  [33X[0;0YA  cache  of the contents of any JavaScript files that have been loaded from
  this  package's  folder.  The existence of this cache means needing to go to
  the filesystem for these files only once per [5XGAP[105X session. This cache is used
  by [2XLoadJavaScriptFile[102X ([14X7.2-2[114X).[133X
  
  [1X7.3-3 JUPVIZFillInJavaScriptTemplate[101X
  
  [33X[1;0Y[29X[2XJUPVIZFillInJavaScriptTemplate[102X( [3Xfilename[103X, [3Xdictionary[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya  string  containing  the  contents  of  the given template file,
            filled in using the given dictionary[133X
  
  [33X[0;0YA  template file is one containing identifiers that begin with a dollar sign
  ([10X$[110X).  For  example,  [10X$one[110X  and [10X$two[110X are both identifiers. One "fills in" the
  template  by  replacing  such  identifiers  with  whatever  text  the caller
  associates with them.[133X
  
  [33X[0;0YThis  function loads the file specified by [3Xfilename[103X by passing that argument
  directly  to  [2XLoadJavaScriptFile[102X  ([14X7.2-2[114X).  If  no such file exists, returns
  [9Xfail[109X. Otherwise, it proceed as follows.[133X
  
  [33X[0;0YFor  each  key-value  pair in the given [3Xdictionary[103X, prefix a [10X$[110X onto the key,
  suffix  a newline character onto the value, and then replace all occurrences
  of the new key with the new value. The resulting string is the result.[133X
  
  [33X[0;0YThe  newline  character  is  included  so  that  if any of the values in the
  [3Xdictionary[103X contains single-line JavaScript comment characters ([10X//[110X) then they
  will not inadvertently affect later code in the template.[133X
  
  [1X7.3-4 JUPVIZRunJavaScriptFromTemplate[101X
  
  [33X[1;0Y[29X[2XJUPVIZRunJavaScriptFromTemplate[102X( [3Xfilename[103X, [3Xdictionary[103X[, [3XreturnHTML[103X] ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe      composition     of     [2XRunJavaScript[102X     ([14X7.2-1[114X)     with
            [2XJUPVIZFillInJavaScriptTemplate[102X ([14X7.3-3[114X)[133X
  
  [33X[0;0YThis  function  is  quite  simple,  and  is just a convenience function. The
  optional third argument is passed on to RunJavaScript internally.[133X
  
  [1X7.3-5 JUPVIZRunJavaScriptUsingRunGAP[101X
  
  [33X[1;0Y[29X[2XJUPVIZRunJavaScriptUsingRunGAP[102X( [3XjsCode[103X[, [3XreturnHTML[103X] ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Yan object that, if rendered in a Jupyter notebook, will run [3XjsCode[103X
            as JavaScript after [10XrunGAP[110X has been defined[133X
  
  [33X[0;0YThere is a JavaScript function called [10XrunGAP[110X, defined in the [11Xusing-runGAP.js[111X
  file  distributed  with  this  package.  That function makes it easy to make
  callbacks from JavaScript in a Jupyter notebook to the [5XGAP[105X kernel underneath
  that  notebook. This [5XGAP[105X function runs the given [3XjsCode[103X in the notebook, but
  only  after  ensuring  that  [10XrunGAP[110X is defined globally in that notebook, so
  that [3XjsCode[103X can call [10XrunGAP[110X as needed.[133X
  
  [33X[0;0YThe optional third argument is passed on to RunJavaScript internally.[133X
  
  [33X[0;0YAn  example  use, from JavaScript, of the [10XrunGAP[110X function appears at the end
  of Section [14X4.3[114X.[133X
  
  [1X7.3-6 JUPVIZRunJavaScriptUsingLibraries[101X
  
  [33X[1;0Y[29X[2XJUPVIZRunJavaScriptUsingLibraries[102X( [3Xlibraries[103X, [3XjsCode[103X[, [3XreturnHTML[103X] ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Yone of two things, documented below[133X
  
  [33X[0;0YIf  run  in  a  Jupyter Notebook, this function returns an object that, when
  rendered by that notebook, will run [3XjsCode[103X as JavaScript after all [3Xlibraries[103X
  have been loaded (which typically happens asynchronously).[133X
  
  [33X[0;0YIf  run  outside of a Jupyter Notebook, this function loads all the code for
  the  given [3Xlibraries[103X from disk and concatenates them (with checks to be sure
  no  library is loaded twice) followed by [3XjsCode[103X. It then calls [2XRunJavaScript[102X
  ([14X7.2-1[114X) on the result, to form a web page and display it to the user.[133X
  
  [33X[0;0YThere  are  a set of JavaScript libraries stored in the [11Xlib/js/[111X subfolder of
  this  package's  installation  folder.  Neither the Jupyter notebook nor the
  temporary  HTML  files created from the command line know, by default, about
  any  of  those libraries. Thus this function is necessary so that [3XjsCode[103X can
  assume the existence of the tools it needs to do its job.[133X
  
  [33X[0;0YIf the first parameter is given as a string instead of a list of strings, it
  is treated as a list of just one string.[133X
  
  [33X[0;0YThe optional third argument is passed on to RunJavaScript internally.[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28XJUPVIZRunJavaScriptUsingLibraries( [ "mylib.js" ],[128X[104X
    [4X[28X    "alert( 'My Lib defines foo to be: ' + window.foo );" );[128X[104X
    [4X[28X# Equivalently:[128X[104X
    [4X[28XJUPVIZRunJavaScriptUsingLibraries( "mylib.js",[128X[104X
    [4X[28X    "alert( 'My Lib defines foo to be: ' + window.foo );" );[128X[104X
  [4X[32X[104X
  
  [1X7.3-7 JUPVIZMakePlotDataSeries[101X
  
  [33X[1;0Y[29X[2XJUPVIZMakePlotDataSeries[102X( [3Xseries[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya  record  with the appropriate fields ([10Xx[110X, [10Xy[110X, [10Xoptions[110X) that can be
            passed to one of the functions in [2XConvertDataSeriesForTool[102X ([14X7.1-2[114X)[133X
  
  [33X[0;0YThis  function  is called by [2XPlot[102X ([14X7.1-1[114X) to convert any of the wide variety
  of  inputs  that  [2XPlot[102X  ([14X7.1-1[114X) might receive into a single internal format.
  Then  that internal format can be converted to the JSON format needed by any
  of the visualization tools supported by this package.[133X
  
  [33X[0;0YSee   the   documentation  for  [2XConvertDataSeriesForTool[102X  ([14X7.1-2[114X)  for  more
  information  on  how  that  latter conversion takes place, and the format it
  expects.[133X
  
  [1X7.3-8 JUPVIZMakePlotGraphRecord[101X
  
  [33X[1;0Y[29X[2XJUPVIZMakePlotGraphRecord[102X( [3Xvarious[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya  record  with  the appropriate fields ([10Xvertices[110X, [10Xedges[110X, [10Xoptions[110X)
            that  can be passed to one of the functions in [2XConvertGraphForTool[102X
            ([14X7.1-4[114X)[133X
  
  [33X[0;0YThis  function  is  called  by  [2XPlotGraph[102X ([14X7.1-3[114X) to convert any of the wide
  variety  of  inputs  that  [2XPlotGraph[102X  ([14X7.1-3[114X)  might  receive  into a single
  internal  format.  Then  that  internal  format can be converted to the JSON
  format needed by any of the visualization tools supported by this package.[133X
  
  [33X[0;0YSee  the  documentation for [2XConvertGraphForTool[102X ([14X7.1-4[114X) for more information
  on how that latter conversion takes place, and the format it expects.[133X
  
  [1X7.3-9 JUPVIZPlotDataSeriesList[101X
  
  [33X[1;0Y[29X[2XJUPVIZPlotDataSeriesList[102X( [3Xseries1[103X, [3Xseries2[103X, [3Xseries3...[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ya  [10XJupyterRenderable[110X  object  ready to be displayed in the Jupyter
            Notebook[133X
  
  [33X[0;0YBecause the [2XPlot[102X ([14X7.1-1[114X) function can take a single data series or many data
  series  as  input,  it  detects which it received, then passes the resulting
  data series (as an array containing one or more series) to this function for
  collecting into a single plot.[133X
  
  [33X[0;0YIt  is  not  expected  that  clients  of this package will need to call this
  internal function.[133X
  
  [1X7.3-10 JUPVIZRecordKeychainLookup[101X
  
  [33X[1;0Y[29X[2XJUPVIZRecordKeychainLookup[102X( [3Xrecord[103X, [3Xkeychain[103X, [3Xdefault[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe result of looking up the chain of keys in the given record[133X
  
  [33X[0;0YIn  nested  records, such as [10XmyRec:=rec(a:=rec(b:=5))[110X, it is common to write
  code  such  as [10XmyRec.a.b[110X to access the internal values. However when records
  are passed as parameters, and may not contain every key (as in the case when
  some  default values should be filled in automatically), code like [10XmyRec.a.b[110X
  could  cause  an error. Thus we wish to first check before indexing a record
  that  the  key  we're looking up exists. If not, we wish to return the value
  given as the [10Xdefault[110X instead.[133X
  
  [33X[0;0YThis  function  accepts  a [10Xrecord[110X (which may have other records inside it as
  values),  an array of strings that describe a chain of keys to follow inward
  ([10X["a","b"][110X  in the example just given), and a [10Xdefault[110X value to return if any
  of the keys do not exist.[133X
  
  [33X[0;0YIt  is  not  expected  that  clients  of this package will need to call this
  internal    function.    It    is    used   primarily   to   implement   the
  [2XJUPVIZFetchWithDefault[102X  ([14X7.3-12[114X) function, which is useful to those who wish
  to  extend  the  [2XConvertDataSeriesForTool[102X  ([14X7.1-2[114X)  and  [2XConvertGraphForTool[102X
  ([14X7.1-4[114X) objects.[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28XmyRec := rec( height := 50, width := 50, title := rec([128X[104X
    [4X[28X  text := "GAP", fontSize := 20[128X[104X
    [4X[28X) );[128X[104X
    [4X[28XJUPVIZRecordKeychainLookup( myRec, [ "height" ], 10 );                # = 50[128X[104X
    [4X[28XJUPVIZRecordKeychainLookup( myRec, [ "width" ], 10 );                 # = 50[128X[104X
    [4X[28XJUPVIZRecordKeychainLookup( myRec, [ "depth" ], 10 );                 # = 10[128X[104X
    [4X[28XJUPVIZRecordKeychainLookup( myRec, [ "title", "text" ], "Title" );    # = "GAP"[128X[104X
    [4X[28XJUPVIZRecordKeychainLookup( myRec, [ "title", "color" ], "black" );   # = "black"[128X[104X
    [4X[28XJUPVIZRecordKeychainLookup( myRec, [ "one", "two", "three" ], fail ); # = fail[128X[104X
  [4X[32X[104X
  
  [1X7.3-11 JUPVIZRecordsKeychainLookup[101X
  
  [33X[1;0Y[29X[2XJUPVIZRecordsKeychainLookup[102X( [3Xrecords[103X, [3Xkeychain[103X, [3Xdefault[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ythe  result  of  looking up the chain of keys in each of the given
            records until a lookup succeeds[133X
  
  [33X[0;0YThis  function  is  extremely similar to [2XJUPVIZRecordKeychainLookup[102X ([14X7.3-10[114X)
  with the following difference: The first parameter is a list of records, and
  [2XJUPVIZRecordKeychainLookup[102X ([14X7.3-10[114X) is called on each in succession with the
  same  [10Xkeychain[110X.  If  any of the lookups succeeds, then its value is returned
  and  no  further  searching  through the list is done. If all of the lookups
  fail, the [10Xdefault[110X is returned.[133X
  
  [33X[0;0YIt  is  not  expected  that  clients  of this package will need to call this
  internal    function.    It    is    used   primarily   to   implement   the
  [2XJUPVIZFetchWithDefault[102X  ([14X7.3-12[114X) function, which is useful to those who wish
  to  extend  the  [2XConvertDataSeriesForTool[102X  ([14X7.1-2[114X)  and  [2XConvertGraphForTool[102X
  ([14X7.1-4[114X) objects.[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28XmyRecs := [[128X[104X
    [4X[28X  rec( height := 50, width := 50, title := rec([128X[104X
    [4X[28X    text := "GAP", fontSize := 20[128X[104X
    [4X[28X  ) ),[128X[104X
    [4X[28X  rec( width := 10, depth := 10, color := "blue" )[128X[104X
    [4X[28X];[128X[104X
    [4X[28XJUPVIZRecordsKeychainLookup( myRecs, [ "height" ], 0 );              # = 50[128X[104X
    [4X[28XJUPVIZRecordsKeychainLookup( myRecs, [ "width" ], 0 );               # = 50[128X[104X
    [4X[28XJUPVIZRecordsKeychainLookup( myRecs, [ "depth" ], 0 );               # = 10[128X[104X
    [4X[28XJUPVIZRecordsKeychainLookup( myRecs, [ "title", "text" ], "Title" ); # = "GAP"[128X[104X
    [4X[28XJUPVIZRecordsKeychainLookup( myRecs, [ "color" ], "" );              # = "blue"[128X[104X
    [4X[28XJUPVIZRecordsKeychainLookup( myRecs, [ "flavor" ], fail );           # = fail[128X[104X
  [4X[32X[104X
  
  [1X7.3-12 JUPVIZFetchWithDefault[101X
  
  [33X[1;0Y[29X[2XJUPVIZFetchWithDefault[102X( [3Xrecord[103X, [3Xothers[103X, [3Xchain[103X, [3Xdefault[103X, [3Xaction[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ynothing[133X
  
  [33X[0;0YThis  function  is  designed  to  make it easier to write new entries in the
  [2XConvertDataSeriesForTool[102X  ([14X7.1-2[114X) and [2XConvertGraphForTool[102X ([14X7.1-4[114X) functions.
  Those  functions are often processing a list of records (here called [10Xothers[110X)
  sometimes  with  one  record the most important one (here called [10Xrecord[110X) and
  looking    up    a    [10Xchain[110X    of   keys   (using   [10Xdefault[110X   just   as   in
  [2XJUPVIZRecordKeychainLookup[102X  ([14X7.3-10[114X))  and  then taking some [10Xaction[110X based on
  the  result.  This function just allows all of that to be done with a single
  call.[133X
  
  [33X[0;0YSpecifically,    it    considers    the   array   of   records   formed   by
  [10XConcatenation([record],others)[110X    and    calls   [2XJUPVIZRecordsKeychainLookup[102X
  ([14X7.3-11[114X)  on it with the given [10Xchain[110X and [10Xdefault[110X. (If the [10Xchain[110X is a string,
  it  is automatically converted to a length-one list with the string inside.)
  Whatever  the result, the function [10Xaction[110X is called on it, even if it is the
  default.[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28X# Trivial examples:[128X[104X
    [4X[28XmyRec := rec( a := 5 );[128X[104X
    [4X[28XmyRecs := [ rec( b := 3 ), rec( a := 6 ) ];[128X[104X
    [4X[28Xf := function ( x ) Print( x, "\n" ); end;[128X[104X
    [4X[28XJUPVIZFetchWithDefault( myRec, myRecs, "a", 0, f );       # prints 5[128X[104X
    [4X[28XJUPVIZFetchWithDefault( myRec, myRecs, "b", 0, f );       # prints 3[128X[104X
    [4X[28XJUPVIZFetchWithDefault( myRec, myRecs, "c", 0, f );       # prints 0[128X[104X
    [4X[28XJUPVIZFetchWithDefault( myRec, myRecs, ["a","b"], 0, f ); # prints 0[128X[104X
    [4X[28X# Useful example:[128X[104X
    [4X[28XJUPVIZFetchWithDefault( primaryRecord, secondaryRecordsList,[128X[104X
    [4X[28X  [ "options", "height" ], 400,[128X[104X
    [4X[28X  function ( h ) myGraphJSON.height := h; end[128X[104X
    [4X[28X);[128X[104X
  [4X[32X[104X
  
  [33X[0;0YSee also [2XJUPVIZFetchIfPresent[102X ([14X7.3-13[114X).[133X
  
  [1X7.3-13 JUPVIZFetchIfPresent[101X
  
  [33X[1;0Y[29X[2XJUPVIZFetchIfPresent[102X( [3Xrecord[103X, [3Xothers[103X, [3Xchain[103X, [3Xaction[103X ) [32X function[133X
  [6XReturns:[106X  [33X[0;10Ynothing[133X
  
  [33X[0;0YThis  function  is extremely similar to [2XJUPVIZFetchWithDefault[102X ([14X7.3-12[114X) with
  the  following  exception:  No  default  value  is provided, and thus if the
  lookup fails for all the records (including [10Xrecord[110X and everything in [10Xothers[110X)
  then the [10Xaction[110X is not called.[133X
  
  [33X[0;0YExamples:[133X
  
  [4X[32X  Example  [32X[104X
    [4X[28XmyRec := rec( a := 5 );[128X[104X
    [4X[28XmyRecs := [ rec( b := 3 ), rec( a := 6 ) ];[128X[104X
    [4X[28Xf := function ( x ) Print( x, "\n" ); end;[128X[104X
    [4X[28XJUPVIZFetchIfPresent( myRec, myRecs, "a", 0, f );       # prints 5[128X[104X
    [4X[28XJUPVIZFetchIfPresent( myRec, myRecs, "b", 0, f );       # prints 3[128X[104X
    [4X[28XJUPVIZFetchIfPresent( myRec, myRecs, "c", 0, f );       # does nothing[128X[104X
    [4X[28XJUPVIZFetchIfPresent( myRec, myRecs, ["a","b"], 0, f ); # does nothing[128X[104X
  [4X[32X[104X
  
  
  [1X7.4 [33X[0;0YRepresentation wrapper[133X[101X
  
  [33X[0;0YThis  code  is documented for completeness's sake only. It is not needed for
  clients  of this package. Package maintainers may be interested in it in the
  future.[133X
  
  [33X[0;0YThe [5XJupyterKernel[105X package defines a method [10XJupyterRender[110X that determines how
  [5XGAP[105X  data  will be shown to the user in the Jupyter notebook interface. When
  there is no method implemented for a specific data type, the fallback method
  uses the built-in [5XGAP[105X method [10XViewString[110X.[133X
  
  [33X[0;0YThis  presents a problem, because we are often transmitting string data (the
  contents  of  JavaScript  files)  from  the  [5XGAP[105X kernel to the notebook, and
  [10XViewString[110X  is not careful about how it escapes characters such as quotation
  marks, which can seriously mangle code. Thus we must define our own type and
  [10XJupyterRender[110X method for that type, to prevent the use of [10XViewString[110X.[133X
  
  [33X[0;0YThe declarations documented below do just that. In the event that [10XViewString[110X
  were  upgraded  to  more  useful behavior, this workaround could probably be
  removed.  Note  that  it  is used explicitly in the [11Xusing-library.js[111X file in
  this package.[133X
  
  [33X[0;0YIf  this  package is loaded without the [5XJupyterKernel[105X package having already
  been loaded, then the following functions and tools are not defined, because
  their  definitions  rely  on global data made available by the [5XJupyterKernel[105X
  package.[133X
  
  [1X7.4-1 JUPVIZIsFileContents[101X
  
  [33X[1;0Y[29X[2XJUPVIZIsFileContents[102X( [3Xarg[103X ) [32X filter[133X
  [6XReturns:[106X  [33X[0;10Y[10Xtrue[110X or [10Xfalse[110X[133X
  
  [33X[0;0YThe  type  we create is called [10XFileContents[110X, because that is our purpose for
  it (to preserve, unaltered, the contents of a text file).[133X
  
  [1X7.4-2 JUPVIZIsFileContentsRep[101X
  
  [33X[1;0Y[29X[2XJUPVIZIsFileContentsRep[102X( [3Xarg[103X ) [32X filter[133X
  [6XReturns:[106X  [33X[0;10Y[10Xtrue[110X or [10Xfalse[110X[133X
  
  [33X[0;0YThe representation for the [10XFileContents[110X type[133X
  
  [1X7.4-3 JUPVIZFileContents[101X
  
  [33X[1;0Y[29X[2XJUPVIZFileContents[102X( [3Xarg[103X ) [32X operation[133X
  
  [33X[0;0YA constructor for [10XFileContents[110X objects[133X
  
  [33X[0;0YElsewhere,  the  [5XJupyterViz[105X package also installs a [10XJupyterRender[110X method for
  [10XFileContents[110X objects that just returns their text content untouched.[133X
  
