Ticket #1321: trac_1321-sage_graphed_v3.patch

File trac_1321-sage_graphed_v3.patch, 7.2 KB (added by mpatel, 7 years ago)

Adds two keyword options. See the comment. Version 3 of the sage repo patch. This replaces previous versions.

  • sage/graphs/all.py

    # HG changeset patch
    # User Mitesh Patel <qed777@gmail.com>
    # Date 1259046749 28800
    # Node ID 70c557c79f2dbdfe7f83fe098e4a28b95ae4da7f
    # Parent  fe6f925335a11f59386ba4cb0c4590555ef0d3d4
    #1321/graph theory: A graph editor by Radoslav Kirov
    
    diff --git a/sage/graphs/all.py b/sage/graphs/all.py
    a b import sage.graphs.graph_fast 
    88import graph_coloring
    99from sage.graphs.cliquer import *
    1010from graph_database import graph_db_info
     11from graph_editor import graph_editor
  • new file sage/graphs/graph_editor.py

    diff --git a/sage/graphs/graph_editor.py b/sage/graphs/graph_editor.py
    new file mode 100644
    - +  
     1#*****************************************************************************
     2#      Copyright (C) 2009   Radoslav Kirov
     3#                   
     4#  Distributed under the terms of the GNU General Public License (GPL)
     5#
     6#    This code is distributed in the hope that it will be useful,
     7#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     8#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     9#    General Public License for more details.
     10#
     11#  The full text of the GPL is available at:
     12#
     13#                  http://www.gnu.org/licenses/
     14#*****************************************************************************
     15import sys
     16
     17from graph import Graph
     18from graph_generators import graphs
     19from sage.misc.html import html
     20
     21import sagenb.notebook.interact
     22from sagenb.misc.support import EMBEDDED_MODE
     23
     24
     25def graph_to_js(g):
     26    """
     27    Returns a string representation of a :class:`Graph` instance
     28    usable by the :func:`graph_editor`.  The encoded information is
     29    the number of vertices, their 2D positions, and a list of edges.
     30
     31    INPUT:
     32
     33    - ``g`` - a :class:`Graph` instance
     34
     35    OUTPUT:
     36
     37    - a string
     38
     39    EXAMPLES::
     40
     41        sage: from sage.graphs.graph_editor import graph_to_js
     42        sage: G = graphs.CompleteGraph(4)
     43        sage: graph_to_js(G)
     44        'num_vertices=4;edges=[[0,1],[0,2],[0,3],[1,2],[1,3],[2,3]];pos=[[0.5,0.0],[0.0,0.49999999999999989],[0.49999999999999989,1.0],[1.0,0.50000000000000011]];'
     45        sage: graph_to_js(graphs.StarGraph(2))
     46        'num_vertices=3;edges=[[0,1],[0,2]];pos=[[0.75,0.5],[1.0,0.0],[0.0,1.0]];'
     47    """
     48    string = ''
     49    vertex_list = g.get_vertices().keys()
     50    string += 'num_vertices=' + str(len(vertex_list)) + ';'
     51    string += 'edges=['
     52    for i, e in enumerate(g.edges()):
     53        if(i != 0):
     54            string += ','
     55        string += '[' + str(vertex_list.index(e[0])) + ',' + str(vertex_list.index(e[1])) + ']'
     56    string += '];'
     57    string += 'pos=['
     58    pos = g.get_pos()
     59    max_x = max([i[0] for i in pos.values()])
     60    max_y = max([i[1] for i in pos.values()])
     61    min_x = min([i[0] for i in pos.values()])
     62    min_y = min([i[1] for i in pos.values()])
     63    if max_x == 0:
     64        max_x = 1
     65    if max_y == 0:
     66        max_y = 1
     67    for i, v in enumerate(vertex_list):
     68        if(i != 0):
     69            string += ','
     70        new_pos = [float(pos[v][0] - min_x) / (max_x - min_x),
     71                   1.0 - float(pos[v][1] - min_y) / (max_y - min_y)]
     72        string += str(new_pos)
     73    string += '];'
     74    string = string.replace(' ', '')
     75    return string
     76   
     77def graph_editor(graph=graphs.CompleteGraph(2), graph_name=None,
     78                 replace_input=True):
     79    """
     80    Opens a graph editor in the Sage notebook.
     81   
     82    INPUT:
     83
     84    - ``graph`` - a :class:`Graph` instance (default:
     85      graphs.CompleteGraph(2)); the graph to edit
     86
     87    - ``graph_name`` - a string (default: None); the variable name to
     88      use for the updated instance; by default, this function attempts
     89      to determine the name automatically
     90
     91    - ``replace_input`` - a boolean (default: True); whether to
     92      replace the text in the input cell with the updated graph data
     93      when "Save" is clicked; if this is False, the data is **still**
     94      evaluated as if it had been entered in the cell
     95
     96    EXAMPLES::
     97
     98        sage: g = graphs.CompleteGraph(3)
     99        sage: graph_editor(g)                       # not tested
     100        sage: graph_editor(graphs.HouseGraph())     # not tested
     101        sage: graph_editor(graph_name='my_graph')   # not tested
     102        sage: h = graphs.StarGraph(6)
     103        sage: graph_editor(h, replace_input=False)  # not tested
     104    """
     105    if not EMBEDDED_MODE:
     106        return "This graph editor only runs in the Sage notebook."
     107   
     108    if not isinstance(graph.get_pos(), dict):
     109        if graph.is_planar():
     110            graph.set_planar_positions()
     111        else:
     112            import sage.graphs.graph_fast as gf
     113            graph.set_pos(gf.spring_layout_fast_split(graph, iterations=1000))
     114
     115    if graph_name is None:
     116        graph_name = ''
     117        locs = sys._getframe(1).f_locals
     118        for var in locs:
     119            if id(locs[var]) == id(graph):
     120                graph_name = var
     121
     122    cell_id = sagenb.notebook.interact.SAGE_CELL_ID
     123
     124    # TODO: Put reasonable checks for large graphs, before disaster
     125    # occurs (i.e., breaks browser).
     126   
     127    close_button = r"""<button onclick="cell_delete_output(%(cell_id)s);">Close</button>""" % locals()
     128
     129    if replace_input:
     130        eval_strategy = r"""
     131    f += ' graph_editor(' + g[2] + ');'
     132    \$('#cell_input_%(cell_id)s').val(f);
     133    cell_input_resize(%(cell_id)s);
     134    evaluate_cell(%(cell_id)s, false);
     135""" % locals()
     136    else:
     137        eval_strategy = r"""
     138    saved_input = \$('#cell_input_%(cell_id)s').val();
     139    \$('#cell_input_%(cell_id)s').val(f);
     140    evaluate_cell(%(cell_id)s, false);
     141    \$('#cell_input_%(cell_id)s').val(saved_input);
     142    send_cell_input(%(cell_id)s);
     143    cell_input_resize(%(cell_id)s);
     144""" % locals()
     145
     146    update_button = r"""<button onclick="
     147    var f, g, saved_input;
     148    g = \$('#iframe_graph_editor_%(cell_id)s')[0].contentWindow.update_sage();
     149
     150    if (g[2] === '') {
     151        alert('You need to give a Sage variable name to the graph, before saving it.');
     152        return;
     153    }
     154    f = g[2] + ' = Graph(' + g[0] + '); ' + g[2] + '.set_pos(' + g[1] + '); '
     155    %(eval_strategy)s
     156">Save</button>""" % locals()
     157 
     158    graph_js = graph_to_js(graph)
     159    data_fields = """<input type="hidden" id="graph_data_%(cell_id)s" value="%(graph_js)s"><input type="hidden" id="graph_name_%(cell_id)s" value="%(graph_name)s">""" % locals()
     160
     161    return html(r"""<div id="graph_editor_%(cell_id)s"><table><tbody>
     162      <tr><td><iframe style="width: 800px; height: 400px; border: 0;" id="iframe_graph_editor_%(cell_id)s" src="/javascript/graph_editor/graph_editor.html?cell_id=%(cell_id)s"></iframe>%(data_fields)s</td></tr>
     163      <tr><td>%(update_button)s%(close_button)s</td></tr>
     164</tbody></table></div>""" % locals())
     165
     166# This is commented out because the mouse_out call raises an error in
     167# Firebug's console when the event fires but the function itself has
     168# not yet been loaded.
     169
     170#      <tr><td><iframe style="width: 800px; height: 400px; border: 0;" id="iframe_graph_editor_%(cell_id)s" src="/javascript/graph_editor/graph_editor.html?cell_id=%(cell_id)s" onmouseout="\$('#iframe_graph_editor_%(cell_id)s')[0].contentWindow.mouse_out();"></iframe>%(data_fields)s</td></tr>