From 1fd0dd8b28bac19431a8c577ee78ea655882ad82 Mon Sep 17 00:00:00 2001 From: Gertjan van den Burg Date: Wed, 31 Jul 2019 16:28:31 +0100 Subject: Add support for multidimensional datasets --- app/admin/routes.py | 4 +- app/main/demo.py | 31 +++ app/main/routes.py | 5 +- app/static/css/admin/view_annotation.css | 6 + app/static/css/demo/evaluate.css | 5 + app/static/css/main/annotate.css | 5 + app/static/js/buttons.js | 14 +- app/static/js/makeChart.js | 1 - app/static/js/makeChartMulti.js | 319 ++++++++++++++++++++++++ app/static/js/updateTable.js | 74 ++++++ app/templates/admin/annotations_by_dataset.html | 4 + app/templates/annotate/index.html | 6 +- app/templates/demo/evaluate.html | 37 +-- demo_data/demo_800.json | 224 +++++++++++++++++ 14 files changed, 709 insertions(+), 26 deletions(-) create mode 100644 app/static/js/makeChartMulti.js create mode 100644 demo_data/demo_800.json diff --git a/app/admin/routes.py b/app/admin/routes.py index b8ca81b..9b7688b 100644 --- a/app/admin/routes.py +++ b/app/admin/routes.py @@ -129,7 +129,7 @@ def manage_users(): @admin_required def manage_datasets(): dataset_list = [(d.id, d.name) for d in Dataset.query.all()] - dataset_list.sort(key=lambda x : x[1]) + dataset_list.sort(key=lambda x: x[1]) form = AdminManageDatasetsForm() form.dataset.choices = dataset_list @@ -281,11 +281,13 @@ def view_annotations_by_dataset(dset_id): anno_clean.append(dict(user=uid, index=ann.cp_index)) data = load_data_for_chart(dataset.name, dataset.md5sum) + is_multi = len(data["chart_data"]["values"]) > 1 data["annotations"] = anno_clean return render_template( "admin/annotations_by_dataset.html", title="View Annotations for dataset", data=data, + is_multi=is_multi, ) diff --git a/app/main/demo.py b/app/main/demo.py index afb7f61..2edae04 100644 --- a/app/main/demo.py +++ b/app/main/demo.py @@ -252,6 +252,32 @@ DEMO_DATA = { ) }, }, + 8: { + "dataset": {"name": "demo_800"}, + "learn": { + "text": markdown.markdown( + textwrap.dedent( + """ + In practice time series datasets are not just one + dimensional, but can be multidimensional too. A change + point in such a time series does not necessarily occur in + all dimensions simultaneously. It is therefore important to + evaluate the behaviour of each dimension individually, as + well as in relation to the others.""" + ) + ) + }, + "annotate": {"text": RUBRIC}, + "evaluate": { + "text": markdown.markdown( + textwrap.dedent( + """ + In this example of a multidimensional time series, the + change only occurred in a single dimension.""" + ) + ) + }, + }, } @@ -373,13 +399,16 @@ def demo_annotate(demo_id): "error", ) return redirect(url_for("main.index")) + chart_data = load_data_for_chart(dataset.name, dataset.md5sum) + is_multi = len(chart_data["chart_data"]["values"]) > 1 return render_template( "annotate/index.html", title="Introduction – %i" % demo_id, data=chart_data, rubric=demo_data["text"], identifier=demo_id, + is_multi=is_multi, ) @@ -398,6 +427,7 @@ def demo_evaluate(demo_id, phase_id, form): name=DEMO_DATA[demo_id]["dataset"]["name"] ).first() chart_data = load_data_for_chart(dataset.name, dataset.md5sum) + is_multi = len(chart_data["chart_data"]["values"]) > 1 true_changepoints = get_demo_true_cps(dataset.name) if true_changepoints is None: flash( @@ -415,6 +445,7 @@ def demo_evaluate(demo_id, phase_id, form): annotations_true=annotations_true, text=demo_data["text"], form=form, + is_multi=is_multi ) diff --git a/app/main/routes.py b/app/main/routes.py index ad78f27..02ec7c9 100644 --- a/app/main/routes.py +++ b/app/main/routes.py @@ -18,7 +18,8 @@ logger = logging.getLogger(__name__) RUBRIC = """ Please mark the point(s) in the time series where an abrupt change in the behaviour of the series occurs. The goal is to define segments of the time - series that are separated by places where these abrupt changes occur. + series that are separated by places where these abrupt changes occur. Recall + that it is also possible for there to be no such changes.
""" @@ -112,10 +113,12 @@ def annotate(task_id): flash( "An internal error occurred loading this dataset, the admin has been notified. Please try again later. We apologise for the inconvenience." ) + is_multi = len(data["chart_data"]["values"]) > 1 return render_template( "annotate/index.html", title=task.dataset.name.title(), identifier=task.id, data=data, rubric=RUBRIC, + is_multi=is_multi, ) diff --git a/app/static/css/admin/view_annotation.css b/app/static/css/admin/view_annotation.css index 11bf3c8..09d5a4d 100644 --- a/app/static/css/admin/view_annotation.css +++ b/app/static/css/admin/view_annotation.css @@ -9,6 +9,12 @@ clip-path: url(#clip); } +.z-line line { + stroke: #ccc; + shape-rendering: crispEdges; +} + + .ann-line { fill: none; stroke-dasharray: 5; diff --git a/app/static/css/demo/evaluate.css b/app/static/css/demo/evaluate.css index 0c7dbc2..aea3162 100644 --- a/app/static/css/demo/evaluate.css +++ b/app/static/css/demo/evaluate.css @@ -19,6 +19,11 @@ clip-path: url(#clip); } +.z-line line { + stroke: #ccc; + shape-rendering: crispEdges; +} + circle { clip-path: url(#clip); fill: blue; diff --git a/app/static/css/main/annotate.css b/app/static/css/main/annotate.css index 595f2a2..d1ff2b3 100644 --- a/app/static/css/main/annotate.css +++ b/app/static/css/main/annotate.css @@ -9,6 +9,11 @@ clip-path: url(#clip); } +.z-line line { + stroke: #ccc; + shape-rendering: crispEdges; +} + circle { clip-path: url(#clip); fill: blue; diff --git a/app/static/js/buttons.js b/app/static/js/buttons.js index 75adad2..edd3f56 100644 --- a/app/static/js/buttons.js +++ b/app/static/js/buttons.js @@ -47,15 +47,19 @@ function submitOnClick(identifier) { var obj = {}; obj["identifier"] = identifier; obj["changepoints"] = []; - var i, cp; + + var i, cp, xval, seen = []; for (i=0; i + {% if is_multi %} + + {% else %} + {% endif %} - + {% if is_multi %} + + {% else %} + + {% endif %} - - - +{% block scripts %} + {{ super() }} + + {% if is_multi %} + + {% else %} + + {% endif %} + + {% endblock %} diff --git a/demo_data/demo_800.json b/demo_data/demo_800.json new file mode 100644 index 0000000..4151e74 --- /dev/null +++ b/demo_data/demo_800.json @@ -0,0 +1,224 @@ +{ + "name": "demo_800", + "n_obs": 100, + "n_dim": 2, + "demo": { + "true_CPs": [ + 65 + ] + }, + "series": [ + { + "label": "V1", + "type": "float", + "raw": [ + 2.4048337302746465, + 2.7168349605639315, + 0.9041074861194818, + 0.14437038954839643, + -0.5221323890548066, + -1.7599042604063269, + -2.548293050233459, + -2.208426298362067, + -1.256954097725121, + 1.2673541962415547, + 1.1733075975968035, + 2.572511100788756, + 4.835403025842459, + 4.5522544564588365, + 3.1314009643946106, + 2.9117530434659322, + 1.989596205887107, + 0.12295916283122152, + -1.572080765613325, + -1.4020154454558442, + -0.5797659111967578, + 1.3052476134525937, + 2.463483078997914, + 2.6208640977905917, + 5.276333136526055, + 6.189478034635046, + 4.749709400197241, + 4.332421204937167, + 3.5869975973229327, + 2.418661492344107, + -0.6660467926540834, + 0.558797974643422, + 0.42616473119351966, + 0.7669826506319701, + 1.9841902051028015, + 4.037621600143654, + 4.716794663084997, + 6.351483458807052, + 8.15722901100052, + 6.799628004587378, + 4.679336321650161, + 4.620601716252461, + 2.035199758371592, + 1.436517310229426, + 1.1046729586309985, + 1.7317671802316381, + 3.7804685922880745, + 4.904957692680897, + 6.577527584844899, + 7.772812515037654, + 8.7669639673688, + 7.7275133582092925, + 8.081106500414604, + 5.633331811986405, + 4.320656385064652, + 3.675975491302624, + 2.239294039901483, + 3.752799894422126, + 3.578790640480911, + 4.956034869436094, + 6.672164066165842, + 7.360081623700845, + 9.562433533804628, + 10.265674738007569, + 9.101981636121108, + -2.194041154997131, + -3.7012586157863887, + -7.653582763774726, + -9.292337495769667, + -8.902372732926226, + -9.767801399199508, + -8.340357720658075, + -5.0078952785839865, + -4.048857544065237, + -1.3177865542217697, + -0.9020124604731076, + -2.243740257406788, + -2.917482586327878, + -4.543662767507734, + -7.306029963030574, + -10.384296518475317, + -12.165420998763718, + -12.178529260880655, + -10.812463114033422, + -10.252447277392156, + -7.776749620293404, + -4.635861860775694, + -3.767672729617822, + -3.487478378396219, + -4.924371469527412, + -5.449262162042549, + -8.8927776405326, + -11.5780076846028, + -13.993805845864184, + -14.50818663568779, + -15.426098632186385, + -13.788291197384886, + -11.466791970497958, + -8.09824714195754, + -6.507185697165474 + ] + }, + { + "label": "V2", + "type": "float", + "raw": [ + -0.512144907328231, + 1.180877094568944, + 3.21495688649086, + 3.30100039164296, + 3.131495877850537, + 2.7083848725753303, + 0.7046621090030554, + -0.3722455317527476, + -2.763208097405329, + -2.851611407399316, + -1.7838053015227253, + -1.1835756790551795, + -0.05856749542015677, + 1.0602337342952541, + 2.5560931755237783, + 4.177640415008337, + 5.523261596773609, + 4.800082701701678, + 3.4350373458935746, + 1.2402178666145889, + 0.049773845309929565, + -1.1708812671512536, + -1.593035979997087, + -0.2755433654490299, + 0.6089266866075381, + 1.0410460807006094, + 5.082064906086399, + 5.505648973005408, + 7.120925673938372, + 5.483312226619, + 5.950385821097255, + 4.2473500772756445, + 2.297363185979542, + 0.015007388288893253, + 0.4463898055824315, + 0.38522786716705426, + 1.80126348142217, + 2.8821847137728254, + 4.781507667944923, + 5.425458351881453, + 6.146347067030369, + 7.202635814182365, + 6.337887131797799, + 5.616181429738069, + 4.970747236155149, + 2.8316763970841063, + 1.039352795004348, + 1.1794953229977527, + 2.1759611489770676, + 3.5479131243271196, + 3.8850902219360375, + 6.719505790505435, + 6.73812227273263, + 8.735255788221282, + 9.109738825694748, + 7.288225019795107, + 6.532489310182096, + 4.626223961087513, + 4.086838254635324, + 3.6636721899874596, + 3.396811467240758, + 3.332395646124288, + 6.04695253681218, + 7.7372895641498625, + 8.78651148176425, + 9.823884515175894, + 9.491162963215556, + 10.60522937026037, + 7.6503138685368945, + 7.060110792801475, + 5.377920287327379, + 4.471776085391286, + 4.873833216101378, + 3.5502975827744505, + 6.981666375706383, + 7.77963248562725, + 8.358288716655693, + 10.16088761127809, + 10.503949710979114, + 9.802832103790408, + 10.117476586020533, + 9.351456920006646, + 7.955556636697319, + 5.013496099614551, + 5.993411963284857, + 5.572772912761436, + 6.629075184090689, + 6.8058184040419105, + 9.35773531204678, + 10.718106089686358, + 10.635573210445399, + 11.818990011454368, + 11.103782047235141, + 10.911261978781269, + 10.683238595620933, + 8.45732816202584, + 6.884877092827968, + 6.826985186303127, + 5.915951292057806, + 7.975570042788154 + ] + } + ] +} \ No newline at end of file -- cgit v1.2.3