Skip to content

Commit

Permalink
Merge pull request #17 from ClimateCompatibleGrowth/type_and_rank
Browse files Browse the repository at this point in the history
Type and rank
  • Loading branch information
willu47 authored Apr 4, 2024
2 parents ed3709c + 61644b2 commit 0e2fcb8
Show file tree
Hide file tree
Showing 12 changed files with 304 additions and 114 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ build/

# Ignore environment variables file
.env

# Ignore system files
.DS_Store
40 changes: 36 additions & 4 deletions app/app.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
from flask import Flask, render_template
from flask import Flask, render_template, request

from model import (Author, Output, AuthorList, OutputList, Nodes, Edges,
CountryList, Country)

from logging import getLogger, basicConfig, DEBUG

logger = getLogger(__name__)
basicConfig(filename='example.log', filemode='w', encoding='utf-8', level=DEBUG)


app = Flask(__name__)



@app.route('/countries/<id>')
def country(id: str):
country_model = Country()
outputs, country = country_model.get(id)
return render_template('country.html', title='Country', outputs=outputs, country=country)

result_type = request.args.get('type')
logger.debug(f"Obtained filter {result_type}")
if result_type:
logger.info(f"Filtering outputs on {result_type}")
outputs, country = country_model.get(id, result_type=result_type)
else:
outputs, country = country_model.get(id)

return render_template('country.html', title='Country', outputs=outputs,
country=country)


@app.route('/countries')
Expand All @@ -23,7 +40,15 @@ def country_list():
@app.route('/authors/<id>')
def author(id: str):
author_model = Author()
entity = author_model.get(id)
result_type = request.args.get('type')
logger.debug(f"Obtained filter {result_type}")
if result_type:
logger.info(f"Filtering outputs on {result_type}")
entity = author_model.get(id, type=result_type)
else:
entity = author_model.get(id)
logger.debug(entity)

return render_template('author.html', title='Author', author=entity)


Expand All @@ -37,13 +62,20 @@ def author_list():
@app.route('/outputs')
def output_list():
model = OutputList()
entity = model.get()
result_type = request.args.get('type')
logger.debug(f"Obtained filter {result_type}")
if result_type:
logger.info(f"Filtering outputs on {result_type}")
entity = model.filter_type(result_type=result_type)
else:
entity = model.get()
return render_template('outputs.html', title='Output List', outputs=entity)


@app.route('/outputs/<id>')
def output(id: str):
output_model = Output()

entity = output_model.get(id)
return render_template('output.html', title='Output', output=entity)

Expand Down
118 changes: 94 additions & 24 deletions app/model.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from neo4j import GraphDatabase
from neo4j import GraphDatabase, Driver
import os
from functools import wraps

Expand Down Expand Up @@ -31,23 +31,54 @@ class OutputList:
@connect_to_db
def get(self, db):
"""
Notes
-----
MATCH (o:Article)
OPTIONAL MATCH (p)-[:REFERS_TO]->(c:Country)
RETURN o, collect(c) as countries;
"""
query = """
MATCH (o:Article)
OPTIONAL MATCH (o)-[:REFERS_TO]->(c:Country)
RETURN o as output, collect(c) as countries;
MATCH (o:Article)
OPTIONAL MATCH (o)-[:REFERS_TO]->(c:Country)
CALL
{
WITH o
MATCH (a:Author)-[b:author_of]->(o)
RETURN a
ORDER BY b.rank
}
RETURN o as outputs, collect(DISTINCT c) as countries, collect(a) as authors;
"""
records, summary, keys = db.execute_query(query)
articles = [x.data() for x in records]

return articles

@connect_to_db
def filter_type(self, db: Driver, result_type: str):
"""Returns all outputs with ordered authors filtering on result type
Arguments
---------
dbL
result_type: str
"""
query = """
MATCH (o:Article)
WHERE o.result_type = $result_type
OPTIONAL MATCH (o)-[:REFERS_TO]->(c:Country)
CALL
{
WITH o
MATCH (a:Author)-[b:author_of]->(o)
RETURN a
ORDER BY b.rank
}
RETURN o as outputs,
collect(DISTINCT c) as countries,
collect(a) as authors;
"""
records, summary, keys = db.execute_query(query,
result_type=result_type)
articles = [x.data() for x in records]

return articles


class AuthorList:

Expand All @@ -72,14 +103,14 @@ def get(self, db):
class Author:

