Commit 5f68e1a3 authored by Romain Loth's avatar Romain Loth

graph api + mygraphs: trigger async generation with new cooc node id immediate return

parent 30c7e640
...@@ -38,7 +38,6 @@ def countCooccurrences( corpus_id=None , cooc_id=None ...@@ -38,7 +38,6 @@ def countCooccurrences( corpus_id=None , cooc_id=None
limit :: Int limit :: Int
''' '''
# FIXME remove the lines below after factorization of parameters # FIXME remove the lines below after factorization of parameters
parameters = dict() parameters = dict()
parameters['field1'] = field1 parameters['field1'] = field1
...@@ -68,14 +67,20 @@ def countCooccurrences( corpus_id=None , cooc_id=None ...@@ -68,14 +67,20 @@ def countCooccurrences( corpus_id=None , cooc_id=None
cooc_id = coocNode.id cooc_id = coocNode.id
else : else :
cooc_id = int(cooc_id[0]) cooc_id = int(cooc_id[0])
# when cooc_id preexisted, but we want to continue (reset = True)
# (to give new contents to this cooc_id)
elif reset:
print("GRAPH #%s ... Counting new cooccurrences data." % cooc_id)
session.query( NodeNgramNgram ).filter( NodeNgramNgram.node_id == cooc_id ).delete()
session.commit()
# when cooc_id preexisted and we just want to load it (reset = False)
else: else:
print("GRAPH #%s ... Loading cooccurrences computed already." % cooc_id) print("GRAPH #%s ... Loading cooccurrences computed already." % cooc_id)
cooc = session.query( NodeNgramNgram.ngram1_id, NodeNgramNgram.ngram2_id, NodeNgramNgram.weight ).filter( NodeNgramNgram.node_id == cooc_id ).all() cooc = session.query( NodeNgramNgram.ngram1_id, NodeNgramNgram.ngram2_id, NodeNgramNgram.weight ).filter( NodeNgramNgram.node_id == cooc_id ).all()
return(int(cooc_id),WeightedMatrix(cooc)) return(int(cooc_id),WeightedMatrix(cooc))
if reset == True :
session.query( NodeNgramNgram ).filter( NodeNgramNgram.node_id == cooc_id ).delete()
session.commit()
NodeNgramX = aliased(NodeNgram) NodeNgramX = aliased(NodeNgram)
...@@ -202,29 +207,29 @@ def countCooccurrences( corpus_id=None , cooc_id=None ...@@ -202,29 +207,29 @@ def countCooccurrences( corpus_id=None , cooc_id=None
#cooc_query = cooc_query.order_by(desc('cooc_score')) #cooc_query = cooc_query.order_by(desc('cooc_score'))
matrix = WeightedMatrix(cooc_query) matrix = WeightedMatrix(cooc_query)
print("GRAPH #%s Filtering the matrix with Map and Group Lists." % cooc_id) print("GRAPH #%s Filtering the matrix with Map and Group Lists." % cooc_id)
cooc = filterMatrix(matrix, mapList_id, groupList_id) cooc = filterMatrix(matrix, mapList_id, groupList_id)
parameters['MapList_id'] = str(mapList_id) parameters['MapList_id'] = str(mapList_id)
parameters['GroupList_id'] = str(groupList_id) parameters['GroupList_id'] = str(groupList_id)
# TODO factorize savings on db # TODO factorize savings on db
if save_on_db: if save_on_db:
# Saving the cooccurrences # Saving the cooccurrences
cooc.save(cooc_id) cooc.save(cooc_id)
print("GRAPH #%s ... Node Cooccurrence Matrix saved" % cooc_id) print("GRAPH #%s ... Node Cooccurrence Matrix saved" % cooc_id)
# Saving the parameters # Saving the parameters
print("GRAPH #%s ... Parameters saved in Node." % cooc_id) print("GRAPH #%s ... Parameters saved in Node." % cooc_id)
coocNode = session.query(Node).filter(Node.id==cooc_id).first() coocNode = session.query(Node).filter(Node.id==cooc_id).first()
coocNode.hyperdata["parameters"] = dict() coocNode.hyperdata["parameters"] = dict()
coocNode.hyperdata["parameters"] = parameters coocNode.hyperdata["parameters"] = parameters
coocNode.save_hyperdata() coocNode.save_hyperdata()
session.commit() session.commit()
#data = cooc2graph(coocNode.id, cooc, distance=distance, bridgeness=bridgeness) #data = cooc2graph(coocNode.id, cooc, distance=distance, bridgeness=bridgeness)
#return data #return data
return(coocNode.id, cooc) return(coocNode.id, cooc)
...@@ -51,7 +51,7 @@ def compute_graph( corpus_id=None , cooc_id=None ...@@ -51,7 +51,7 @@ def compute_graph( corpus_id=None , cooc_id=None
, mapList_id=mapList_id , groupList_id=groupList_id , mapList_id=mapList_id , groupList_id=groupList_id
, isMonopartite=True , threshold = threshold , isMonopartite=True , threshold = threshold
, distance=distance , bridgeness=bridgeness , distance=distance , bridgeness=bridgeness
, save_on_db = True , save_on_db = True , reset = reset
) )
print("GRAPH #%d ... Cooccurrences computed." % (cooc_id)) print("GRAPH #%d ... Cooccurrences computed." % (cooc_id))
...@@ -73,13 +73,13 @@ def compute_graph( corpus_id=None , cooc_id=None ...@@ -73,13 +73,13 @@ def compute_graph( corpus_id=None , cooc_id=None
node.hyperdata[distance] = dict() node.hyperdata[distance] = dict()
node.hyperdata[distance][bridgeness] = data node.hyperdata[distance][bridgeness] = data
node.hyperdata[distance]["nodes"] = len(G.nodes()) node.hyperdata[distance]["nodes"] = len(G.nodes())
node.hyperdata[distance]["edges"] = len(G.edges()) node.hyperdata[distance]["edges"] = len(G.edges())
node.save_hyperdata() node.save_hyperdata()
session.commit() session.commit()
print("GRAPH #%d ... Notify by email owner of the graph." % cooc_id) print("GRAPH #%d ... Notify by email owner of the graph." % cooc_id)
corpus = session.query(Node).filter(Node.id==corpus_id).first() corpus = session.query(Node).filter(Node.id==corpus_id).first()
notify_owner(corpus, cooc_id, distance, bridgeness) notify_owner(corpus, cooc_id, distance, bridgeness)
...@@ -99,25 +99,25 @@ def get_graph( request=None , corpus=None ...@@ -99,25 +99,25 @@ def get_graph( request=None , corpus=None
''' '''
Get_graph : main steps: Get_graph : main steps:
0) Check the parameters 0) Check the parameters
get_graph :: GraphParameters -> Either (Dic Nodes Links) (Dic State Length) get_graph :: GraphParameters -> Either (Dic Nodes Links) (Dic State Length)
where type Length = Int where type Length = Int
get_graph first checks the parameters and return either graph data or a dict with get_graph first checks the parameters and return either graph data or a dict with
state "type" with an integer to indicate the size of the parameter state "type" with an integer to indicate the size of the parameter
(maybe we could add a String in that step to factor and give here the error message) (maybe we could add a String in that step to factor and give here the error message)
1) compute_graph (see function above) 1) compute_graph (see function above)
2) return graph 2) return graph
''' '''
overwrite_node_contents = False
# Case of graph has been computed already # Case of graph has been computed already
if cooc_id is not None: if cooc_id is not None:
print("GRAPH#%d ... Loading data already computed." % int(cooc_id)) print("GRAPH#%d ... Loading data already computed." % int(cooc_id))
node = session.query(Node).filter(Node.id == cooc_id).first() node = session.query(Node).filter(Node.id == cooc_id).first()
# Structure of the Node.hyperdata[distance][bridbeness] # Structure of the Node.hyperdata[distance][bridbeness]
# All parameters (but distance and bridgeness) # All parameters (but distance and bridgeness)
# are in Node.hyperdata["parameters"] # are in Node.hyperdata["parameters"]
...@@ -130,6 +130,23 @@ def get_graph( request=None , corpus=None ...@@ -130,6 +130,23 @@ def get_graph( request=None , corpus=None
if graph.get(str(bridgeness), None) is not None: if graph.get(str(bridgeness), None) is not None:
return graph[str(bridgeness)] return graph[str(bridgeness)]
# new graph: we give it an empty node with new id and status
elif saveOnly:
# NB: we do creation already here (instead of same in countCooccurrences)
# to guarantee a unique ref id to the saveOnly graph (async generation)
new_node = corpus.add_child(
typename = "COOCCURRENCES",
name = "GRAPH (in corpus %s)" % corpus.id
)
session.add(new_node)
session.commit()
cooc_id = new_node.id
# and the empty content will need redoing by countCooccurrences
overwrite_node_contents = True
print("GRAPH #%d ... Created new empty data node for saveOnly" % int(cooc_id))
# Case of graph has not been computed already # Case of graph has not been computed already
# First, check the parameters # First, check the parameters
...@@ -198,10 +215,10 @@ def get_graph( request=None , corpus=None ...@@ -198,10 +215,10 @@ def get_graph( request=None , corpus=None
, mapList_id=mapList_id , groupList_id=groupList_id , mapList_id=mapList_id , groupList_id=groupList_id
, isMonopartite=True , threshold = threshold , isMonopartite=True , threshold = threshold
, distance=distance , bridgeness=bridgeness , distance=distance , bridgeness=bridgeness
, save_on_db = True , save_on_db = True , reset=overwrite_node_contents
#, limit=size #, limit=size
) )
return {"state" : "saveOnly"} return {"state" : "saveOnly", "target_id" : cooc_id}
elif corpus_size > graph_constraints['corpusMax']: elif corpus_size > graph_constraints['corpusMax']:
# Then compute cooc asynchronously with celery # Then compute cooc asynchronously with celery
...@@ -211,10 +228,10 @@ def get_graph( request=None , corpus=None ...@@ -211,10 +228,10 @@ def get_graph( request=None , corpus=None
, mapList_id=mapList_id , groupList_id=groupList_id , mapList_id=mapList_id , groupList_id=groupList_id
, isMonopartite=True , threshold = threshold , isMonopartite=True , threshold = threshold
, distance=distance , bridgeness=bridgeness , distance=distance , bridgeness=bridgeness
, save_on_db = True , save_on_db = True , reset=overwrite_node_contents
#, limit=size #, limit=size
) )
# Dict to inform user that corpus maximum is reached # Dict to inform user that corpus maximum is reached
# then graph is computed asynchronously # then graph is computed asynchronously
return {"state" : "corpusMax", "length" : corpus_size} return {"state" : "corpusMax", "length" : corpus_size}
...@@ -230,7 +247,7 @@ def get_graph( request=None , corpus=None ...@@ -230,7 +247,7 @@ def get_graph( request=None , corpus=None
, mapList_id=mapList_id , groupList_id=groupList_id , mapList_id=mapList_id , groupList_id=groupList_id
, isMonopartite=True , threshold = threshold , isMonopartite=True , threshold = threshold
, distance=distance , bridgeness=bridgeness , distance=distance , bridgeness=bridgeness
, save_on_db = True , save_on_db = True , reset=overwrite_node_contents
#, limit=size #, limit=size
) )
......
...@@ -18,6 +18,11 @@ class Graph(APIView): ...@@ -18,6 +18,11 @@ class Graph(APIView):
Get all the parameters first Get all the parameters first
graph?field1=ngrams&field2=ngrams& graph?field1=ngrams&field2=ngrams&
graph?field1=ngrams&field2=ngrams&start=''&end='' graph?field1=ngrams&field2=ngrams&start=''&end=''
NB save new graph mode
(option saveOnly=True without a cooc_id)
can return the new cooc id in the json
before counting + filling data in async
''' '''
if not request.user.is_authenticated(): if not request.user.is_authenticated():
...@@ -56,7 +61,6 @@ class Graph(APIView): ...@@ -56,7 +61,6 @@ class Graph(APIView):
type_ = str(request.GET.get ('type' , 'node_link' )) type_ = str(request.GET.get ('type' , 'node_link' ))
distance = str(request.GET.get ('distance' , 'conditional')) distance = str(request.GET.get ('distance' , 'conditional'))
# Get default map List of corpus # Get default map List of corpus
if mapList_id == 0 : if mapList_id == 0 :
mapList_id = ( session.query ( Node.id ) mapList_id = ( session.query ( Node.id )
...@@ -100,7 +104,7 @@ class Graph(APIView): ...@@ -100,7 +104,7 @@ class Graph(APIView):
, field1=field1 , field2=field2 , field1=field1 , field2=field2
, mapList_id = mapList_id , groupList_id = groupList_id , mapList_id = mapList_id , groupList_id = groupList_id
, start=start , end=end , start=start , end=end
, threshold =threshold , threshold =threshold
, distance=distance , bridgeness=bridgeness , distance=distance , bridgeness=bridgeness
, saveOnly=saveOnly , saveOnly=saveOnly
) )
...@@ -127,10 +131,10 @@ class Graph(APIView): ...@@ -127,10 +131,10 @@ class Graph(APIView):
# async data case # async data case
link = "http://%s/projects/%d/corpora/%d/myGraphs" % (request.get_host(), corpus.parent_id, corpus.id) link = "http://%s/projects/%d/corpora/%d/myGraphs" % (request.get_host(), corpus.parent_id, corpus.id)
return JsonHttpResponse({ return JsonHttpResponse({
'msg': '''Your graph is saved: 'id': data["target_id"],
'msg': '''Your graph is being saved:
%s %s
''' % format_html(link), ''' % format_html(link)
}, status=200) }, status=200)
elif data["state"] == "corpusMin": elif data["state"] == "corpusMin":
......
...@@ -10,6 +10,43 @@ ...@@ -10,6 +10,43 @@
<script src="{% static "lib/jquery/1.11.1/jquery.min.js" %}" type="text/javascript"></script> <script src="{% static "lib/jquery/1.11.1/jquery.min.js" %}" type="text/javascript"></script>
<script type="text/javascript">
/**
* function goFirstGraph()
*
* 1) run a "save new graph" ajax on graph api
* 2) retrieve the new cooc_id in immediate response
* 3) monitor status of the async generation
*/
function goFirstGraph() {
var graphApi = "/api/projects/{{project.id}}/corpora/{{ corpus.id }}/explorer"
var graphParams = "saveOnly=True&distance=conditional&bridgeness=5"
var coocId = null
// run a "save new graph" ajax
$.ajax({
method: "GET",
url: graphApi + '?' + graphParams,
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data){
// retrieve the new coocId
console.log("data", data)
console.log("data.id", data.id)
},
error: function(result) {
console.log("result", result)
}
});
}
//
</script>
{% endblock %} {% endblock %}
...@@ -35,15 +72,15 @@ ...@@ -35,15 +72,15 @@
From: {% if not cooc.hyperdata.parameters.start %} begin of corpus {% else %} {{cooc.hyperdata.parameters.start}} {% endif %} From: {% if not cooc.hyperdata.parameters.start %} begin of corpus {% else %} {{cooc.hyperdata.parameters.start}} {% endif %}
, To: {% if not cooc.hyperdata.parameters.end %} end of corpus {% else %} {{cooc.hyperdata.parameters.end}} {% endif %} , To: {% if not cooc.hyperdata.parameters.end %} end of corpus {% else %} {{cooc.hyperdata.parameters.end}} {% endif %}
<br> <br>
<ul> <ul>
<li> <li>
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=5"> <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=5">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> <span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
{% if cooc.hyperdata.conditional %} {% if cooc.hyperdata.conditional %}
~{{ cooc.hyperdata.conditional.nodes }} nodes, ~{{ cooc.hyperdata.conditional.nodes }} nodes,
~{{ cooc.hyperdata.conditional.edges }} edges ~{{ cooc.hyperdata.conditional.edges }} edges
with <b>Conditional</b> distance with <b>Conditional</b> distance
{% else %} {% else %}
Compute this graph with Conditional distance Compute this graph with Conditional distance
...@@ -55,9 +92,9 @@ ...@@ -55,9 +92,9 @@
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=5"> <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=5">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> <span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
{% if cooc.hyperdata.distributional %} {% if cooc.hyperdata.distributional %}
~{{ cooc.hyperdata.distributional.nodes }} nodes, ~{{ cooc.hyperdata.distributional.nodes }} nodes,
~{{ cooc.hyperdata.distributional.edges }} edges ~{{ cooc.hyperdata.distributional.edges }} edges
with <b>Distributional</b> distance with <b>Distributional</b> distance
{% else %} {% else %}
Compute this graph with Distributional distance Compute this graph with Distributional distance
...@@ -68,7 +105,7 @@ ...@@ -68,7 +105,7 @@
<br> <br>
<!-- <li>{{cooc.id}}</li> <!-- <li>{{cooc.id}}</li>
<ul> <ul>
<li> <li>
...@@ -123,7 +160,7 @@ ...@@ -123,7 +160,7 @@
</button> </button>
</a> </a>
--!> -->
<button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom" <button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content=" data-content="
...@@ -176,12 +213,14 @@ ...@@ -176,12 +213,14 @@
<li>Choose a distance</li> <li>Choose a distance</li>
<li>Click on the distance or on MyGraph which is this page</li> <li>Click on the distance or on MyGraph which is this page</li>
</ol> </ol>
<h4> <h4>
<span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span> <span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>
Do you want to test ?</h4> Do you want to test ?</h4>
</li> </li>
<a href="/projects/{{project.id}}/corpora/{{ corpus.id }}/explorer?field1=ngrams&amp;field2=ngrams&amp;distance=conditional&amp;bridgeness=5">Compute a new graph with conditional distance!</a> <btn class="btn btn-info" onclick="goFirstGraph()">
<span style="font-size:120%">Compute a new graph</span> <br/> with conditional distance
</btn>
{% endif %} {% endif %}
</ul> </ul>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment