Annotation Focus
basicviewportannotationszoomfocus
Console
PMA.UI version: 2.43.3
Annotation focus tool
annotation_focus.html
1<!doctype >
2<html lang="en">
3
4<head>
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=10">
7 <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
8 <meta name="google" content="notranslate">
9
10 <!-- Include PMA.UI required libraries downloaded or from CDN -->
11 <script src="./pma.ui/jquery-3.1.0.js"></script>
12 <link href="./pma.ui/font-awesome.min.css" type="text/css" rel="stylesheet">
13
14 <!-- Include optional libraries downloaded or from CDN -->
15 <link rel="stylesheet" href="./pma.ui/bootstrap.min.css">
16 <script src="./pma.ui/bootstrap.bundle.min.js"></script>
17
18 <!-- Include PMA.UI script & css -->
19 <script src="./pma.ui/pma.ui.js"></script>
20 <link href="./pma.ui/pma.ui.css" type="text/css" rel="stylesheet">
21
22 <!-- Include custom script & css -->
23 <script src="./js/annotation_focus.js"></script>
24 <link href="./css/annotation_focus.css" type="text/css" rel="stylesheet">
25
26 <title>Annotation Focus</title>
27
28</head>
29
30<body>
31 <div id="annotation-tools" class="slide">
32 <div class="btn-group btn-group-sm">
33 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="Circle" title="Circle">
34 <i class="fa fa-circle-o"></i>
35 </button>
36 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="Rectangle" title="Rectangle">
37 <i class="fa fa-square-o"></i>
38 </button>
39 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="Polygon" title="Polygon">
40 <i class="fa fa-square"></i>
41 </button>
42 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="Freehand" title="Freehand">
43 <i class="fa fa-pencil"></i>
44 </button>
45 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="Arrow" title="Arrow">
46 <i class="fa fa-arrow-right"></i>
47 </button>
48 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="Ellipse" title="Ellipse">
49 <i class="fa fa-circle"></i>
50 </button>
51 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="MultiPoint" title="MultiPoint">
52 <i class="fa fa-dot-circle-o"></i>
53 </button>
54 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="ClosedFreehand" title="Closed freehand">
55 <i class="fa fa-pencil-square"></i>
56 </button>
57 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="Line" title="Line">
58 <i class="fa fa-minus"></i>
59 </button>
60 <button type="button" class="btn btn-default" disabled data-action="draw" data-type="CompoundFreehand" title="Compound polygon">
61 <i class="fa fa-minus"></i>
62 </button>
63 </div>
64 <input id="color-picker-hidden" type='hidden' value='#78eb10' class="color-picker" />
65 <div id="color-picker-container" class="btn-group btn-group-sm">
66 <input id="color-picker-native" type='color' value='#78eb10' class="color-picker" />
67 </div>
68 <div class="btn-group btn-group-sm">
69 <button type="button" class="btn btn-default color-btn" data-color="#0000ff" style="color:#0000ff">
70 <i class='fa fa-square'></i>
71 </button>
72 <button type="button" class="btn btn-default color-btn" data-color="#ff0000" style="color:#ff0000">
73 <i class='fa fa-square'></i>
74 </button>
75 <button type="button" class="btn btn-default color-btn" data-color="#00ff00" style="color:#00ff00">
76 <i class='fa fa-square'></i>
77 </button>
78 </div>
79 <div class="btn-group btn-group-sm" data-toggle="buttons">
80 <button type="button" class="btn btn-primary" disabled data-action="delete" data-type title="Delete">
81 <i class="fa fa-times"></i>
82 </button>
83 <button type="button" class="btn btn-primary" disabled data-action="deleteall" data-type title="Delete all">
84 <i class="fa fa-times-circle"></i>
85 </button>
86 <button type="button" class="btn btn-primary" disabled data-action="save" data-type title="Save">
87 <i class="fa fa-save"></i>
88 </button>
89 </div>
90 <div class="btn-group btn-group-sm">
91 <button type="button" class="focus-button btn btn-primary" data-action="annotation-zoom" data-zoom="true" title="Annotation zoom">
92 <span class="caret">Annotation Zoom <i class="fa fa-search-plus"></i></span>
93 </button>
94 <button type="button" class="focus-button btn btn-primary" data-action="annotation-center" data-zoom="false" title="Annotation center">
95 <span class="caret">Annotation Center <i class="fas fa-crosshairs"></i></span>
96 </button>
97 </div>
98 <div class="btn-group btn-group-sm">
99 <span class="annotation-helper-icon">
100 <i class="fas fa-spinner fa-spin"></i>
101 <span class="badge bg-success"><i class="fas fa-check"></i> Saved</span>
102 <span class="badge bg-danger"><i class="fas fa-times"></i> Error</span>
103 </span>
104 </div>
105 </div>
106 <div id="viewer"></div>
107</body>
108
109</html>
annotation_focus.css
1html,
2body {
3 height: 100%;
4 padding: 0px;
5 margin: 0px;
6 overflow: hidden;
7}
8
9body .pma-ui-viewport-container {
10 height: calc(100% - 64px);
11 width: 100%;
12}
13
14button {
15 border: 1px solid lightgrey !important;
16}
17
18.btn-group {
19 padding: 0 5px;
20}
21
22.annotation-helper-icon i,
23.annotation-helper-icon span {
24 display: none;
25}
26
27.annotation-helper-icon.loading i {
28 display: initial;
29}
30
31.annotation-helper-icon.loading span {
32 display: none;
33}
34
35.annotation-helper-icon.saved i,
36.annotation-helper-icon.saved span.badge.bg-danger {
37 display: none;
38}
39
40.annotation-helper-icon.saved span.badge.bg-success {
41 display: initial;
42}
43
44.annotation-helper-icon.error i,
45.annotation-helper-icon.error span.badge.bg-success {
46 display: none;
47}
48
49.annotation-helper-icon.error span.badge.bg-danger {
50 display: block;
51}
52
53#viewer {
54 border: 2px solid rgba(0, 60, 136, .5);
55}
56
57#annotation-tools {
58 padding: 15px 5px;
59}
60
61#focus-button {
62 width: 120px;
63}
annotation_focus.js
1var serverUrl = "https://host.pathomation.com/pma.core.3/";
2var imageUrl = "wsiformats/brightfield/3DHistech/CMU-1.mrxs";
3var imageBaseUrl = "https://host.pathomation.com/pma.view/Content/themes/base/Images/";
4var usr = "PMA_UI_demo";
5var pwd = "PMA_UI_demo";
6
7console.log(`PMA.UI version: ${PMA.UI.getVersion()}`);
8
9function supportsColorPicker() {
10 var colorInput;
11 colorInput = $('<input type="color" value="!" />')[0];
12 return colorInput.type === 'color' && colorInput.value !== '!';
13}
14
15function drawCommands(action, type) {
16 if (action) {
17 window.pointCounting = false;
18
19 if (action == "draw") {
20 annotationManager.stopTool();
21 var color = $(".color-picker").val();
22 if (type == 'Rectangle' || type == 'Ellipse' || type == 'Circle') {
23 size = [4000, 8000];
24 }
25
26 var f = window.annotationManager.getSelection();
27
28 window.annotationManager.startDrawing({
29 type: type,
30 color: color,
31 fillColor: "rgba(33,44,55,255)",
32 lineThickness: Math.floor(Math.random() * 15) + 1,
33 iconRelativePath: null,
34 feature: type == "MultiPoint" && f.length > 0 ? f[0] : undefined,
35 notes: $("#annotation-text").val() ? $("#annotation-text").val() : " "
36 });
37 }
38 else if (action == "delete") {
39 var singleAnnotation = window.annotationManager.getSelection();
40
41 if (singleAnnotation && singleAnnotation.length > 0) {
42 window.annotationManager.deleteAnnotation(singleAnnotation[0].getId());
43 }
44 }
45 else if (action == "deleteall") {
46 var allAnnotations = zuim.mainViewport.getAnnotations();
47
48 for (var i = 0; i < allAnnotations.length; i++) {
49 window.annotationManager.deleteAnnotation(allAnnotations[i].getId());
50 }
51 }
52 else if (action == "save") {
53 saveAnnotations();
54 }
55 }
56}
57
58function saveAnnotations(e) {
59 if (e) {
60 var metadata = e.hasOwnProperty("feature") ? e.feature.metaData : (e.hasOwnProperty("length") && e.length !== 0 ? e[0].metaData : null);
61 if (metadata) {
62 metadata.Notes = $("#annotation-text").val() ? $("#annotation-text").val() : " ";
63 }
64 }
65
66 $(".annotation-helper-icon").addClass("loading");
67 window.annotationManager.saveAnnotations();
68}
69
70$(document).ready(function () {
71 var jsColorPicker = null;
72 if (supportsColorPicker()) {
73 $("#color-picker-js").remove();
74 $("#color-picker-hidden").remove();
75 } else {
76 $("#color-picker-native").remove();
77 jsColorPicker = new jscolor($("#color-picker-js")[0], {
78 valueElement: $("#color-picker-hidden")[0],
79 hash: true,
80 closable: true,
81 closeText: "Close"
82 });
83 }
84
85 $("button.color-btn").click(function (e) {
86 var clr = $(this).data("color");
87 $("#color-picker-native").val(clr);
88 if (jsColorPicker) {
89 jsColorPicker.fromString(clr);
90 }
91 });
92
93 $("button[data-action][data-type], a[data-action][data-type]").click(function (e) {
94 e.preventDefault();
95 drawCommands($(this).data("action"), $(this).data("type"));
96 });
97
98 window.context = new PMA.UI.Components.Context({
99 caller: "sdk demo"
100 });
101
102 new PMA.UI.Authentication.AutoLogin(window.context, [{
103 serverUrl: serverUrl,
104 username: usr,
105 password: pwd
106 },]);
107
108 var contextsDict = {};
109
110 window.zuim = new PMA.UI.Components.SlideLoader(window.context, {
111 element: "#viewer",
112 overview: true,
113 channels: {
114 collapsed: true
115 },
116 dimensions: true,
117 filename: false,
118 scaleLine: true,
119 annotations: {
120 imageBaseUrl: imageBaseUrl,
121 imageScale: 1,
122 labels: true,
123 contexts: null,
124 filter: function (x) {
125 contextsDict[x.Context] = 1;
126 return true;
127 }
128 },
129 annotationsLayers: false,
130 colorAdjustments: false,
131 digitalZoomLevels: 2,
132 loadingBar: true,
133 highQuality: true,
134 barcode: {
135 collapsed: true
136 },
137 snapshot: false,
138 // theme: "modern",
139 magnifier: false,
140 flip: {
141 horizontally: false,
142 vertically: false,
143 }
144 });
145
146 zuim.listen(PMA.UI.Components.Events.SlideLoaded, function (args) {
147 $("button, input").removeAttr("disabled");
148 $("button[data-action='delete']").attr("disabled", true);
149 $("button[data-action='annotation-zoom']").attr("disabled", true);
150 $("button[data-action='annotation-center']").attr("disabled", true);
151
152 window.annotationManager = new PMA.UI.Components.Annotations({
153 context: window.context,
154 element: null,
155 viewport: zuim.mainViewport,
156 serverUrl: args.serverUrl,
157 path: args.path,
158 enabled: true
159 });
160
161 window.annotationManager.listen(PMA.UI.Components.Events.AnnotationsSelectionChanged, function (e) {
162 if (e) {
163 $("button[data-action='delete']").attr("disabled", false);
164 $("button[data-action='annotation-zoom']").attr("disabled", false);
165 $("button[data-action='annotation-center']").attr("disabled", false);
166
167 var metadata = e.hasOwnProperty("feature") ? e.feature.metaData : (e.hasOwnProperty("length") && e.length !== 0 ? e[0].metaData : null);
168 if (metadata) {
169 $("#annotation-text").val(metadata.Notes);
170 } else {
171 $("button[data-action='delete']").attr("disabled", true);
172 $("button[data-action='annotation-zoom']").attr("disabled", true);
173 $("button[data-action='annotation-center']").attr("disabled", true);
174 }
175 }
176 });
177
178 window.annotationManager.listen(PMA.UI.Components.Events.AnnotationAdded, function (e) {
179 e.feature.metaData.Context = "kagelos-test";
180 e.feature.metaData.LayerID = 2;
181 window.annotationManager.setMetadata(e.feature, e.feature.metaData);
182 });
183
184 window.annotationManager.listen(PMA.UI.Components.Events.AnnotationDeleted, function (e) {
185 $("button[data-action='delete']").attr("disabled", true);
186 $("button[data-action='annotation-zoom']").attr("disabled", true);
187 $("button[data-action='annotation-center']").attr("disabled", true);
188 });
189
190 window.annotationManager.listen(PMA.UI.Components.Events.AnnotationsSaved, function (e) {
191 if (e && e.success) {
192 $(".annotation-helper-icon").removeClass("loading").addClass("saved");
193 } else {
194 $(".annotation-helper-icon").removeClass("loading").addClass("error");
195 }
196
197 setTimeout(function () {
198 $(".annotation-helper-icon").removeClass("loading error saved");
199 }, 1000);
200 });
201 });
202
203 $("body").keydown(function (event) {
204 if (!$(event.target).is('input') && (event.key == "Delete" || event.key == "Del")) {
205 drawCommands("delete", null);
206 }
207 });
208
209 $("button[data-action='annotation-zoom'], button[data-action='annotation-center']").click(function (e) {
210 e.preventDefault();
211
212 var zoom = $(this).data("zoom")
213 checkAnnotation(zoom);
214 });
215
216 zuim.load(serverUrl, imageUrl);
217});
218
219function checkAnnotation(zoom) {
220 if (typeof zoom === 'undefined') {
221 return;
222 }
223
224 var selectedAnnotation = window.annotationManager.getSelection()[0].getId();
225 window.zuim.mainViewport.focusToAnnotation(selectedAnnotation, zoom);
226}