@connect_to_db
def get(self, id, db):
def get(self, id, db, type=None):
"""
Notes
-----
MATCH (a:Author)
RETURN a.first_name as first_name, a.last_name as last_name, p.name as affiliation;
RETURN a.first_name as first_name, a.last_name as last_name,
p.name as affiliation;
MATCH (a:Author)-[r:author_of]->(p:Article)
OPTIONAL MATCH (a:Author)-[:member_of]->(p:Partner)
WHERE a.uuid = $uuid
Expand All @@ -89,7 +120,9 @@ def get(self, id, db):
author_query = """MATCH (a:Author) WHERE a.uuid = $uuid
OPTIONAL MATCH (a)-[:member_of]->(p:Partner)
OPTIONAL MATCH (a)-[:member_of]->(u:Workstream)
RETURN a.uuid as uuid, a.orcid as orcid, a.first_name as first_name, a.last_name as last_name, collect(p.id, p.name) as affiliations,
RETURN a.uuid as uuid, a.orcid as orcid,
a.first_name as first_name, a.last_name as last_name,
collect(p.id, p.name) as affiliations,
collect(u.id, u.name) as workstreams;
"""
author, summary, keys = db.execute_query(author_query, uuid=id)
Expand All @@ -103,11 +136,37 @@ def get(self, id, db):

results['collaborators'] = colabs

publications_query = """MATCH (a:Author)-[:author_of]->(p:Output)
MATCH (b:Author)-[:author_of]->(p)
WHERE a.uuid = $uuid
RETURN DISTINCT p as outputs, collect(b) as authors;"""
result, summary, keys = db.execute_query(publications_query, uuid=id)
if type and type in ['publication', 'dataset', 'software', 'other']:
publications_query = """MATCH (a:Author)-[:author_of]->(p:Output)
WHERE (a.uuid) = $uuid AND (p.result_type = $type)
CALL {
WITH p
MATCH (b:Author)-[r:author_of]->(p)
RETURN b
ORDER BY r.rank
}
OPTIONAL MATCH (p)-[:REFERS_TO]->(c:Country)
RETURN p as outputs,
collect(DISTINCT c) as countries,
collect(b) as authors
ORDER BY outputs.publication_year DESCENDING;"""
else:
publications_query = """MATCH (a:Author)-[:author_of]->(p:Output)
WHERE a.uuid = $uuid
CALL {
WITH p
MATCH (b:Author)-[r:author_of]->(p)
RETURN b
ORDER BY r.rank
}
OPTIONAL MATCH (p)-[:REFERS_TO]->(c:Country)
RETURN p as outputs,
collect(DISTINCT c) as countries,
collect(b) as authors
ORDER BY outputs.publication_year DESCENDING;"""
result, summary, keys = db.execute_query(publications_query,
uuid=id,
type=type)
results['outputs'] = [x.data() for x in result]

return results
Expand Down Expand Up @@ -169,7 +228,7 @@ def get(self, db):
class CountryList:

@connect_to_db
def get(self, db):
def get(self, db: Driver):

query = """MATCH (c:Country)<-[:REFERS_TO]-(p:Article)
RETURN DISTINCT c
Expand All @@ -181,17 +240,28 @@ def get(self, db):
class Country:

@connect_to_db
def get(self, id: str, db):
def get(self, id: str, db: Driver, result_type=None):

query = """
if result_type:
query = """
MATCH (o:Output)-[r:REFERS_TO]->(c:Country)
MATCH (a:Author)-[:author_of]->(o:Output)
WHERE c.id = $id AND (o.result_type = $result_type)
RETURN o as outputs, collect(a) as authors;
"""
results, _, _ = db.execute_query(query, id=id,
result_type=result_type)
else:
query = """
MATCH (o:Output)-[r:REFERS_TO]->(c:Country)
MATCH (a:Author)-[:author_of]->(o:Output)
WHERE c.id = $id
RETURN o as outputs, collect(a) as authors;
"""
results, summary, keys = db.execute_query(query, id=id)
results, _, _ = db.execute_query(query, id=id,
result_type=result_type)
outputs = [x.data() for x in results]
query = """MATCH (c:Country) WHERE c.id = $id RETURN c as country;"""
results, summary, keys = db.execute_query(query, id=id)
results, _, _ = db.execute_query(query, id=id)
country = results[0].data()['country']
return outputs, country
1 change: 1 addition & 0 deletions app/static/js/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ node.call(d3.drag()
.on("end", dragended));

function dblclick(event, a){
const url = ""
switch(a.group) {
case 0:
url = "/authors/" + a.id
Expand Down
71 changes: 71 additions & 0 deletions app/static/js/world.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const HOVER_COLOR = "#d36f80"


function mouseOverHandler(d, i) {
d3.select(this).attr("fill", HOVER_COLOR)
}
function mouseOutHandler(d, i) {
d3.select(this).attr("fill", "red")
}
function clickHandler(d, i) {
const url = "/countries/" + i.id
window.location.assign(url, '_blank')
}


// The svg
const svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");

// Map and projection
const projection = d3.geoNaturalEarth1()
.scale(width / 1.3 / Math.PI)
.translate([width / 2, height / 2])


const countries = country_data;

// Load external data and draw base map
d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson").then( function(data) {

// Draw the map
svg.append("g")
.selectAll("path")
.data(data.features)
.join("path")
.attr("fill", "#69b3a2")
.attr("d", d3.geoPath()
.projection(projection)
)
.style("stroke", "#fff")
})

// Load external data and highlight countries
d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson").then( function(data){

// Filter data

countries.forEach(country => {

const filtered_data = data.features.filter(d => {return d.properties.name==country.c.name})

// Draw the map
svg.append("g")
.selectAll("path")
.data(filtered_data)
.join("path")
.attr("fill", "red")
.attr("d", d3.geoPath()
.projection(projection)
)
.style("stroke", "#fff")
.on("mouseover", mouseOverHandler)
.on("mouseout", mouseOutHandler)
.on("click", clickHandler)

}
);

})

Loading

0 comments on commit 0e2fcb8

Please sign in to comment.