Skip to content

Commit

Permalink
vega visualization framework (start)
Browse files Browse the repository at this point in the history
  • Loading branch information
open-risk committed Jun 21, 2024
1 parent 32d8a2b commit 2687ce2
Show file tree
Hide file tree
Showing 12 changed files with 399 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ v0.8 (Upcoming)
* sqlite bug workaround: python ./manage.py shell -c "import django;django.db.connection.cursor().execute('SELECT InitSpatialMetaData(1);')";
* Enhancements: Postgres backend option
* Scripts for deleting user data from database
* Vega visualization framework

v0.7.1 (14-09-2023)
-------------------
Expand Down
4 changes: 2 additions & 2 deletions CODE_OF_CONDUCT.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Code of Conduct
===============

This code of conduct applies to all online spaces managed by Open Risk. This includes Github, mailing lists, the issue tracker, the Open Risk Commons and/or any other forums created by the Open Risk team towards community usage.
This code of conduct applies to all online spaces managed by Open Risk. This includes Github, mailing lists, issue trackers, the Open Risk Commons and/or any other forums created by the Open Risk team towards community usage.

.. warning:: Violations of this code also outside the above mentioned spaces may affect a person's ability to participate within them.

Expand All @@ -23,4 +23,4 @@ This code of conduct applies to all online spaces managed by Open Risk. This inc
* Repeated harassment of others. In general, if someone asks you to stop, then stop.


Original text courtesy of the Django Project
Original text of this Code of Conduct is courtesy of the Django Project
1 change: 1 addition & 0 deletions equinox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
'policy',
'risk',
'reporting',
'visualization',
'debug_toolbar',
'behave_django'
]
Expand Down
4 changes: 2 additions & 2 deletions portfolio/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from django.contrib.auth.decorators import login_required
from django.views.generic import ListView
from django.views.generic.base import TemplateView

Expand All @@ -36,8 +36,8 @@ def get_context_data(self, **kwargs):
context = super(ListView, self).get_context_data(**kwargs)
return context


class AssetMapView(TemplateView):
"""Asset Markers Map view."""

template_name = "asset_map.html"

4 changes: 4 additions & 0 deletions reporting/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
ChangeLog
===========================

v0.7.0 (21-06-2024)
-------------------
* Vega visualization framework

v0.6.0 (03-06-2023)
-------------------
* Model testing framework
Expand Down
16 changes: 4 additions & 12 deletions reporting/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,22 +158,17 @@ class Meta:
verbose_name_plural = "Results"


OBJECTIVE_CHOICE = [(0, 'General Information'), (1, 'Concentration Risk'), (2, 'Origination'),
(3, 'Risk Appetite'), (4, 'Risk Capital'), (5, 'Other')]


class Visualization(models.Model):
"""
The Visualization Data object holds the structural Vega / Vega-Lite specification of a visualization
Includes reference to user creating the Visualization
"""

VISUALIZATION_DATA_CHOICES = [(0, 'Load portfolio data from local JSON files'),
(1, 'Fetch portfolio data via REST API'),
(2, 'Create new portfolio from local JSON configuration'),
(3, 'Fetch portfolio configuration via REST API'),
(4, 'Attached portfolio data in JSON format')]

OBJECTIVE_CHOICE = [(0, 'Portfolio Information'), (1, 'Concentration Risk'), (2, 'Origination'),
(3, 'Risk Appetite'), (4, 'Risk Capital'), (5, 'Other')]

name = models.CharField(max_length=200, help_text="Assigned name to help manage Visualization collections")
user_id = models.ForeignKey(User, on_delete=models.CASCADE, default=1, help_text="The creator of the Visualization")
creation_date = models.DateTimeField(auto_now_add=True)
Expand All @@ -185,9 +180,6 @@ class Visualization(models.Model):
description = models.TextField(null=True, blank=True, help_text="A description of the main purpose and "
"characteristics of the Visualization")

visualization_data_mode = models.IntegerField(default=1, null=True, blank=True, choices=VISUALIZATION_DATA_CHOICES,
help_text="Select the mode for portfolio data inputs")

visualization_data = models.JSONField(null=True, blank=True, help_text="Container for visualization data")
visualization_data_url = models.URLField(null=True, blank=True, help_text="URL for visualization data")
results_url = models.CharField(max_length=200, null=True, blank=True, help_text="Where to store the results")
Expand Down
71 changes: 71 additions & 0 deletions reporting/templates/reporting/vega_viz.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{% extends "start/generic.html" %}

{% load static %}
{% load custom_tags %}
{% load humanize %}

