@jax-data-science/sci-image-visualizer 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/geometry/reconstruct.mjs +11 -1
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +18 -6
- package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +29 -14
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +6 -1
- package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +9 -4
- package/esm2022/lib/region-editor/region-editor.component.mjs +13 -1
- package/esm2022/lib/routing-visualizer.service.mjs +4 -1
- package/esm2022/lib/spatial/spatial-controls.facade.mjs +71 -21
- package/esm2022/lib/spatial/spatial-selection.mjs +70 -1
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +53 -11
- package/esm2022/lib/store/region-selection.mjs +21 -4
- package/esm2022/lib/store/region-store.service.mjs +22 -3
- package/esm2022/lib/store/spatial-selection.service.mjs +13 -1
- package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +3 -3
- package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-a68Hw5rw.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DURPqs5a.mjs} +770 -500
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DURPqs5a.mjs.map +1 -0
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-CvadfzjS.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-D0IQ6PjZ.mjs} +2 -2
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-CvadfzjS.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-D0IQ6PjZ.mjs.map} +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +2 -2
- package/lib/contracts/region-editor-api.contract.d.ts +3 -0
- package/lib/contracts/visualizer.contract.d.ts +25 -2
- package/lib/geometry/reconstruct.d.ts +6 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +13 -1
- package/lib/implementations/napari-js/napari-tool-bridge.d.ts +11 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +3 -0
- package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +6 -1
- package/lib/routing-visualizer.service.d.ts +1 -0
- package/lib/spatial/spatial-controls.facade.d.ts +16 -2
- package/lib/spatial/spatial-selection.d.ts +16 -1
- package/lib/spatial-controls/spatial-controls.component.d.ts +14 -3
- package/lib/store/region-selection.d.ts +14 -3
- package/lib/store/region-store.service.d.ts +14 -1
- package/lib/store/spatial-selection.service.d.ts +8 -0
- package/package.json +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-a68Hw5rw.mjs.map +0 -1
|
@@ -13,6 +13,16 @@ import * as i0 from "@angular/core";
|
|
|
13
13
|
export class SpatialSelectionStore {
|
|
14
14
|
constructor() {
|
|
15
15
|
this.selection$ = new BehaviorSubject(emptySelection());
|
|
16
|
+
/** Bumped by every write, a clear of nothing included (see {@link revision}). */
|
|
17
|
+
this.writes = 0;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* How many times the selection was written (set or cleared, by any writer). A selection
|
|
21
|
+
* computed asynchronously compares it before publishing: a newer write — a Clear, a legend
|
|
22
|
+
* click, a linked chart's brush — supersedes it.
|
|
23
|
+
*/
|
|
24
|
+
revision() {
|
|
25
|
+
return this.writes;
|
|
16
26
|
}
|
|
17
27
|
/** Emits on every change, including a clear. */
|
|
18
28
|
getSelection$() {
|
|
@@ -30,9 +40,11 @@ export class SpatialSelectionStore {
|
|
|
30
40
|
* "selected nothing" ROI visibly clears rather than silently keeping the
|
|
31
41
|
* previous selection on screen. */
|
|
32
42
|
set(selection) {
|
|
43
|
+
this.writes++;
|
|
33
44
|
this.selection$.next(selection);
|
|
34
45
|
}
|
|
35
46
|
clear() {
|
|
47
|
+
this.writes++;
|
|
36
48
|
if (this.selection$.value.count === 0 && this.selection$.value.mask.length === 0)
|
|
37
49
|
return;
|
|
38
50
|
this.selection$.next(emptySelection());
|
|
@@ -44,4 +56,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
|
|
|
44
56
|
type: Injectable,
|
|
45
57
|
args: [{ providedIn: 'root' }]
|
|
46
58
|
}] });
|
|
47
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC1zZWxlY3Rpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3RvcmUvc3BhdGlhbC1zZWxlY3Rpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQWMsTUFBTSxNQUFNLENBQUM7QUFFbkQsT0FBTyxFQUF3QixjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQzs7QUFFcEY7Ozs7Ozs7R0FPRztBQUVILE1BQU0sT0FBTyxxQkFBcUI7SUFEbEM7UUFFbUIsZUFBVSxHQUFHLElBQUksZUFBZSxDQUF1QixjQUFjLEVBQUUsQ0FBQyxDQUFDO1FBQzFGLGlGQUFpRjtRQUN6RSxXQUFNLEdBQUcsQ0FBQyxDQUFDO0tBdUNwQjtJQXJDQzs7OztPQUlHO0lBQ0gsUUFBUTtRQUNOLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQsZ0RBQWdEO0lBQ2hELGFBQWE7UUFDWCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDeEMsQ0FBQztJQUVELGlFQUFpRTtJQUNqRSxPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQztJQUMvQixDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLE9BQU87UUFDTCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVEOzt3Q0FFb0M7SUFDcEMsR0FBRyxDQUFDLFNBQStCO1FBQ2pDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNkLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxLQUFLO1FBQ0gsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2QsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUFFLE9BQU87UUFDekYsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztJQUN6QyxDQUFDOzhHQXpDVSxxQkFBcUI7a0hBQXJCLHFCQUFxQixjQURSLE1BQU07OzJGQUNuQixxQkFBcUI7a0JBRGpDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFNwYXRpYWxTZWxlY3Rpb25NYXNrLCBlbXB0eVNlbGVjdGlvbiB9IGZyb20gJy4uL3NwYXRpYWwvc3BhdGlhbC1zZWxlY3Rpb24nO1xuXG4vKipcbiAqIFRoZSBzZXQgb2YgY3VycmVudGx5LXNlbGVjdGVkIHNwYXRpYWwgb2JzZXJ2YXRpb25zLCBzaGFyZWQgdGhlIHdheVxuICogYFJlZ2lvblN0b3JlYCBzaGFyZXMgcmVnaW9uczogb25lIHN0b3JlLCBtYW55IHdyaXRlcnMgKGFuIFJPSSBzZWxlY3Rpb24sIGFcbiAqIGxlZ2VuZCBjbGljaywgYSBmdXR1cmUgY2hhcnQgYnJ1c2gpLCBvbmUgcmVhZGVyIHBlciBjb25zdW1lci5cbiAqXG4gKiBEZWxpYmVyYXRlbHkgdGhpbiDigJQgZXZlcnkgcnVsZSBhYm91dCBXSElDSCBvYnNlcnZhdGlvbnMgYXJlIHNlbGVjdGVkIGxpdmVzIGluXG4gKiB0aGUgcHVyZSBgc3BhdGlhbC1zZWxlY3Rpb24udHNgOyB0aGlzIG9ubHkgaG9sZHMgdGhlIGFuc3dlciBhbmQgYW5ub3VuY2VzIGl0LlxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFNwYXRpYWxTZWxlY3Rpb25TdG9yZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2VsZWN0aW9uJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8U3BhdGlhbFNlbGVjdGlvbk1hc2s+KGVtcHR5U2VsZWN0aW9uKCkpO1xuICAvKiogQnVtcGVkIGJ5IGV2ZXJ5IHdyaXRlLCBhIGNsZWFyIG9mIG5vdGhpbmcgaW5jbHVkZWQgKHNlZSB7QGxpbmsgcmV2aXNpb259KS4gKi9cbiAgcHJpdmF0ZSB3cml0ZXMgPSAwO1xuXG4gIC8qKlxuICAgKiBIb3cgbWFueSB0aW1lcyB0aGUgc2VsZWN0aW9uIHdhcyB3cml0dGVuIChzZXQgb3IgY2xlYXJlZCwgYnkgYW55IHdyaXRlcikuIEEgc2VsZWN0aW9uXG4gICAqIGNvbXB1dGVkIGFzeW5jaHJvbm91c2x5IGNvbXBhcmVzIGl0IGJlZm9yZSBwdWJsaXNoaW5nOiBhIG5ld2VyIHdyaXRlIOKAlCBhIENsZWFyLCBhIGxlZ2VuZFxuICAgKiBjbGljaywgYSBsaW5rZWQgY2hhcnQncyBicnVzaCDigJQgc3VwZXJzZWRlcyBpdC5cbiAgICovXG4gIHJldmlzaW9uKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMud3JpdGVzO1xuICB9XG5cbiAgLyoqIEVtaXRzIG9uIGV2ZXJ5IGNoYW5nZSwgaW5jbHVkaW5nIGEgY2xlYXIuICovXG4gIGdldFNlbGVjdGlvbiQoKTogT2JzZXJ2YWJsZTxTcGF0aWFsU2VsZWN0aW9uTWFzaz4ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGlvbiQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICAvKiogU3luY2hyb25vdXMgcmVhZCwgZm9yIGEgcmVuZGVyZXIgYnVpbGRpbmcgaXRzIGZpcnN0IGZyYW1lLiAqL1xuICBjdXJyZW50KCk6IFNwYXRpYWxTZWxlY3Rpb25NYXNrIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3Rpb24kLnZhbHVlO1xuICB9XG5cbiAgLyoqIFRydWUgd2hlbiBub3RoaW5nIGlzIHNlbGVjdGVkIOKAlCB0aGUgc3RhdGUgaW4gd2hpY2ggbm90aGluZyBpcyBtdXRlZC4gKi9cbiAgaXNFbXB0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3Rpb24kLnZhbHVlLmNvdW50ID09PSAwO1xuICB9XG5cbiAgLyoqIFJlcGxhY2UgdGhlIHNlbGVjdGlvbi4gQW4gZW1wdHkgcmVzdWx0IGlzIHB1Ymxpc2hlZCBsaWtlIGFueSBvdGhlciwgc28gYVxuICAgKiAgXCJzZWxlY3RlZCBub3RoaW5nXCIgUk9JIHZpc2libHkgY2xlYXJzIHJhdGhlciB0aGFuIHNpbGVudGx5IGtlZXBpbmcgdGhlXG4gICAqICBwcmV2aW91cyBzZWxlY3Rpb24gb24gc2NyZWVuLiAqL1xuICBzZXQoc2VsZWN0aW9uOiBTcGF0aWFsU2VsZWN0aW9uTWFzayk6IHZvaWQge1xuICAgIHRoaXMud3JpdGVzKys7XG4gICAgdGhpcy5zZWxlY3Rpb24kLm5leHQoc2VsZWN0aW9uKTtcbiAgfVxuXG4gIGNsZWFyKCk6IHZvaWQge1xuICAgIHRoaXMud3JpdGVzKys7XG4gICAgaWYgKHRoaXMuc2VsZWN0aW9uJC52YWx1ZS5jb3VudCA9PT0gMCAmJiB0aGlzLnNlbGVjdGlvbiQudmFsdWUubWFzay5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aGlzLnNlbGVjdGlvbiQubmV4dChlbXB0eVNlbGVjdGlvbigpKTtcbiAgfVxufVxuIl19
|
|
@@ -33,11 +33,11 @@ export class ToolbarHelpDialogComponent {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: ToolbarHelpDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
36
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: ToolbarHelpDialogComponent, isStandalone: true, selector: "toolbar-help-dialog", inputs: { visible: "visible", contributedTools: "contributedTools", dialogTools: "dialogTools" }, outputs: { visibleChange: "visibleChange" }, usesOnChanges: true, ngImport: i0, template: "<p-dialog\n header=\"Plotting help\"\n [visible]=\"visible\"\n (visibleChange)=\"visibleChange.emit($event)\"\n [modal]=\"true\"\n [style]=\"{ width: '50vw' }\"\n [maximizable]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n>\n <p>\n Click a file in the left-hand tree to display it. By default it opens in the <b>Image</b> view \u2014 a natively\n tiled, deeply zoomable raster (OpenSeadragon) with a navigator minimap and a physical-units scale bar.\n <b>Click the image to zoom</b> toward the clicked point; scroll to zoom and drag to pan. When a stack is open,\n a slice slider (Image view) or image-mode toggle (other views) appears. Regions can also be edited in the\n <b>Region Editor</b>, opened with the\n <img src=\"assets/plotting/region-editor.svg\" width=\"14\" height=\"14\" alt=\"Region Editor\" />\n toolbar button as a floating dialog. Drag the <i class=\"pi pi-bars\"></i> handle to detach this toolbar into a\n floating window.\n </p>\n\n <h3>Plot-type dropdown</h3>\n <p>\n The <b>plot-type dropdown</b> switches how the file is visualized: <b>Image</b>, <b>Heatmap</b>,\n <b>Contour</b>, <b>Surface</b>, <b>Volume</b>, <b>Isosurface</b>, and \u2014 when a spatial-omics dataset is open \u2014\n <b>Spatial omics</b> and <b>Spatial omics 3D</b>.\n </p>\n <p>\n <b>Only the modes the data can actually support are offered</b>, so the list changes with what is loaded rather\n than showing entries that would come up blank:\n </p>\n <ul>\n <li>\n <b>Contour</b>, <b>Volume</b> and <b>Isosurface</b> need a grayscale image; the two 3D ones also need a\n z-stack.\n </li>\n <li>\n <b>Spatial omics</b> needs a published dataset, and <b>Spatial omics 3D</b> needs one whose coordinates carry\n a z.\n </li>\n <li>\n The pixel modes (<b>Image</b>, <b>Heatmap</b>, <b>Surface</b>) are withheld for a dataset that brings no\n tissue image \u2014 seqFISH records coordinates and no section, so there is nothing for them to draw.\n </li>\n </ul>\n <ul>\n <li>\n \"<b>Isosurface band</b>\" slider (Isosurface): sets the intensity band the surfaces are drawn for, mapped onto\n the volume's real intensity range.\n </li>\n <li>\n \"<b>3D camera</b>\" (Surface / Scatter 3D / Isosurface): zoom <i class=\"pi pi-search\"></i>, pan\n <i class=\"pi pi-arrows-alt\"></i>, orbit <i class=\"pi pi-globe\"></i>, turntable <i class=\"pi pi-sync\"></i>,\n and reset camera <i class=\"pi pi-home\"></i>; scroll to zoom the 3D scene.\n </li>\n </ul>\n\n <h3>Image manipulation tools</h3>\n <ul>\n <li>\n \"<b>Region Editor</b>\" <img src=\"assets/plotting/region-editor.svg\" width=\"15\" height=\"15\" />: opens the\n Region Editor as a floating, draggable dialog \u2014 a per-image table of every region (class, colour, area) with\n bulk select/label/colour/delete and GeoJSON import/export. It stays in sync with the image, so you can keep\n it open while drawing.\n </li>\n <li>\n \"<b>Intensity profile lines</b>\" <img src=\"assets/plotting/spline-chart.svg\" width=\"15\" height=\"15\" /> (<i\n >work in progress \u2014 not yet stable</i\n >): adds a coloured line ROI; a floating inset chart plots intensity along each line, updates live as you\n drag it, and re-samples at the current zoom resolution. Each added line gets its own colour; select a line\n and use the trash tool <i class=\"pi pi-trash\"></i> to remove it (and its trace).\n </li>\n <li>\n \"<b>Channels & Histogram</b>\" <img src=\"assets/plotting/invert.svg\" width=\"15\" height=\"15\" />: opens a\n floating dialog for brightness/contrast, gamma, and per-channel display, plus the\n <b>colormap / LUT</b> controls (grayscale only) \u2014 a <b>reverse</b> toggle and a colormap dropdown (default:\n inverted greys).\n </li>\n <li>\n \"<b>Smoothen</b>\" <img src=\"assets/plotting/smooth.svg\" width=\"15\" height=\"15\" /> (Image view only): the\n image opens showing <b>raw pixels</b> (nearest-neighbour), so zooming in renders crisp blocks for pixel\n inspection. Toggle this on for bilinear smoothing; the icon turns white while smoothing is active.\n </li>\n </ul>\n\n <h3>Download & view tools</h3>\n <ul>\n <li>\"<b>Download</b>\" <i class=\"pi pi-download\"></i>: download the current image as a PNG.</li>\n <li>\n \"<b>Fit to view</b>\" / autoscale <i class=\"pi pi-window-maximize\"></i>: resets the image to its original\n dimensions. In stack mode it also resets to single-image mode.\n </li>\n </ul>\n\n <h3>Zoom tools</h3>\n <ul>\n <li>\n \"<b>Zoom box</b>\" <img src=\"assets/plotting/zoom-box.svg\" width=\"15\" height=\"15\" /> (<kbd>b</kbd>): drag a\n box to select an area to zoom into.\n </li>\n <li>\"<b>Pan</b>\" <i class=\"pi pi-arrows-alt\"></i> (<kbd>p</kbd>): drag to pan the image.</li>\n <li>\"<b>Zoom in</b>\" <i class=\"pi pi-search-plus\"></i> (<kbd>+</kbd>): zoom in one step.</li>\n <li>\n \"<b>Zoom out</b>\" <i class=\"pi pi-search-minus\"></i> (<kbd>-</kbd>): zoom out one step, stopping at the\n original image dimensions.\n </li>\n </ul>\n\n <h3>Region tools</h3>\n <p>\n By default no tool is selected (all greyed-out); selecting a tool highlights it. The vertex-editing tools\n (polygon, add/delete vertex, move, B\u00E9zier conversions) are available in the <b>Image</b> view only. On a\n <b>donut</b> (a region with a hole), the inner-ring vertices are editable too \u2014 drag, add, and delete them just\n like the outer ring.\n </p>\n <ul>\n <li>\n \"<b>Selection</b>\" <i class=\"pi pi-arrow-up-right\"></i> (<kbd>s</kbd>): a neutral mode that turns off\n whatever drawing tool was active (wand, vertex eraser, rectangle, etc.). Use it to step out of editing\n without picking another tool.\n </li>\n <li>\n \"<b>Rectangular region</b>\" <i class=\"pi pi-stop\"></i> (<kbd>r</kbd>): click and drag to create a rectangular\n region.\n </li>\n <li>\n \"<b>Polyline</b>\" <img src=\"assets/plotting/polyline.svg\" width=\"14\" height=\"14\" /> (<kbd>l</kbd>): draw an\n open (non-closed) polyline by clicking and dragging. Polylines can be edited and exported to GeoJSON as a\n <code>LineString</code> feature.\n </li>\n <li>\n \"<b>Freeform region</b>\" <i class=\"pi pi-pencil\"></i> (<kbd>f</kbd>): click and drag to draw a closed\n freeform polygon.\n </li>\n <li>\n \"<b>Brush</b>\" <img src=\"assets/plotting/paintbrush.svg\" width=\"15\" height=\"15\" />: click and drag to paint a\n region with a circular brush \u2014 the painted stroke is the region. A <b>Size</b> slider (brush diameter, in\n image pixels) appears in the toolbar while the brush is active. Hold <kbd>Shift</kbd> while painting to\n <b>erase</b> (subtract) from a region instead. Painting over an existing region extends it; brushing across\n two regions merges them. Painting a closed ring (or shift-erasing an interior pocket) leaves the enclosed\n area empty \u2014 a <b>donut</b> (Image view).\n </li>\n <li>\n \"<b>Polygon</b>\" <img src=\"assets/plotting/polygon-vertices.svg\" width=\"15\" height=\"15\" />: click to place\n each vertex; click the first point to close the polygon.\n </li>\n <li>\n \"<b>Add vertex</b>\" <img src=\"assets/plotting/vertex-add.svg\" width=\"15\" height=\"15\" />: click an edge of the\n selected polygon to insert a new vertex.\n </li>\n <li>\n \"<b>Delete vertex</b>\" <img src=\"assets/plotting/vertex-delete.svg\" width=\"15\" height=\"15\" />: click a vertex\n of the selected polygon to remove it.\n </li>\n <li>\n <b>Moving a region</b> <img src=\"assets/plotting/region-move.svg\" width=\"15\" height=\"15\" />: with the Select\n tool, drag the selected region's body (or a rectangle's handles to resize it).\n </li>\n <li>\n <b>Convert to B\u00E9zier</b> <img src=\"assets/plotting/to-bezier.svg\" width=\"15\" height=\"15\" /> /\n <b>Convert to polygon</b> <img src=\"assets/plotting/to-polygon.svg\" width=\"15\" height=\"15\" /> (Image view):\n right-click the selected region and pick the conversion in the context menu to turn it into a smooth B\u00E9zier\n curve, or back into a straight-edged polygon.\n </li>\n <li>\n \"<b>Wand</b>\" <img src=\"assets/plotting/wand.svg\" width=\"15\" height=\"15\" /> (<kbd>w</kbd>): click to grow a\n region from pixels with similar values around the click point. Hold <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> for an\n exact-match flood fill; drag to keep extending the selection while moving; hold <kbd>Shift</kbd> while\n clicking or dragging on an existing region to <b>erase</b> pixels from it. Use the <b>Sens.</b> slider that\n appears to make the wand stricter (higher = smaller selection) or looser. Subsequent clicks keep extending\n the same region; clicking inside an existing region adopts it, and growing into another region merges them.\n </li>\n <li>\n \"<b>Vertex eraser</b>\" <i class=\"pi pi-eraser\"></i> (<kbd>e</kbd>): click or click-and-drag to remove polygon\n vertices that fall inside the cursor circle from any region, including a region's inner rings (donut holes).\n Use the <b>Radius</b> slider to set the eraser size in image pixels. Polygons reduced below 3 vertices (or\n polylines below 2) are deleted entirely; a hole reduced below 3 vertices is removed.\n </li>\n <li>\n \"<b>Undo</b>\" <img src=\"assets/plotting/undo.svg\" width=\"15\" height=\"15\" />\n (<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd>): reverts the last region action (draw, delete, edit, wand/brush\n stroke, segmentation, \u2026). Up to the last\n <b>10</b> actions can be undone; the button greys out when there's nothing left to undo.\n </li>\n <li>\n \"<b>Redo</b>\"\n <img src=\"assets/plotting/redo.svg\" width=\"15\" height=\"15\" />\n (<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> or\n <kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Y</kbd>): re-applies the most recently undone action. Performing a new\n region action clears what can be redone.\n </li>\n <li>\n \"<b>Delete region</b>\" <i class=\"pi pi-trash\"></i> (<kbd>Del</kbd>): deletes the selected region. This can\n also be done from the Region Editor.\n </li>\n </ul>\n\n <h3>Region actions (right-click the image)</h3>\n <p>\n Right-click a region \u2014 or the current multi-selection \u2014 to open the \"<b>Selected region(s)</b>\" group at the\n top of the context menu. These act immediately on the selection (they're not drawing modes) and are fully\n undo/redo-able:\n </p>\n <ul>\n <li>\n \"<b>Select all regions</b>\" <i class=\"pi pi-check-square\"></i>: select every region on the image (also in the\n Region Editor toolbar).\n </li>\n <li>\n \"<b>Merge / group</b>\": combine 2+ selected regions into one. If the pieces don't touch, the result is a\n single multi-part region (sparse \"bits\").\n </li>\n <li>\"<b>Ungroup</b>\": split a multi-part region back into one region per piece.</li>\n <li>\n \"<b>Inverse</b>\": replace the selection with everything <i>outside</i> it \u2014 the image rectangle with the\n selected regions punched out as holes. Works at any image size.\n </li>\n <li>\n \"<b>Simplify</b>\": reduce a region's vertex count (Douglas\u2013Peucker) by an altitude threshold in pixels \u2014 pick\n <b>Light</b> (1 px), <b>Medium</b> (3 px), <b>Strong</b> (8 px), or <b>Custom\u2026</b> for a\n slider. Applies to the exterior and any holes (and every part of a multi-part region).\n </li>\n <li>\n \"<b>Convert to B\u00E9zier</b>\" / \"<b>Convert to polygon</b>\" (Image view) and \"<b>Delete</b>\" also live in this\n group; the conversions are only here, not in the toolbar.\n </li>\n </ul>\n\n <h3>Segmentation & detection tools</h3>\n <p>\n AI-assisted segmentation and detection that run entirely in the browser. The first run of any model downloads\n it (a progress toast is shown); it's then cached.\n </p>\n <p>\n Two shapes of tool: the <b>prompted</b> ones (Segment, Point prompts, Cellpose) act on rectangles you draw, and\n generated regions inherit the color of the rectangle they came from<span *ngIf=\"contributedTools.length\"\n >; the <b>no-prompt</b> ones ({{ contributedToolNames }}) sweep the whole current view, so there is nothing\n to draw first</span\n >.\n </p>\n <p>\n Each model dropdown <i class=\"pi pi-chevron-down\"></i> lists the available checkpoints with a\n <i class=\"pi pi-info-circle\"></i> beside each one \u2014 hover it for that model's size, speed, training domain and\n accuracy, so you can pick without leaving the toolbar.\n </p>\n <ul>\n <li>\n \"<b>Segment</b>\" <img src=\"assets/plotting/sam-box-prompt.svg\" width=\"15\" height=\"15\" /> (box prompt): draw\n one or more <b>Rectangular regions</b> around the objects of interest, then click Segment. Each rectangle is\n replaced by the SAM mask of the object inside it.\n </li>\n <li>\n \"<b>Point prompts</b>\" <img src=\"assets/plotting/sam-point-prompt.svg\" width=\"15\" height=\"15\" />: click\n directly on an object to segment it as a <b>new</b> region. Each click starts a fresh object \u2014 clicking\n another object won't grow the previous one. <kbd>Shift</kbd>/<kbd>Alt</kbd>-click adds an\n <i>exclude</i> point that refines the current object; <kbd>Esc</kbd> undoes it, <kbd>Enter</kbd> commits it.\n </li>\n <li>\n \"<b>Model picker</b>\" <i class=\"pi pi-chevron-down\"></i>: the dropdown attached to the Segment button chooses\n the SAM model \u2014 <b>micro-sam ViT-T</b> (default; small, fast) or <b>micro-sam ViT-B</b> (larger, highest\n accuracy) for light microscopy, or <b>patho-sam ViT-B</b> for histopathology (H&E / stained tissue). All\n are promptable Segment Anything models finetuned for biomedical images; they differ in the\n <i>image encoder</i> (the heavy once-per-image step) and the training domain \u2014 box and point prompting behave\n the same. The choice applies to <i>both</i> the box and point tools, which share one loaded model and image\n encoding, so the first run after switching models (or images) downloads and encodes once for both.\n </li>\n <li>\n \"<b>Cellpose</b>\" <img src=\"assets/plotting/cells.svg\" width=\"15\" height=\"15\" />: draw rectangles, then click\n Cellpose to automatically segment every cell inside each rectangle (client-side cellpose-SAM) \u2014 one region\n per detected cell. No clicking on individual cells needed.\n </li>\n <!-- Contributed tools describe themselves. This library ships none, so an\n open build's help lists only the prompted tools above \u2014 the text no\n longer promises buttons that are not there. -->\n <ng-container *ngFor=\"let tool of contributedTools\">\n <li *ngIf=\"tool.help\" [innerHTML]=\"tool.help.body\"></li>\n </ng-container>\n <ng-container *ngFor=\"let tool of dialogTools\">\n <li *ngIf=\"tool.help\" [innerHTML]=\"tool.help.body\"></li>\n </ng-container>\n </ul>\n\n <h3>Spatial omics</h3>\n <p>\n In <b>Spatial omics</b> mode each observation \u2014 a cell or a Visium spot \u2014 is drawn at its own coordinates, over\n the tissue image where the dataset registers onto one. The\n <img src=\"assets/plotting/spatial-omics.svg\" width=\"14\" height=\"14\" alt=\"Spatial omics\" />\n panel colours them by a <b>column</b> (a cell type, a cluster) or by a <b>gene</b>, and the two are exclusive\n so what drives the colours is never ambiguous.\n </p>\n <ul>\n <li>\n \"<b>Select from ROIs</b>\": turns the regions you have drawn into a selection of observations. Everything else\n then follows that selection.\n </li>\n <li>\"<b>Point size</b>\" / \"<b>Opacity</b>\": how the markers are drawn, not what is selected.</li>\n </ul>\n\n <h3>Distribution charts</h3>\n <p>\n The <b>Distribution</b> section of the spatial-omics panel charts whatever the map is coloured by, so the two\n can never disagree. Each tab answers a different question, and the <i class=\"pi pi-question-circle\"></i> beside\n them explains the one on screen \u2014 including what it must <em>not</em> be read for.\n </p>\n <ul>\n <li>\n \"<b>Counts</b>\": how many observations per category. A category is a label, not a magnitude, so a frequency\n is the only distribution it has.\n </li>\n <li>\n \"<b>Histogram</b>\" / \"<b>Violin</b>\" / \"<b>Box</b>\": how a continuous value is distributed \u2014 over everything,\n or split by a grouping column.\n </li>\n <li>\n \"<b>Heatmap</b>\": mean expression of the genes you pick within each group. Z-scored per gene by default, so a\n colour means \"above or below this gene's own average\" rather than \"highly expressed\".\n </li>\n <li>\n \"<b>Embedding</b>\": a UMAP, PCA or t-SNE over the same cells. <b>Lasso it to select on the map</b> \u2014 both\n views read the same selection. Only PCA labels its axes with a percentage, because only its axes explain a\n measurable share of the variance; UMAP and t-SNE coordinates are arbitrary, so distance between distant\n clusters should not be read.\n </li>\n <li>\n \"<b>Detach</b>\": moves the charts into their own window so they can sit beside the map instead of inside the\n panel. Switching tabs keeps the window where it is.\n </li>\n </ul>\n\n <h3>Help</h3>\n <p>\"<b>Help</b>\" <i class=\"pi pi-question-circle\"></i>: opens this dialog.</p>\n\n <h3>Keyboard shortcuts</h3>\n <table class=\"shortcuts-table\">\n <tr>\n <td><kbd>+</kbd> / <kbd>=</kbd></td>\n <td>Zoom in</td>\n </tr>\n <tr>\n <td><kbd>-</kbd></td>\n <td>Zoom out</td>\n </tr>\n <tr>\n <td><kbd>b</kbd></td>\n <td>Toggle zoom box mode</td>\n </tr>\n <tr>\n <td><kbd>p</kbd></td>\n <td>Toggle pan mode</td>\n </tr>\n <tr>\n <td><kbd>f</kbd></td>\n <td>Toggle freeform region drawing</td>\n </tr>\n <tr>\n <td><kbd>l</kbd></td>\n <td>Toggle polyline drawing</td>\n </tr>\n <tr>\n <td><kbd>r</kbd></td>\n <td>Toggle rectangular region drawing</td>\n </tr>\n <tr>\n <td><kbd>w</kbd></td>\n <td>Toggle wand tool</td>\n </tr>\n <tr>\n <td>Wand + <kbd>Shift</kbd></td>\n <td>Erase pixels from the active region</td>\n </tr>\n <tr>\n <td>Wand + <kbd>Ctrl</kbd>/<kbd>Cmd</kbd></td>\n <td>Exact-match flood fill (no smoothing)</td>\n </tr>\n <tr>\n <td><kbd>e</kbd></td>\n <td>Toggle vertex eraser</td>\n </tr>\n <tr>\n <td><kbd>s</kbd></td>\n <td>Selection mode (deactivates drawing tools)</td>\n </tr>\n <tr>\n <td>Point prompt + <kbd>Shift</kbd>/<kbd>Alt</kbd></td>\n <td>Add an exclude point (refine the current object)</td>\n </tr>\n <tr>\n <td><kbd>Enter</kbd></td>\n <td>Commit the current SAM point object</td>\n </tr>\n <tr>\n <td><kbd>Esc</kbd></td>\n <td>Undo the current SAM point object</td>\n </tr>\n <tr>\n <td><kbd>Del</kbd> / <kbd>\u232B</kbd></td>\n <td>Delete selected region</td>\n </tr>\n <tr>\n <td><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd></td>\n <td>Undo the last region action (up to 10)</td>\n </tr>\n <tr>\n <td><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> / <kbd>Ctrl</kbd>+<kbd>Y</kbd></td>\n <td>Redo the last undone region action</td>\n </tr>\n </table>\n\n <ng-template pTemplate=\"footer\">\n <p-button icon=\"pi pi-check\" (click)=\"visibleChange.emit(false)\" label=\"Ok\" styleClass=\"p-button-text\">\n </p-button>\n </ng-template>\n</p-dialog>\n", styles: ["kbd{background:#e8e8e8;border:1px solid #bbb;border-radius:3px;padding:1px 5px;font-family:monospace;font-size:.85em}.shortcuts-table{border-collapse:collapse}.shortcuts-table td{padding:.25rem .75rem .25rem 0;vertical-align:middle}.shortcuts-table td:first-child{white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: SharedModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i3.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i4.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "visible", "style", "position"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
36
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: ToolbarHelpDialogComponent, isStandalone: true, selector: "toolbar-help-dialog", inputs: { visible: "visible", contributedTools: "contributedTools", dialogTools: "dialogTools" }, outputs: { visibleChange: "visibleChange" }, usesOnChanges: true, ngImport: i0, template: "<p-dialog\n header=\"Plotting help\"\n [visible]=\"visible\"\n (visibleChange)=\"visibleChange.emit($event)\"\n [modal]=\"true\"\n [style]=\"{ width: '50vw' }\"\n [maximizable]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n>\n <p>\n Click a file in the left-hand tree to display it. By default it opens in the <b>Image</b> view \u2014 a natively\n tiled, deeply zoomable raster (OpenSeadragon) with a navigator minimap and a physical-units scale bar.\n <b>Click the image to zoom</b> toward the clicked point; scroll to zoom and drag to pan. When a stack is open,\n a slice slider (Image view) or image-mode toggle (other views) appears. Regions can also be edited in the\n <b>Region Editor</b>, opened with the\n <img src=\"assets/plotting/region-editor.svg\" width=\"14\" height=\"14\" alt=\"Region Editor\" />\n toolbar button as a floating dialog. Drag the <i class=\"pi pi-bars\"></i> handle to detach this toolbar into a\n floating window.\n </p>\n\n <h3>Plot-type dropdown</h3>\n <p>\n The <b>plot-type dropdown</b> switches how the file is visualized: <b>Image</b>, <b>Heatmap</b>,\n <b>Contour</b>, <b>Surface</b>, <b>Volume</b>, <b>Isosurface</b>, and \u2014 when a spatial-omics dataset is open \u2014\n <b>Spatial omics</b> and <b>Spatial omics 3D</b>.\n </p>\n <p>\n <b>Only the modes the data can actually support are offered</b>, so the list changes with what is loaded rather\n than showing entries that would come up blank:\n </p>\n <ul>\n <li>\n <b>Contour</b>, <b>Volume</b> and <b>Isosurface</b> need a grayscale image; the two 3D ones also need a\n z-stack.\n </li>\n <li>\n <b>Spatial omics</b> needs a published dataset, and <b>Spatial omics 3D</b> needs one whose coordinates carry\n a z.\n </li>\n <li>\n The pixel modes (<b>Image</b>, <b>Heatmap</b>, <b>Surface</b>) are withheld for a dataset that brings no\n tissue image \u2014 seqFISH records coordinates and no section, so there is nothing for them to draw.\n </li>\n </ul>\n <ul>\n <li>\n \"<b>Isosurface band</b>\" slider (Isosurface): sets the intensity band the surfaces are drawn for, mapped onto\n the volume's real intensity range.\n </li>\n <li>\n \"<b>3D camera</b>\" (Surface / Scatter 3D / Isosurface): zoom <i class=\"pi pi-search\"></i>, pan\n <i class=\"pi pi-arrows-alt\"></i>, orbit <i class=\"pi pi-globe\"></i>, turntable <i class=\"pi pi-sync\"></i>,\n and reset camera <i class=\"pi pi-home\"></i>; scroll to zoom the 3D scene.\n </li>\n </ul>\n\n <h3>Image manipulation tools</h3>\n <ul>\n <li>\n \"<b>Region Editor</b>\" <img src=\"assets/plotting/region-editor.svg\" width=\"15\" height=\"15\" />: opens the\n Region Editor as a floating, draggable dialog \u2014 a per-image table of every region (class, colour, area) with\n bulk select/label/colour/delete and GeoJSON import/export. It stays in sync with the image, so you can keep\n it open while drawing.\n </li>\n <li>\n \"<b>Intensity profile lines</b>\" <img src=\"assets/plotting/spline-chart.svg\" width=\"15\" height=\"15\" /> (<i\n >work in progress \u2014 not yet stable</i\n >): adds a coloured line ROI; a floating inset chart plots intensity along each line, updates live as you\n drag it, and re-samples at the current zoom resolution. Each added line gets its own colour; select a line\n and use the trash tool <i class=\"pi pi-trash\"></i> to remove it (and its trace).\n </li>\n <li>\n \"<b>Channels & Histogram</b>\" <img src=\"assets/plotting/invert.svg\" width=\"15\" height=\"15\" />: opens a\n floating dialog for brightness/contrast, gamma, and per-channel display, plus the\n <b>colormap / LUT</b> controls (grayscale only) \u2014 a <b>reverse</b> toggle and a colormap dropdown (default:\n inverted greys).\n </li>\n <li>\n \"<b>Smoothen</b>\" <img src=\"assets/plotting/smooth.svg\" width=\"15\" height=\"15\" /> (Image view only): the\n image opens showing <b>raw pixels</b> (nearest-neighbour), so zooming in renders crisp blocks for pixel\n inspection. Toggle this on for bilinear smoothing; the icon turns white while smoothing is active.\n </li>\n </ul>\n\n <h3>Download & view tools</h3>\n <ul>\n <li>\"<b>Download</b>\" <i class=\"pi pi-download\"></i>: download the current image as a PNG.</li>\n <li>\n \"<b>Fit to view</b>\" / autoscale <i class=\"pi pi-window-maximize\"></i>: resets the image to its original\n dimensions. In stack mode it also resets to single-image mode.\n </li>\n </ul>\n\n <h3>Zoom tools</h3>\n <ul>\n <li>\n \"<b>Zoom box</b>\" <img src=\"assets/plotting/zoom-box.svg\" width=\"15\" height=\"15\" /> (<kbd>b</kbd>): drag a\n box to select an area to zoom into.\n </li>\n <li>\"<b>Pan</b>\" <i class=\"pi pi-arrows-alt\"></i> (<kbd>p</kbd>): drag to pan the image.</li>\n <li>\"<b>Zoom in</b>\" <i class=\"pi pi-search-plus\"></i> (<kbd>+</kbd>): zoom in one step.</li>\n <li>\n \"<b>Zoom out</b>\" <i class=\"pi pi-search-minus\"></i> (<kbd>-</kbd>): zoom out one step, stopping at the\n original image dimensions.\n </li>\n </ul>\n\n <h3>Region tools</h3>\n <p>\n By default no tool is selected (all greyed-out); selecting a tool highlights it. The vertex-editing tools\n (polygon, add/delete vertex, move, B\u00E9zier conversions) are available in the <b>Image</b> view only. On a\n <b>donut</b> (a region with a hole), the inner-ring vertices are editable too \u2014 drag, add, and delete them just\n like the outer ring.\n </p>\n <ul>\n <li>\n \"<b>Selection</b>\" <i class=\"pi pi-arrow-up-right\"></i> (<kbd>s</kbd>): a neutral mode that turns off\n whatever drawing tool was active (wand, vertex eraser, rectangle, etc.). Use it to step out of editing\n without picking another tool.\n </li>\n <li>\n \"<b>Rectangular region</b>\" <i class=\"pi pi-stop\"></i> (<kbd>r</kbd>): click and drag to create a rectangular\n region.\n </li>\n <li>\n \"<b>Polyline</b>\" <img src=\"assets/plotting/polyline.svg\" width=\"14\" height=\"14\" /> (<kbd>l</kbd>): draw an\n open (non-closed) polyline by clicking and dragging. Polylines can be edited and exported to GeoJSON as a\n <code>LineString</code> feature.\n </li>\n <li>\n \"<b>Freeform region</b>\" <i class=\"pi pi-pencil\"></i> (<kbd>f</kbd>): click and drag to draw a closed\n freeform polygon.\n </li>\n <li>\n \"<b>Brush</b>\" <img src=\"assets/plotting/paintbrush.svg\" width=\"15\" height=\"15\" />: click and drag to paint a\n region with a circular brush \u2014 the painted stroke is the region. A <b>Size</b> slider (brush diameter, in\n image pixels) appears in the toolbar while the brush is active. Hold <kbd>Shift</kbd> while painting to\n <b>erase</b> (subtract) from a region instead. Painting over an existing region extends it; brushing across\n two regions merges them. Painting a closed ring (or shift-erasing an interior pocket) leaves the enclosed\n area empty \u2014 a <b>donut</b> (Image view).\n </li>\n <li>\n \"<b>Polygon</b>\" <img src=\"assets/plotting/polygon-vertices.svg\" width=\"15\" height=\"15\" />: click to place\n each vertex; click the first point to close the polygon.\n </li>\n <li>\n \"<b>Add vertex</b>\" <img src=\"assets/plotting/vertex-add.svg\" width=\"15\" height=\"15\" />: click an edge of the\n selected polygon to insert a new vertex.\n </li>\n <li>\n \"<b>Delete vertex</b>\" <img src=\"assets/plotting/vertex-delete.svg\" width=\"15\" height=\"15\" />: click a vertex\n of the selected polygon to remove it.\n </li>\n <li>\n <b>Moving a region</b> <img src=\"assets/plotting/region-move.svg\" width=\"15\" height=\"15\" />: with the Select\n tool, drag the selected region's body (or a rectangle's handles to resize it).\n </li>\n <li>\n <b>Convert to B\u00E9zier</b> <img src=\"assets/plotting/to-bezier.svg\" width=\"15\" height=\"15\" /> /\n <b>Convert to polygon</b> <img src=\"assets/plotting/to-polygon.svg\" width=\"15\" height=\"15\" /> (Image view):\n right-click the selected region and pick the conversion in the context menu to turn it into a smooth B\u00E9zier\n curve, or back into a straight-edged polygon.\n </li>\n <li>\n \"<b>Wand</b>\" <img src=\"assets/plotting/wand.svg\" width=\"15\" height=\"15\" /> (<kbd>w</kbd>): click to grow a\n region from pixels with similar values around the click point. Hold <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> for an\n exact-match flood fill; drag to keep extending the selection while moving; hold <kbd>Shift</kbd> while\n clicking or dragging on an existing region to <b>erase</b> pixels from it. Use the <b>Sens.</b> slider that\n appears to make the wand stricter (higher = smaller selection) or looser. Subsequent clicks keep extending\n the same region; clicking inside an existing region adopts it, and growing into another region merges them.\n </li>\n <li>\n \"<b>Vertex eraser</b>\" <i class=\"pi pi-eraser\"></i> (<kbd>e</kbd>): click or click-and-drag to remove polygon\n vertices that fall inside the cursor circle from any region, including a region's inner rings (donut holes).\n Use the <b>Radius</b> slider to set the eraser size in image pixels. Polygons reduced below 3 vertices (or\n polylines below 2) are deleted entirely; a hole reduced below 3 vertices is removed.\n </li>\n <li>\n \"<b>Undo</b>\" <img src=\"assets/plotting/undo.svg\" width=\"15\" height=\"15\" />\n (<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd>): reverts the last region action (draw, delete, edit, wand/brush\n stroke, segmentation, \u2026). Up to the last\n <b>10</b> actions can be undone; the button greys out when there's nothing left to undo.\n </li>\n <li>\n \"<b>Redo</b>\"\n <img src=\"assets/plotting/redo.svg\" width=\"15\" height=\"15\" />\n (<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> or\n <kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Y</kbd>): re-applies the most recently undone action. Performing a new\n region action clears what can be redone.\n </li>\n <li>\n \"<b>Delete region</b>\" <i class=\"pi pi-trash\"></i> (<kbd>Del</kbd>): deletes the selected region. This can\n also be done from the Region Editor.\n </li>\n </ul>\n\n <h3>Region actions (right-click the image)</h3>\n <p>\n Right-click a region \u2014 or the current multi-selection \u2014 to open the \"<b>Selected region(s)</b>\" group at the\n top of the context menu. These act immediately on the selection (they're not drawing modes) and are fully\n undo/redo-able:\n </p>\n <ul>\n <li>\n \"<b>Select all regions</b>\" <i class=\"pi pi-check-square\"></i>: select every region on the image (also in the\n Region Editor toolbar).\n </li>\n <li>\n \"<b>Merge / group</b>\": combine 2+ selected regions into one. If the pieces don't touch, the result is a\n single multi-part region (sparse \"bits\").\n </li>\n <li>\"<b>Ungroup</b>\": split a multi-part region back into one region per piece.</li>\n <li>\n \"<b>Inverse</b>\": replace the selection with everything <i>outside</i> it \u2014 the image rectangle with the\n selected regions punched out as holes. Works at any image size.\n </li>\n <li>\n \"<b>Simplify</b>\": reduce a region's vertex count (Douglas\u2013Peucker) by an altitude threshold in pixels \u2014 pick\n <b>Light</b> (1 px), <b>Medium</b> (3 px), <b>Strong</b> (8 px), or <b>Custom\u2026</b> for a\n slider. Applies to the exterior and any holes (and every part of a multi-part region).\n </li>\n <li>\n \"<b>Convert to B\u00E9zier</b>\" / \"<b>Convert to polygon</b>\" (Image view) and \"<b>Delete</b>\" also live in this\n group; the conversions are only here, not in the toolbar.\n </li>\n </ul>\n\n <h3>Segmentation & detection tools</h3>\n <p>\n AI-assisted segmentation and detection that run entirely in the browser. The first run of any model downloads\n it (a progress toast is shown); it's then cached.\n </p>\n <p>\n Two shapes of tool: the <b>prompted</b> ones (Segment, Point prompts, Cellpose) act on rectangles you draw, and\n generated regions inherit the color of the rectangle they came from<span *ngIf=\"contributedTools.length\"\n >; the <b>no-prompt</b> ones ({{ contributedToolNames }}) sweep the whole current view, so there is nothing\n to draw first</span\n >.\n </p>\n <p>\n Each model dropdown <i class=\"pi pi-chevron-down\"></i> lists the available checkpoints with a\n <i class=\"pi pi-info-circle\"></i> beside each one \u2014 hover it for that model's size, speed, training domain and\n accuracy, so you can pick without leaving the toolbar.\n </p>\n <ul>\n <li>\n \"<b>Segment</b>\" <img src=\"assets/plotting/sam-box-prompt.svg\" width=\"15\" height=\"15\" /> (box prompt): draw\n one or more <b>Rectangular regions</b> around the objects of interest, then click Segment. Each rectangle is\n replaced by the SAM mask of the object inside it.\n </li>\n <li>\n \"<b>Point prompts</b>\" <img src=\"assets/plotting/sam-point-prompt.svg\" width=\"15\" height=\"15\" />: click\n directly on an object to segment it as a <b>new</b> region. Each click starts a fresh object \u2014 clicking\n another object won't grow the previous one. <kbd>Shift</kbd>/<kbd>Alt</kbd>-click adds an\n <i>exclude</i> point that refines the current object; <kbd>Esc</kbd> undoes it, <kbd>Enter</kbd> commits it.\n </li>\n <li>\n \"<b>Model picker</b>\" <i class=\"pi pi-chevron-down\"></i>: the dropdown attached to the Segment button chooses\n the SAM model \u2014 <b>micro-sam ViT-T</b> (default; small, fast) or <b>micro-sam ViT-B</b> (larger, highest\n accuracy) for light microscopy, or <b>patho-sam ViT-B</b> for histopathology (H&E / stained tissue). All\n are promptable Segment Anything models finetuned for biomedical images; they differ in the\n <i>image encoder</i> (the heavy once-per-image step) and the training domain \u2014 box and point prompting behave\n the same. The choice applies to <i>both</i> the box and point tools, which share one loaded model and image\n encoding, so the first run after switching models (or images) downloads and encodes once for both.\n </li>\n <li>\n \"<b>Cellpose</b>\" <img src=\"assets/plotting/cells.svg\" width=\"15\" height=\"15\" />: draw rectangles, then click\n Cellpose to automatically segment every cell inside each rectangle (client-side cellpose-SAM) \u2014 one region\n per detected cell. No clicking on individual cells needed.\n </li>\n <!-- Contributed tools describe themselves. This library ships none, so an\n open build's help lists only the prompted tools above \u2014 the text no\n longer promises buttons that are not there. -->\n <ng-container *ngFor=\"let tool of contributedTools\">\n <li *ngIf=\"tool.help\" [innerHTML]=\"tool.help.body\"></li>\n </ng-container>\n <ng-container *ngFor=\"let tool of dialogTools\">\n <li *ngIf=\"tool.help\" [innerHTML]=\"tool.help.body\"></li>\n </ng-container>\n </ul>\n\n <h3>Spatial omics</h3>\n <p>\n In <b>Spatial omics</b> mode each observation \u2014 a cell or a Visium spot \u2014 is drawn at its own coordinates, over\n the tissue image where the dataset registers onto one. The\n <img src=\"assets/plotting/spatial-omics.svg\" width=\"14\" height=\"14\" alt=\"Spatial omics\" />\n panel colours them by a <b>column</b> (a cell type, a cluster) or by a <b>gene</b>, and the two are exclusive\n so what drives the colours is never ambiguous.\n </p>\n <ul>\n <li>\n \"<b>Select from ROIs</b>\": turns the regions you have drawn into a selection of observations. Everything else\n then follows that selection. In 3D, with classes picked in the Region Editor's class tree (or their surfaces\n clicked), it selects the observations inside those classes' volumes.\n </li>\n <li>\"<b>Point size</b>\" / \"<b>Opacity</b>\": how the markers are drawn, not what is selected.</li>\n </ul>\n\n <h3>Distribution charts</h3>\n <p>\n The <b>Distribution</b> section of the spatial-omics panel charts whatever the map is coloured by, so the two\n can never disagree. Each tab answers a different question, and the <i class=\"pi pi-question-circle\"></i> beside\n them explains the one on screen \u2014 including what it must <em>not</em> be read for.\n </p>\n <ul>\n <li>\n \"<b>Counts</b>\": how many observations per category. A category is a label, not a magnitude, so a frequency\n is the only distribution it has.\n </li>\n <li>\n \"<b>Histogram</b>\" / \"<b>Violin</b>\" / \"<b>Box</b>\": how a continuous value is distributed \u2014 over everything,\n or split by a grouping column.\n </li>\n <li>\n \"<b>Heatmap</b>\": mean expression of the genes you pick within each group. Z-scored per gene by default, so a\n colour means \"above or below this gene's own average\" rather than \"highly expressed\".\n </li>\n <li>\n \"<b>Embedding</b>\": a UMAP, PCA or t-SNE over the same cells. <b>Lasso it to select on the map</b> \u2014 both\n views read the same selection. Only PCA labels its axes with a percentage, because only its axes explain a\n measurable share of the variance; UMAP and t-SNE coordinates are arbitrary, so distance between distant\n clusters should not be read.\n </li>\n <li>\n \"<b>Detach</b>\": moves the charts into their own window so they can sit beside the map instead of inside the\n panel. Switching tabs keeps the window where it is.\n </li>\n </ul>\n\n <h3>Help</h3>\n <p>\"<b>Help</b>\" <i class=\"pi pi-question-circle\"></i>: opens this dialog.</p>\n\n <h3>Keyboard shortcuts</h3>\n <table class=\"shortcuts-table\">\n <tr>\n <td><kbd>+</kbd> / <kbd>=</kbd></td>\n <td>Zoom in</td>\n </tr>\n <tr>\n <td><kbd>-</kbd></td>\n <td>Zoom out</td>\n </tr>\n <tr>\n <td><kbd>b</kbd></td>\n <td>Toggle zoom box mode</td>\n </tr>\n <tr>\n <td><kbd>p</kbd></td>\n <td>Toggle pan mode</td>\n </tr>\n <tr>\n <td><kbd>f</kbd></td>\n <td>Toggle freeform region drawing</td>\n </tr>\n <tr>\n <td><kbd>l</kbd></td>\n <td>Toggle polyline drawing</td>\n </tr>\n <tr>\n <td><kbd>r</kbd></td>\n <td>Toggle rectangular region drawing</td>\n </tr>\n <tr>\n <td><kbd>w</kbd></td>\n <td>Toggle wand tool</td>\n </tr>\n <tr>\n <td>Wand + <kbd>Shift</kbd></td>\n <td>Erase pixels from the active region</td>\n </tr>\n <tr>\n <td>Wand + <kbd>Ctrl</kbd>/<kbd>Cmd</kbd></td>\n <td>Exact-match flood fill (no smoothing)</td>\n </tr>\n <tr>\n <td><kbd>e</kbd></td>\n <td>Toggle vertex eraser</td>\n </tr>\n <tr>\n <td><kbd>s</kbd></td>\n <td>Selection mode (deactivates drawing tools)</td>\n </tr>\n <tr>\n <td>Point prompt + <kbd>Shift</kbd>/<kbd>Alt</kbd></td>\n <td>Add an exclude point (refine the current object)</td>\n </tr>\n <tr>\n <td><kbd>Enter</kbd></td>\n <td>Commit the current SAM point object</td>\n </tr>\n <tr>\n <td><kbd>Esc</kbd></td>\n <td>Undo the current SAM point object</td>\n </tr>\n <tr>\n <td><kbd>Del</kbd> / <kbd>\u232B</kbd></td>\n <td>Delete selected region</td>\n </tr>\n <tr>\n <td><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd></td>\n <td>Undo the last region action (up to 10)</td>\n </tr>\n <tr>\n <td><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> / <kbd>Ctrl</kbd>+<kbd>Y</kbd></td>\n <td>Redo the last undone region action</td>\n </tr>\n </table>\n\n <ng-template pTemplate=\"footer\">\n <p-button icon=\"pi pi-check\" (click)=\"visibleChange.emit(false)\" label=\"Ok\" styleClass=\"p-button-text\">\n </p-button>\n </ng-template>\n</p-dialog>\n", styles: ["kbd{background:#e8e8e8;border:1px solid #bbb;border-radius:3px;padding:1px 5px;font-family:monospace;font-size:.85em}.shortcuts-table{border-collapse:collapse}.shortcuts-table td{padding:.25rem .75rem .25rem 0;vertical-align:middle}.shortcuts-table td:first-child{white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: SharedModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i3.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i4.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "visible", "style", "position"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
37
37
|
}
|
|
38
38
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: ToolbarHelpDialogComponent, decorators: [{
|
|
39
39
|
type: Component,
|
|
40
|
-
args: [{ selector: 'toolbar-help-dialog', standalone: true, imports: [CommonModule, SharedModule, ButtonModule, DialogModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<p-dialog\n header=\"Plotting help\"\n [visible]=\"visible\"\n (visibleChange)=\"visibleChange.emit($event)\"\n [modal]=\"true\"\n [style]=\"{ width: '50vw' }\"\n [maximizable]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n>\n <p>\n Click a file in the left-hand tree to display it. By default it opens in the <b>Image</b> view \u2014 a natively\n tiled, deeply zoomable raster (OpenSeadragon) with a navigator minimap and a physical-units scale bar.\n <b>Click the image to zoom</b> toward the clicked point; scroll to zoom and drag to pan. When a stack is open,\n a slice slider (Image view) or image-mode toggle (other views) appears. Regions can also be edited in the\n <b>Region Editor</b>, opened with the\n <img src=\"assets/plotting/region-editor.svg\" width=\"14\" height=\"14\" alt=\"Region Editor\" />\n toolbar button as a floating dialog. Drag the <i class=\"pi pi-bars\"></i> handle to detach this toolbar into a\n floating window.\n </p>\n\n <h3>Plot-type dropdown</h3>\n <p>\n The <b>plot-type dropdown</b> switches how the file is visualized: <b>Image</b>, <b>Heatmap</b>,\n <b>Contour</b>, <b>Surface</b>, <b>Volume</b>, <b>Isosurface</b>, and \u2014 when a spatial-omics dataset is open \u2014\n <b>Spatial omics</b> and <b>Spatial omics 3D</b>.\n </p>\n <p>\n <b>Only the modes the data can actually support are offered</b>, so the list changes with what is loaded rather\n than showing entries that would come up blank:\n </p>\n <ul>\n <li>\n <b>Contour</b>, <b>Volume</b> and <b>Isosurface</b> need a grayscale image; the two 3D ones also need a\n z-stack.\n </li>\n <li>\n <b>Spatial omics</b> needs a published dataset, and <b>Spatial omics 3D</b> needs one whose coordinates carry\n a z.\n </li>\n <li>\n The pixel modes (<b>Image</b>, <b>Heatmap</b>, <b>Surface</b>) are withheld for a dataset that brings no\n tissue image \u2014 seqFISH records coordinates and no section, so there is nothing for them to draw.\n </li>\n </ul>\n <ul>\n <li>\n \"<b>Isosurface band</b>\" slider (Isosurface): sets the intensity band the surfaces are drawn for, mapped onto\n the volume's real intensity range.\n </li>\n <li>\n \"<b>3D camera</b>\" (Surface / Scatter 3D / Isosurface): zoom <i class=\"pi pi-search\"></i>, pan\n <i class=\"pi pi-arrows-alt\"></i>, orbit <i class=\"pi pi-globe\"></i>, turntable <i class=\"pi pi-sync\"></i>,\n and reset camera <i class=\"pi pi-home\"></i>; scroll to zoom the 3D scene.\n </li>\n </ul>\n\n <h3>Image manipulation tools</h3>\n <ul>\n <li>\n \"<b>Region Editor</b>\" <img src=\"assets/plotting/region-editor.svg\" width=\"15\" height=\"15\" />: opens the\n Region Editor as a floating, draggable dialog \u2014 a per-image table of every region (class, colour, area) with\n bulk select/label/colour/delete and GeoJSON import/export. It stays in sync with the image, so you can keep\n it open while drawing.\n </li>\n <li>\n \"<b>Intensity profile lines</b>\" <img src=\"assets/plotting/spline-chart.svg\" width=\"15\" height=\"15\" /> (<i\n >work in progress \u2014 not yet stable</i\n >): adds a coloured line ROI; a floating inset chart plots intensity along each line, updates live as you\n drag it, and re-samples at the current zoom resolution. Each added line gets its own colour; select a line\n and use the trash tool <i class=\"pi pi-trash\"></i> to remove it (and its trace).\n </li>\n <li>\n \"<b>Channels & Histogram</b>\" <img src=\"assets/plotting/invert.svg\" width=\"15\" height=\"15\" />: opens a\n floating dialog for brightness/contrast, gamma, and per-channel display, plus the\n <b>colormap / LUT</b> controls (grayscale only) \u2014 a <b>reverse</b> toggle and a colormap dropdown (default:\n inverted greys).\n </li>\n <li>\n \"<b>Smoothen</b>\" <img src=\"assets/plotting/smooth.svg\" width=\"15\" height=\"15\" /> (Image view only): the\n image opens showing <b>raw pixels</b> (nearest-neighbour), so zooming in renders crisp blocks for pixel\n inspection. Toggle this on for bilinear smoothing; the icon turns white while smoothing is active.\n </li>\n </ul>\n\n <h3>Download & view tools</h3>\n <ul>\n <li>\"<b>Download</b>\" <i class=\"pi pi-download\"></i>: download the current image as a PNG.</li>\n <li>\n \"<b>Fit to view</b>\" / autoscale <i class=\"pi pi-window-maximize\"></i>: resets the image to its original\n dimensions. In stack mode it also resets to single-image mode.\n </li>\n </ul>\n\n <h3>Zoom tools</h3>\n <ul>\n <li>\n \"<b>Zoom box</b>\" <img src=\"assets/plotting/zoom-box.svg\" width=\"15\" height=\"15\" /> (<kbd>b</kbd>): drag a\n box to select an area to zoom into.\n </li>\n <li>\"<b>Pan</b>\" <i class=\"pi pi-arrows-alt\"></i> (<kbd>p</kbd>): drag to pan the image.</li>\n <li>\"<b>Zoom in</b>\" <i class=\"pi pi-search-plus\"></i> (<kbd>+</kbd>): zoom in one step.</li>\n <li>\n \"<b>Zoom out</b>\" <i class=\"pi pi-search-minus\"></i> (<kbd>-</kbd>): zoom out one step, stopping at the\n original image dimensions.\n </li>\n </ul>\n\n <h3>Region tools</h3>\n <p>\n By default no tool is selected (all greyed-out); selecting a tool highlights it. The vertex-editing tools\n (polygon, add/delete vertex, move, B\u00E9zier conversions) are available in the <b>Image</b> view only. On a\n <b>donut</b> (a region with a hole), the inner-ring vertices are editable too \u2014 drag, add, and delete them just\n like the outer ring.\n </p>\n <ul>\n <li>\n \"<b>Selection</b>\" <i class=\"pi pi-arrow-up-right\"></i> (<kbd>s</kbd>): a neutral mode that turns off\n whatever drawing tool was active (wand, vertex eraser, rectangle, etc.). Use it to step out of editing\n without picking another tool.\n </li>\n <li>\n \"<b>Rectangular region</b>\" <i class=\"pi pi-stop\"></i> (<kbd>r</kbd>): click and drag to create a rectangular\n region.\n </li>\n <li>\n \"<b>Polyline</b>\" <img src=\"assets/plotting/polyline.svg\" width=\"14\" height=\"14\" /> (<kbd>l</kbd>): draw an\n open (non-closed) polyline by clicking and dragging. Polylines can be edited and exported to GeoJSON as a\n <code>LineString</code> feature.\n </li>\n <li>\n \"<b>Freeform region</b>\" <i class=\"pi pi-pencil\"></i> (<kbd>f</kbd>): click and drag to draw a closed\n freeform polygon.\n </li>\n <li>\n \"<b>Brush</b>\" <img src=\"assets/plotting/paintbrush.svg\" width=\"15\" height=\"15\" />: click and drag to paint a\n region with a circular brush \u2014 the painted stroke is the region. A <b>Size</b> slider (brush diameter, in\n image pixels) appears in the toolbar while the brush is active. Hold <kbd>Shift</kbd> while painting to\n <b>erase</b> (subtract) from a region instead. Painting over an existing region extends it; brushing across\n two regions merges them. Painting a closed ring (or shift-erasing an interior pocket) leaves the enclosed\n area empty \u2014 a <b>donut</b> (Image view).\n </li>\n <li>\n \"<b>Polygon</b>\" <img src=\"assets/plotting/polygon-vertices.svg\" width=\"15\" height=\"15\" />: click to place\n each vertex; click the first point to close the polygon.\n </li>\n <li>\n \"<b>Add vertex</b>\" <img src=\"assets/plotting/vertex-add.svg\" width=\"15\" height=\"15\" />: click an edge of the\n selected polygon to insert a new vertex.\n </li>\n <li>\n \"<b>Delete vertex</b>\" <img src=\"assets/plotting/vertex-delete.svg\" width=\"15\" height=\"15\" />: click a vertex\n of the selected polygon to remove it.\n </li>\n <li>\n <b>Moving a region</b> <img src=\"assets/plotting/region-move.svg\" width=\"15\" height=\"15\" />: with the Select\n tool, drag the selected region's body (or a rectangle's handles to resize it).\n </li>\n <li>\n <b>Convert to B\u00E9zier</b> <img src=\"assets/plotting/to-bezier.svg\" width=\"15\" height=\"15\" /> /\n <b>Convert to polygon</b> <img src=\"assets/plotting/to-polygon.svg\" width=\"15\" height=\"15\" /> (Image view):\n right-click the selected region and pick the conversion in the context menu to turn it into a smooth B\u00E9zier\n curve, or back into a straight-edged polygon.\n </li>\n <li>\n \"<b>Wand</b>\" <img src=\"assets/plotting/wand.svg\" width=\"15\" height=\"15\" /> (<kbd>w</kbd>): click to grow a\n region from pixels with similar values around the click point. Hold <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> for an\n exact-match flood fill; drag to keep extending the selection while moving; hold <kbd>Shift</kbd> while\n clicking or dragging on an existing region to <b>erase</b> pixels from it. Use the <b>Sens.</b> slider that\n appears to make the wand stricter (higher = smaller selection) or looser. Subsequent clicks keep extending\n the same region; clicking inside an existing region adopts it, and growing into another region merges them.\n </li>\n <li>\n \"<b>Vertex eraser</b>\" <i class=\"pi pi-eraser\"></i> (<kbd>e</kbd>): click or click-and-drag to remove polygon\n vertices that fall inside the cursor circle from any region, including a region's inner rings (donut holes).\n Use the <b>Radius</b> slider to set the eraser size in image pixels. Polygons reduced below 3 vertices (or\n polylines below 2) are deleted entirely; a hole reduced below 3 vertices is removed.\n </li>\n <li>\n \"<b>Undo</b>\" <img src=\"assets/plotting/undo.svg\" width=\"15\" height=\"15\" />\n (<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd>): reverts the last region action (draw, delete, edit, wand/brush\n stroke, segmentation, \u2026). Up to the last\n <b>10</b> actions can be undone; the button greys out when there's nothing left to undo.\n </li>\n <li>\n \"<b>Redo</b>\"\n <img src=\"assets/plotting/redo.svg\" width=\"15\" height=\"15\" />\n (<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> or\n <kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Y</kbd>): re-applies the most recently undone action. Performing a new\n region action clears what can be redone.\n </li>\n <li>\n \"<b>Delete region</b>\" <i class=\"pi pi-trash\"></i> (<kbd>Del</kbd>): deletes the selected region. This can\n also be done from the Region Editor.\n </li>\n </ul>\n\n <h3>Region actions (right-click the image)</h3>\n <p>\n Right-click a region \u2014 or the current multi-selection \u2014 to open the \"<b>Selected region(s)</b>\" group at the\n top of the context menu. These act immediately on the selection (they're not drawing modes) and are fully\n undo/redo-able:\n </p>\n <ul>\n <li>\n \"<b>Select all regions</b>\" <i class=\"pi pi-check-square\"></i>: select every region on the image (also in the\n Region Editor toolbar).\n </li>\n <li>\n \"<b>Merge / group</b>\": combine 2+ selected regions into one. If the pieces don't touch, the result is a\n single multi-part region (sparse \"bits\").\n </li>\n <li>\"<b>Ungroup</b>\": split a multi-part region back into one region per piece.</li>\n <li>\n \"<b>Inverse</b>\": replace the selection with everything <i>outside</i> it \u2014 the image rectangle with the\n selected regions punched out as holes. Works at any image size.\n </li>\n <li>\n \"<b>Simplify</b>\": reduce a region's vertex count (Douglas\u2013Peucker) by an altitude threshold in pixels \u2014 pick\n <b>Light</b> (1 px), <b>Medium</b> (3 px), <b>Strong</b> (8 px), or <b>Custom\u2026</b> for a\n slider. Applies to the exterior and any holes (and every part of a multi-part region).\n </li>\n <li>\n \"<b>Convert to B\u00E9zier</b>\" / \"<b>Convert to polygon</b>\" (Image view) and \"<b>Delete</b>\" also live in this\n group; the conversions are only here, not in the toolbar.\n </li>\n </ul>\n\n <h3>Segmentation & detection tools</h3>\n <p>\n AI-assisted segmentation and detection that run entirely in the browser. The first run of any model downloads\n it (a progress toast is shown); it's then cached.\n </p>\n <p>\n Two shapes of tool: the <b>prompted</b> ones (Segment, Point prompts, Cellpose) act on rectangles you draw, and\n generated regions inherit the color of the rectangle they came from<span *ngIf=\"contributedTools.length\"\n >; the <b>no-prompt</b> ones ({{ contributedToolNames }}) sweep the whole current view, so there is nothing\n to draw first</span\n >.\n </p>\n <p>\n Each model dropdown <i class=\"pi pi-chevron-down\"></i> lists the available checkpoints with a\n <i class=\"pi pi-info-circle\"></i> beside each one \u2014 hover it for that model's size, speed, training domain and\n accuracy, so you can pick without leaving the toolbar.\n </p>\n <ul>\n <li>\n \"<b>Segment</b>\" <img src=\"assets/plotting/sam-box-prompt.svg\" width=\"15\" height=\"15\" /> (box prompt): draw\n one or more <b>Rectangular regions</b> around the objects of interest, then click Segment. Each rectangle is\n replaced by the SAM mask of the object inside it.\n </li>\n <li>\n \"<b>Point prompts</b>\" <img src=\"assets/plotting/sam-point-prompt.svg\" width=\"15\" height=\"15\" />: click\n directly on an object to segment it as a <b>new</b> region. Each click starts a fresh object \u2014 clicking\n another object won't grow the previous one. <kbd>Shift</kbd>/<kbd>Alt</kbd>-click adds an\n <i>exclude</i> point that refines the current object; <kbd>Esc</kbd> undoes it, <kbd>Enter</kbd> commits it.\n </li>\n <li>\n \"<b>Model picker</b>\" <i class=\"pi pi-chevron-down\"></i>: the dropdown attached to the Segment button chooses\n the SAM model \u2014 <b>micro-sam ViT-T</b> (default; small, fast) or <b>micro-sam ViT-B</b> (larger, highest\n accuracy) for light microscopy, or <b>patho-sam ViT-B</b> for histopathology (H&E / stained tissue). All\n are promptable Segment Anything models finetuned for biomedical images; they differ in the\n <i>image encoder</i> (the heavy once-per-image step) and the training domain \u2014 box and point prompting behave\n the same. The choice applies to <i>both</i> the box and point tools, which share one loaded model and image\n encoding, so the first run after switching models (or images) downloads and encodes once for both.\n </li>\n <li>\n \"<b>Cellpose</b>\" <img src=\"assets/plotting/cells.svg\" width=\"15\" height=\"15\" />: draw rectangles, then click\n Cellpose to automatically segment every cell inside each rectangle (client-side cellpose-SAM) \u2014 one region\n per detected cell. No clicking on individual cells needed.\n </li>\n <!-- Contributed tools describe themselves. This library ships none, so an\n open build's help lists only the prompted tools above \u2014 the text no\n longer promises buttons that are not there. -->\n <ng-container *ngFor=\"let tool of contributedTools\">\n <li *ngIf=\"tool.help\" [innerHTML]=\"tool.help.body\"></li>\n </ng-container>\n <ng-container *ngFor=\"let tool of dialogTools\">\n <li *ngIf=\"tool.help\" [innerHTML]=\"tool.help.body\"></li>\n </ng-container>\n </ul>\n\n <h3>Spatial omics</h3>\n <p>\n In <b>Spatial omics</b> mode each observation \u2014 a cell or a Visium spot \u2014 is drawn at its own coordinates, over\n the tissue image where the dataset registers onto one. The\n <img src=\"assets/plotting/spatial-omics.svg\" width=\"14\" height=\"14\" alt=\"Spatial omics\" />\n panel colours them by a <b>column</b> (a cell type, a cluster) or by a <b>gene</b>, and the two are exclusive\n so what drives the colours is never ambiguous.\n </p>\n <ul>\n <li>\n \"<b>Select from ROIs</b>\": turns the regions you have drawn into a selection of observations. Everything else\n then follows that selection.\n </li>\n <li>\"<b>Point size</b>\" / \"<b>Opacity</b>\": how the markers are drawn, not what is selected.</li>\n </ul>\n\n <h3>Distribution charts</h3>\n <p>\n The <b>Distribution</b> section of the spatial-omics panel charts whatever the map is coloured by, so the two\n can never disagree. Each tab answers a different question, and the <i class=\"pi pi-question-circle\"></i> beside\n them explains the one on screen \u2014 including what it must <em>not</em> be read for.\n </p>\n <ul>\n <li>\n \"<b>Counts</b>\": how many observations per category. A category is a label, not a magnitude, so a frequency\n is the only distribution it has.\n </li>\n <li>\n \"<b>Histogram</b>\" / \"<b>Violin</b>\" / \"<b>Box</b>\": how a continuous value is distributed \u2014 over everything,\n or split by a grouping column.\n </li>\n <li>\n \"<b>Heatmap</b>\": mean expression of the genes you pick within each group. Z-scored per gene by default, so a\n colour means \"above or below this gene's own average\" rather than \"highly expressed\".\n </li>\n <li>\n \"<b>Embedding</b>\": a UMAP, PCA or t-SNE over the same cells. <b>Lasso it to select on the map</b> \u2014 both\n views read the same selection. Only PCA labels its axes with a percentage, because only its axes explain a\n measurable share of the variance; UMAP and t-SNE coordinates are arbitrary, so distance between distant\n clusters should not be read.\n </li>\n <li>\n \"<b>Detach</b>\": moves the charts into their own window so they can sit beside the map instead of inside the\n panel. Switching tabs keeps the window where it is.\n </li>\n </ul>\n\n <h3>Help</h3>\n <p>\"<b>Help</b>\" <i class=\"pi pi-question-circle\"></i>: opens this dialog.</p>\n\n <h3>Keyboard shortcuts</h3>\n <table class=\"shortcuts-table\">\n <tr>\n <td><kbd>+</kbd> / <kbd>=</kbd></td>\n <td>Zoom in</td>\n </tr>\n <tr>\n <td><kbd>-</kbd></td>\n <td>Zoom out</td>\n </tr>\n <tr>\n <td><kbd>b</kbd></td>\n <td>Toggle zoom box mode</td>\n </tr>\n <tr>\n <td><kbd>p</kbd></td>\n <td>Toggle pan mode</td>\n </tr>\n <tr>\n <td><kbd>f</kbd></td>\n <td>Toggle freeform region drawing</td>\n </tr>\n <tr>\n <td><kbd>l</kbd></td>\n <td>Toggle polyline drawing</td>\n </tr>\n <tr>\n <td><kbd>r</kbd></td>\n <td>Toggle rectangular region drawing</td>\n </tr>\n <tr>\n <td><kbd>w</kbd></td>\n <td>Toggle wand tool</td>\n </tr>\n <tr>\n <td>Wand + <kbd>Shift</kbd></td>\n <td>Erase pixels from the active region</td>\n </tr>\n <tr>\n <td>Wand + <kbd>Ctrl</kbd>/<kbd>Cmd</kbd></td>\n <td>Exact-match flood fill (no smoothing)</td>\n </tr>\n <tr>\n <td><kbd>e</kbd></td>\n <td>Toggle vertex eraser</td>\n </tr>\n <tr>\n <td><kbd>s</kbd></td>\n <td>Selection mode (deactivates drawing tools)</td>\n </tr>\n <tr>\n <td>Point prompt + <kbd>Shift</kbd>/<kbd>Alt</kbd></td>\n <td>Add an exclude point (refine the current object)</td>\n </tr>\n <tr>\n <td><kbd>Enter</kbd></td>\n <td>Commit the current SAM point object</td>\n </tr>\n <tr>\n <td><kbd>Esc</kbd></td>\n <td>Undo the current SAM point object</td>\n </tr>\n <tr>\n <td><kbd>Del</kbd> / <kbd>\u232B</kbd></td>\n <td>Delete selected region</td>\n </tr>\n <tr>\n <td><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd></td>\n <td>Undo the last region action (up to 10)</td>\n </tr>\n <tr>\n <td><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> / <kbd>Ctrl</kbd>+<kbd>Y</kbd></td>\n <td>Redo the last undone region action</td>\n </tr>\n </table>\n\n <ng-template pTemplate=\"footer\">\n <p-button icon=\"pi pi-check\" (click)=\"visibleChange.emit(false)\" label=\"Ok\" styleClass=\"p-button-text\">\n </p-button>\n </ng-template>\n</p-dialog>\n", styles: ["kbd{background:#e8e8e8;border:1px solid #bbb;border-radius:3px;padding:1px 5px;font-family:monospace;font-size:.85em}.shortcuts-table{border-collapse:collapse}.shortcuts-table td{padding:.25rem .75rem .25rem 0;vertical-align:middle}.shortcuts-table td:first-child{white-space:nowrap}\n"] }]
|
|
40
|
+
args: [{ selector: 'toolbar-help-dialog', standalone: true, imports: [CommonModule, SharedModule, ButtonModule, DialogModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<p-dialog\n header=\"Plotting help\"\n [visible]=\"visible\"\n (visibleChange)=\"visibleChange.emit($event)\"\n [modal]=\"true\"\n [style]=\"{ width: '50vw' }\"\n [maximizable]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n>\n <p>\n Click a file in the left-hand tree to display it. By default it opens in the <b>Image</b> view \u2014 a natively\n tiled, deeply zoomable raster (OpenSeadragon) with a navigator minimap and a physical-units scale bar.\n <b>Click the image to zoom</b> toward the clicked point; scroll to zoom and drag to pan. When a stack is open,\n a slice slider (Image view) or image-mode toggle (other views) appears. Regions can also be edited in the\n <b>Region Editor</b>, opened with the\n <img src=\"assets/plotting/region-editor.svg\" width=\"14\" height=\"14\" alt=\"Region Editor\" />\n toolbar button as a floating dialog. Drag the <i class=\"pi pi-bars\"></i> handle to detach this toolbar into a\n floating window.\n </p>\n\n <h3>Plot-type dropdown</h3>\n <p>\n The <b>plot-type dropdown</b> switches how the file is visualized: <b>Image</b>, <b>Heatmap</b>,\n <b>Contour</b>, <b>Surface</b>, <b>Volume</b>, <b>Isosurface</b>, and \u2014 when a spatial-omics dataset is open \u2014\n <b>Spatial omics</b> and <b>Spatial omics 3D</b>.\n </p>\n <p>\n <b>Only the modes the data can actually support are offered</b>, so the list changes with what is loaded rather\n than showing entries that would come up blank:\n </p>\n <ul>\n <li>\n <b>Contour</b>, <b>Volume</b> and <b>Isosurface</b> need a grayscale image; the two 3D ones also need a\n z-stack.\n </li>\n <li>\n <b>Spatial omics</b> needs a published dataset, and <b>Spatial omics 3D</b> needs one whose coordinates carry\n a z.\n </li>\n <li>\n The pixel modes (<b>Image</b>, <b>Heatmap</b>, <b>Surface</b>) are withheld for a dataset that brings no\n tissue image \u2014 seqFISH records coordinates and no section, so there is nothing for them to draw.\n </li>\n </ul>\n <ul>\n <li>\n \"<b>Isosurface band</b>\" slider (Isosurface): sets the intensity band the surfaces are drawn for, mapped onto\n the volume's real intensity range.\n </li>\n <li>\n \"<b>3D camera</b>\" (Surface / Scatter 3D / Isosurface): zoom <i class=\"pi pi-search\"></i>, pan\n <i class=\"pi pi-arrows-alt\"></i>, orbit <i class=\"pi pi-globe\"></i>, turntable <i class=\"pi pi-sync\"></i>,\n and reset camera <i class=\"pi pi-home\"></i>; scroll to zoom the 3D scene.\n </li>\n </ul>\n\n <h3>Image manipulation tools</h3>\n <ul>\n <li>\n \"<b>Region Editor</b>\" <img src=\"assets/plotting/region-editor.svg\" width=\"15\" height=\"15\" />: opens the\n Region Editor as a floating, draggable dialog \u2014 a per-image table of every region (class, colour, area) with\n bulk select/label/colour/delete and GeoJSON import/export. It stays in sync with the image, so you can keep\n it open while drawing.\n </li>\n <li>\n \"<b>Intensity profile lines</b>\" <img src=\"assets/plotting/spline-chart.svg\" width=\"15\" height=\"15\" /> (<i\n >work in progress \u2014 not yet stable</i\n >): adds a coloured line ROI; a floating inset chart plots intensity along each line, updates live as you\n drag it, and re-samples at the current zoom resolution. Each added line gets its own colour; select a line\n and use the trash tool <i class=\"pi pi-trash\"></i> to remove it (and its trace).\n </li>\n <li>\n \"<b>Channels & Histogram</b>\" <img src=\"assets/plotting/invert.svg\" width=\"15\" height=\"15\" />: opens a\n floating dialog for brightness/contrast, gamma, and per-channel display, plus the\n <b>colormap / LUT</b> controls (grayscale only) \u2014 a <b>reverse</b> toggle and a colormap dropdown (default:\n inverted greys).\n </li>\n <li>\n \"<b>Smoothen</b>\" <img src=\"assets/plotting/smooth.svg\" width=\"15\" height=\"15\" /> (Image view only): the\n image opens showing <b>raw pixels</b> (nearest-neighbour), so zooming in renders crisp blocks for pixel\n inspection. Toggle this on for bilinear smoothing; the icon turns white while smoothing is active.\n </li>\n </ul>\n\n <h3>Download & view tools</h3>\n <ul>\n <li>\"<b>Download</b>\" <i class=\"pi pi-download\"></i>: download the current image as a PNG.</li>\n <li>\n \"<b>Fit to view</b>\" / autoscale <i class=\"pi pi-window-maximize\"></i>: resets the image to its original\n dimensions. In stack mode it also resets to single-image mode.\n </li>\n </ul>\n\n <h3>Zoom tools</h3>\n <ul>\n <li>\n \"<b>Zoom box</b>\" <img src=\"assets/plotting/zoom-box.svg\" width=\"15\" height=\"15\" /> (<kbd>b</kbd>): drag a\n box to select an area to zoom into.\n </li>\n <li>\"<b>Pan</b>\" <i class=\"pi pi-arrows-alt\"></i> (<kbd>p</kbd>): drag to pan the image.</li>\n <li>\"<b>Zoom in</b>\" <i class=\"pi pi-search-plus\"></i> (<kbd>+</kbd>): zoom in one step.</li>\n <li>\n \"<b>Zoom out</b>\" <i class=\"pi pi-search-minus\"></i> (<kbd>-</kbd>): zoom out one step, stopping at the\n original image dimensions.\n </li>\n </ul>\n\n <h3>Region tools</h3>\n <p>\n By default no tool is selected (all greyed-out); selecting a tool highlights it. The vertex-editing tools\n (polygon, add/delete vertex, move, B\u00E9zier conversions) are available in the <b>Image</b> view only. On a\n <b>donut</b> (a region with a hole), the inner-ring vertices are editable too \u2014 drag, add, and delete them just\n like the outer ring.\n </p>\n <ul>\n <li>\n \"<b>Selection</b>\" <i class=\"pi pi-arrow-up-right\"></i> (<kbd>s</kbd>): a neutral mode that turns off\n whatever drawing tool was active (wand, vertex eraser, rectangle, etc.). Use it to step out of editing\n without picking another tool.\n </li>\n <li>\n \"<b>Rectangular region</b>\" <i class=\"pi pi-stop\"></i> (<kbd>r</kbd>): click and drag to create a rectangular\n region.\n </li>\n <li>\n \"<b>Polyline</b>\" <img src=\"assets/plotting/polyline.svg\" width=\"14\" height=\"14\" /> (<kbd>l</kbd>): draw an\n open (non-closed) polyline by clicking and dragging. Polylines can be edited and exported to GeoJSON as a\n <code>LineString</code> feature.\n </li>\n <li>\n \"<b>Freeform region</b>\" <i class=\"pi pi-pencil\"></i> (<kbd>f</kbd>): click and drag to draw a closed\n freeform polygon.\n </li>\n <li>\n \"<b>Brush</b>\" <img src=\"assets/plotting/paintbrush.svg\" width=\"15\" height=\"15\" />: click and drag to paint a\n region with a circular brush \u2014 the painted stroke is the region. A <b>Size</b> slider (brush diameter, in\n image pixels) appears in the toolbar while the brush is active. Hold <kbd>Shift</kbd> while painting to\n <b>erase</b> (subtract) from a region instead. Painting over an existing region extends it; brushing across\n two regions merges them. Painting a closed ring (or shift-erasing an interior pocket) leaves the enclosed\n area empty \u2014 a <b>donut</b> (Image view).\n </li>\n <li>\n \"<b>Polygon</b>\" <img src=\"assets/plotting/polygon-vertices.svg\" width=\"15\" height=\"15\" />: click to place\n each vertex; click the first point to close the polygon.\n </li>\n <li>\n \"<b>Add vertex</b>\" <img src=\"assets/plotting/vertex-add.svg\" width=\"15\" height=\"15\" />: click an edge of the\n selected polygon to insert a new vertex.\n </li>\n <li>\n \"<b>Delete vertex</b>\" <img src=\"assets/plotting/vertex-delete.svg\" width=\"15\" height=\"15\" />: click a vertex\n of the selected polygon to remove it.\n </li>\n <li>\n <b>Moving a region</b> <img src=\"assets/plotting/region-move.svg\" width=\"15\" height=\"15\" />: with the Select\n tool, drag the selected region's body (or a rectangle's handles to resize it).\n </li>\n <li>\n <b>Convert to B\u00E9zier</b> <img src=\"assets/plotting/to-bezier.svg\" width=\"15\" height=\"15\" /> /\n <b>Convert to polygon</b> <img src=\"assets/plotting/to-polygon.svg\" width=\"15\" height=\"15\" /> (Image view):\n right-click the selected region and pick the conversion in the context menu to turn it into a smooth B\u00E9zier\n curve, or back into a straight-edged polygon.\n </li>\n <li>\n \"<b>Wand</b>\" <img src=\"assets/plotting/wand.svg\" width=\"15\" height=\"15\" /> (<kbd>w</kbd>): click to grow a\n region from pixels with similar values around the click point. Hold <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> for an\n exact-match flood fill; drag to keep extending the selection while moving; hold <kbd>Shift</kbd> while\n clicking or dragging on an existing region to <b>erase</b> pixels from it. Use the <b>Sens.</b> slider that\n appears to make the wand stricter (higher = smaller selection) or looser. Subsequent clicks keep extending\n the same region; clicking inside an existing region adopts it, and growing into another region merges them.\n </li>\n <li>\n \"<b>Vertex eraser</b>\" <i class=\"pi pi-eraser\"></i> (<kbd>e</kbd>): click or click-and-drag to remove polygon\n vertices that fall inside the cursor circle from any region, including a region's inner rings (donut holes).\n Use the <b>Radius</b> slider to set the eraser size in image pixels. Polygons reduced below 3 vertices (or\n polylines below 2) are deleted entirely; a hole reduced below 3 vertices is removed.\n </li>\n <li>\n \"<b>Undo</b>\" <img src=\"assets/plotting/undo.svg\" width=\"15\" height=\"15\" />\n (<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd>): reverts the last region action (draw, delete, edit, wand/brush\n stroke, segmentation, \u2026). Up to the last\n <b>10</b> actions can be undone; the button greys out when there's nothing left to undo.\n </li>\n <li>\n \"<b>Redo</b>\"\n <img src=\"assets/plotting/redo.svg\" width=\"15\" height=\"15\" />\n (<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> or\n <kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Y</kbd>): re-applies the most recently undone action. Performing a new\n region action clears what can be redone.\n </li>\n <li>\n \"<b>Delete region</b>\" <i class=\"pi pi-trash\"></i> (<kbd>Del</kbd>): deletes the selected region. This can\n also be done from the Region Editor.\n </li>\n </ul>\n\n <h3>Region actions (right-click the image)</h3>\n <p>\n Right-click a region \u2014 or the current multi-selection \u2014 to open the \"<b>Selected region(s)</b>\" group at the\n top of the context menu. These act immediately on the selection (they're not drawing modes) and are fully\n undo/redo-able:\n </p>\n <ul>\n <li>\n \"<b>Select all regions</b>\" <i class=\"pi pi-check-square\"></i>: select every region on the image (also in the\n Region Editor toolbar).\n </li>\n <li>\n \"<b>Merge / group</b>\": combine 2+ selected regions into one. If the pieces don't touch, the result is a\n single multi-part region (sparse \"bits\").\n </li>\n <li>\"<b>Ungroup</b>\": split a multi-part region back into one region per piece.</li>\n <li>\n \"<b>Inverse</b>\": replace the selection with everything <i>outside</i> it \u2014 the image rectangle with the\n selected regions punched out as holes. Works at any image size.\n </li>\n <li>\n \"<b>Simplify</b>\": reduce a region's vertex count (Douglas\u2013Peucker) by an altitude threshold in pixels \u2014 pick\n <b>Light</b> (1 px), <b>Medium</b> (3 px), <b>Strong</b> (8 px), or <b>Custom\u2026</b> for a\n slider. Applies to the exterior and any holes (and every part of a multi-part region).\n </li>\n <li>\n \"<b>Convert to B\u00E9zier</b>\" / \"<b>Convert to polygon</b>\" (Image view) and \"<b>Delete</b>\" also live in this\n group; the conversions are only here, not in the toolbar.\n </li>\n </ul>\n\n <h3>Segmentation & detection tools</h3>\n <p>\n AI-assisted segmentation and detection that run entirely in the browser. The first run of any model downloads\n it (a progress toast is shown); it's then cached.\n </p>\n <p>\n Two shapes of tool: the <b>prompted</b> ones (Segment, Point prompts, Cellpose) act on rectangles you draw, and\n generated regions inherit the color of the rectangle they came from<span *ngIf=\"contributedTools.length\"\n >; the <b>no-prompt</b> ones ({{ contributedToolNames }}) sweep the whole current view, so there is nothing\n to draw first</span\n >.\n </p>\n <p>\n Each model dropdown <i class=\"pi pi-chevron-down\"></i> lists the available checkpoints with a\n <i class=\"pi pi-info-circle\"></i> beside each one \u2014 hover it for that model's size, speed, training domain and\n accuracy, so you can pick without leaving the toolbar.\n </p>\n <ul>\n <li>\n \"<b>Segment</b>\" <img src=\"assets/plotting/sam-box-prompt.svg\" width=\"15\" height=\"15\" /> (box prompt): draw\n one or more <b>Rectangular regions</b> around the objects of interest, then click Segment. Each rectangle is\n replaced by the SAM mask of the object inside it.\n </li>\n <li>\n \"<b>Point prompts</b>\" <img src=\"assets/plotting/sam-point-prompt.svg\" width=\"15\" height=\"15\" />: click\n directly on an object to segment it as a <b>new</b> region. Each click starts a fresh object \u2014 clicking\n another object won't grow the previous one. <kbd>Shift</kbd>/<kbd>Alt</kbd>-click adds an\n <i>exclude</i> point that refines the current object; <kbd>Esc</kbd> undoes it, <kbd>Enter</kbd> commits it.\n </li>\n <li>\n \"<b>Model picker</b>\" <i class=\"pi pi-chevron-down\"></i>: the dropdown attached to the Segment button chooses\n the SAM model \u2014 <b>micro-sam ViT-T</b> (default; small, fast) or <b>micro-sam ViT-B</b> (larger, highest\n accuracy) for light microscopy, or <b>patho-sam ViT-B</b> for histopathology (H&E / stained tissue). All\n are promptable Segment Anything models finetuned for biomedical images; they differ in the\n <i>image encoder</i> (the heavy once-per-image step) and the training domain \u2014 box and point prompting behave\n the same. The choice applies to <i>both</i> the box and point tools, which share one loaded model and image\n encoding, so the first run after switching models (or images) downloads and encodes once for both.\n </li>\n <li>\n \"<b>Cellpose</b>\" <img src=\"assets/plotting/cells.svg\" width=\"15\" height=\"15\" />: draw rectangles, then click\n Cellpose to automatically segment every cell inside each rectangle (client-side cellpose-SAM) \u2014 one region\n per detected cell. No clicking on individual cells needed.\n </li>\n <!-- Contributed tools describe themselves. This library ships none, so an\n open build's help lists only the prompted tools above \u2014 the text no\n longer promises buttons that are not there. -->\n <ng-container *ngFor=\"let tool of contributedTools\">\n <li *ngIf=\"tool.help\" [innerHTML]=\"tool.help.body\"></li>\n </ng-container>\n <ng-container *ngFor=\"let tool of dialogTools\">\n <li *ngIf=\"tool.help\" [innerHTML]=\"tool.help.body\"></li>\n </ng-container>\n </ul>\n\n <h3>Spatial omics</h3>\n <p>\n In <b>Spatial omics</b> mode each observation \u2014 a cell or a Visium spot \u2014 is drawn at its own coordinates, over\n the tissue image where the dataset registers onto one. The\n <img src=\"assets/plotting/spatial-omics.svg\" width=\"14\" height=\"14\" alt=\"Spatial omics\" />\n panel colours them by a <b>column</b> (a cell type, a cluster) or by a <b>gene</b>, and the two are exclusive\n so what drives the colours is never ambiguous.\n </p>\n <ul>\n <li>\n \"<b>Select from ROIs</b>\": turns the regions you have drawn into a selection of observations. Everything else\n then follows that selection. In 3D, with classes picked in the Region Editor's class tree (or their surfaces\n clicked), it selects the observations inside those classes' volumes.\n </li>\n <li>\"<b>Point size</b>\" / \"<b>Opacity</b>\": how the markers are drawn, not what is selected.</li>\n </ul>\n\n <h3>Distribution charts</h3>\n <p>\n The <b>Distribution</b> section of the spatial-omics panel charts whatever the map is coloured by, so the two\n can never disagree. Each tab answers a different question, and the <i class=\"pi pi-question-circle\"></i> beside\n them explains the one on screen \u2014 including what it must <em>not</em> be read for.\n </p>\n <ul>\n <li>\n \"<b>Counts</b>\": how many observations per category. A category is a label, not a magnitude, so a frequency\n is the only distribution it has.\n </li>\n <li>\n \"<b>Histogram</b>\" / \"<b>Violin</b>\" / \"<b>Box</b>\": how a continuous value is distributed \u2014 over everything,\n or split by a grouping column.\n </li>\n <li>\n \"<b>Heatmap</b>\": mean expression of the genes you pick within each group. Z-scored per gene by default, so a\n colour means \"above or below this gene's own average\" rather than \"highly expressed\".\n </li>\n <li>\n \"<b>Embedding</b>\": a UMAP, PCA or t-SNE over the same cells. <b>Lasso it to select on the map</b> \u2014 both\n views read the same selection. Only PCA labels its axes with a percentage, because only its axes explain a\n measurable share of the variance; UMAP and t-SNE coordinates are arbitrary, so distance between distant\n clusters should not be read.\n </li>\n <li>\n \"<b>Detach</b>\": moves the charts into their own window so they can sit beside the map instead of inside the\n panel. Switching tabs keeps the window where it is.\n </li>\n </ul>\n\n <h3>Help</h3>\n <p>\"<b>Help</b>\" <i class=\"pi pi-question-circle\"></i>: opens this dialog.</p>\n\n <h3>Keyboard shortcuts</h3>\n <table class=\"shortcuts-table\">\n <tr>\n <td><kbd>+</kbd> / <kbd>=</kbd></td>\n <td>Zoom in</td>\n </tr>\n <tr>\n <td><kbd>-</kbd></td>\n <td>Zoom out</td>\n </tr>\n <tr>\n <td><kbd>b</kbd></td>\n <td>Toggle zoom box mode</td>\n </tr>\n <tr>\n <td><kbd>p</kbd></td>\n <td>Toggle pan mode</td>\n </tr>\n <tr>\n <td><kbd>f</kbd></td>\n <td>Toggle freeform region drawing</td>\n </tr>\n <tr>\n <td><kbd>l</kbd></td>\n <td>Toggle polyline drawing</td>\n </tr>\n <tr>\n <td><kbd>r</kbd></td>\n <td>Toggle rectangular region drawing</td>\n </tr>\n <tr>\n <td><kbd>w</kbd></td>\n <td>Toggle wand tool</td>\n </tr>\n <tr>\n <td>Wand + <kbd>Shift</kbd></td>\n <td>Erase pixels from the active region</td>\n </tr>\n <tr>\n <td>Wand + <kbd>Ctrl</kbd>/<kbd>Cmd</kbd></td>\n <td>Exact-match flood fill (no smoothing)</td>\n </tr>\n <tr>\n <td><kbd>e</kbd></td>\n <td>Toggle vertex eraser</td>\n </tr>\n <tr>\n <td><kbd>s</kbd></td>\n <td>Selection mode (deactivates drawing tools)</td>\n </tr>\n <tr>\n <td>Point prompt + <kbd>Shift</kbd>/<kbd>Alt</kbd></td>\n <td>Add an exclude point (refine the current object)</td>\n </tr>\n <tr>\n <td><kbd>Enter</kbd></td>\n <td>Commit the current SAM point object</td>\n </tr>\n <tr>\n <td><kbd>Esc</kbd></td>\n <td>Undo the current SAM point object</td>\n </tr>\n <tr>\n <td><kbd>Del</kbd> / <kbd>\u232B</kbd></td>\n <td>Delete selected region</td>\n </tr>\n <tr>\n <td><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd></td>\n <td>Undo the last region action (up to 10)</td>\n </tr>\n <tr>\n <td><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> / <kbd>Ctrl</kbd>+<kbd>Y</kbd></td>\n <td>Redo the last undone region action</td>\n </tr>\n </table>\n\n <ng-template pTemplate=\"footer\">\n <p-button icon=\"pi pi-check\" (click)=\"visibleChange.emit(false)\" label=\"Ok\" styleClass=\"p-button-text\">\n </p-button>\n </ng-template>\n</p-dialog>\n", styles: ["kbd{background:#e8e8e8;border:1px solid #bbb;border-radius:3px;padding:1px 5px;font-family:monospace;font-size:.85em}.shortcuts-table{border-collapse:collapse}.shortcuts-table td{padding:.25rem .75rem .25rem 0;vertical-align:middle}.shortcuts-table td:first-child{white-space:nowrap}\n"] }]
|
|
41
41
|
}], propDecorators: { visible: [{
|
|
42
42
|
type: Input
|
|
43
43
|
}], visibleChange: [{
|
|
@@ -47,4 +47,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
|
|
|
47
47
|
}], dialogTools: [{
|
|
48
48
|
type: Input
|
|
49
49
|
}] } });
|
|
50
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbGJhci1oZWxwLWRpYWxvZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3Rvb2xiYXIvdG9vbGJhci1oZWxwLWRpYWxvZy90b29sYmFyLWhlbHAtZGlhbG9nLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci90b29sYmFyLWhlbHAtZGlhbG9nL3Rvb2xiYXItaGVscC1kaWFsb2cuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDM0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7O0FBSTlDOzs7R0FHRztBQVNILE1BQU0sT0FBTywwQkFBMEI7SUFSdkM7UUFTRSwwQkFBMEI7UUFDakIsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUN6QixxRUFBcUU7UUFDM0Qsa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBVyxDQUFDO1FBRXRELG1FQUFtRTtRQUMxRCxxQkFBZ0IsR0FBOEIsRUFBRSxDQUFDO1FBQzFELGdFQUFnRTtRQUN2RCxnQkFBVyxHQUFvQyxFQUFFLENBQUM7UUFFM0Q7OytEQUV1RDtRQUM3Qyx5QkFBb0IsR0FBRyxFQUFFLENBQUM7S0FPckM7SUFMQyxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxPQUFPLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25GLENBQUM7SUFDSCxDQUFDOzhHQXBCVSwwQkFBMEI7a0dBQTFCLDBCQUEwQixtUEM1QnZDLG0wbkJBNlpBLHNWRHRZWSxZQUFZLCtQQUFFLFlBQVkscUlBQUUsWUFBWSw2WEFBRSxZQUFZOzsyRkFLckQsMEJBQTBCO2tCQVJ0QyxTQUFTOytCQUNFLHFCQUFxQixjQUNuQixJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLENBQUMsbUJBR2hELHVCQUF1QixDQUFDLE1BQU07OEJBSXRDLE9BQU87c0JBQWYsS0FBSztnQkFFSSxhQUFhO3NCQUF0QixNQUFNO2dCQUdFLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFNoYXJlZE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYXBpJztcbmltcG9ydCB7IEJ1dHRvbk1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYnV0dG9uJztcbmltcG9ydCB7IERpYWxvZ01vZHVsZSB9IGZyb20gJ3ByaW1lbmcvZGlhbG9nJztcblxuaW1wb3J0IHsgVG9vbGJhckRpYWxvZ1Rvb2xDb250cmlidXRpb24sIFRvb2xiYXJUb29sQ29udHJpYnV0aW9uIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3Rvb2xiYXItdG9vbC5jb250cmFjdCc7XG5cbi8qKlxuICogVGhlIHBsb3R0aW5nIHRvb2xiYXIncyBoZWxwIGRpYWxvZzogc3RhdGljIGRvY3VtZW50YXRpb24gb2YgZXZlcnkgdG9vbCwgcGx1c1xuICogdGhlIGhlbHAgZWFjaCBjb250cmlidXRlZCB0b29sIGJyaW5ncy5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9vbGJhci1oZWxwLWRpYWxvZycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIFNoYXJlZE1vZHVsZSwgQnV0dG9uTW9kdWxlLCBEaWFsb2dNb2R1bGVdLFxuICB0ZW1wbGF0ZVVybDogJy4vdG9vbGJhci1oZWxwLWRpYWxvZy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3Rvb2xiYXItaGVscC1kaWFsb2cuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFRvb2xiYXJIZWxwRGlhbG9nQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcbiAgLyoqIFRoZSBkaWFsb2cgaXMgb3Blbi4gKi9cbiAgQElucHV0KCkgdmlzaWJsZSA9IGZhbHNlO1xuICAvKiogVGhlIGRpYWxvZyB3YXMgY2xvc2VkIChgZmFsc2VgKTsgdHdvLXdheSB3aXRoIHtAbGluayB2aXNpYmxlfS4gKi9cbiAgQE91dHB1dCgpIHZpc2libGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgLyoqIENvbnRyaWJ1dGVkIG5vLXByb21wdCB0b29scyAodGhlaXIgaGVscCBlbnRyaWVzIGFyZSBsaXN0ZWQpLiAqL1xuICBASW5wdXQoKSBjb250cmlidXRlZFRvb2xzOiBUb29sYmFyVG9vbENvbnRyaWJ1dGlvbltdID0gW107XG4gIC8qKiBDb250cmlidXRlZCBkaWFsb2cgdG9vbHMgKHRoZWlyIGhlbHAgZW50cmllcyBhcmUgbGlzdGVkKS4gKi9cbiAgQElucHV0KCkgZGlhbG9nVG9vbHM6IFRvb2xiYXJEaWFsb2dUb29sQ29udHJpYnV0aW9uW10gPSBbXTtcblxuICAvKiogQ29udHJpYnV0ZWQgdG9vbCBuYW1lcyBmb3IgdGhlIHByb21wdGVkL25vLXByb21wdCBjb250cmFzdCwgZS5nLlxuICAgKiAgXCJZT0xPLCBSZXRpbmFsIGxheWVyc1wiLiBFbXB0eSB3aGVuIG5vdGhpbmcgaXMgcmVnaXN0ZXJlZCwgd2hpY2ggaXMgd2h5XG4gICAqICB0aGUgc2VudGVuY2UgdGhhdCB1c2VzIGl0IGlzIGl0c2VsZiBjb25kaXRpb25hbC4gKi9cbiAgcHJvdGVjdGVkIGNvbnRyaWJ1dGVkVG9vbE5hbWVzID0gJyc7XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWydjb250cmlidXRlZFRvb2xzJ10pIHtcbiAgICAgIHRoaXMuY29udHJpYnV0ZWRUb29sTmFtZXMgPSB0aGlzLmNvbnRyaWJ1dGVkVG9vbHMubWFwKCh0KSA9PiB0LmxhYmVsKS5qb2luKCcsICcpO1xuICAgIH1cbiAgfVxufVxuIiwiPHAtZGlhbG9nXG4gIGhlYWRlcj1cIlBsb3R0aW5nIGhlbHBcIlxuICBbdmlzaWJsZV09XCJ2aXNpYmxlXCJcbiAgKHZpc2libGVDaGFuZ2UpPVwidmlzaWJsZUNoYW5nZS5lbWl0KCRldmVudClcIlxuICBbbW9kYWxdPVwidHJ1ZVwiXG4gIFtzdHlsZV09XCJ7IHdpZHRoOiAnNTB2dycgfVwiXG4gIFttYXhpbWl6YWJsZV09XCJ0cnVlXCJcbiAgW2RyYWdnYWJsZV09XCJmYWxzZVwiXG4gIFtyZXNpemFibGVdPVwiZmFsc2VcIlxuPlxuICA8cD5cbiAgICBDbGljayBhIGZpbGUgaW4gdGhlIGxlZnQtaGFuZCB0cmVlIHRvIGRpc3BsYXkgaXQuIEJ5IGRlZmF1bHQgaXQgb3BlbnMgaW4gdGhlIDxiPkltYWdlPC9iPiB2aWV3IOKAlCBhIG5hdGl2ZWx5XG4gICAgdGlsZWQsIGRlZXBseSB6b29tYWJsZSByYXN0ZXIgKE9wZW5TZWFkcmFnb24pIHdpdGggYSBuYXZpZ2F0b3IgbWluaW1hcCBhbmQgYSBwaHlzaWNhbC11bml0cyBzY2FsZSBiYXIuXG4gICAgPGI+Q2xpY2sgdGhlIGltYWdlIHRvIHpvb208L2I+IHRvd2FyZCB0aGUgY2xpY2tlZCBwb2ludDsgc2Nyb2xsIHRvIHpvb20gYW5kIGRyYWcgdG8gcGFuLiBXaGVuIGEgc3RhY2sgaXMgb3BlbixcbiAgICBhIHNsaWNlIHNsaWRlciAoSW1hZ2Ugdmlldykgb3IgaW1hZ2UtbW9kZSB0b2dnbGUgKG90aGVyIHZpZXdzKSBhcHBlYXJzLiBSZWdpb25zIGNhbiBhbHNvIGJlIGVkaXRlZCBpbiB0aGVcbiAgICA8Yj5SZWdpb24gRWRpdG9yPC9iPiwgb3BlbmVkIHdpdGggdGhlXG4gICAgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvcmVnaW9uLWVkaXRvci5zdmdcIiB3aWR0aD1cIjE0XCIgaGVpZ2h0PVwiMTRcIiBhbHQ9XCJSZWdpb24gRWRpdG9yXCIgLz5cbiAgICB0b29sYmFyIGJ1dHRvbiBhcyBhIGZsb2F0aW5nIGRpYWxvZy4gRHJhZyB0aGUgPGkgY2xhc3M9XCJwaSBwaS1iYXJzXCI+PC9pPiBoYW5kbGUgdG8gZGV0YWNoIHRoaXMgdG9vbGJhciBpbnRvIGFcbiAgICBmbG9hdGluZyB3aW5kb3cuXG4gIDwvcD5cblxuICA8aDM+UGxvdC10eXBlIGRyb3Bkb3duPC9oMz5cbiAgPHA+XG4gICAgVGhlIDxiPnBsb3QtdHlwZSBkcm9wZG93bjwvYj4gc3dpdGNoZXMgaG93IHRoZSBmaWxlIGlzIHZpc3VhbGl6ZWQ6IDxiPkltYWdlPC9iPiwgPGI+SGVhdG1hcDwvYj4sXG4gICAgPGI+Q29udG91cjwvYj4sIDxiPlN1cmZhY2U8L2I+LCA8Yj5Wb2x1bWU8L2I+LCA8Yj5Jc29zdXJmYWNlPC9iPiwgYW5kIOKAlCB3aGVuIGEgc3BhdGlhbC1vbWljcyBkYXRhc2V0IGlzIG9wZW4g4oCUXG4gICAgPGI+U3BhdGlhbCBvbWljczwvYj4gYW5kIDxiPlNwYXRpYWwgb21pY3MgM0Q8L2I+LlxuICA8L3A+XG4gIDxwPlxuICAgIDxiPk9ubHkgdGhlIG1vZGVzIHRoZSBkYXRhIGNhbiBhY3R1YWxseSBzdXBwb3J0IGFyZSBvZmZlcmVkPC9iPiwgc28gdGhlIGxpc3QgY2hhbmdlcyB3aXRoIHdoYXQgaXMgbG9hZGVkIHJhdGhlclxuICAgIHRoYW4gc2hvd2luZyBlbnRyaWVzIHRoYXQgd291bGQgY29tZSB1cCBibGFuazpcbiAgPC9wPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgPGI+Q29udG91cjwvYj4sIDxiPlZvbHVtZTwvYj4gYW5kIDxiPklzb3N1cmZhY2U8L2I+IG5lZWQgYSBncmF5c2NhbGUgaW1hZ2U7IHRoZSB0d28gM0Qgb25lcyBhbHNvIG5lZWQgYVxuICAgICAgei1zdGFjay5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIDxiPlNwYXRpYWwgb21pY3M8L2I+IG5lZWRzIGEgcHVibGlzaGVkIGRhdGFzZXQsIGFuZCA8Yj5TcGF0aWFsIG9taWNzIDNEPC9iPiBuZWVkcyBvbmUgd2hvc2UgY29vcmRpbmF0ZXMgY2FycnlcbiAgICAgIGEgei5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFRoZSBwaXhlbCBtb2RlcyAoPGI+SW1hZ2U8L2I+LCA8Yj5IZWF0bWFwPC9iPiwgPGI+U3VyZmFjZTwvYj4pIGFyZSB3aXRoaGVsZCBmb3IgYSBkYXRhc2V0IHRoYXQgYnJpbmdzIG5vXG4gICAgICB0aXNzdWUgaW1hZ2Ug4oCUIHNlcUZJU0ggcmVjb3JkcyBjb29yZGluYXRlcyBhbmQgbm8gc2VjdGlvbiwgc28gdGhlcmUgaXMgbm90aGluZyBmb3IgdGhlbSB0byBkcmF3LlxuICAgIDwvbGk+XG4gIDwvdWw+XG4gIDx1bD5cbiAgICA8bGk+XG4gICAgICBcIjxiPklzb3N1cmZhY2UgYmFuZDwvYj5cIiBzbGlkZXIgKElzb3N1cmZhY2UpOiBzZXRzIHRoZSBpbnRlbnNpdHkgYmFuZCB0aGUgc3VyZmFjZXMgYXJlIGRyYXduIGZvciwgbWFwcGVkIG9udG9cbiAgICAgIHRoZSB2b2x1bWUncyByZWFsIGludGVuc2l0eSByYW5nZS5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+M0QgY2FtZXJhPC9iPlwiIChTdXJmYWNlIC8gU2NhdHRlciAzRCAvIElzb3N1cmZhY2UpOiB6b29tIDxpIGNsYXNzPVwicGkgcGktc2VhcmNoXCI+PC9pPiwgcGFuXG4gICAgICA8aSBjbGFzcz1cInBpIHBpLWFycm93cy1hbHRcIj48L2k+LCBvcmJpdCA8aSBjbGFzcz1cInBpIHBpLWdsb2JlXCI+PC9pPiwgdHVybnRhYmxlIDxpIGNsYXNzPVwicGkgcGktc3luY1wiPjwvaT4sXG4gICAgICBhbmQgcmVzZXQgY2FtZXJhIDxpIGNsYXNzPVwicGkgcGktaG9tZVwiPjwvaT47IHNjcm9sbCB0byB6b29tIHRoZSAzRCBzY2VuZS5cbiAgICA8L2xpPlxuICA8L3VsPlxuXG4gIDxoMz5JbWFnZSBtYW5pcHVsYXRpb24gdG9vbHM8L2gzPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5SZWdpb24gRWRpdG9yPC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3JlZ2lvbi1lZGl0b3Iuc3ZnXCIgd2lkdGg9XCIxNVwiIGhlaWdodD1cIjE1XCIgLz46IG9wZW5zIHRoZVxuICAgICAgUmVnaW9uIEVkaXRvciBhcyBhIGZsb2F0aW5nLCBkcmFnZ2FibGUgZGlhbG9nIOKAlCBhIHBlci1pbWFnZSB0YWJsZSBvZiBldmVyeSByZWdpb24gKGNsYXNzLCBjb2xvdXIsIGFyZWEpIHdpdGhcbiAgICAgIGJ1bGsgc2VsZWN0L2xhYmVsL2NvbG91ci9kZWxldGUgYW5kIEdlb0pTT04gaW1wb3J0L2V4cG9ydC4gSXQgc3RheXMgaW4gc3luYyB3aXRoIHRoZSBpbWFnZSwgc28geW91IGNhbiBrZWVwXG4gICAgICBpdCBvcGVuIHdoaWxlIGRyYXdpbmcuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkludGVuc2l0eSBwcm9maWxlIGxpbmVzPC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3NwbGluZS1jaGFydC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPiAoPGlcbiAgICAgICAgPndvcmsgaW4gcHJvZ3Jlc3Mg4oCUIG5vdCB5ZXQgc3RhYmxlPC9pXG4gICAgICA+KTogYWRkcyBhIGNvbG91cmVkIGxpbmUgUk9JOyBhIGZsb2F0aW5nIGluc2V0IGNoYXJ0IHBsb3RzIGludGVuc2l0eSBhbG9uZyBlYWNoIGxpbmUsIHVwZGF0ZXMgbGl2ZSBhcyB5b3VcbiAgICAgIGRyYWcgaXQsIGFuZCByZS1zYW1wbGVzIGF0IHRoZSBjdXJyZW50IHpvb20gcmVzb2x1dGlvbi4gRWFjaCBhZGRlZCBsaW5lIGdldHMgaXRzIG93biBjb2xvdXI7IHNlbGVjdCBhIGxpbmVcbiAgICAgIGFuZCB1c2UgdGhlIHRyYXNoIHRvb2wgPGkgY2xhc3M9XCJwaSBwaS10cmFzaFwiPjwvaT4gdG8gcmVtb3ZlIGl0IChhbmQgaXRzIHRyYWNlKS5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+Q2hhbm5lbHMgJmFtcDsgSGlzdG9ncmFtPC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL2ludmVydC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPjogb3BlbnMgYVxuICAgICAgZmxvYXRpbmcgZGlhbG9nIGZvciBicmlnaHRuZXNzL2NvbnRyYXN0LCBnYW1tYSwgYW5kIHBlci1jaGFubmVsIGRpc3BsYXksIHBsdXMgdGhlXG4gICAgICA8Yj5jb2xvcm1hcCAvIExVVDwvYj4gY29udHJvbHMgKGdyYXlzY2FsZSBvbmx5KSDigJQgYSA8Yj5yZXZlcnNlPC9iPiB0b2dnbGUgYW5kIGEgY29sb3JtYXAgZHJvcGRvd24gKGRlZmF1bHQ6XG4gICAgICBpbnZlcnRlZCBncmV5cykuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPlNtb290aGVuPC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3Ntb290aC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPiAoSW1hZ2UgdmlldyBvbmx5KTogdGhlXG4gICAgICBpbWFnZSBvcGVucyBzaG93aW5nIDxiPnJhdyBwaXhlbHM8L2I+IChuZWFyZXN0LW5laWdoYm91ciksIHNvIHpvb21pbmcgaW4gcmVuZGVycyBjcmlzcCBibG9ja3MgZm9yIHBpeGVsXG4gICAgICBpbnNwZWN0aW9uLiBUb2dnbGUgdGhpcyBvbiBmb3IgYmlsaW5lYXIgc21vb3RoaW5nOyB0aGUgaWNvbiB0dXJucyB3aGl0ZSB3aGlsZSBzbW9vdGhpbmcgaXMgYWN0aXZlLlxuICAgIDwvbGk+XG4gIDwvdWw+XG5cbiAgPGgzPkRvd25sb2FkICZhbXA7IHZpZXcgdG9vbHM8L2gzPlxuICA8dWw+XG4gICAgPGxpPlwiPGI+RG93bmxvYWQ8L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1kb3dubG9hZFwiPjwvaT46IGRvd25sb2FkIHRoZSBjdXJyZW50IGltYWdlIGFzIGEgUE5HLjwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5GaXQgdG8gdmlldzwvYj5cIiAvIGF1dG9zY2FsZSA8aSBjbGFzcz1cInBpIHBpLXdpbmRvdy1tYXhpbWl6ZVwiPjwvaT46IHJlc2V0cyB0aGUgaW1hZ2UgdG8gaXRzIG9yaWdpbmFsXG4gICAgICBkaW1lbnNpb25zLiBJbiBzdGFjayBtb2RlIGl0IGFsc28gcmVzZXRzIHRvIHNpbmdsZS1pbWFnZSBtb2RlLlxuICAgIDwvbGk+XG4gIDwvdWw+XG5cbiAgPGgzPlpvb20gdG9vbHM8L2gzPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5ab29tIGJveDwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy96b29tLWJveC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPiAoPGtiZD5iPC9rYmQ+KTogZHJhZyBhXG4gICAgICBib3ggdG8gc2VsZWN0IGFuIGFyZWEgdG8gem9vbSBpbnRvLlxuICAgIDwvbGk+XG4gICAgPGxpPlwiPGI+UGFuPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktYXJyb3dzLWFsdFwiPjwvaT4gKDxrYmQ+cDwva2JkPik6IGRyYWcgdG8gcGFuIHRoZSBpbWFnZS48L2xpPlxuICAgIDxsaT5cIjxiPlpvb20gaW48L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1zZWFyY2gtcGx1c1wiPjwvaT4gKDxrYmQ+Kzwva2JkPik6IHpvb20gaW4gb25lIHN0ZXAuPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPlpvb20gb3V0PC9iPlwiIDxpIGNsYXNzPVwicGkgcGktc2VhcmNoLW1pbnVzXCI+PC9pPiAoPGtiZD4tPC9rYmQ+KTogem9vbSBvdXQgb25lIHN0ZXAsIHN0b3BwaW5nIGF0IHRoZVxuICAgICAgb3JpZ2luYWwgaW1hZ2UgZGltZW5zaW9ucy5cbiAgICA8L2xpPlxuICA8L3VsPlxuXG4gIDxoMz5SZWdpb24gdG9vbHM8L2gzPlxuICA8cD5cbiAgICBCeSBkZWZhdWx0IG5vIHRvb2wgaXMgc2VsZWN0ZWQgKGFsbCBncmV5ZWQtb3V0KTsgc2VsZWN0aW5nIGEgdG9vbCBoaWdobGlnaHRzIGl0LiBUaGUgdmVydGV4LWVkaXRpbmcgdG9vbHNcbiAgICAocG9seWdvbiwgYWRkL2RlbGV0ZSB2ZXJ0ZXgsIG1vdmUsIELDqXppZXIgY29udmVyc2lvbnMpIGFyZSBhdmFpbGFibGUgaW4gdGhlIDxiPkltYWdlPC9iPiB2aWV3IG9ubHkuIE9uIGFcbiAgICA8Yj5kb251dDwvYj4gKGEgcmVnaW9uIHdpdGggYSBob2xlKSwgdGhlIGlubmVyLXJpbmcgdmVydGljZXMgYXJlIGVkaXRhYmxlIHRvbyDigJQgZHJhZywgYWRkLCBhbmQgZGVsZXRlIHRoZW0ganVzdFxuICAgIGxpa2UgdGhlIG91dGVyIHJpbmcuXG4gIDwvcD5cbiAgPHVsPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+U2VsZWN0aW9uPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktYXJyb3ctdXAtcmlnaHRcIj48L2k+ICg8a2JkPnM8L2tiZD4pOiBhIG5ldXRyYWwgbW9kZSB0aGF0IHR1cm5zIG9mZlxuICAgICAgd2hhdGV2ZXIgZHJhd2luZyB0b29sIHdhcyBhY3RpdmUgKHdhbmQsIHZlcnRleCBlcmFzZXIsIHJlY3RhbmdsZSwgZXRjLikuIFVzZSBpdCB0byBzdGVwIG91dCBvZiBlZGl0aW5nXG4gICAgICB3aXRob3V0IHBpY2tpbmcgYW5vdGhlciB0b29sLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5SZWN0YW5ndWxhciByZWdpb248L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1zdG9wXCI+PC9pPiAoPGtiZD5yPC9rYmQ+KTogY2xpY2sgYW5kIGRyYWcgdG8gY3JlYXRlIGEgcmVjdGFuZ3VsYXJcbiAgICAgIHJlZ2lvbi5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+UG9seWxpbmU8L2I+XCIgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvcG9seWxpbmUuc3ZnXCIgd2lkdGg9XCIxNFwiIGhlaWdodD1cIjE0XCIgLz4gKDxrYmQ+bDwva2JkPik6IGRyYXcgYW5cbiAgICAgIG9wZW4gKG5vbi1jbG9zZWQpIHBvbHlsaW5lIGJ5IGNsaWNraW5nIGFuZCBkcmFnZ2luZy4gUG9seWxpbmVzIGNhbiBiZSBlZGl0ZWQgYW5kIGV4cG9ydGVkIHRvIEdlb0pTT04gYXMgYVxuICAgICAgPGNvZGU+TGluZVN0cmluZzwvY29kZT4gZmVhdHVyZS5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+RnJlZWZvcm0gcmVnaW9uPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktcGVuY2lsXCI+PC9pPiAoPGtiZD5mPC9rYmQ+KTogY2xpY2sgYW5kIGRyYWcgdG8gZHJhdyBhIGNsb3NlZFxuICAgICAgZnJlZWZvcm0gcG9seWdvbi5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+QnJ1c2g8L2I+XCIgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvcGFpbnRicnVzaC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPjogY2xpY2sgYW5kIGRyYWcgdG8gcGFpbnQgYVxuICAgICAgcmVnaW9uIHdpdGggYSBjaXJjdWxhciBicnVzaCDigJQgdGhlIHBhaW50ZWQgc3Ryb2tlIGlzIHRoZSByZWdpb24uIEEgPGI+U2l6ZTwvYj4gc2xpZGVyIChicnVzaCBkaWFtZXRlciwgaW5cbiAgICAgIGltYWdlIHBpeGVscykgYXBwZWFycyBpbiB0aGUgdG9vbGJhciB3aGlsZSB0aGUgYnJ1c2ggaXMgYWN0aXZlLiBIb2xkIDxrYmQ+U2hpZnQ8L2tiZD4gd2hpbGUgcGFpbnRpbmcgdG9cbiAgICAgIDxiPmVyYXNlPC9iPiAoc3VidHJhY3QpIGZyb20gYSByZWdpb24gaW5zdGVhZC4gUGFpbnRpbmcgb3ZlciBhbiBleGlzdGluZyByZWdpb24gZXh0ZW5kcyBpdDsgYnJ1c2hpbmcgYWNyb3NzXG4gICAgICB0d28gcmVnaW9ucyBtZXJnZXMgdGhlbS4gUGFpbnRpbmcgYSBjbG9zZWQgcmluZyAob3Igc2hpZnQtZXJhc2luZyBhbiBpbnRlcmlvciBwb2NrZXQpIGxlYXZlcyB0aGUgZW5jbG9zZWRcbiAgICAgIGFyZWEgZW1wdHkg4oCUIGEgPGI+ZG9udXQ8L2I+IChJbWFnZSB2aWV3KS5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+UG9seWdvbjwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy9wb2x5Z29uLXZlcnRpY2VzLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+OiBjbGljayB0byBwbGFjZVxuICAgICAgZWFjaCB2ZXJ0ZXg7IGNsaWNrIHRoZSBmaXJzdCBwb2ludCB0byBjbG9zZSB0aGUgcG9seWdvbi5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+QWRkIHZlcnRleDwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy92ZXJ0ZXgtYWRkLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+OiBjbGljayBhbiBlZGdlIG9mIHRoZVxuICAgICAgc2VsZWN0ZWQgcG9seWdvbiB0byBpbnNlcnQgYSBuZXcgdmVydGV4LlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5EZWxldGUgdmVydGV4PC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3ZlcnRleC1kZWxldGUuc3ZnXCIgd2lkdGg9XCIxNVwiIGhlaWdodD1cIjE1XCIgLz46IGNsaWNrIGEgdmVydGV4XG4gICAgICBvZiB0aGUgc2VsZWN0ZWQgcG9seWdvbiB0byByZW1vdmUgaXQuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICA8Yj5Nb3ZpbmcgYSByZWdpb248L2I+IDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3JlZ2lvbi1tb3ZlLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+OiB3aXRoIHRoZSBTZWxlY3RcbiAgICAgIHRvb2wsIGRyYWcgdGhlIHNlbGVjdGVkIHJlZ2lvbidzIGJvZHkgKG9yIGEgcmVjdGFuZ2xlJ3MgaGFuZGxlcyB0byByZXNpemUgaXQpLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgPGI+Q29udmVydCB0byBCw6l6aWVyPC9iPiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy90by1iZXppZXIuc3ZnXCIgd2lkdGg9XCIxNVwiIGhlaWdodD1cIjE1XCIgLz4gL1xuICAgICAgPGI+Q29udmVydCB0byBwb2x5Z29uPC9iPiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy90by1wb2x5Z29uLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+IChJbWFnZSB2aWV3KTpcbiAgICAgIHJpZ2h0LWNsaWNrIHRoZSBzZWxlY3RlZCByZWdpb24gYW5kIHBpY2sgdGhlIGNvbnZlcnNpb24gaW4gdGhlIGNvbnRleHQgbWVudSB0byB0dXJuIGl0IGludG8gYSBzbW9vdGggQsOpemllclxuICAgICAgY3VydmUsIG9yIGJhY2sgaW50byBhIHN0cmFpZ2h0LWVkZ2VkIHBvbHlnb24uXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPldhbmQ8L2I+XCIgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvd2FuZC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPiAoPGtiZD53PC9rYmQ+KTogY2xpY2sgdG8gZ3JvdyBhXG4gICAgICByZWdpb24gZnJvbSBwaXhlbHMgd2l0aCBzaW1pbGFyIHZhbHVlcyBhcm91bmQgdGhlIGNsaWNrIHBvaW50LiBIb2xkIDxrYmQ+Q3RybDwva2JkPi88a2JkPkNtZDwva2JkPiBmb3IgYW5cbiAgICAgIGV4YWN0LW1hdGNoIGZsb29kIGZpbGw7IGRyYWcgdG8ga2VlcCBleHRlbmRpbmcgdGhlIHNlbGVjdGlvbiB3aGlsZSBtb3Zpbmc7IGhvbGQgPGtiZD5TaGlmdDwva2JkPiB3aGlsZVxuICAgICAgY2xpY2tpbmcgb3IgZHJhZ2dpbmcgb24gYW4gZXhpc3RpbmcgcmVnaW9uIHRvIDxiPmVyYXNlPC9iPiBwaXhlbHMgZnJvbSBpdC4gVXNlIHRoZSA8Yj5TZW5zLjwvYj4gc2xpZGVyIHRoYXRcbiAgICAgIGFwcGVhcnMgdG8gbWFrZSB0aGUgd2FuZCBzdHJpY3RlciAoaGlnaGVyID0gc21hbGxlciBzZWxlY3Rpb24pIG9yIGxvb3Nlci4gU3Vic2VxdWVudCBjbGlja3Mga2VlcCBleHRlbmRpbmdcbiAgICAgIHRoZSBzYW1lIHJlZ2lvbjsgY2xpY2tpbmcgaW5zaWRlIGFuIGV4aXN0aW5nIHJlZ2lvbiBhZG9wdHMgaXQsIGFuZCBncm93aW5nIGludG8gYW5vdGhlciByZWdpb24gbWVyZ2VzIHRoZW0uXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPlZlcnRleCBlcmFzZXI8L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1lcmFzZXJcIj48L2k+ICg8a2JkPmU8L2tiZD4pOiBjbGljayBvciBjbGljay1hbmQtZHJhZyB0byByZW1vdmUgcG9seWdvblxuICAgICAgdmVydGljZXMgdGhhdCBmYWxsIGluc2lkZSB0aGUgY3Vyc29yIGNpcmNsZSBmcm9tIGFueSByZWdpb24sIGluY2x1ZGluZyBhIHJlZ2lvbidzIGlubmVyIHJpbmdzIChkb251dCBob2xlcykuXG4gICAgICBVc2UgdGhlIDxiPlJhZGl1czwvYj4gc2xpZGVyIHRvIHNldCB0aGUgZXJhc2VyIHNpemUgaW4gaW1hZ2UgcGl4ZWxzLiBQb2x5Z29ucyByZWR1Y2VkIGJlbG93IDMgdmVydGljZXMgKG9yXG4gICAgICBwb2x5bGluZXMgYmVsb3cgMikgYXJlIGRlbGV0ZWQgZW50aXJlbHk7IGEgaG9sZSByZWR1Y2VkIGJlbG93IDMgdmVydGljZXMgaXMgcmVtb3ZlZC5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+VW5kbzwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy91bmRvLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+XG4gICAgICAoPGtiZD5DdHJsPC9rYmQ+LzxrYmQ+Q21kPC9rYmQ+KzxrYmQ+Wjwva2JkPik6IHJldmVydHMgdGhlIGxhc3QgcmVnaW9uIGFjdGlvbiAoZHJhdywgZGVsZXRlLCBlZGl0LCB3YW5kL2JydXNoXG4gICAgICBzdHJva2UsIHNlZ21lbnRhdGlvbiwg4oCmKS4gVXAgdG8gdGhlIGxhc3RcbiAgICAgIDxiPjEwPC9iPiBhY3Rpb25zIGNhbiBiZSB1bmRvbmU7IHRoZSBidXR0b24gZ3JleXMgb3V0IHdoZW4gdGhlcmUncyBub3RoaW5nIGxlZnQgdG8gdW5kby5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+UmVkbzwvYj5cIlxuICAgICAgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvcmVkby5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPlxuICAgICAgKDxrYmQ+Q3RybDwva2JkPi88a2JkPkNtZDwva2JkPis8a2JkPlNoaWZ0PC9rYmQ+KzxrYmQ+Wjwva2JkPiBvclxuICAgICAgPGtiZD5DdHJsPC9rYmQ+LzxrYmQ+Q21kPC9rYmQ+KzxrYmQ+WTwva2JkPik6IHJlLWFwcGxpZXMgdGhlIG1vc3QgcmVjZW50bHkgdW5kb25lIGFjdGlvbi4gUGVyZm9ybWluZyBhIG5ld1xuICAgICAgcmVnaW9uIGFjdGlvbiBjbGVhcnMgd2hhdCBjYW4gYmUgcmVkb25lLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5EZWxldGUgcmVnaW9uPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktdHJhc2hcIj48L2k+ICg8a2JkPkRlbDwva2JkPik6IGRlbGV0ZXMgdGhlIHNlbGVjdGVkIHJlZ2lvbi4gVGhpcyBjYW5cbiAgICAgIGFsc28gYmUgZG9uZSBmcm9tIHRoZSBSZWdpb24gRWRpdG9yLlxuICAgIDwvbGk+XG4gIDwvdWw+XG5cbiAgPGgzPlJlZ2lvbiBhY3Rpb25zIChyaWdodC1jbGljayB0aGUgaW1hZ2UpPC9oMz5cbiAgPHA+XG4gICAgUmlnaHQtY2xpY2sgYSByZWdpb24g4oCUIG9yIHRoZSBjdXJyZW50IG11bHRpLXNlbGVjdGlvbiDigJQgdG8gb3BlbiB0aGUgXCI8Yj5TZWxlY3RlZCByZWdpb24ocyk8L2I+XCIgZ3JvdXAgYXQgdGhlXG4gICAgdG9wIG9mIHRoZSBjb250ZXh0IG1lbnUuIFRoZXNlIGFjdCBpbW1lZGlhdGVseSBvbiB0aGUgc2VsZWN0aW9uICh0aGV5J3JlIG5vdCBkcmF3aW5nIG1vZGVzKSBhbmQgYXJlIGZ1bGx5XG4gICAgdW5kby9yZWRvLWFibGU6XG4gIDwvcD5cbiAgPHVsPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+U2VsZWN0IGFsbCByZWdpb25zPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktY2hlY2stc3F1YXJlXCI+PC9pPjogc2VsZWN0IGV2ZXJ5IHJlZ2lvbiBvbiB0aGUgaW1hZ2UgKGFsc28gaW4gdGhlXG4gICAgICBSZWdpb24gRWRpdG9yIHRvb2xiYXIpLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5NZXJnZSAvIGdyb3VwPC9iPlwiOiBjb21iaW5lIDIrIHNlbGVjdGVkIHJlZ2lvbnMgaW50byBvbmUuIElmIHRoZSBwaWVjZXMgZG9uJ3QgdG91Y2gsIHRoZSByZXN1bHQgaXMgYVxuICAgICAgc2luZ2xlIG11bHRpLXBhcnQgcmVnaW9uIChzcGFyc2UgXCJiaXRzXCIpLlxuICAgIDwvbGk+XG4gICAgPGxpPlwiPGI+VW5ncm91cDwvYj5cIjogc3BsaXQgYSBtdWx0aS1wYXJ0IHJlZ2lvbiBiYWNrIGludG8gb25lIHJlZ2lvbiBwZXIgcGllY2UuPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkludmVyc2U8L2I+XCI6IHJlcGxhY2UgdGhlIHNlbGVjdGlvbiB3aXRoIGV2ZXJ5dGhpbmcgPGk+b3V0c2lkZTwvaT4gaXQg4oCUIHRoZSBpbWFnZSByZWN0YW5nbGUgd2l0aCB0aGVcbiAgICAgIHNlbGVjdGVkIHJlZ2lvbnMgcHVuY2hlZCBvdXQgYXMgaG9sZXMuIFdvcmtzIGF0IGFueSBpbWFnZSBzaXplLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5TaW1wbGlmeTwvYj5cIjogcmVkdWNlIGEgcmVnaW9uJ3MgdmVydGV4IGNvdW50IChEb3VnbGFz4oCTUGV1Y2tlcikgYnkgYW4gYWx0aXR1ZGUgdGhyZXNob2xkIGluIHBpeGVscyDigJQgcGlja1xuICAgICAgPGI+TGlnaHQ8L2I+ICgxJm5ic3A7cHgpLCA8Yj5NZWRpdW08L2I+ICgzJm5ic3A7cHgpLCA8Yj5TdHJvbmc8L2I+ICg4Jm5ic3A7cHgpLCBvciA8Yj5DdXN0b23igKY8L2I+IGZvciBhXG4gICAgICBzbGlkZXIuIEFwcGxpZXMgdG8gdGhlIGV4dGVyaW9yIGFuZCBhbnkgaG9sZXMgKGFuZCBldmVyeSBwYXJ0IG9mIGEgbXVsdGktcGFydCByZWdpb24pLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5Db252ZXJ0IHRvIELDqXppZXI8L2I+XCIgLyBcIjxiPkNvbnZlcnQgdG8gcG9seWdvbjwvYj5cIiAoSW1hZ2UgdmlldykgYW5kIFwiPGI+RGVsZXRlPC9iPlwiIGFsc28gbGl2ZSBpbiB0aGlzXG4gICAgICBncm91cDsgdGhlIGNvbnZlcnNpb25zIGFyZSBvbmx5IGhlcmUsIG5vdCBpbiB0aGUgdG9vbGJhci5cbiAgICA8L2xpPlxuICA8L3VsPlxuXG4gIDxoMz5TZWdtZW50YXRpb24gJmFtcDsgZGV0ZWN0aW9uIHRvb2xzPC9oMz5cbiAgPHA+XG4gICAgQUktYXNzaXN0ZWQgc2VnbWVudGF0aW9uIGFuZCBkZXRlY3Rpb24gdGhhdCBydW4gZW50aXJlbHkgaW4gdGhlIGJyb3dzZXIuIFRoZSBmaXJzdCBydW4gb2YgYW55IG1vZGVsIGRvd25sb2Fkc1xuICAgIGl0IChhIHByb2dyZXNzIHRvYXN0IGlzIHNob3duKTsgaXQncyB0aGVuIGNhY2hlZC5cbiAgPC9wPlxuICA8cD5cbiAgICBUd28gc2hhcGVzIG9mIHRvb2w6IHRoZSA8Yj5wcm9tcHRlZDwvYj4gb25lcyAoU2VnbWVudCwgUG9pbnQgcHJvbXB0cywgQ2VsbHBvc2UpIGFjdCBvbiByZWN0YW5nbGVzIHlvdSBkcmF3LCBhbmRcbiAgICBnZW5lcmF0ZWQgcmVnaW9ucyBpbmhlcml0IHRoZSBjb2xvciBvZiB0aGUgcmVjdGFuZ2xlIHRoZXkgY2FtZSBmcm9tPHNwYW4gKm5nSWY9XCJjb250cmlidXRlZFRvb2xzLmxlbmd0aFwiXG4gICAgICA+OyB0aGUgPGI+bm8tcHJvbXB0PC9iPiBvbmVzICh7eyBjb250cmlidXRlZFRvb2xOYW1lcyB9fSkgc3dlZXAgdGhlIHdob2xlIGN1cnJlbnQgdmlldywgc28gdGhlcmUgaXMgbm90aGluZ1xuICAgICAgdG8gZHJhdyBmaXJzdDwvc3BhblxuICAgID4uXG4gIDwvcD5cbiAgPHA+XG4gICAgRWFjaCBtb2RlbCBkcm9wZG93biA8aSBjbGFzcz1cInBpIHBpLWNoZXZyb24tZG93blwiPjwvaT4gbGlzdHMgdGhlIGF2YWlsYWJsZSBjaGVja3BvaW50cyB3aXRoIGFcbiAgICA8aSBjbGFzcz1cInBpIHBpLWluZm8tY2lyY2xlXCI+PC9pPiBiZXNpZGUgZWFjaCBvbmUg4oCUIGhvdmVyIGl0IGZvciB0aGF0IG1vZGVsJ3Mgc2l6ZSwgc3BlZWQsIHRyYWluaW5nIGRvbWFpbiBhbmRcbiAgICBhY2N1cmFjeSwgc28geW91IGNhbiBwaWNrIHdpdGhvdXQgbGVhdmluZyB0aGUgdG9vbGJhci5cbiAgPC9wPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5TZWdtZW50PC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3NhbS1ib3gtcHJvbXB0LnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+IChib3ggcHJvbXB0KTogZHJhd1xuICAgICAgb25lIG9yIG1vcmUgPGI+UmVjdGFuZ3VsYXIgcmVnaW9uczwvYj4gYXJvdW5kIHRoZSBvYmplY3RzIG9mIGludGVyZXN0LCB0aGVuIGNsaWNrIFNlZ21lbnQuIEVhY2ggcmVjdGFuZ2xlIGlzXG4gICAgICByZXBsYWNlZCBieSB0aGUgU0FNIG1hc2sgb2YgdGhlIG9iamVjdCBpbnNpZGUgaXQuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPlBvaW50IHByb21wdHM8L2I+XCIgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvc2FtLXBvaW50LXByb21wdC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPjogY2xpY2tcbiAgICAgIGRpcmVjdGx5IG9uIGFuIG9iamVjdCB0byBzZWdtZW50IGl0IGFzIGEgPGI+bmV3PC9iPiByZWdpb24uIEVhY2ggY2xpY2sgc3RhcnRzIGEgZnJlc2ggb2JqZWN0IOKAlCBjbGlja2luZ1xuICAgICAgYW5vdGhlciBvYmplY3Qgd29uJ3QgZ3JvdyB0aGUgcHJldmlvdXMgb25lLiA8a2JkPlNoaWZ0PC9rYmQ+LzxrYmQ+QWx0PC9rYmQ+LWNsaWNrIGFkZHMgYW5cbiAgICAgIDxpPmV4Y2x1ZGU8L2k+IHBvaW50IHRoYXQgcmVmaW5lcyB0aGUgY3VycmVudCBvYmplY3Q7IDxrYmQ+RXNjPC9rYmQ+IHVuZG9lcyBpdCwgPGtiZD5FbnRlcjwva2JkPiBjb21taXRzIGl0LlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5Nb2RlbCBwaWNrZXI8L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1jaGV2cm9uLWRvd25cIj48L2k+OiB0aGUgZHJvcGRvd24gYXR0YWNoZWQgdG8gdGhlIFNlZ21lbnQgYnV0dG9uIGNob29zZXNcbiAgICAgIHRoZSBTQU0gbW9kZWwg4oCUIDxiPm1pY3JvLXNhbSBWaVQtVDwvYj4gKGRlZmF1bHQ7IHNtYWxsLCBmYXN0KSBvciA8Yj5taWNyby1zYW0gVmlULUI8L2I+IChsYXJnZXIsIGhpZ2hlc3RcbiAgICAgIGFjY3VyYWN5KSBmb3IgbGlnaHQgbWljcm9zY29weSwgb3IgPGI+cGF0aG8tc2FtIFZpVC1CPC9iPiBmb3IgaGlzdG9wYXRob2xvZ3kgKEgmYW1wO0UgLyBzdGFpbmVkIHRpc3N1ZSkuIEFsbFxuICAgICAgYXJlIHByb21wdGFibGUgU2VnbWVudCBBbnl0aGluZyBtb2RlbHMgZmluZXR1bmVkIGZvciBiaW9tZWRpY2FsIGltYWdlczsgdGhleSBkaWZmZXIgaW4gdGhlXG4gICAgICA8aT5pbWFnZSBlbmNvZGVyPC9pPiAodGhlIGhlYXZ5IG9uY2UtcGVyLWltYWdlIHN0ZXApIGFuZCB0aGUgdHJhaW5pbmcgZG9tYWluIOKAlCBib3ggYW5kIHBvaW50IHByb21wdGluZyBiZWhhdmVcbiAgICAgIHRoZSBzYW1lLiBUaGUgY2hvaWNlIGFwcGxpZXMgdG8gPGk+Ym90aDwvaT4gdGhlIGJveCBhbmQgcG9pbnQgdG9vbHMsIHdoaWNoIHNoYXJlIG9uZSBsb2FkZWQgbW9kZWwgYW5kIGltYWdlXG4gICAgICBlbmNvZGluZywgc28gdGhlIGZpcnN0IHJ1biBhZnRlciBzd2l0Y2hpbmcgbW9kZWxzIChvciBpbWFnZXMpIGRvd25sb2FkcyBhbmQgZW5jb2RlcyBvbmNlIGZvciBib3RoLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5DZWxscG9zZTwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy9jZWxscy5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPjogZHJhdyByZWN0YW5nbGVzLCB0aGVuIGNsaWNrXG4gICAgICBDZWxscG9zZSB0byBhdXRvbWF0aWNhbGx5IHNlZ21lbnQgZXZlcnkgY2VsbCBpbnNpZGUgZWFjaCByZWN0YW5nbGUgKGNsaWVudC1zaWRlIGNlbGxwb3NlLVNBTSkg4oCUIG9uZSByZWdpb25cbiAgICAgIHBlciBkZXRlY3RlZCBjZWxsLiBObyBjbGlja2luZyBvbiBpbmRpdmlkdWFsIGNlbGxzIG5lZWRlZC5cbiAgICA8L2xpPlxuICAgIDwhLS0gQ29udHJpYnV0ZWQgdG9vbHMgZGVzY3JpYmUgdGhlbXNlbHZlcy4gVGhpcyBsaWJyYXJ5IHNoaXBzIG5vbmUsIHNvIGFuXG4gICAgICAgICBvcGVuIGJ1aWxkJ3MgaGVscCBsaXN0cyBvbmx5IHRoZSBwcm9tcHRlZCB0b29scyBhYm92ZSDigJQgdGhlIHRleHQgbm9cbiAgICAgICAgIGxvbmdlciBwcm9taXNlcyBidXR0b25zIHRoYXQgYXJlIG5vdCB0aGVyZS4gLS0+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgdG9vbCBvZiBjb250cmlidXRlZFRvb2xzXCI+XG4gICAgICA8bGkgKm5nSWY9XCJ0b29sLmhlbHBcIiBbaW5uZXJIVE1MXT1cInRvb2wuaGVscC5ib2R5XCI+PC9saT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCB0b29sIG9mIGRpYWxvZ1Rvb2xzXCI+XG4gICAgICA8bGkgKm5nSWY9XCJ0b29sLmhlbHBcIiBbaW5uZXJIVE1MXT1cInRvb2wuaGVscC5ib2R5XCI+PC9saT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC91bD5cblxuICA8aDM+U3BhdGlhbCBvbWljczwvaDM+XG4gIDxwPlxuICAgIEluIDxiPlNwYXRpYWwgb21pY3M8L2I+IG1vZGUgZWFjaCBvYnNlcnZhdGlvbiDigJQgYSBjZWxsIG9yIGEgVmlzaXVtIHNwb3Qg4oCUIGlzIGRyYXduIGF0IGl0cyBvd24gY29vcmRpbmF0ZXMsIG92ZXJcbiAgICB0aGUgdGlzc3VlIGltYWdlIHdoZXJlIHRoZSBkYXRhc2V0IHJlZ2lzdGVycyBvbnRvIG9uZS4gVGhlXG4gICAgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvc3BhdGlhbC1vbWljcy5zdmdcIiB3aWR0aD1cIjE0XCIgaGVpZ2h0PVwiMTRcIiBhbHQ9XCJTcGF0aWFsIG9taWNzXCIgLz5cbiAgICBwYW5lbCBjb2xvdXJzIHRoZW0gYnkgYSA8Yj5jb2x1bW48L2I+IChhIGNlbGwgdHlwZSwgYSBjbHVzdGVyKSBvciBieSBhIDxiPmdlbmU8L2I+LCBhbmQgdGhlIHR3byBhcmUgZXhjbHVzaXZlXG4gICAgc28gd2hhdCBkcml2ZXMgdGhlIGNvbG91cnMgaXMgbmV2ZXIgYW1iaWd1b3VzLlxuICA8L3A+XG4gIDx1bD5cbiAgICA8bGk+XG4gICAgICBcIjxiPlNlbGVjdCBmcm9tIFJPSXM8L2I+XCI6IHR1cm5zIHRoZSByZWdpb25zIHlvdSBoYXZlIGRyYXduIGludG8gYSBzZWxlY3Rpb24gb2Ygb2JzZXJ2YXRpb25zLiBFdmVyeXRoaW5nIGVsc2VcbiAgICAgIHRoZW4gZm9sbG93cyB0aGF0IHNlbGVjdGlvbi5cbiAgICA8L2xpPlxuICAgIDxsaT5cIjxiPlBvaW50IHNpemU8L2I+XCIgLyBcIjxiPk9wYWNpdHk8L2I+XCI6IGhvdyB0aGUgbWFya2VycyBhcmUgZHJhd24sIG5vdCB3aGF0IGlzIHNlbGVjdGVkLjwvbGk+XG4gIDwvdWw+XG5cbiAgPGgzPkRpc3RyaWJ1dGlvbiBjaGFydHM8L2gzPlxuICA8cD5cbiAgICBUaGUgPGI+RGlzdHJpYnV0aW9uPC9iPiBzZWN0aW9uIG9mIHRoZSBzcGF0aWFsLW9taWNzIHBhbmVsIGNoYXJ0cyB3aGF0ZXZlciB0aGUgbWFwIGlzIGNvbG91cmVkIGJ5LCBzbyB0aGUgdHdvXG4gICAgY2FuIG5ldmVyIGRpc2FncmVlLiBFYWNoIHRhYiBhbnN3ZXJzIGEgZGlmZmVyZW50IHF1ZXN0aW9uLCBhbmQgdGhlIDxpIGNsYXNzPVwicGkgcGktcXVlc3Rpb24tY2lyY2xlXCI+PC9pPiBiZXNpZGVcbiAgICB0aGVtIGV4cGxhaW5zIHRoZSBvbmUgb24gc2NyZWVuIOKAlCBpbmNsdWRpbmcgd2hhdCBpdCBtdXN0IDxlbT5ub3Q8L2VtPiBiZSByZWFkIGZvci5cbiAgPC9wPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5Db3VudHM8L2I+XCI6IGhvdyBtYW55IG9ic2VydmF0aW9ucyBwZXIgY2F0ZWdvcnkuIEEgY2F0ZWdvcnkgaXMgYSBsYWJlbCwgbm90IGEgbWFnbml0dWRlLCBzbyBhIGZyZXF1ZW5jeVxuICAgICAgaXMgdGhlIG9ubHkgZGlzdHJpYnV0aW9uIGl0IGhhcy5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+SGlzdG9ncmFtPC9iPlwiIC8gXCI8Yj5WaW9saW48L2I+XCIgLyBcIjxiPkJveDwvYj5cIjogaG93IGEgY29udGludW91cyB2YWx1ZSBpcyBkaXN0cmlidXRlZCDigJQgb3ZlciBldmVyeXRoaW5nLFxuICAgICAgb3Igc3BsaXQgYnkgYSBncm91cGluZyBjb2x1bW4uXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkhlYXRtYXA8L2I+XCI6IG1lYW4gZXhwcmVzc2lvbiBvZiB0aGUgZ2VuZXMgeW91IHBpY2sgd2l0aGluIGVhY2ggZ3JvdXAuIFotc2NvcmVkIHBlciBnZW5lIGJ5IGRlZmF1bHQsIHNvIGFcbiAgICAgIGNvbG91ciBtZWFucyBcImFib3ZlIG9yIGJlbG93IHRoaXMgZ2VuZSdzIG93biBhdmVyYWdlXCIgcmF0aGVyIHRoYW4gXCJoaWdobHkgZXhwcmVzc2VkXCIuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkVtYmVkZGluZzwvYj5cIjogYSBVTUFQLCBQQ0Egb3IgdC1TTkUgb3ZlciB0aGUgc2FtZSBjZWxscy4gPGI+TGFzc28gaXQgdG8gc2VsZWN0IG9uIHRoZSBtYXA8L2I+IOKAlCBib3RoXG4gICAgICB2aWV3cyByZWFkIHRoZSBzYW1lIHNlbGVjdGlvbi4gT25seSBQQ0EgbGFiZWxzIGl0cyBheGVzIHdpdGggYSBwZXJjZW50YWdlLCBiZWNhdXNlIG9ubHkgaXRzIGF4ZXMgZXhwbGFpbiBhXG4gICAgICBtZWFzdXJhYmxlIHNoYXJlIG9mIHRoZSB2YXJpYW5jZTsgVU1BUCBhbmQgdC1TTkUgY29vcmRpbmF0ZXMgYXJlIGFyYml0cmFyeSwgc28gZGlzdGFuY2UgYmV0d2VlbiBkaXN0YW50XG4gICAgICBjbHVzdGVycyBzaG91bGQgbm90IGJlIHJlYWQuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkRldGFjaDwvYj5cIjogbW92ZXMgdGhlIGNoYXJ0cyBpbnRvIHRoZWlyIG93biB3aW5kb3cgc28gdGhleSBjYW4gc2l0IGJlc2lkZSB0aGUgbWFwIGluc3RlYWQgb2YgaW5zaWRlIHRoZVxuICAgICAgcGFuZWwuIFN3aXRjaGluZyB0YWJzIGtlZXBzIHRoZSB3aW5kb3cgd2hlcmUgaXQgaXMuXG4gICAgPC9saT5cbiAgPC91bD5cblxuICA8aDM+SGVscDwvaDM+XG4gIDxwPlwiPGI+SGVscDwvYj5cIiA8aSBjbGFzcz1cInBpIHBpLXF1ZXN0aW9uLWNpcmNsZVwiPjwvaT46IG9wZW5zIHRoaXMgZGlhbG9nLjwvcD5cblxuICA8aDM+S2V5Ym9hcmQgc2hvcnRjdXRzPC9oMz5cbiAgPHRhYmxlIGNsYXNzPVwic2hvcnRjdXRzLXRhYmxlXCI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+Kzwva2JkPiAvIDxrYmQ+PTwva2JkPjwvdGQ+XG4gICAgICA8dGQ+Wm9vbSBpbjwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD4tPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5ab29tIG91dDwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD5iPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5Ub2dnbGUgem9vbSBib3ggbW9kZTwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD5wPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5Ub2dnbGUgcGFuIG1vZGU8L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+Zjwva2JkPjwvdGQ+XG4gICAgICA8dGQ+VG9nZ2xlIGZyZWVmb3JtIHJlZ2lvbiBkcmF3aW5nPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPmw8L2tiZD48L3RkPlxuICAgICAgPHRkPlRvZ2dsZSBwb2x5bGluZSBkcmF3aW5nPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPnI8L2tiZD48L3RkPlxuICAgICAgPHRkPlRvZ2dsZSByZWN0YW5ndWxhciByZWdpb24gZHJhd2luZzwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD53PC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5Ub2dnbGUgd2FuZCB0b29sPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD5XYW5kICsgPGtiZD5TaGlmdDwva2JkPjwvdGQ+XG4gICAgICA8dGQ+RXJhc2UgcGl4ZWxzIGZyb20gdGhlIGFjdGl2ZSByZWdpb248L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPldhbmQgKyA8a2JkPkN0cmw8L2tiZD4vPGtiZD5DbWQ8L2tiZD48L3RkPlxuICAgICAgPHRkPkV4YWN0LW1hdGNoIGZsb29kIGZpbGwgKG5vIHNtb290aGluZyk8L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+ZTwva2JkPjwvdGQ+XG4gICAgICA8dGQ+VG9nZ2xlIHZlcnRleCBlcmFzZXI8L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+czwva2JkPjwvdGQ+XG4gICAgICA8dGQ+U2VsZWN0aW9uIG1vZGUgKGRlYWN0aXZhdGVzIGRyYXdpbmcgdG9vbHMpPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD5Qb2ludCBwcm9tcHQgKyA8a2JkPlNoaWZ0PC9rYmQ+LzxrYmQ+QWx0PC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5BZGQgYW4gZXhjbHVkZSBwb2ludCAocmVmaW5lIHRoZSBjdXJyZW50IG9iamVjdCk8L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+RW50ZXI8L2tiZD48L3RkPlxuICAgICAgPHRkPkNvbW1pdCB0aGUgY3VycmVudCBTQU0gcG9pbnQgb2JqZWN0PC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPkVzYzwva2JkPjwvdGQ+XG4gICAgICA8dGQ+VW5kbyB0aGUgY3VycmVudCBTQU0gcG9pbnQgb2JqZWN0PC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPkRlbDwva2JkPiAvIDxrYmQ+4oyrPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5EZWxldGUgc2VsZWN0ZWQgcmVnaW9uPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPkN0cmw8L2tiZD4vPGtiZD5DbWQ8L2tiZD4rPGtiZD5aPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5VbmRvIHRoZSBsYXN0IHJlZ2lvbiBhY3Rpb24gKHVwIHRvIDEwKTwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD5DdHJsPC9rYmQ+LzxrYmQ+Q21kPC9rYmQ+KzxrYmQ+U2hpZnQ8L2tiZD4rPGtiZD5aPC9rYmQ+IC8gPGtiZD5DdHJsPC9rYmQ+KzxrYmQ+WTwva2JkPjwvdGQ+XG4gICAgICA8dGQ+UmVkbyB0aGUgbGFzdCB1bmRvbmUgcmVnaW9uIGFjdGlvbjwvdGQ+XG4gICAgPC90cj5cbiAgPC90YWJsZT5cblxuICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiZm9vdGVyXCI+XG4gICAgPHAtYnV0dG9uIGljb249XCJwaSBwaS1jaGVja1wiIChjbGljayk9XCJ2aXNpYmxlQ2hhbmdlLmVtaXQoZmFsc2UpXCIgbGFiZWw9XCJPa1wiIHN0eWxlQ2xhc3M9XCJwLWJ1dHRvbi10ZXh0XCI+XG4gICAgPC9wLWJ1dHRvbj5cbiAgPC9uZy10ZW1wbGF0ZT5cbjwvcC1kaWFsb2c+XG4iXX0=
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbGJhci1oZWxwLWRpYWxvZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3Rvb2xiYXIvdG9vbGJhci1oZWxwLWRpYWxvZy90b29sYmFyLWhlbHAtZGlhbG9nLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci90b29sYmFyLWhlbHAtZGlhbG9nL3Rvb2xiYXItaGVscC1kaWFsb2cuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDM0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7O0FBSTlDOzs7R0FHRztBQVNILE1BQU0sT0FBTywwQkFBMEI7SUFSdkM7UUFTRSwwQkFBMEI7UUFDakIsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUN6QixxRUFBcUU7UUFDM0Qsa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBVyxDQUFDO1FBRXRELG1FQUFtRTtRQUMxRCxxQkFBZ0IsR0FBOEIsRUFBRSxDQUFDO1FBQzFELGdFQUFnRTtRQUN2RCxnQkFBVyxHQUFvQyxFQUFFLENBQUM7UUFFM0Q7OytEQUV1RDtRQUM3Qyx5QkFBb0IsR0FBRyxFQUFFLENBQUM7S0FPckM7SUFMQyxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxPQUFPLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25GLENBQUM7SUFDSCxDQUFDOzhHQXBCVSwwQkFBMEI7a0dBQTFCLDBCQUEwQixtUEM1QnZDLCs5bkJBOFpBLHNWRHZZWSxZQUFZLCtQQUFFLFlBQVkscUlBQUUsWUFBWSw2WEFBRSxZQUFZOzsyRkFLckQsMEJBQTBCO2tCQVJ0QyxTQUFTOytCQUNFLHFCQUFxQixjQUNuQixJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLENBQUMsbUJBR2hELHVCQUF1QixDQUFDLE1BQU07OEJBSXRDLE9BQU87c0JBQWYsS0FBSztnQkFFSSxhQUFhO3NCQUF0QixNQUFNO2dCQUdFLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFNoYXJlZE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYXBpJztcbmltcG9ydCB7IEJ1dHRvbk1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYnV0dG9uJztcbmltcG9ydCB7IERpYWxvZ01vZHVsZSB9IGZyb20gJ3ByaW1lbmcvZGlhbG9nJztcblxuaW1wb3J0IHsgVG9vbGJhckRpYWxvZ1Rvb2xDb250cmlidXRpb24sIFRvb2xiYXJUb29sQ29udHJpYnV0aW9uIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3Rvb2xiYXItdG9vbC5jb250cmFjdCc7XG5cbi8qKlxuICogVGhlIHBsb3R0aW5nIHRvb2xiYXIncyBoZWxwIGRpYWxvZzogc3RhdGljIGRvY3VtZW50YXRpb24gb2YgZXZlcnkgdG9vbCwgcGx1c1xuICogdGhlIGhlbHAgZWFjaCBjb250cmlidXRlZCB0b29sIGJyaW5ncy5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9vbGJhci1oZWxwLWRpYWxvZycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIFNoYXJlZE1vZHVsZSwgQnV0dG9uTW9kdWxlLCBEaWFsb2dNb2R1bGVdLFxuICB0ZW1wbGF0ZVVybDogJy4vdG9vbGJhci1oZWxwLWRpYWxvZy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3Rvb2xiYXItaGVscC1kaWFsb2cuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFRvb2xiYXJIZWxwRGlhbG9nQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcbiAgLyoqIFRoZSBkaWFsb2cgaXMgb3Blbi4gKi9cbiAgQElucHV0KCkgdmlzaWJsZSA9IGZhbHNlO1xuICAvKiogVGhlIGRpYWxvZyB3YXMgY2xvc2VkIChgZmFsc2VgKTsgdHdvLXdheSB3aXRoIHtAbGluayB2aXNpYmxlfS4gKi9cbiAgQE91dHB1dCgpIHZpc2libGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgLyoqIENvbnRyaWJ1dGVkIG5vLXByb21wdCB0b29scyAodGhlaXIgaGVscCBlbnRyaWVzIGFyZSBsaXN0ZWQpLiAqL1xuICBASW5wdXQoKSBjb250cmlidXRlZFRvb2xzOiBUb29sYmFyVG9vbENvbnRyaWJ1dGlvbltdID0gW107XG4gIC8qKiBDb250cmlidXRlZCBkaWFsb2cgdG9vbHMgKHRoZWlyIGhlbHAgZW50cmllcyBhcmUgbGlzdGVkKS4gKi9cbiAgQElucHV0KCkgZGlhbG9nVG9vbHM6IFRvb2xiYXJEaWFsb2dUb29sQ29udHJpYnV0aW9uW10gPSBbXTtcblxuICAvKiogQ29udHJpYnV0ZWQgdG9vbCBuYW1lcyBmb3IgdGhlIHByb21wdGVkL25vLXByb21wdCBjb250cmFzdCwgZS5nLlxuICAgKiAgXCJZT0xPLCBSZXRpbmFsIGxheWVyc1wiLiBFbXB0eSB3aGVuIG5vdGhpbmcgaXMgcmVnaXN0ZXJlZCwgd2hpY2ggaXMgd2h5XG4gICAqICB0aGUgc2VudGVuY2UgdGhhdCB1c2VzIGl0IGlzIGl0c2VsZiBjb25kaXRpb25hbC4gKi9cbiAgcHJvdGVjdGVkIGNvbnRyaWJ1dGVkVG9vbE5hbWVzID0gJyc7XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWydjb250cmlidXRlZFRvb2xzJ10pIHtcbiAgICAgIHRoaXMuY29udHJpYnV0ZWRUb29sTmFtZXMgPSB0aGlzLmNvbnRyaWJ1dGVkVG9vbHMubWFwKCh0KSA9PiB0LmxhYmVsKS5qb2luKCcsICcpO1xuICAgIH1cbiAgfVxufVxuIiwiPHAtZGlhbG9nXG4gIGhlYWRlcj1cIlBsb3R0aW5nIGhlbHBcIlxuICBbdmlzaWJsZV09XCJ2aXNpYmxlXCJcbiAgKHZpc2libGVDaGFuZ2UpPVwidmlzaWJsZUNoYW5nZS5lbWl0KCRldmVudClcIlxuICBbbW9kYWxdPVwidHJ1ZVwiXG4gIFtzdHlsZV09XCJ7IHdpZHRoOiAnNTB2dycgfVwiXG4gIFttYXhpbWl6YWJsZV09XCJ0cnVlXCJcbiAgW2RyYWdnYWJsZV09XCJmYWxzZVwiXG4gIFtyZXNpemFibGVdPVwiZmFsc2VcIlxuPlxuICA8cD5cbiAgICBDbGljayBhIGZpbGUgaW4gdGhlIGxlZnQtaGFuZCB0cmVlIHRvIGRpc3BsYXkgaXQuIEJ5IGRlZmF1bHQgaXQgb3BlbnMgaW4gdGhlIDxiPkltYWdlPC9iPiB2aWV3IOKAlCBhIG5hdGl2ZWx5XG4gICAgdGlsZWQsIGRlZXBseSB6b29tYWJsZSByYXN0ZXIgKE9wZW5TZWFkcmFnb24pIHdpdGggYSBuYXZpZ2F0b3IgbWluaW1hcCBhbmQgYSBwaHlzaWNhbC11bml0cyBzY2FsZSBiYXIuXG4gICAgPGI+Q2xpY2sgdGhlIGltYWdlIHRvIHpvb208L2I+IHRvd2FyZCB0aGUgY2xpY2tlZCBwb2ludDsgc2Nyb2xsIHRvIHpvb20gYW5kIGRyYWcgdG8gcGFuLiBXaGVuIGEgc3RhY2sgaXMgb3BlbixcbiAgICBhIHNsaWNlIHNsaWRlciAoSW1hZ2Ugdmlldykgb3IgaW1hZ2UtbW9kZSB0b2dnbGUgKG90aGVyIHZpZXdzKSBhcHBlYXJzLiBSZWdpb25zIGNhbiBhbHNvIGJlIGVkaXRlZCBpbiB0aGVcbiAgICA8Yj5SZWdpb24gRWRpdG9yPC9iPiwgb3BlbmVkIHdpdGggdGhlXG4gICAgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvcmVnaW9uLWVkaXRvci5zdmdcIiB3aWR0aD1cIjE0XCIgaGVpZ2h0PVwiMTRcIiBhbHQ9XCJSZWdpb24gRWRpdG9yXCIgLz5cbiAgICB0b29sYmFyIGJ1dHRvbiBhcyBhIGZsb2F0aW5nIGRpYWxvZy4gRHJhZyB0aGUgPGkgY2xhc3M9XCJwaSBwaS1iYXJzXCI+PC9pPiBoYW5kbGUgdG8gZGV0YWNoIHRoaXMgdG9vbGJhciBpbnRvIGFcbiAgICBmbG9hdGluZyB3aW5kb3cuXG4gIDwvcD5cblxuICA8aDM+UGxvdC10eXBlIGRyb3Bkb3duPC9oMz5cbiAgPHA+XG4gICAgVGhlIDxiPnBsb3QtdHlwZSBkcm9wZG93bjwvYj4gc3dpdGNoZXMgaG93IHRoZSBmaWxlIGlzIHZpc3VhbGl6ZWQ6IDxiPkltYWdlPC9iPiwgPGI+SGVhdG1hcDwvYj4sXG4gICAgPGI+Q29udG91cjwvYj4sIDxiPlN1cmZhY2U8L2I+LCA8Yj5Wb2x1bWU8L2I+LCA8Yj5Jc29zdXJmYWNlPC9iPiwgYW5kIOKAlCB3aGVuIGEgc3BhdGlhbC1vbWljcyBkYXRhc2V0IGlzIG9wZW4g4oCUXG4gICAgPGI+U3BhdGlhbCBvbWljczwvYj4gYW5kIDxiPlNwYXRpYWwgb21pY3MgM0Q8L2I+LlxuICA8L3A+XG4gIDxwPlxuICAgIDxiPk9ubHkgdGhlIG1vZGVzIHRoZSBkYXRhIGNhbiBhY3R1YWxseSBzdXBwb3J0IGFyZSBvZmZlcmVkPC9iPiwgc28gdGhlIGxpc3QgY2hhbmdlcyB3aXRoIHdoYXQgaXMgbG9hZGVkIHJhdGhlclxuICAgIHRoYW4gc2hvd2luZyBlbnRyaWVzIHRoYXQgd291bGQgY29tZSB1cCBibGFuazpcbiAgPC9wPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgPGI+Q29udG91cjwvYj4sIDxiPlZvbHVtZTwvYj4gYW5kIDxiPklzb3N1cmZhY2U8L2I+IG5lZWQgYSBncmF5c2NhbGUgaW1hZ2U7IHRoZSB0d28gM0Qgb25lcyBhbHNvIG5lZWQgYVxuICAgICAgei1zdGFjay5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIDxiPlNwYXRpYWwgb21pY3M8L2I+IG5lZWRzIGEgcHVibGlzaGVkIGRhdGFzZXQsIGFuZCA8Yj5TcGF0aWFsIG9taWNzIDNEPC9iPiBuZWVkcyBvbmUgd2hvc2UgY29vcmRpbmF0ZXMgY2FycnlcbiAgICAgIGEgei5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFRoZSBwaXhlbCBtb2RlcyAoPGI+SW1hZ2U8L2I+LCA8Yj5IZWF0bWFwPC9iPiwgPGI+U3VyZmFjZTwvYj4pIGFyZSB3aXRoaGVsZCBmb3IgYSBkYXRhc2V0IHRoYXQgYnJpbmdzIG5vXG4gICAgICB0aXNzdWUgaW1hZ2Ug4oCUIHNlcUZJU0ggcmVjb3JkcyBjb29yZGluYXRlcyBhbmQgbm8gc2VjdGlvbiwgc28gdGhlcmUgaXMgbm90aGluZyBmb3IgdGhlbSB0byBkcmF3LlxuICAgIDwvbGk+XG4gIDwvdWw+XG4gIDx1bD5cbiAgICA8bGk+XG4gICAgICBcIjxiPklzb3N1cmZhY2UgYmFuZDwvYj5cIiBzbGlkZXIgKElzb3N1cmZhY2UpOiBzZXRzIHRoZSBpbnRlbnNpdHkgYmFuZCB0aGUgc3VyZmFjZXMgYXJlIGRyYXduIGZvciwgbWFwcGVkIG9udG9cbiAgICAgIHRoZSB2b2x1bWUncyByZWFsIGludGVuc2l0eSByYW5nZS5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+M0QgY2FtZXJhPC9iPlwiIChTdXJmYWNlIC8gU2NhdHRlciAzRCAvIElzb3N1cmZhY2UpOiB6b29tIDxpIGNsYXNzPVwicGkgcGktc2VhcmNoXCI+PC9pPiwgcGFuXG4gICAgICA8aSBjbGFzcz1cInBpIHBpLWFycm93cy1hbHRcIj48L2k+LCBvcmJpdCA8aSBjbGFzcz1cInBpIHBpLWdsb2JlXCI+PC9pPiwgdHVybnRhYmxlIDxpIGNsYXNzPVwicGkgcGktc3luY1wiPjwvaT4sXG4gICAgICBhbmQgcmVzZXQgY2FtZXJhIDxpIGNsYXNzPVwicGkgcGktaG9tZVwiPjwvaT47IHNjcm9sbCB0byB6b29tIHRoZSAzRCBzY2VuZS5cbiAgICA8L2xpPlxuICA8L3VsPlxuXG4gIDxoMz5JbWFnZSBtYW5pcHVsYXRpb24gdG9vbHM8L2gzPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5SZWdpb24gRWRpdG9yPC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3JlZ2lvbi1lZGl0b3Iuc3ZnXCIgd2lkdGg9XCIxNVwiIGhlaWdodD1cIjE1XCIgLz46IG9wZW5zIHRoZVxuICAgICAgUmVnaW9uIEVkaXRvciBhcyBhIGZsb2F0aW5nLCBkcmFnZ2FibGUgZGlhbG9nIOKAlCBhIHBlci1pbWFnZSB0YWJsZSBvZiBldmVyeSByZWdpb24gKGNsYXNzLCBjb2xvdXIsIGFyZWEpIHdpdGhcbiAgICAgIGJ1bGsgc2VsZWN0L2xhYmVsL2NvbG91ci9kZWxldGUgYW5kIEdlb0pTT04gaW1wb3J0L2V4cG9ydC4gSXQgc3RheXMgaW4gc3luYyB3aXRoIHRoZSBpbWFnZSwgc28geW91IGNhbiBrZWVwXG4gICAgICBpdCBvcGVuIHdoaWxlIGRyYXdpbmcuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkludGVuc2l0eSBwcm9maWxlIGxpbmVzPC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3NwbGluZS1jaGFydC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPiAoPGlcbiAgICAgICAgPndvcmsgaW4gcHJvZ3Jlc3Mg4oCUIG5vdCB5ZXQgc3RhYmxlPC9pXG4gICAgICA+KTogYWRkcyBhIGNvbG91cmVkIGxpbmUgUk9JOyBhIGZsb2F0aW5nIGluc2V0IGNoYXJ0IHBsb3RzIGludGVuc2l0eSBhbG9uZyBlYWNoIGxpbmUsIHVwZGF0ZXMgbGl2ZSBhcyB5b3VcbiAgICAgIGRyYWcgaXQsIGFuZCByZS1zYW1wbGVzIGF0IHRoZSBjdXJyZW50IHpvb20gcmVzb2x1dGlvbi4gRWFjaCBhZGRlZCBsaW5lIGdldHMgaXRzIG93biBjb2xvdXI7IHNlbGVjdCBhIGxpbmVcbiAgICAgIGFuZCB1c2UgdGhlIHRyYXNoIHRvb2wgPGkgY2xhc3M9XCJwaSBwaS10cmFzaFwiPjwvaT4gdG8gcmVtb3ZlIGl0IChhbmQgaXRzIHRyYWNlKS5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+Q2hhbm5lbHMgJmFtcDsgSGlzdG9ncmFtPC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL2ludmVydC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPjogb3BlbnMgYVxuICAgICAgZmxvYXRpbmcgZGlhbG9nIGZvciBicmlnaHRuZXNzL2NvbnRyYXN0LCBnYW1tYSwgYW5kIHBlci1jaGFubmVsIGRpc3BsYXksIHBsdXMgdGhlXG4gICAgICA8Yj5jb2xvcm1hcCAvIExVVDwvYj4gY29udHJvbHMgKGdyYXlzY2FsZSBvbmx5KSDigJQgYSA8Yj5yZXZlcnNlPC9iPiB0b2dnbGUgYW5kIGEgY29sb3JtYXAgZHJvcGRvd24gKGRlZmF1bHQ6XG4gICAgICBpbnZlcnRlZCBncmV5cykuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPlNtb290aGVuPC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3Ntb290aC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPiAoSW1hZ2UgdmlldyBvbmx5KTogdGhlXG4gICAgICBpbWFnZSBvcGVucyBzaG93aW5nIDxiPnJhdyBwaXhlbHM8L2I+IChuZWFyZXN0LW5laWdoYm91ciksIHNvIHpvb21pbmcgaW4gcmVuZGVycyBjcmlzcCBibG9ja3MgZm9yIHBpeGVsXG4gICAgICBpbnNwZWN0aW9uLiBUb2dnbGUgdGhpcyBvbiBmb3IgYmlsaW5lYXIgc21vb3RoaW5nOyB0aGUgaWNvbiB0dXJucyB3aGl0ZSB3aGlsZSBzbW9vdGhpbmcgaXMgYWN0aXZlLlxuICAgIDwvbGk+XG4gIDwvdWw+XG5cbiAgPGgzPkRvd25sb2FkICZhbXA7IHZpZXcgdG9vbHM8L2gzPlxuICA8dWw+XG4gICAgPGxpPlwiPGI+RG93bmxvYWQ8L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1kb3dubG9hZFwiPjwvaT46IGRvd25sb2FkIHRoZSBjdXJyZW50IGltYWdlIGFzIGEgUE5HLjwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5GaXQgdG8gdmlldzwvYj5cIiAvIGF1dG9zY2FsZSA8aSBjbGFzcz1cInBpIHBpLXdpbmRvdy1tYXhpbWl6ZVwiPjwvaT46IHJlc2V0cyB0aGUgaW1hZ2UgdG8gaXRzIG9yaWdpbmFsXG4gICAgICBkaW1lbnNpb25zLiBJbiBzdGFjayBtb2RlIGl0IGFsc28gcmVzZXRzIHRvIHNpbmdsZS1pbWFnZSBtb2RlLlxuICAgIDwvbGk+XG4gIDwvdWw+XG5cbiAgPGgzPlpvb20gdG9vbHM8L2gzPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5ab29tIGJveDwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy96b29tLWJveC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPiAoPGtiZD5iPC9rYmQ+KTogZHJhZyBhXG4gICAgICBib3ggdG8gc2VsZWN0IGFuIGFyZWEgdG8gem9vbSBpbnRvLlxuICAgIDwvbGk+XG4gICAgPGxpPlwiPGI+UGFuPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktYXJyb3dzLWFsdFwiPjwvaT4gKDxrYmQ+cDwva2JkPik6IGRyYWcgdG8gcGFuIHRoZSBpbWFnZS48L2xpPlxuICAgIDxsaT5cIjxiPlpvb20gaW48L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1zZWFyY2gtcGx1c1wiPjwvaT4gKDxrYmQ+Kzwva2JkPik6IHpvb20gaW4gb25lIHN0ZXAuPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPlpvb20gb3V0PC9iPlwiIDxpIGNsYXNzPVwicGkgcGktc2VhcmNoLW1pbnVzXCI+PC9pPiAoPGtiZD4tPC9rYmQ+KTogem9vbSBvdXQgb25lIHN0ZXAsIHN0b3BwaW5nIGF0IHRoZVxuICAgICAgb3JpZ2luYWwgaW1hZ2UgZGltZW5zaW9ucy5cbiAgICA8L2xpPlxuICA8L3VsPlxuXG4gIDxoMz5SZWdpb24gdG9vbHM8L2gzPlxuICA8cD5cbiAgICBCeSBkZWZhdWx0IG5vIHRvb2wgaXMgc2VsZWN0ZWQgKGFsbCBncmV5ZWQtb3V0KTsgc2VsZWN0aW5nIGEgdG9vbCBoaWdobGlnaHRzIGl0LiBUaGUgdmVydGV4LWVkaXRpbmcgdG9vbHNcbiAgICAocG9seWdvbiwgYWRkL2RlbGV0ZSB2ZXJ0ZXgsIG1vdmUsIELDqXppZXIgY29udmVyc2lvbnMpIGFyZSBhdmFpbGFibGUgaW4gdGhlIDxiPkltYWdlPC9iPiB2aWV3IG9ubHkuIE9uIGFcbiAgICA8Yj5kb251dDwvYj4gKGEgcmVnaW9uIHdpdGggYSBob2xlKSwgdGhlIGlubmVyLXJpbmcgdmVydGljZXMgYXJlIGVkaXRhYmxlIHRvbyDigJQgZHJhZywgYWRkLCBhbmQgZGVsZXRlIHRoZW0ganVzdFxuICAgIGxpa2UgdGhlIG91dGVyIHJpbmcuXG4gIDwvcD5cbiAgPHVsPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+U2VsZWN0aW9uPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktYXJyb3ctdXAtcmlnaHRcIj48L2k+ICg8a2JkPnM8L2tiZD4pOiBhIG5ldXRyYWwgbW9kZSB0aGF0IHR1cm5zIG9mZlxuICAgICAgd2hhdGV2ZXIgZHJhd2luZyB0b29sIHdhcyBhY3RpdmUgKHdhbmQsIHZlcnRleCBlcmFzZXIsIHJlY3RhbmdsZSwgZXRjLikuIFVzZSBpdCB0byBzdGVwIG91dCBvZiBlZGl0aW5nXG4gICAgICB3aXRob3V0IHBpY2tpbmcgYW5vdGhlciB0b29sLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5SZWN0YW5ndWxhciByZWdpb248L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1zdG9wXCI+PC9pPiAoPGtiZD5yPC9rYmQ+KTogY2xpY2sgYW5kIGRyYWcgdG8gY3JlYXRlIGEgcmVjdGFuZ3VsYXJcbiAgICAgIHJlZ2lvbi5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+UG9seWxpbmU8L2I+XCIgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvcG9seWxpbmUuc3ZnXCIgd2lkdGg9XCIxNFwiIGhlaWdodD1cIjE0XCIgLz4gKDxrYmQ+bDwva2JkPik6IGRyYXcgYW5cbiAgICAgIG9wZW4gKG5vbi1jbG9zZWQpIHBvbHlsaW5lIGJ5IGNsaWNraW5nIGFuZCBkcmFnZ2luZy4gUG9seWxpbmVzIGNhbiBiZSBlZGl0ZWQgYW5kIGV4cG9ydGVkIHRvIEdlb0pTT04gYXMgYVxuICAgICAgPGNvZGU+TGluZVN0cmluZzwvY29kZT4gZmVhdHVyZS5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+RnJlZWZvcm0gcmVnaW9uPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktcGVuY2lsXCI+PC9pPiAoPGtiZD5mPC9rYmQ+KTogY2xpY2sgYW5kIGRyYWcgdG8gZHJhdyBhIGNsb3NlZFxuICAgICAgZnJlZWZvcm0gcG9seWdvbi5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+QnJ1c2g8L2I+XCIgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvcGFpbnRicnVzaC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPjogY2xpY2sgYW5kIGRyYWcgdG8gcGFpbnQgYVxuICAgICAgcmVnaW9uIHdpdGggYSBjaXJjdWxhciBicnVzaCDigJQgdGhlIHBhaW50ZWQgc3Ryb2tlIGlzIHRoZSByZWdpb24uIEEgPGI+U2l6ZTwvYj4gc2xpZGVyIChicnVzaCBkaWFtZXRlciwgaW5cbiAgICAgIGltYWdlIHBpeGVscykgYXBwZWFycyBpbiB0aGUgdG9vbGJhciB3aGlsZSB0aGUgYnJ1c2ggaXMgYWN0aXZlLiBIb2xkIDxrYmQ+U2hpZnQ8L2tiZD4gd2hpbGUgcGFpbnRpbmcgdG9cbiAgICAgIDxiPmVyYXNlPC9iPiAoc3VidHJhY3QpIGZyb20gYSByZWdpb24gaW5zdGVhZC4gUGFpbnRpbmcgb3ZlciBhbiBleGlzdGluZyByZWdpb24gZXh0ZW5kcyBpdDsgYnJ1c2hpbmcgYWNyb3NzXG4gICAgICB0d28gcmVnaW9ucyBtZXJnZXMgdGhlbS4gUGFpbnRpbmcgYSBjbG9zZWQgcmluZyAob3Igc2hpZnQtZXJhc2luZyBhbiBpbnRlcmlvciBwb2NrZXQpIGxlYXZlcyB0aGUgZW5jbG9zZWRcbiAgICAgIGFyZWEgZW1wdHkg4oCUIGEgPGI+ZG9udXQ8L2I+IChJbWFnZSB2aWV3KS5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+UG9seWdvbjwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy9wb2x5Z29uLXZlcnRpY2VzLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+OiBjbGljayB0byBwbGFjZVxuICAgICAgZWFjaCB2ZXJ0ZXg7IGNsaWNrIHRoZSBmaXJzdCBwb2ludCB0byBjbG9zZSB0aGUgcG9seWdvbi5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+QWRkIHZlcnRleDwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy92ZXJ0ZXgtYWRkLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+OiBjbGljayBhbiBlZGdlIG9mIHRoZVxuICAgICAgc2VsZWN0ZWQgcG9seWdvbiB0byBpbnNlcnQgYSBuZXcgdmVydGV4LlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5EZWxldGUgdmVydGV4PC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3ZlcnRleC1kZWxldGUuc3ZnXCIgd2lkdGg9XCIxNVwiIGhlaWdodD1cIjE1XCIgLz46IGNsaWNrIGEgdmVydGV4XG4gICAgICBvZiB0aGUgc2VsZWN0ZWQgcG9seWdvbiB0byByZW1vdmUgaXQuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICA8Yj5Nb3ZpbmcgYSByZWdpb248L2I+IDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3JlZ2lvbi1tb3ZlLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+OiB3aXRoIHRoZSBTZWxlY3RcbiAgICAgIHRvb2wsIGRyYWcgdGhlIHNlbGVjdGVkIHJlZ2lvbidzIGJvZHkgKG9yIGEgcmVjdGFuZ2xlJ3MgaGFuZGxlcyB0byByZXNpemUgaXQpLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgPGI+Q29udmVydCB0byBCw6l6aWVyPC9iPiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy90by1iZXppZXIuc3ZnXCIgd2lkdGg9XCIxNVwiIGhlaWdodD1cIjE1XCIgLz4gL1xuICAgICAgPGI+Q29udmVydCB0byBwb2x5Z29uPC9iPiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy90by1wb2x5Z29uLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+IChJbWFnZSB2aWV3KTpcbiAgICAgIHJpZ2h0LWNsaWNrIHRoZSBzZWxlY3RlZCByZWdpb24gYW5kIHBpY2sgdGhlIGNvbnZlcnNpb24gaW4gdGhlIGNvbnRleHQgbWVudSB0byB0dXJuIGl0IGludG8gYSBzbW9vdGggQsOpemllclxuICAgICAgY3VydmUsIG9yIGJhY2sgaW50byBhIHN0cmFpZ2h0LWVkZ2VkIHBvbHlnb24uXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPldhbmQ8L2I+XCIgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvd2FuZC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPiAoPGtiZD53PC9rYmQ+KTogY2xpY2sgdG8gZ3JvdyBhXG4gICAgICByZWdpb24gZnJvbSBwaXhlbHMgd2l0aCBzaW1pbGFyIHZhbHVlcyBhcm91bmQgdGhlIGNsaWNrIHBvaW50LiBIb2xkIDxrYmQ+Q3RybDwva2JkPi88a2JkPkNtZDwva2JkPiBmb3IgYW5cbiAgICAgIGV4YWN0LW1hdGNoIGZsb29kIGZpbGw7IGRyYWcgdG8ga2VlcCBleHRlbmRpbmcgdGhlIHNlbGVjdGlvbiB3aGlsZSBtb3Zpbmc7IGhvbGQgPGtiZD5TaGlmdDwva2JkPiB3aGlsZVxuICAgICAgY2xpY2tpbmcgb3IgZHJhZ2dpbmcgb24gYW4gZXhpc3RpbmcgcmVnaW9uIHRvIDxiPmVyYXNlPC9iPiBwaXhlbHMgZnJvbSBpdC4gVXNlIHRoZSA8Yj5TZW5zLjwvYj4gc2xpZGVyIHRoYXRcbiAgICAgIGFwcGVhcnMgdG8gbWFrZSB0aGUgd2FuZCBzdHJpY3RlciAoaGlnaGVyID0gc21hbGxlciBzZWxlY3Rpb24pIG9yIGxvb3Nlci4gU3Vic2VxdWVudCBjbGlja3Mga2VlcCBleHRlbmRpbmdcbiAgICAgIHRoZSBzYW1lIHJlZ2lvbjsgY2xpY2tpbmcgaW5zaWRlIGFuIGV4aXN0aW5nIHJlZ2lvbiBhZG9wdHMgaXQsIGFuZCBncm93aW5nIGludG8gYW5vdGhlciByZWdpb24gbWVyZ2VzIHRoZW0uXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPlZlcnRleCBlcmFzZXI8L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1lcmFzZXJcIj48L2k+ICg8a2JkPmU8L2tiZD4pOiBjbGljayBvciBjbGljay1hbmQtZHJhZyB0byByZW1vdmUgcG9seWdvblxuICAgICAgdmVydGljZXMgdGhhdCBmYWxsIGluc2lkZSB0aGUgY3Vyc29yIGNpcmNsZSBmcm9tIGFueSByZWdpb24sIGluY2x1ZGluZyBhIHJlZ2lvbidzIGlubmVyIHJpbmdzIChkb251dCBob2xlcykuXG4gICAgICBVc2UgdGhlIDxiPlJhZGl1czwvYj4gc2xpZGVyIHRvIHNldCB0aGUgZXJhc2VyIHNpemUgaW4gaW1hZ2UgcGl4ZWxzLiBQb2x5Z29ucyByZWR1Y2VkIGJlbG93IDMgdmVydGljZXMgKG9yXG4gICAgICBwb2x5bGluZXMgYmVsb3cgMikgYXJlIGRlbGV0ZWQgZW50aXJlbHk7IGEgaG9sZSByZWR1Y2VkIGJlbG93IDMgdmVydGljZXMgaXMgcmVtb3ZlZC5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+VW5kbzwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy91bmRvLnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+XG4gICAgICAoPGtiZD5DdHJsPC9rYmQ+LzxrYmQ+Q21kPC9rYmQ+KzxrYmQ+Wjwva2JkPik6IHJldmVydHMgdGhlIGxhc3QgcmVnaW9uIGFjdGlvbiAoZHJhdywgZGVsZXRlLCBlZGl0LCB3YW5kL2JydXNoXG4gICAgICBzdHJva2UsIHNlZ21lbnRhdGlvbiwg4oCmKS4gVXAgdG8gdGhlIGxhc3RcbiAgICAgIDxiPjEwPC9iPiBhY3Rpb25zIGNhbiBiZSB1bmRvbmU7IHRoZSBidXR0b24gZ3JleXMgb3V0IHdoZW4gdGhlcmUncyBub3RoaW5nIGxlZnQgdG8gdW5kby5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+UmVkbzwvYj5cIlxuICAgICAgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvcmVkby5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPlxuICAgICAgKDxrYmQ+Q3RybDwva2JkPi88a2JkPkNtZDwva2JkPis8a2JkPlNoaWZ0PC9rYmQ+KzxrYmQ+Wjwva2JkPiBvclxuICAgICAgPGtiZD5DdHJsPC9rYmQ+LzxrYmQ+Q21kPC9rYmQ+KzxrYmQ+WTwva2JkPik6IHJlLWFwcGxpZXMgdGhlIG1vc3QgcmVjZW50bHkgdW5kb25lIGFjdGlvbi4gUGVyZm9ybWluZyBhIG5ld1xuICAgICAgcmVnaW9uIGFjdGlvbiBjbGVhcnMgd2hhdCBjYW4gYmUgcmVkb25lLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5EZWxldGUgcmVnaW9uPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktdHJhc2hcIj48L2k+ICg8a2JkPkRlbDwva2JkPik6IGRlbGV0ZXMgdGhlIHNlbGVjdGVkIHJlZ2lvbi4gVGhpcyBjYW5cbiAgICAgIGFsc28gYmUgZG9uZSBmcm9tIHRoZSBSZWdpb24gRWRpdG9yLlxuICAgIDwvbGk+XG4gIDwvdWw+XG5cbiAgPGgzPlJlZ2lvbiBhY3Rpb25zIChyaWdodC1jbGljayB0aGUgaW1hZ2UpPC9oMz5cbiAgPHA+XG4gICAgUmlnaHQtY2xpY2sgYSByZWdpb24g4oCUIG9yIHRoZSBjdXJyZW50IG11bHRpLXNlbGVjdGlvbiDigJQgdG8gb3BlbiB0aGUgXCI8Yj5TZWxlY3RlZCByZWdpb24ocyk8L2I+XCIgZ3JvdXAgYXQgdGhlXG4gICAgdG9wIG9mIHRoZSBjb250ZXh0IG1lbnUuIFRoZXNlIGFjdCBpbW1lZGlhdGVseSBvbiB0aGUgc2VsZWN0aW9uICh0aGV5J3JlIG5vdCBkcmF3aW5nIG1vZGVzKSBhbmQgYXJlIGZ1bGx5XG4gICAgdW5kby9yZWRvLWFibGU6XG4gIDwvcD5cbiAgPHVsPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+U2VsZWN0IGFsbCByZWdpb25zPC9iPlwiIDxpIGNsYXNzPVwicGkgcGktY2hlY2stc3F1YXJlXCI+PC9pPjogc2VsZWN0IGV2ZXJ5IHJlZ2lvbiBvbiB0aGUgaW1hZ2UgKGFsc28gaW4gdGhlXG4gICAgICBSZWdpb24gRWRpdG9yIHRvb2xiYXIpLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5NZXJnZSAvIGdyb3VwPC9iPlwiOiBjb21iaW5lIDIrIHNlbGVjdGVkIHJlZ2lvbnMgaW50byBvbmUuIElmIHRoZSBwaWVjZXMgZG9uJ3QgdG91Y2gsIHRoZSByZXN1bHQgaXMgYVxuICAgICAgc2luZ2xlIG11bHRpLXBhcnQgcmVnaW9uIChzcGFyc2UgXCJiaXRzXCIpLlxuICAgIDwvbGk+XG4gICAgPGxpPlwiPGI+VW5ncm91cDwvYj5cIjogc3BsaXQgYSBtdWx0aS1wYXJ0IHJlZ2lvbiBiYWNrIGludG8gb25lIHJlZ2lvbiBwZXIgcGllY2UuPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkludmVyc2U8L2I+XCI6IHJlcGxhY2UgdGhlIHNlbGVjdGlvbiB3aXRoIGV2ZXJ5dGhpbmcgPGk+b3V0c2lkZTwvaT4gaXQg4oCUIHRoZSBpbWFnZSByZWN0YW5nbGUgd2l0aCB0aGVcbiAgICAgIHNlbGVjdGVkIHJlZ2lvbnMgcHVuY2hlZCBvdXQgYXMgaG9sZXMuIFdvcmtzIGF0IGFueSBpbWFnZSBzaXplLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5TaW1wbGlmeTwvYj5cIjogcmVkdWNlIGEgcmVnaW9uJ3MgdmVydGV4IGNvdW50IChEb3VnbGFz4oCTUGV1Y2tlcikgYnkgYW4gYWx0aXR1ZGUgdGhyZXNob2xkIGluIHBpeGVscyDigJQgcGlja1xuICAgICAgPGI+TGlnaHQ8L2I+ICgxJm5ic3A7cHgpLCA8Yj5NZWRpdW08L2I+ICgzJm5ic3A7cHgpLCA8Yj5TdHJvbmc8L2I+ICg4Jm5ic3A7cHgpLCBvciA8Yj5DdXN0b23igKY8L2I+IGZvciBhXG4gICAgICBzbGlkZXIuIEFwcGxpZXMgdG8gdGhlIGV4dGVyaW9yIGFuZCBhbnkgaG9sZXMgKGFuZCBldmVyeSBwYXJ0IG9mIGEgbXVsdGktcGFydCByZWdpb24pLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5Db252ZXJ0IHRvIELDqXppZXI8L2I+XCIgLyBcIjxiPkNvbnZlcnQgdG8gcG9seWdvbjwvYj5cIiAoSW1hZ2UgdmlldykgYW5kIFwiPGI+RGVsZXRlPC9iPlwiIGFsc28gbGl2ZSBpbiB0aGlzXG4gICAgICBncm91cDsgdGhlIGNvbnZlcnNpb25zIGFyZSBvbmx5IGhlcmUsIG5vdCBpbiB0aGUgdG9vbGJhci5cbiAgICA8L2xpPlxuICA8L3VsPlxuXG4gIDxoMz5TZWdtZW50YXRpb24gJmFtcDsgZGV0ZWN0aW9uIHRvb2xzPC9oMz5cbiAgPHA+XG4gICAgQUktYXNzaXN0ZWQgc2VnbWVudGF0aW9uIGFuZCBkZXRlY3Rpb24gdGhhdCBydW4gZW50aXJlbHkgaW4gdGhlIGJyb3dzZXIuIFRoZSBmaXJzdCBydW4gb2YgYW55IG1vZGVsIGRvd25sb2Fkc1xuICAgIGl0IChhIHByb2dyZXNzIHRvYXN0IGlzIHNob3duKTsgaXQncyB0aGVuIGNhY2hlZC5cbiAgPC9wPlxuICA8cD5cbiAgICBUd28gc2hhcGVzIG9mIHRvb2w6IHRoZSA8Yj5wcm9tcHRlZDwvYj4gb25lcyAoU2VnbWVudCwgUG9pbnQgcHJvbXB0cywgQ2VsbHBvc2UpIGFjdCBvbiByZWN0YW5nbGVzIHlvdSBkcmF3LCBhbmRcbiAgICBnZW5lcmF0ZWQgcmVnaW9ucyBpbmhlcml0IHRoZSBjb2xvciBvZiB0aGUgcmVjdGFuZ2xlIHRoZXkgY2FtZSBmcm9tPHNwYW4gKm5nSWY9XCJjb250cmlidXRlZFRvb2xzLmxlbmd0aFwiXG4gICAgICA+OyB0aGUgPGI+bm8tcHJvbXB0PC9iPiBvbmVzICh7eyBjb250cmlidXRlZFRvb2xOYW1lcyB9fSkgc3dlZXAgdGhlIHdob2xlIGN1cnJlbnQgdmlldywgc28gdGhlcmUgaXMgbm90aGluZ1xuICAgICAgdG8gZHJhdyBmaXJzdDwvc3BhblxuICAgID4uXG4gIDwvcD5cbiAgPHA+XG4gICAgRWFjaCBtb2RlbCBkcm9wZG93biA8aSBjbGFzcz1cInBpIHBpLWNoZXZyb24tZG93blwiPjwvaT4gbGlzdHMgdGhlIGF2YWlsYWJsZSBjaGVja3BvaW50cyB3aXRoIGFcbiAgICA8aSBjbGFzcz1cInBpIHBpLWluZm8tY2lyY2xlXCI+PC9pPiBiZXNpZGUgZWFjaCBvbmUg4oCUIGhvdmVyIGl0IGZvciB0aGF0IG1vZGVsJ3Mgc2l6ZSwgc3BlZWQsIHRyYWluaW5nIGRvbWFpbiBhbmRcbiAgICBhY2N1cmFjeSwgc28geW91IGNhbiBwaWNrIHdpdGhvdXQgbGVhdmluZyB0aGUgdG9vbGJhci5cbiAgPC9wPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5TZWdtZW50PC9iPlwiIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3NhbS1ib3gtcHJvbXB0LnN2Z1wiIHdpZHRoPVwiMTVcIiBoZWlnaHQ9XCIxNVwiIC8+IChib3ggcHJvbXB0KTogZHJhd1xuICAgICAgb25lIG9yIG1vcmUgPGI+UmVjdGFuZ3VsYXIgcmVnaW9uczwvYj4gYXJvdW5kIHRoZSBvYmplY3RzIG9mIGludGVyZXN0LCB0aGVuIGNsaWNrIFNlZ21lbnQuIEVhY2ggcmVjdGFuZ2xlIGlzXG4gICAgICByZXBsYWNlZCBieSB0aGUgU0FNIG1hc2sgb2YgdGhlIG9iamVjdCBpbnNpZGUgaXQuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPlBvaW50IHByb21wdHM8L2I+XCIgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvc2FtLXBvaW50LXByb21wdC5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPjogY2xpY2tcbiAgICAgIGRpcmVjdGx5IG9uIGFuIG9iamVjdCB0byBzZWdtZW50IGl0IGFzIGEgPGI+bmV3PC9iPiByZWdpb24uIEVhY2ggY2xpY2sgc3RhcnRzIGEgZnJlc2ggb2JqZWN0IOKAlCBjbGlja2luZ1xuICAgICAgYW5vdGhlciBvYmplY3Qgd29uJ3QgZ3JvdyB0aGUgcHJldmlvdXMgb25lLiA8a2JkPlNoaWZ0PC9rYmQ+LzxrYmQ+QWx0PC9rYmQ+LWNsaWNrIGFkZHMgYW5cbiAgICAgIDxpPmV4Y2x1ZGU8L2k+IHBvaW50IHRoYXQgcmVmaW5lcyB0aGUgY3VycmVudCBvYmplY3Q7IDxrYmQ+RXNjPC9rYmQ+IHVuZG9lcyBpdCwgPGtiZD5FbnRlcjwva2JkPiBjb21taXRzIGl0LlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5Nb2RlbCBwaWNrZXI8L2I+XCIgPGkgY2xhc3M9XCJwaSBwaS1jaGV2cm9uLWRvd25cIj48L2k+OiB0aGUgZHJvcGRvd24gYXR0YWNoZWQgdG8gdGhlIFNlZ21lbnQgYnV0dG9uIGNob29zZXNcbiAgICAgIHRoZSBTQU0gbW9kZWwg4oCUIDxiPm1pY3JvLXNhbSBWaVQtVDwvYj4gKGRlZmF1bHQ7IHNtYWxsLCBmYXN0KSBvciA8Yj5taWNyby1zYW0gVmlULUI8L2I+IChsYXJnZXIsIGhpZ2hlc3RcbiAgICAgIGFjY3VyYWN5KSBmb3IgbGlnaHQgbWljcm9zY29weSwgb3IgPGI+cGF0aG8tc2FtIFZpVC1CPC9iPiBmb3IgaGlzdG9wYXRob2xvZ3kgKEgmYW1wO0UgLyBzdGFpbmVkIHRpc3N1ZSkuIEFsbFxuICAgICAgYXJlIHByb21wdGFibGUgU2VnbWVudCBBbnl0aGluZyBtb2RlbHMgZmluZXR1bmVkIGZvciBiaW9tZWRpY2FsIGltYWdlczsgdGhleSBkaWZmZXIgaW4gdGhlXG4gICAgICA8aT5pbWFnZSBlbmNvZGVyPC9pPiAodGhlIGhlYXZ5IG9uY2UtcGVyLWltYWdlIHN0ZXApIGFuZCB0aGUgdHJhaW5pbmcgZG9tYWluIOKAlCBib3ggYW5kIHBvaW50IHByb21wdGluZyBiZWhhdmVcbiAgICAgIHRoZSBzYW1lLiBUaGUgY2hvaWNlIGFwcGxpZXMgdG8gPGk+Ym90aDwvaT4gdGhlIGJveCBhbmQgcG9pbnQgdG9vbHMsIHdoaWNoIHNoYXJlIG9uZSBsb2FkZWQgbW9kZWwgYW5kIGltYWdlXG4gICAgICBlbmNvZGluZywgc28gdGhlIGZpcnN0IHJ1biBhZnRlciBzd2l0Y2hpbmcgbW9kZWxzIChvciBpbWFnZXMpIGRvd25sb2FkcyBhbmQgZW5jb2RlcyBvbmNlIGZvciBib3RoLlxuICAgIDwvbGk+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5DZWxscG9zZTwvYj5cIiA8aW1nIHNyYz1cImFzc2V0cy9wbG90dGluZy9jZWxscy5zdmdcIiB3aWR0aD1cIjE1XCIgaGVpZ2h0PVwiMTVcIiAvPjogZHJhdyByZWN0YW5nbGVzLCB0aGVuIGNsaWNrXG4gICAgICBDZWxscG9zZSB0byBhdXRvbWF0aWNhbGx5IHNlZ21lbnQgZXZlcnkgY2VsbCBpbnNpZGUgZWFjaCByZWN0YW5nbGUgKGNsaWVudC1zaWRlIGNlbGxwb3NlLVNBTSkg4oCUIG9uZSByZWdpb25cbiAgICAgIHBlciBkZXRlY3RlZCBjZWxsLiBObyBjbGlja2luZyBvbiBpbmRpdmlkdWFsIGNlbGxzIG5lZWRlZC5cbiAgICA8L2xpPlxuICAgIDwhLS0gQ29udHJpYnV0ZWQgdG9vbHMgZGVzY3JpYmUgdGhlbXNlbHZlcy4gVGhpcyBsaWJyYXJ5IHNoaXBzIG5vbmUsIHNvIGFuXG4gICAgICAgICBvcGVuIGJ1aWxkJ3MgaGVscCBsaXN0cyBvbmx5IHRoZSBwcm9tcHRlZCB0b29scyBhYm92ZSDigJQgdGhlIHRleHQgbm9cbiAgICAgICAgIGxvbmdlciBwcm9taXNlcyBidXR0b25zIHRoYXQgYXJlIG5vdCB0aGVyZS4gLS0+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgdG9vbCBvZiBjb250cmlidXRlZFRvb2xzXCI+XG4gICAgICA8bGkgKm5nSWY9XCJ0b29sLmhlbHBcIiBbaW5uZXJIVE1MXT1cInRvb2wuaGVscC5ib2R5XCI+PC9saT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCB0b29sIG9mIGRpYWxvZ1Rvb2xzXCI+XG4gICAgICA8bGkgKm5nSWY9XCJ0b29sLmhlbHBcIiBbaW5uZXJIVE1MXT1cInRvb2wuaGVscC5ib2R5XCI+PC9saT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC91bD5cblxuICA8aDM+U3BhdGlhbCBvbWljczwvaDM+XG4gIDxwPlxuICAgIEluIDxiPlNwYXRpYWwgb21pY3M8L2I+IG1vZGUgZWFjaCBvYnNlcnZhdGlvbiDigJQgYSBjZWxsIG9yIGEgVmlzaXVtIHNwb3Qg4oCUIGlzIGRyYXduIGF0IGl0cyBvd24gY29vcmRpbmF0ZXMsIG92ZXJcbiAgICB0aGUgdGlzc3VlIGltYWdlIHdoZXJlIHRoZSBkYXRhc2V0IHJlZ2lzdGVycyBvbnRvIG9uZS4gVGhlXG4gICAgPGltZyBzcmM9XCJhc3NldHMvcGxvdHRpbmcvc3BhdGlhbC1vbWljcy5zdmdcIiB3aWR0aD1cIjE0XCIgaGVpZ2h0PVwiMTRcIiBhbHQ9XCJTcGF0aWFsIG9taWNzXCIgLz5cbiAgICBwYW5lbCBjb2xvdXJzIHRoZW0gYnkgYSA8Yj5jb2x1bW48L2I+IChhIGNlbGwgdHlwZSwgYSBjbHVzdGVyKSBvciBieSBhIDxiPmdlbmU8L2I+LCBhbmQgdGhlIHR3byBhcmUgZXhjbHVzaXZlXG4gICAgc28gd2hhdCBkcml2ZXMgdGhlIGNvbG91cnMgaXMgbmV2ZXIgYW1iaWd1b3VzLlxuICA8L3A+XG4gIDx1bD5cbiAgICA8bGk+XG4gICAgICBcIjxiPlNlbGVjdCBmcm9tIFJPSXM8L2I+XCI6IHR1cm5zIHRoZSByZWdpb25zIHlvdSBoYXZlIGRyYXduIGludG8gYSBzZWxlY3Rpb24gb2Ygb2JzZXJ2YXRpb25zLiBFdmVyeXRoaW5nIGVsc2VcbiAgICAgIHRoZW4gZm9sbG93cyB0aGF0IHNlbGVjdGlvbi4gSW4gM0QsIHdpdGggY2xhc3NlcyBwaWNrZWQgaW4gdGhlIFJlZ2lvbiBFZGl0b3IncyBjbGFzcyB0cmVlIChvciB0aGVpciBzdXJmYWNlc1xuICAgICAgY2xpY2tlZCksIGl0IHNlbGVjdHMgdGhlIG9ic2VydmF0aW9ucyBpbnNpZGUgdGhvc2UgY2xhc3Nlcycgdm9sdW1lcy5cbiAgICA8L2xpPlxuICAgIDxsaT5cIjxiPlBvaW50IHNpemU8L2I+XCIgLyBcIjxiPk9wYWNpdHk8L2I+XCI6IGhvdyB0aGUgbWFya2VycyBhcmUgZHJhd24sIG5vdCB3aGF0IGlzIHNlbGVjdGVkLjwvbGk+XG4gIDwvdWw+XG5cbiAgPGgzPkRpc3RyaWJ1dGlvbiBjaGFydHM8L2gzPlxuICA8cD5cbiAgICBUaGUgPGI+RGlzdHJpYnV0aW9uPC9iPiBzZWN0aW9uIG9mIHRoZSBzcGF0aWFsLW9taWNzIHBhbmVsIGNoYXJ0cyB3aGF0ZXZlciB0aGUgbWFwIGlzIGNvbG91cmVkIGJ5LCBzbyB0aGUgdHdvXG4gICAgY2FuIG5ldmVyIGRpc2FncmVlLiBFYWNoIHRhYiBhbnN3ZXJzIGEgZGlmZmVyZW50IHF1ZXN0aW9uLCBhbmQgdGhlIDxpIGNsYXNzPVwicGkgcGktcXVlc3Rpb24tY2lyY2xlXCI+PC9pPiBiZXNpZGVcbiAgICB0aGVtIGV4cGxhaW5zIHRoZSBvbmUgb24gc2NyZWVuIOKAlCBpbmNsdWRpbmcgd2hhdCBpdCBtdXN0IDxlbT5ub3Q8L2VtPiBiZSByZWFkIGZvci5cbiAgPC9wPlxuICA8dWw+XG4gICAgPGxpPlxuICAgICAgXCI8Yj5Db3VudHM8L2I+XCI6IGhvdyBtYW55IG9ic2VydmF0aW9ucyBwZXIgY2F0ZWdvcnkuIEEgY2F0ZWdvcnkgaXMgYSBsYWJlbCwgbm90IGEgbWFnbml0dWRlLCBzbyBhIGZyZXF1ZW5jeVxuICAgICAgaXMgdGhlIG9ubHkgZGlzdHJpYnV0aW9uIGl0IGhhcy5cbiAgICA8L2xpPlxuICAgIDxsaT5cbiAgICAgIFwiPGI+SGlzdG9ncmFtPC9iPlwiIC8gXCI8Yj5WaW9saW48L2I+XCIgLyBcIjxiPkJveDwvYj5cIjogaG93IGEgY29udGludW91cyB2YWx1ZSBpcyBkaXN0cmlidXRlZCDigJQgb3ZlciBldmVyeXRoaW5nLFxuICAgICAgb3Igc3BsaXQgYnkgYSBncm91cGluZyBjb2x1bW4uXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkhlYXRtYXA8L2I+XCI6IG1lYW4gZXhwcmVzc2lvbiBvZiB0aGUgZ2VuZXMgeW91IHBpY2sgd2l0aGluIGVhY2ggZ3JvdXAuIFotc2NvcmVkIHBlciBnZW5lIGJ5IGRlZmF1bHQsIHNvIGFcbiAgICAgIGNvbG91ciBtZWFucyBcImFib3ZlIG9yIGJlbG93IHRoaXMgZ2VuZSdzIG93biBhdmVyYWdlXCIgcmF0aGVyIHRoYW4gXCJoaWdobHkgZXhwcmVzc2VkXCIuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkVtYmVkZGluZzwvYj5cIjogYSBVTUFQLCBQQ0Egb3IgdC1TTkUgb3ZlciB0aGUgc2FtZSBjZWxscy4gPGI+TGFzc28gaXQgdG8gc2VsZWN0IG9uIHRoZSBtYXA8L2I+IOKAlCBib3RoXG4gICAgICB2aWV3cyByZWFkIHRoZSBzYW1lIHNlbGVjdGlvbi4gT25seSBQQ0EgbGFiZWxzIGl0cyBheGVzIHdpdGggYSBwZXJjZW50YWdlLCBiZWNhdXNlIG9ubHkgaXRzIGF4ZXMgZXhwbGFpbiBhXG4gICAgICBtZWFzdXJhYmxlIHNoYXJlIG9mIHRoZSB2YXJpYW5jZTsgVU1BUCBhbmQgdC1TTkUgY29vcmRpbmF0ZXMgYXJlIGFyYml0cmFyeSwgc28gZGlzdGFuY2UgYmV0d2VlbiBkaXN0YW50XG4gICAgICBjbHVzdGVycyBzaG91bGQgbm90IGJlIHJlYWQuXG4gICAgPC9saT5cbiAgICA8bGk+XG4gICAgICBcIjxiPkRldGFjaDwvYj5cIjogbW92ZXMgdGhlIGNoYXJ0cyBpbnRvIHRoZWlyIG93biB3aW5kb3cgc28gdGhleSBjYW4gc2l0IGJlc2lkZSB0aGUgbWFwIGluc3RlYWQgb2YgaW5zaWRlIHRoZVxuICAgICAgcGFuZWwuIFN3aXRjaGluZyB0YWJzIGtlZXBzIHRoZSB3aW5kb3cgd2hlcmUgaXQgaXMuXG4gICAgPC9saT5cbiAgPC91bD5cblxuICA8aDM+SGVscDwvaDM+XG4gIDxwPlwiPGI+SGVscDwvYj5cIiA8aSBjbGFzcz1cInBpIHBpLXF1ZXN0aW9uLWNpcmNsZVwiPjwvaT46IG9wZW5zIHRoaXMgZGlhbG9nLjwvcD5cblxuICA8aDM+S2V5Ym9hcmQgc2hvcnRjdXRzPC9oMz5cbiAgPHRhYmxlIGNsYXNzPVwic2hvcnRjdXRzLXRhYmxlXCI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+Kzwva2JkPiAvIDxrYmQ+PTwva2JkPjwvdGQ+XG4gICAgICA8dGQ+Wm9vbSBpbjwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD4tPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5ab29tIG91dDwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD5iPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5Ub2dnbGUgem9vbSBib3ggbW9kZTwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD5wPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5Ub2dnbGUgcGFuIG1vZGU8L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+Zjwva2JkPjwvdGQ+XG4gICAgICA8dGQ+VG9nZ2xlIGZyZWVmb3JtIHJlZ2lvbiBkcmF3aW5nPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPmw8L2tiZD48L3RkPlxuICAgICAgPHRkPlRvZ2dsZSBwb2x5bGluZSBkcmF3aW5nPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPnI8L2tiZD48L3RkPlxuICAgICAgPHRkPlRvZ2dsZSByZWN0YW5ndWxhciByZWdpb24gZHJhd2luZzwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD53PC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5Ub2dnbGUgd2FuZCB0b29sPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD5XYW5kICsgPGtiZD5TaGlmdDwva2JkPjwvdGQ+XG4gICAgICA8dGQ+RXJhc2UgcGl4ZWxzIGZyb20gdGhlIGFjdGl2ZSByZWdpb248L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPldhbmQgKyA8a2JkPkN0cmw8L2tiZD4vPGtiZD5DbWQ8L2tiZD48L3RkPlxuICAgICAgPHRkPkV4YWN0LW1hdGNoIGZsb29kIGZpbGwgKG5vIHNtb290aGluZyk8L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+ZTwva2JkPjwvdGQ+XG4gICAgICA8dGQ+VG9nZ2xlIHZlcnRleCBlcmFzZXI8L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+czwva2JkPjwvdGQ+XG4gICAgICA8dGQ+U2VsZWN0aW9uIG1vZGUgKGRlYWN0aXZhdGVzIGRyYXdpbmcgdG9vbHMpPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD5Qb2ludCBwcm9tcHQgKyA8a2JkPlNoaWZ0PC9rYmQ+LzxrYmQ+QWx0PC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5BZGQgYW4gZXhjbHVkZSBwb2ludCAocmVmaW5lIHRoZSBjdXJyZW50IG9iamVjdCk8L3RkPlxuICAgIDwvdHI+XG4gICAgPHRyPlxuICAgICAgPHRkPjxrYmQ+RW50ZXI8L2tiZD48L3RkPlxuICAgICAgPHRkPkNvbW1pdCB0aGUgY3VycmVudCBTQU0gcG9pbnQgb2JqZWN0PC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPkVzYzwva2JkPjwvdGQ+XG4gICAgICA8dGQ+VW5kbyB0aGUgY3VycmVudCBTQU0gcG9pbnQgb2JqZWN0PC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPkRlbDwva2JkPiAvIDxrYmQ+4oyrPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5EZWxldGUgc2VsZWN0ZWQgcmVnaW9uPC90ZD5cbiAgICA8L3RyPlxuICAgIDx0cj5cbiAgICAgIDx0ZD48a2JkPkN0cmw8L2tiZD4vPGtiZD5DbWQ8L2tiZD4rPGtiZD5aPC9rYmQ+PC90ZD5cbiAgICAgIDx0ZD5VbmRvIHRoZSBsYXN0IHJlZ2lvbiBhY3Rpb24gKHVwIHRvIDEwKTwvdGQ+XG4gICAgPC90cj5cbiAgICA8dHI+XG4gICAgICA8dGQ+PGtiZD5DdHJsPC9rYmQ+LzxrYmQ+Q21kPC9rYmQ+KzxrYmQ+U2hpZnQ8L2tiZD4rPGtiZD5aPC9rYmQ+IC8gPGtiZD5DdHJsPC9rYmQ+KzxrYmQ+WTwva2JkPjwvdGQ+XG4gICAgICA8dGQ+UmVkbyB0aGUgbGFzdCB1bmRvbmUgcmVnaW9uIGFjdGlvbjwvdGQ+XG4gICAgPC90cj5cbiAgPC90YWJsZT5cblxuICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiZm9vdGVyXCI+XG4gICAgPHAtYnV0dG9uIGljb249XCJwaSBwaS1jaGVja1wiIChjbGljayk9XCJ2aXNpYmxlQ2hhbmdlLmVtaXQoZmFsc2UpXCIgbGFiZWw9XCJPa1wiIHN0eWxlQ2xhc3M9XCJwLWJ1dHRvbi10ZXh0XCI+XG4gICAgPC9wLWJ1dHRvbj5cbiAgPC9uZy10ZW1wbGF0ZT5cbjwvcC1kaWFsb2c+XG4iXX0=
|