PMA.UI Examples 2.43.3by Pathomation

Annotation Focus

basicviewportannotationszoomfocus
Console
PMA.UI version: 2.43.3
Annotation focus tool
annotation_focus.html
1<!doctype html>
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}