{% block title %}
{{ title }} Standard Visualization
{% endblock %}

{% block extrahead %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega/5.7.0/vega.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega-lite/3.4.0/vega-lite.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega-embed/5.1.3/vega-embed.js"></script>
{% endblock %}

{% block extrastyle %}
{{ block.super }}
<style media="screen">
.vega-actions a {
margin-right: 5px;
}
</style>
{% endblock %}

{% block messages %}
<div class="helpblock">
<p><i class="fa fa-hand-pointer-o"></i> Declarative Visualization: <b>{{ object.name }} :</b>
<i>{{ object.description }}</i></p>
</div>
{% endblock %}


{% block content %}

<div id="page" class="container-responsive">

<div class="row">
<div class="col-sm-12">
<div id="vis"></div>
</div>
</div>

</div>

<script>
let myData = "{{ visualization_data | escapejs }}";
let spec = "{{ vega_specification | escapejs }}";
let data = JSON.parse(myData);
let vspec = JSON.parse(spec);
console.log(vspec);
console.log(data);

vspec.data = data;visualization_single.html

let runtime = vega.parse(vspec);
let changeSet = vega.changeset().remove(vega.truthy).insert(data);
console.log(changeSet);

let view = new vega.View(runtime)
.logLevel(vega.Warn) // set view logging level
.initialize(document.querySelector('#vis')) // set parent DOM element
.renderer('svg') // set render type (defaults to 'canvas')
.hover() // enable hover event processing
.run(); // update and render the view
</script>


{% endblock %}

3 changes: 2 additions & 1 deletion reporting/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from django.urls import re_path
from django.urls import re_path, path

from reporting import views

Expand Down Expand Up @@ -52,4 +52,5 @@
re_path(r'^portfolio_aggregates$', views.portfolio_aggregates, name='portfolio_aggregates'),
# re_path(r'^result_types$', views.result_types, name='result_types'),
re_path(r'^results_view/(?P<pk>\d+)$', views.results_view, name='results_view'),
re_path(r'^visualization_vega$', views.visualization_vega, name='visualization_vega'),
]
22 changes: 21 additions & 1 deletion reporting/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
from portfolio.models import MultiAreaSource
from reference.NUTS3Data import NUTS3PointData
from reporting.forms import CustomPortfolioAggregatesForm, portfolio_attributes, aggregation_choices
from reporting.models import Calculation, SummaryStatistics, AggregatedStatistics
from reporting.models import Calculation, SummaryStatistics, AggregatedStatistics, Visualization

"""
Expand Down Expand Up @@ -788,3 +788,23 @@ def visualization_sector(request):
context.update({'img_list': img_list})
context.update({'dataset': top_level})
return HttpResponse(t.template.render(context))


@login_required(login_url='/login/')
def visualization_vega(request, pk):
"""
"""

# get the Visualization object
visualization = Visualization.objects.get(pk=pk)
context = RequestContext(request, {})

t = loader.get_template('vega_viz.html')
spec = json.dumps(visualization.vega_specification)
data = json.dumps(visualization.visualization_data)
context.update({'object': visualization})
context.update({'visualization_data': data})
context.update({'vega_specification': spec})

return HttpResponse(t.template.render(context))
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ django-import-export
django-prettyjson
django-countries
django-extensions
django-jsoneditor
django-htmx
django-debug-toolbar~=4.3.0
psycopg2
Expand All @@ -26,6 +27,6 @@ behave-django
pytest~=8.0.1
pytest-bdd
coverage
requests~=2.32.0
requests~=2.31.0
behave~=1.2.6
setuptools~=69.5.1
33 changes: 33 additions & 0 deletions visualization/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from django.contrib import admin
from django.db.models import JSONField
from jsoneditor.forms import JSONEditor

from visualization.models import VegaSpecification, VegaLiteSpecification


class VegaSpecificationAdmin(admin.ModelAdmin):
formfield_overrides = {
JSONField: {'widget': JSONEditor},
}
#
# Searchable fields
#
search_fields = ['description']
list_display = ('title', 'width', 'height', 'description',)
save_as = True
view_on_site = False


class VegaLiteSpecificationAdmin(admin.ModelAdmin):
formfield_overrides = {
JSONField: {'widget': JSONEditor},
}

search_fields = ['description']
list_display = ('title', 'description',)
save_as = True
view_on_site = False


admin.site.register(VegaSpecification, VegaSpecificationAdmin)
admin.site.register(VegaLiteSpecification, VegaLiteSpecificationAdmin)
Loading

0 comments on commit 2687ce2

Please sign in to comment.