1
+ import os
2
+ import pathlib
3
+ import shutil
4
+ import tempfile
5
+ import threading
6
+ import time
7
+ from io import StringIO
8
+ from collections import Counter
9
+ from flask import render_template , current_app
10
+
11
+ from mmif import DocumentTypes
12
+ from mmif .serialize .annotation import Text
13
+ from mmif .vocabulary import AnnotationTypes
14
+ from lapps .discriminators import Uri
15
+ import displacy
16
+
17
+ from helpers import *
18
+
19
+ import cache
20
+
21
+ """
22
+ Methods to render MMIF documents and their annotations in various formats.
23
+ """
24
+
25
+ # -- Documents --
26
+
27
+ def render_documents (mmif , viz_id ):
28
+ """
29
+ Returns HTML Tab representation of all documents in the MMIF object.
30
+ """
31
+ tabs = []
32
+ for document in mmif .documents :
33
+ doc_path = get_doc_path (document )
34
+ if document .at_type == DocumentTypes .TextDocument :
35
+ html_tab = render_text (doc_path )
36
+ elif document .at_type == DocumentTypes .ImageDocument :
37
+ html_tab = render_image (doc_path )
38
+ elif document .at_type == DocumentTypes .AudioDocument :
39
+ html_tab = render_audio (doc_path )
40
+ elif document .at_type == DocumentTypes .VideoDocument :
41
+ html_tab = render_video (doc_path , mmif , viz_id )
42
+
43
+ tabs .append ({"id" : document .id ,
44
+ "tab_name" : document .at_type .shortname ,
45
+ "html" : html_tab })
46
+ return tabs
47
+
48
+ def render_text (text_path ):
49
+ """Return the content of the text document, but with some HTML tags added."""
50
+ if not os .path .isfile (text_path ):
51
+ raise FileNotFoundError (f"File not found: { text_path } " )
52
+ with open (text_path ) as t_file :
53
+ content = t_file .read ().replace ("\n " , "<br/>\n " )
54
+ return f"{ content } \n "
55
+
56
+ def render_image (img_path ):
57
+ return ""
58
+
59
+ def render_audio (audio_path ):
60
+ return ""
61
+
62
+ def render_video (vid_path , mmif , viz_id ):
63
+ vid_path = url2posix (vid_path )
64
+ html = StringIO ()
65
+ html .write ('<video id="vid" controls crossorigin="anonymous" >\n ' )
66
+ html .write (f' <source src=\" { vid_path } \" >\n ' )
67
+ for view in mmif .views :
68
+ if get_abstract_view_type (view ) == "ASR" :
69
+ vtt_path = get_vtt_file (view , viz_id )
70
+ rel_vtt_path = vtt_path [(len ("/tmp/" ) + len (current_app .static_folder )):]
71
+ html .write (f' <track kind="captions" srclang="en" src="/{ rel_vtt_path } " label="transcript" default/>\n ' )
72
+ html .write ("</video>\n " )
73
+ return html .getvalue ()
74
+
75
+ # -- Annotations --
76
+
77
+ def render_annotations (mmif , viz_id ):
78
+ """
79
+ Returns HTML Tab representation of all annotations in the MMIF object.
80
+ """
81
+ tabs = []
82
+ # These tabs should always be present
83
+ tabs .append ({"id" : "info" , "tab_name" : "Info" , "html" : render_info (mmif )})
84
+ tabs .append ({"id" : "annotations" , "tab_name" : "Annotations" , "html" : render_annotation_table (mmif )})
85
+ tabs .append ({"id" : "tree" , "tab_name" : "Tree" , "html" : render_jstree (mmif )})
86
+ # These tabs are optional
87
+ for view in mmif .views :
88
+ abstract_view_type = get_abstract_view_type (view )
89
+ app_shortname = view .metadata .app .split ("/" )[- 2 ]
90
+ if abstract_view_type == "NER" :
91
+ tabs .append ({"id" : view .id , "tab_name" : f"{ app_shortname } -{ view .id } " , "html" : render_ner (mmif , view )})
92
+ elif abstract_view_type == "ASR" :
93
+ tabs .append ({"id" : view .id , "tab_name" : f"{ app_shortname } -{ view .id } " , "html" : render_asr_vtt (view , viz_id )})
94
+ return tabs
95
+
96
+ def render_info (mmif ):
97
+ s = StringIO ('Howdy' )
98
+ s .write ("<pre>" )
99
+ for document in mmif .documents :
100
+ at_type = document .at_type .shortname
101
+ location = document .location
102
+ s .write ("%s %s\n " % (at_type , location ))
103
+ s .write ('\n ' )
104
+ for view in mmif .views :
105
+ app = view .metadata .app
106
+ status = get_status (view )
107
+ s .write ('%s %s %s %d\n ' % (view .id , app , status , len (view .annotations )))
108
+ if len (view .annotations ) > 0 :
109
+ s .write ('\n ' )
110
+ types = Counter ([a .at_type .shortname
111
+ for a in view .annotations ])
112
+ for attype , count in types .items ():
113
+ s .write (' %4d %s\n ' % (count , attype ))
114
+ s .write ('\n ' )
115
+ s .write ("</pre>" )
116
+ return s .getvalue ()
117
+
118
+
119
+ def render_annotation_table (mmif ):
120
+ s = StringIO ('Howdy' )
121
+ for view in mmif .views :
122
+ status = get_status (view )
123
+ s .write ('<p><b>%s %s</b> %s %d annotations</p>\n '
124
+ % (view .id , view .metadata .app , status , len (view .annotations )))
125
+ s .write ("<blockquote>\n " )
126
+ s .write ("<table cellspacing=0 cellpadding=5 border=1>\n " )
127
+ limit_len = lambda str : str [:500 ] + " . . . }" if len (str ) > 500 else str
128
+ for annotation in view .annotations :
129
+ s .write (' <tr>\n ' )
130
+ s .write (' <td>%s</td>\n ' % annotation .id )
131
+ s .write (' <td>%s</td>\n ' % annotation .at_type .shortname )
132
+ s .write (' <td>%s</td>\n ' % limit_len (get_properties (annotation )))
133
+ s .write (' </tr>\n ' )
134
+ s .write ("</table>\n " )
135
+ s .write ("</blockquote>\n " )
136
+ return s .getvalue ()
137
+
138
+ def render_jstree (mmif ):
139
+ return render_template ('interactive.html' , mmif = mmif , aligned_views = [])
140
+
141
+ def render_asr_vtt (view , viz_id ):
142
+ vtt_filename = get_vtt_file (view , viz_id )
143
+ with open (vtt_filename ) as vtt_file :
144
+ vtt_content = vtt_file .read ()
145
+ return f"<pre>{ vtt_content } </pre>"
146
+
147
+ def render_ner (mmif , view ):
148
+ metadata = view .metadata .contains .get (Uri .NE )
149
+ ner_document = metadata .get ('document' )
150
+ return displacy .visualize_ner (mmif , view , ner_document , current_app .root_path )
151
+
152
+ def render_ocr ():
153
+ pass
0 commit comments