diff --git a/common/constants.js b/common/constants.js
index 5054d2ede406c717c9c36669017e7fee0755433f..b37adb9a66e77d60f340b0a8cb2247136ea2ae4e 100644
--- a/common/constants.js
+++ b/common/constants.js
@@ -61,8 +61,8 @@
 
     // Annotations
     USER_ANNOTATION_LIST: 'user annotations footer',
-    USER_ANNOTATION_IMPORT: 'user annotations import',
-    USER_ANNOTATION_EXPORT: 'user annotations export',
+    USER_ANNOTATION_IMPORT: 'Import annotations',
+    USER_ANNOTATION_EXPORT: 'Export all of my annotations',
     USER_ANNOTATION_EXPORT_SINGLE: 'Export annotation',
     USER_ANNOTATION_HIDE: 'user annotations hide',
     USER_ANNOTATION_DELETE: 'Delete annotation',
diff --git a/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.style.css b/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.style.css
index 8d0266fe77710f71d9e50865274cd336aaf8cecc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.style.css
+++ b/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.style.css
@@ -1,6 +0,0 @@
-.header-container
-{
-  padding: 16px;
-  margin: -16px!important;
-  padding-top: 6rem;
-}
diff --git a/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.template.html b/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.template.html
index 697ef4010d189ef662977b2c2716363b6d4e53fe..4438e03e4e2b0b055211ffc49d7ab06bcc08c514 100644
--- a/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.template.html
+++ b/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.template.html
@@ -1,5 +1,5 @@
 <mat-card class="mat-elevation-z4">
-  <div class="header-container bg-50-grey-20">
+  <div class="sidenav-cover-header-container bg-50-grey-20">
     <mat-card-title>
       {{ singleDsView?.name || file.name || filename }}
     </mat-card-title>
diff --git a/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.style.css b/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.style.css
index ccdddfd5e46b96c4f33db7ef7e6370dd1bd59f02..9105967131e061d7d2959065d49a71d716ee398c 100644
--- a/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.style.css
+++ b/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.style.css
@@ -2,10 +2,3 @@
 {
   position: relative;
 }
-
-.header-container
-{
-  padding: 16px;
-  margin: -16px!important;
-  padding-top: 6rem;
-}
diff --git a/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.template.html b/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.template.html
index 455219a1825c31e207e94e6ea46a36774c6871ad..2acd816673e51556d4b66eae36f8b3078472b485 100644
--- a/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.template.html
+++ b/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.template.html
@@ -9,7 +9,7 @@
 </button>
 
 <mat-card class="mat-elevation-z4">
-  <div class="header-container bg-50-grey-20">
+  <div class="sidenav-cover-header-container bg-50-grey-20">
     <mat-card-title>
       <ng-content select="[region-of-interest]"></ng-content>
       <div *ngIf="!fetchFlag; else isLoadingTmpl">
diff --git a/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.style.css b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.style.css
index ee2db754e2ec22f48db4e1353f55895dd8aeb13a..34d152c481193d92a7b78b2fc6c0901f955556f9 100644
--- a/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.style.css
+++ b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.style.css
@@ -20,10 +20,3 @@ mat-icon
   font-size: 95%;
   line-height: normal;
 }
-
-.header-container
-{
-  padding: 16px;
-  margin: -16px!important;
-  padding-top: 6rem;
-}
diff --git a/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
index ac243dc5cf13882cadeafd73c0ddb4ce3700fc8b..8f7b7adcbf4304301b7010e8f02d33f88f1777bc 100644
--- a/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
+++ b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
@@ -2,7 +2,7 @@
   <!-- rgbDarkmode must be checked for strict equality to true/false 
   as if rgb is undefined, rgbDarkmode will be null/undefined
   which is falsy -->
-  <div class="header-container"
+  <div class="sidenav-cover-header-container"
     [ngClass]="{'darktheme': rgbDarkmode === true, 'lighttheme': rgbDarkmode === false}"
     [style.backgroundColor]="rgbString">
     <mat-card-title>
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
index fd16cedee7b3320b858d9f92cf98a63f00faa6f4..59275a07d0ace42729e7864dd4e9d8a66c668510 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
@@ -1,10 +1,17 @@
-import {Component} from "@angular/core";
-import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
+import {Component, ViewChild} from "@angular/core";
 import {ARIA_LABELS} from "common/constants";
 import { ModularUserAnnotationToolService } from "../tools/service";
-import { TExportFormats } from "../tools/type";
+import { IAnnotationGeometry, TExportFormats } from "../tools/type";
 import { ComponentStore } from "src/viewerModule/componentStore";
+import { map, startWith, tap } from "rxjs/operators";
+import { Observable } from "rxjs";
+import { TZipFileConfig } from "src/zipFilesOutput/type";
+import { TFileInputEvent } from "src/getFileInput/type";
+import { FileInputDirective } from "src/getFileInput/getFileInput.directive";
+import { MatSnackBar } from "@angular/material/snack-bar";
+import { unzip } from "src/zipFilesOutput/zipFilesOutput.directive";
 
+const README = 'EXAMPLE OF READ ME TEXT'
 
 @Component({
   selector: 'annotation-list',
@@ -18,13 +25,40 @@ export class AnnotationList {
 
   public ARIA_LABELS = ARIA_LABELS
 
+
+  @ViewChild(FileInputDirective)
+  fileInput: FileInputDirective
+
   public managedAnnotations$ = this.annotSvc.managedAnnotations$
+
+  public manAnnExists$ = this.managedAnnotations$.pipe(
+    map(arr => !!arr && arr.length > 0),
+    startWith(false)
+  )
+
+  public filesExport$: Observable<TZipFileConfig[]> = this.managedAnnotations$.pipe(
+    startWith([] as IAnnotationGeometry[]),
+    map(manAnns => {
+      const readme = {
+        filename: 'README.md',
+        filecontent: README,
+      }
+      const annotationSands = manAnns.map(ann => {
+        return {
+          filename: `${ann.id}.sands.json`,
+          filecontent: JSON.stringify(ann.toSands(), null, 2),
+        }
+      })
+      return [ readme, ...annotationSands ]
+    })
+  )
   constructor(
     private annotSvc: ModularUserAnnotationToolService,
+    private snackbar: MatSnackBar,
     cStore: ComponentStore<{ useFormat: TExportFormats }>,
   ) {
     cStore.setState({
-      useFormat: 'json'
+      useFormat: 'sands'
     })
   }
 
@@ -32,4 +66,67 @@ export class AnnotationList {
   toggleManagedAnnotationVisibility(id: string) {
     this.annotSvc.toggleAnnotationVisibilityById(id)
   }
+
+  private parseAndAddAnnotation(input: string) {
+    const json = JSON.parse(input)
+    const annotation = this.annotSvc.parseAnnotationObject(json)
+    this.annotSvc.importAnnotation(annotation)
+  }
+
+  async handleImportEvent(ev: TFileInputEvent<'text' | 'file'>){
+    try {
+      const clearFileInputAndInform = () => {
+        if (this.fileInput) {
+          this.fileInput.clear()
+        }
+        this.snackbar.open('Annotation imported successfully!', 'Dismiss', {
+          duration: 3000
+        })
+      }
+
+      if (ev.type === 'text') {
+        const input = (ev as TFileInputEvent<'text'>).payload.input
+        /**
+         * parse as json, and go through the parsers
+         */
+        this.parseAndAddAnnotation(input)
+        clearFileInputAndInform()
+        return
+      }
+      if (ev.type === 'file') {
+        const files = (ev as TFileInputEvent<'file'>).payload.files
+        if (files.length === 0) throw new Error(`Need at least one file.`)
+        if (files.length > 1) throw new Error(`Parsing multiple files are not yet supported`)
+        const file = files[0]
+        const isJson = /\.json$/.test(file.name)
+        const isZip = /\.zip$/.test(file.name)
+        if (isZip) {
+          const files = await unzip(file)
+          const sands = files.filter(f => /\.json$/.test(f.filename))
+          for (const sand of sands) {
+            this.parseAndAddAnnotation(sand.filecontent)
+          }
+          clearFileInputAndInform()
+        }
+        if (isJson) {
+          const reader = new FileReader()
+          reader.onload = evt => {
+            const out = evt.target.result
+            this.parseAndAddAnnotation(out as string)
+            clearFileInputAndInform()
+          }
+          reader.onerror = e => { throw e }
+          reader.readAsText(file, 'utf-8')
+        }
+        /**
+         * check if zip or json
+         */
+        return
+      }
+    } catch (e) {
+      this.snackbar.open(`Error importing: ${e.toString()}`, 'Dismiss', {
+        duration: 3000
+      })
+    }
+  }
 }
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
index fcfea4ae4a53a64ad1299f16c7ecf584ef461770..4cd227d10dd4d9a5db7a2e9f6b91f8427c4da849 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
@@ -1,60 +1,92 @@
-<!-- header -->
-
-<div class="d-flex">
-    <h2 class="mat-h2 mt-4 text-muted">
-        Annotations
-    </h2>
-</div>
-
-<mat-divider></mat-divider>
-
-
-<!-- list of annotations -->
-<ng-template [ngIf]="managedAnnotations$ | async" [ngIfElse]="placeholderTmpl" let-managedAnnotations>
-
-    <mat-accordion *ngIf="managedAnnotations.length > 0; else placeholderTmpl"
-        [attr.aria-label]="ARIA_LABELS.USER_ANNOTATION_LIST"
-        class="h-100 d-flex flex-column overflow-auto">
-
-        <!-- expansion panel -->
-        <mat-expansion-panel *ngFor="let managedAnnotation of managedAnnotations"
-            hideToggle>
-
-            <mat-expansion-panel-header [ngClass]="{'highlight': managedAnnotation.highlighted }">
-                <mat-panel-title class="d-flex align-items-center">
-
-                    <!-- toggle visibility -->
-                    <button
-                        mat-icon-button
-                        iav-stop="click"
-                        (click)="toggleManagedAnnotationVisibility(managedAnnotation.id)">
-                        <i [ngClass]="(hiddenAnnotations$ | async | annotationVisiblePipe : managedAnnotation) ?  'fa-eye' : 'fa-eye-slash'" class="fas"></i>
-                    </button>
-                    <span class="flex-shrink-1 flex-grow-1" [ngClass]="{ 'text-muted': !managedAnnotation.name }">
-                        {{ managedAnnotation | singleAnnotationNamePipe : managedAnnotation.name }}
-                    </span>    
-                    <i class="flex-shrink-0 flex-grow-0" [ngClass]="managedAnnotation | singleannotationClsIconPipe"></i>
-                </mat-panel-title>
-            </mat-expansion-panel-header>
-
-            <!-- single annotation edit body -->
-            <ng-template matExpansionPanelContent>
-                <single-annotation-unit
-                    [single-annotation-unit-annotation]="managedAnnotation">
-                </single-annotation-unit>
+<mat-card class="mat-elevantion-z4 h-100">
+    <div class="sidenav-cover-header-container bg-50-grey-20">
+
+        <!-- title -->
+        <mat-card-title>
+            My Annotations
+        </mat-card-title>
+
+        <!-- actions -->
+        <mat-card-subtitle>
+            <!-- import -->
+            <ng-template #importMessageTmpl>
+                Please select a annotation file to import.
             </ng-template>
-        </mat-expansion-panel>
-    </mat-accordion>
-</ng-template>
-
-<!-- place holder when no annotations exist -->
-<ng-template #placeholderTmpl>
-    <mat-card>
-        <span>
-            No annotations visible yet. 
-        </span>
-        <span>
-            Start by adding an annotion, or import an existing annotation.
-        </span>
-    </mat-card>
-</ng-template>
\ No newline at end of file
+
+            <button mat-icon-button
+                (file-input-directive)="handleImportEvent($event)"
+                [file-input-directive-title]="ARIA_LABELS.USER_ANNOTATION_IMPORT"
+                [file-input-directive-text]="true"
+                [file-input-directive-file]="true"
+                [file-input-directive-message]="importMessageTmpl"
+                [attr.aria-label]="ARIA_LABELS.USER_ANNOTATION_IMPORT"
+                [matTooltip]="ARIA_LABELS.USER_ANNOTATION_IMPORT">
+                <i class="fas fa-folder-open"></i>
+            </button>
+
+            <!-- export -->
+            <button mat-icon-button
+                [zip-files-output]="filesExport$ | async"
+                zip-files-output-zip-filename="exported_annotations.zip"
+                [attr.aria-label]="ARIA_LABELS.USER_ANNOTATION_EXPORT"
+                [matTooltip]="ARIA_LABELS.USER_ANNOTATION_EXPORT"
+                [disabled]="!(manAnnExists$ | async)">
+                <i class="fas fa-file-export"></i>
+            </button>
+        </mat-card-subtitle>
+    </div>
+
+    <!-- content -->
+    <mat-card-content class="mt-4 ml-15px-n mr-15px-n pb-4">
+        <!-- list of annotations -->
+        <ng-template [ngIf]="managedAnnotations$ | async" [ngIfElse]="placeholderTmpl" let-managedAnnotations>
+
+            <mat-accordion *ngIf="managedAnnotations.length > 0; else placeholderTmpl"
+                [attr.aria-label]="ARIA_LABELS.USER_ANNOTATION_LIST"
+                class="h-100 d-flex flex-column overflow-auto">
+
+                <!-- expansion panel -->
+                <mat-expansion-panel *ngFor="let managedAnnotation of managedAnnotations"
+                    hideToggle>
+
+                    <mat-expansion-panel-header [ngClass]="{'highlight': managedAnnotation.highlighted }">
+                        <mat-panel-title class="d-flex align-items-center">
+
+                            <!-- toggle visibility -->
+                            <button
+                                mat-icon-button
+                                iav-stop="click"
+                                (click)="toggleManagedAnnotationVisibility(managedAnnotation.id)">
+                                <i [ngClass]="(hiddenAnnotations$ | async | annotationVisiblePipe : managedAnnotation) ?  'fa-eye' : 'fa-eye-slash'" class="fas"></i>
+                            </button>
+                            <span class="flex-shrink-1 flex-grow-1" [ngClass]="{ 'text-muted': !managedAnnotation.name }">
+                                {{ managedAnnotation | singleAnnotationNamePipe : managedAnnotation.name }}
+                            </span>    
+                            <i class="flex-shrink-0 flex-grow-0" [ngClass]="managedAnnotation | singleannotationClsIconPipe"></i>
+                        </mat-panel-title>
+                    </mat-expansion-panel-header>
+
+                    <!-- single annotation edit body -->
+                    <ng-template matExpansionPanelContent>
+                        <div class="d-flex">
+
+                            <!-- spacer for inset single-annotation-unit -->
+                            <div class="w-3em flex-grow-0 flex-shrink-0"></div>
+
+                            <single-annotation-unit [single-annotation-unit-annotation]="managedAnnotation"
+                                class="flex-grow-1 flex-shrink-1">
+                            </single-annotation-unit>
+                        </div>
+                    </ng-template>
+                </mat-expansion-panel>
+            </mat-accordion>
+        </ng-template>
+
+        <!-- place holder when no annotations exist -->
+        <ng-template #placeholderTmpl>
+            <div class="p-4 text-muted">
+                <p>Start by adding an annotation, or import existing annotations.</p>
+            </div>
+        </ng-template>
+    </mat-card-content>
+</mat-card>
diff --git a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
index ee03a1d8d1a611f3857198ae4f6faee3cb7794f1..025e66892e489c2bc1ec828d0be0196b02944c5d 100644
--- a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
+++ b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
@@ -1,15 +1,16 @@
-import { Component } from "@angular/core";
+import { Component, Inject, OnDestroy, Optional } from "@angular/core";
 import { Store } from "@ngrx/store";
 import { ModularUserAnnotationToolService } from "../tools/service";
 import { viewerStateSetViewerMode } from "src/services/state/viewerState.store.helper";
 import { ARIA_LABELS } from 'common/constants'
+import { ClickInterceptor, CLICK_INTERCEPTOR_INJECTOR } from "src/util";
 
 @Component({
   selector: 'annotating-tools-panel',
   templateUrl: './annotationMode.template.html',
   styleUrls: ['./annotationMode.style.css']
 })
-export class AnnotationMode {
+export class AnnotationMode implements OnDestroy{
 
   public ARIA_LABELS = ARIA_LABELS
 
@@ -21,11 +22,20 @@ export class AnnotationMode {
     onClick: Function
   }[] = []
 
+  private onDestroyCb: Function[] = []
+
   constructor(
     private store$: Store<any>,
     private modularToolSvc: ModularUserAnnotationToolService,
+    @Optional() @Inject(CLICK_INTERCEPTOR_INJECTOR) clickInterceptor: ClickInterceptor,
   ) {
     this.moduleAnnotationTypes = this.modularToolSvc.moduleAnnotationTypes
+    if (clickInterceptor) {
+      const { register, deregister } = clickInterceptor
+      const stopClickProp = () => false
+      register(stopClickProp)
+      this.onDestroyCb.push(() => deregister(stopClickProp))
+    }
   }
 
   exitAnnotationMode(){
@@ -36,7 +46,10 @@ export class AnnotationMode {
     )
   }
   deselectTools(){
-    console.log('deselect tools')
     this.modularToolSvc.deselectTools()
   }
+
+  ngOnDestroy(){
+    while (this.onDestroyCb.length > 0) this.onDestroyCb.pop()()
+  }
 }
diff --git a/src/atlasComponents/userAnnotations/annotationService.service.ts b/src/atlasComponents/userAnnotations/annotationService.service.ts
deleted file mode 100644
index 814bb01353e6485a64e30a50b2c9e9c4c9fc486a..0000000000000000000000000000000000000000
--- a/src/atlasComponents/userAnnotations/annotationService.service.ts
+++ /dev/null
@@ -1,363 +0,0 @@
-import {Inject, Injectable, Optional} from "@angular/core";
-import {viewerStateSetViewerMode} from "src/services/state/viewerState/actions";
-import {getUuid} from "src/util/fn";
-import {Store} from "@ngrx/store";
-import {VIEWER_INJECTION_TOKEN} from "src/ui/layerbrowser/layerDetail/layerDetail.component";
-import {AnnotationType, GroupedAnnotation, ViewerAnnotation} from "src/atlasComponents/userAnnotations/annotationInterfaces";
-
-const USER_ANNOTATION_LAYER_NAME = 'user_annotations'
-const USER_ANNOTATION_STORE_KEY = `user_landmarks_demo_2`
-
-const USER_ANNOTATION_LAYER_SPEC = {
-  "type": "annotation",
-  "tool": "annotateBoundingBox",
-  "name": USER_ANNOTATION_LAYER_NAME,
-  "annotationColor": "#ffee00",
-  "annotations": [],
-}
-
-@Injectable()
-export class AnnotationService {
-
-    // Annotations to display on viewer
-    public pureAnnotationsForViewer: ViewerAnnotation[] = []
-
-    // Grouped annotations for user
-    public groupedAnnotations: GroupedAnnotation[] = []
-
-    // Filtered annotations with converted voxed to mm
-    public finalAnnotationList: GroupedAnnotation[] = []
-
-    public addedLayer: any
-    public ellipsoidMinRadius = 0.5
-    public annotationFilter: 'all' | 'current' = 'current'
-
-    public selectedTemplate: {name, id}
-    public voxelSize: any[] = []
-    public selectedAtlas: {name, id}
-    public hoverAnnotation: {id: string, partIndex: number}
-
-    public annotationTypes: AnnotationType[] = [
-      {name: 'Cursor', class: 'fas fa-mouse-pointer', type: 'move', action: 'none'},
-      {name: 'Point', class: 'fas fa-circle', type: 'singleCoordinate', action: 'paint'},
-      {name: 'Line', class: 'fas fa-slash', type: 'doubleCoordinate', action: 'paint'},
-      {name: 'Polygon', class: 'fas fa-draw-polygon', type: 'polygon', action: 'paint'},
-      // {name: 'Bounding box', class: 'far fa-square', type: 'doubleCoordinate', action: 'paint'},
-      // {name: 'Ellipsoid', class: 'fas fa-bullseye', type: 'doubleCoordinate', action: 'paint'},
-      {name: 'Remove', class: 'fas fa-trash', type: 'remove', action: 'remove'},
-    ]
-
-    private get viewer(){
-      return this.injectedViewer || (window as any).viewer
-    }
-
-    constructor(private store$: Store<any>,
-                @Optional() @Inject(VIEWER_INJECTION_TOKEN) private injectedViewer
-    ) {}
-
-    public disable = () => {
-      this.store$.dispatch(viewerStateSetViewerMode({payload: null}))
-    }
-
-    public loadAnnotationLayer() {
-      if (!this.viewer) {
-        throw new Error(`viewer is not initialised`)
-      }
-
-      const layer = this.viewer.layerSpecification.getLayer(
-        USER_ANNOTATION_LAYER_NAME,
-        USER_ANNOTATION_LAYER_SPEC
-      )
-
-      this.addedLayer = this.viewer.layerManager.addManagedLayer(layer)
-    }
-
-    loadAnnotationsOnInit() {
-      const annotationsString = window.localStorage.getItem(USER_ANNOTATION_STORE_KEY)
-      const annotationList = JSON.parse(annotationsString)
-
-      if (annotationList && annotationList.length) {
-        this.pureAnnotationsForViewer = annotationList.filter(a => a.atlas.id === this.selectedAtlas.id)
-
-        this.groupedAnnotations = this.pureAnnotationsForViewer.filter(a => a.type !== 'polygon')
-        this.addPolygonsToGroupedAnnotations(this.pureAnnotationsForViewer.filter(a => a.type === 'polygon'))
-        this.refreshFinalAnnotationList()
-        this.pureAnnotationsForViewer.filter(a => a.annotationVisible && a.template.id === this.selectedTemplate.id)
-          .forEach(a => {
-            this.addAnnotationOnViewer(a)
-          })
-      }
-    }
-
-    getRadii(a, b): number[] {
-      const returnArray: number[] = [Math.abs(b[0] - a[0]), Math.abs(b[1] - a[1]), Math.abs(b[2] - a[2])]
-        .map(n => n === 0? this.ellipsoidMinRadius : n)
-      return returnArray
-    }
-
-    saveAnnotation({id = null,
-      position1 = null,
-      position2 = null,
-      name = null,
-      description = null,
-      type = null,
-      circular = null,
-      atlas = null,
-      template = null,
-    } = {}, store = true, backup = false) {
-      let annotation = {
-        id: id || getUuid(),
-        annotationVisible: true,
-        description,
-        name,
-        position1,
-        position2,
-        circular,
-        template: template || this.selectedTemplate,
-        atlas: this.selectedAtlas,
-        type: type.toLowerCase()
-      }
-
-      const foundIndex = this.pureAnnotationsForViewer.findIndex(x => x.id === annotation.id)
-
-      if (foundIndex >= 0) {
-        annotation = {
-          ...this.pureAnnotationsForViewer[foundIndex],
-          ...annotation
-        }
-      }
-
-      this.addAnnotationOnViewer(annotation)
-
-      if (backup) {
-        const i = this.saveEditList.findIndex((e) => e.id === annotation.id)
-        if (i < 0) {this.saveEditList.push(annotation)
-        } else {this.saveEditList[i] = annotation}
-      }
-
-      if (store) {
-        this.storeAnnotation(annotation)
-      }
-    }
-    public saveEditList = []
-
-    public storeBackup() {
-      if (this.saveEditList.length) {
-        if (this.saveEditList[0].type === 'polygon') {
-          this.addPolygonsToGroupedAnnotations(this.saveEditList)
-        }
-        this.saveEditList.forEach(a => this.storeAnnotation(a))
-        this.saveEditList = []
-      }
-    }
-
-    generateNameByType(type) {
-      const pointAnnotationNumber = this.pureAnnotationsForViewer
-        .filter(a => a.name && a.name.startsWith(type) && (+a.name.split(type)[1]))
-        .map(a => +a.name.split(type)[1])
-
-      return pointAnnotationNumber && pointAnnotationNumber.length?
-        `${type}${Math.max(...pointAnnotationNumber) + 1}` : `${type}1`
-
-    }
-
-    storeAnnotation(annotation) {
-      // give names by type + number
-      // if (!annotation.name && annotation.type !== 'polygon') {
-      //   annotation.name = this.generateNameByType(annotation.type)
-      // }
-
-      const foundIndex = this.pureAnnotationsForViewer.findIndex(x => x.id === annotation.id)
-
-      if (foundIndex >= 0) {
-        annotation = {
-          ...this.pureAnnotationsForViewer[foundIndex],
-          ...annotation
-        }
-        this.pureAnnotationsForViewer[foundIndex] = annotation
-      } else {
-        this.pureAnnotationsForViewer.push(annotation)
-      }
-
-      if(annotation.type !== 'polygon') {
-        const foundIndex = this.groupedAnnotations.findIndex(x => x.id === annotation.id)
-
-        if (foundIndex >= 0) {
-          this.groupedAnnotations[foundIndex] = annotation
-        } else {
-          this.groupedAnnotations.push(annotation)
-        }
-        this.refreshFinalAnnotationList()
-      }
-
-      this.storeToLocalStorage()
-    }
-
-    addAnnotationOnViewer(annotation) {
-      const annotationLayer = this.viewer.layerManager.getLayerByName(USER_ANNOTATION_LAYER_NAME).layer
-      const annotations = annotationLayer.localAnnotations.toJSON()
-
-      annotations.push({
-        description: annotation.description? annotation.description : '',
-        id: annotation.id,
-        point: annotation.type === 'point'? annotation.position1 : null,
-        pointA: annotation.type === 'line' || annotation.type === 'bounding box' || annotation.type === 'polygon'?
-          annotation.position1 : null,
-        pointB: annotation.type === 'line' || annotation.type === 'bounding box' || annotation.type === 'polygon'?
-          annotation.position2 : null,
-        center: annotation.type === 'ellipsoid'?
-          annotation.position1 : null,
-        radii: annotation.type === 'ellipsoid'?
-          annotation.position2 : null,
-        type: annotation.type === 'bounding box'?  'axis_aligned_bounding_box'
-          : annotation.type === 'polygon'? 'line'
-            : annotation.type.toUpperCase()
-      })
-
-      annotationLayer.localAnnotations.restoreState(annotations)
-    }
-
-
-    removeAnnotation(id) {
-      this.removeAnnotationFromViewer(id)
-      this.pureAnnotationsForViewer = this.pureAnnotationsForViewer.filter(a => a.id !== id)
-      this.groupedAnnotations = this.groupedAnnotations.filter(a => a.id !== id.split('_')[0])
-      this.refreshFinalAnnotationList()
-      this.storeToLocalStorage()
-    }
-
-    storeToLocalStorage() {
-      window.localStorage.setItem(USER_ANNOTATION_STORE_KEY, JSON.stringify(this.pureAnnotationsForViewer))
-    }
-
-    removeAnnotationFromViewer(id) {
-      const annotationLayer = this.viewer.layerManager.getLayerByName(USER_ANNOTATION_LAYER_NAME)?.layer
-      if (annotationLayer) {
-        let annotations = annotationLayer.localAnnotations.toJSON()
-        annotations = annotations.filter(a => a.id !== id)
-        annotationLayer.localAnnotations.restoreState(annotations)
-      }
-    }
-
-    addPolygonsToGroupedAnnotations(annotations) {
-      let transformed = [...annotations]
-
-      for (let i = 0; i<annotations.length; i++) {
-
-        const annotationId = annotations[i].id.split('_')
-        if (!transformed.find(t => t.id === annotationId[0])) {
-          const polygonAnnotations = annotations.filter(a => a.id.split('_')[0] === annotationId[0]
-                && a.id.split('_')[1])
-            // clear polygonAnnotations
-            .map(a => {
-              if (a.annotations) {
-                a.annotations = a.annotations.map(an => {
-                  return {
-                    id: an.id,
-                    position1: an.position1,
-                    position2: an.position2
-                  }
-                })
-              }
-              return a
-            })
-
-          const polygonPositions = polygonAnnotations.map((a, index) => {
-            return (index+1) !== polygonAnnotations.length? {
-              position: a.position2,
-              lines: [
-                {id: a.id, point: 2},
-                {id: polygonAnnotations[index+1].id, point: 1}
-              ]
-            } : a.position2.join() !== polygonAnnotations[0].position1.join()? {
-              position: a.position2,
-              lines: [
-                {id: a.id, point: 2}
-              ]
-            } : null
-          }).filter(a => !!a)
-          polygonPositions.unshift({
-            position: polygonAnnotations[0].position1,
-            lines: polygonAnnotations[0].position1.join() === [...polygonAnnotations].pop().position2.join()?
-              [{id: polygonAnnotations[0].id, point: 1}, {id: [...polygonAnnotations].pop().id, point: 2}]
-              : [{id: polygonAnnotations[0].id, point: 1}]
-          })
-
-          transformed = transformed.filter(a => a.id.split('_')[0] !== annotationId[0])
-
-          if (annotations[i].name === null) {
-            annotations[i].name = this.generateNameByType(annotations[i].type)
-          }
-
-          transformed.push({
-            id: annotationId[0],
-            name: annotations[i].name,
-            description: annotations[i].description,
-            type: 'polygon',
-            annotations: polygonAnnotations,
-            positions: polygonPositions,
-            circular: polygonAnnotations[0].position1.join() === [...polygonAnnotations].pop().position2.join(),
-            annotationVisible: annotations[i].annotationVisible,
-            template: annotations[i].template,
-            atlas: this.selectedAtlas
-          })
-        }
-
-      }
-
-      transformed.forEach(tr=> {
-        const foundIndex = this.groupedAnnotations.findIndex(x => x.id === tr.id)
-
-        if (foundIndex >= 0) {
-          this.groupedAnnotations[foundIndex] = tr
-        } else {
-          this.groupedAnnotations.push(tr)
-        }
-        this.refreshFinalAnnotationList()
-      })
-    }
-
-    refreshFinalAnnotationList(filter = null) {
-      if (filter) {this.annotationFilter = filter}
-      this.finalAnnotationList = this.groupedAnnotations
-        // Filter all/current template
-        .filter(a => this.annotationFilter === 'all' || a.template.id === this.selectedTemplate.id)
-        // convert to MM
-        .map(a => {
-          if (a.positions) {
-            a.positions = a.positions.map(p => {
-              return {
-                ...p,
-                position: this.voxelToMM(p.position)
-              }
-            })
-          } else {
-            a.position1 = this.voxelToMM(a.position1)
-            a.position2 = a.position2 && this.voxelToMM(a.position2)
-          }
-
-          a.dimension = 'mm'
-          return a
-        })
-    }
-
-    voxelToMM(r: number[]): number[] {
-      return r.map((r, i) => parseFloat((+r*this.voxelSize[i]/1e6).toFixed(3)))
-    }
-
-    mmToVoxel(mm: number[]): any[] {
-      return mm.map((m, i) => +m*1e6/this.voxelSize[i])
-    }
-
-    getVoxelFromSpace = (spaceId: string) => {
-      return IAV_VOXEL_SIZES_NM[spaceId]
-    }
-}
-
-export const IAV_VOXEL_SIZES_NM = {
-  'minds/core/referencespace/v1.0.0/265d32a0-3d84-40a5-926f-bf89f68212b9': [25000, 25000, 25000],
-  'minds/core/referencespace/v1.0.0/d5717c4a-0fa1-46e6-918c-b8003069ade8': [39062.5, 39062.5, 39062.5],
-  'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588': [21166.666015625, 20000, 21166.666015625],
-  'minds/core/referencespace/v1.0.0/7f39f7be-445b-47c0-9791-e971c0b6d992': [1000000, 1000000, 1000000,],
-  'minds/core/referencespace/v1.0.0/dafcffc5-4826-4bf1-8ff6-46b8a31ff8e2': [1000000, 1000000, 1000000]
-}
diff --git a/src/atlasComponents/userAnnotations/directives/exportAnnotation.directive.ts b/src/atlasComponents/userAnnotations/directives/exportAnnotation.directive.ts
deleted file mode 100644
index 13935dea1a1fe6dd4fa9dbb9654be7043f329e18..0000000000000000000000000000000000000000
--- a/src/atlasComponents/userAnnotations/directives/exportAnnotation.directive.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import {Directive, HostListener, Input} from "@angular/core";
-import * as JSZip from "jszip";
-
-@Directive({
-  selector: '[export-annotations]'
-})
-export class ExportAnnotation {
-
-  @Input('export-annotations') input: any
-
-  @HostListener('click')
-  onClick() {
-    this.exportAnnotations(this.input.annotations, this.input.sands)
-  }
-
-  getSandsObj(position, template) {
-    return {
-      coordinates: {
-        value: position.map(p => +p),
-        unit: 'mm'
-      },
-      coordinateSpace: {
-        fullName: template.name,
-        versionIdentifier: template.id
-      }
-    }
-  }
-
-  exportAnnotations(annotations, sands = false) {
-
-    const zip = new JSZip()
-    const zipFileName = `annotation - ${annotations[0].atlas.name}.zip`
-
-    if (sands) {
-      annotations.forEach(a => {
-        zip.folder(a.name)
-        if (a.positions) {
-          a.positions.forEach(p => {
-            zip.folder(a.name).file(`${p.position}.json`, JSON.stringify(this.getSandsObj(p.position, a.template)))
-          })
-        } else {
-          zip.folder(a.name).file(`${a.position1}.json`, JSON.stringify(this.getSandsObj(a.position1, a.template)))
-          if (a.position2) zip.folder(a.name).file(`${a.position1}.json`, JSON.stringify(this.getSandsObj(a.position2, a.template)))
-        }
-      })
-    } else {
-      annotations.forEach(a => {
-        const fileName = a.name.replace(/[\\/:*?"<>|]/g, "").trim()
-        zip.file(`${fileName}.json`, JSON.stringify(a))
-      })
-    }
-
-
-    zip.file("README.txt",
-      `The annotation has been extracted from the atlas: "${annotations.map(a => a.atlas.name).filter((v, i, a) => a.indexOf(v) === i).join()}" 
-        and template(s): "${annotations.map(a => a.template.name).filter((v, i, a) => a.indexOf(v) === i).join()}"`)
-    zip.generateAsync({
-      type: "base64"
-    }).then(content => {
-      const link = document.createElement('a')
-      link.href = 'data:application/zip;base64,' + content
-      link.download = zipFileName
-      document.body.appendChild(link)
-      link.click()
-      document.body.removeChild(link)
-    })
-  }
-
-}
diff --git a/src/atlasComponents/userAnnotations/directives/importAnnotation.directive.ts b/src/atlasComponents/userAnnotations/directives/importAnnotation.directive.ts
deleted file mode 100644
index 052e1e8805b774746f46dbc18438a96af74020f3..0000000000000000000000000000000000000000
--- a/src/atlasComponents/userAnnotations/directives/importAnnotation.directive.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import {Directive, HostListener, Input} from "@angular/core";
-import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
-
-@Directive({
-  selector: '[import-annotations]'
-})
-export class ImportAnnotation {
-
-  @Input('import-annotations') input: any
-
-  constructor(private ans: AnnotationService) {}
-
-  @HostListener('change', ['$event.target'])
-  onClick(target: any) {
-    if (target.files.length) {
-      this.importFile(target.files[0])
-    }
-  }
-
-  importFile(file) {
-    const sands = this.input.sands || null
-
-    const fileReader = new FileReader()
-    fileReader.readAsText(file, "UTF-8")
-    fileReader.onload = () => {
-      const fileData = JSON.parse(fileReader.result.toString())
-
-      if (sands) {
-        if (!fileData.coordinates || !fileData.coordinates.value || fileData.coordinates.value.length !== 3
-                    || !fileData.coordinateSpace || !fileData.coordinateSpace.fullName || !fileData.coordinateSpace.versionIdentifier) {
-          return
-        }
-        const position1 = this.ans.mmToVoxel(fileData.coordinates.value)
-        this.ans.saveAnnotation({position1,
-          template: {
-            name: fileData.coordinateSpace.fullName,
-            id: fileData.coordinateSpace.versionIdentifier
-          },
-          type: 'point'})
-      } else {
-        const {id, name, description, type,
-          atlas, template, positions, annotations} = fileData
-
-        if (!id || !(fileData.position1 || positions) || !type) {
-          return
-        }
-
-        if (fileData.type !== 'polygon') {
-          const position1 = this.ans.mmToVoxel(fileData.position1.split(',').map(Number))
-          const position2 = fileData.position2 && this.ans.mmToVoxel(fileData.position2.split(',').map(Number))
-
-          this.ans.saveAnnotation({position1, position2,
-            name, description, type, atlas, template
-          })
-        } else if (annotations) {
-          annotations.forEach(a => {
-            this.ans.saveAnnotation({
-              id: a.id,
-              name, description,
-              position1: a.position1,
-              position2: a.position2,
-              type: 'polygon'})
-          })
-          this.ans.groupedAnnotations.push(fileData)
-          this.ans.refreshFinalAnnotationList()
-        }
-
-      }
-    }
-    fileReader.onerror = (error) => {
-      console.warn(error)
-    }
-  }
-}
diff --git a/src/atlasComponents/userAnnotations/directives/keyListener.directive.ts b/src/atlasComponents/userAnnotations/directives/keyListener.directive.ts
deleted file mode 100644
index 5d304fadbf4a99784da2671405d1f11f070c1983..0000000000000000000000000000000000000000
--- a/src/atlasComponents/userAnnotations/directives/keyListener.directive.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import {Directive, ElementRef, HostListener} from "@angular/core";
-
-@Directive({
-  selector: '[annotation-list-key-listener]'
-})
-export class KeyListener {
-
-  constructor(private elementRef: ElementRef) {}
-
-  @HostListener('keydown', ['$event'])
-  onKeyDown(e) {
-    if ((e.ctrlKey || e.metaKey) && e.key === 'Enter' || e === 'Escape' || e.key === 'Enter') {
-      e.stopPropagation()
-      this.elementRef.nativeElement.blur()
-    }
-  }
-
-}
diff --git a/src/atlasComponents/userAnnotations/module.ts b/src/atlasComponents/userAnnotations/module.ts
index e3c764001977ef4907627a681d9e39342cbc722d..46f329bcb327691ae1bcd22384a6b80555028c3b 100644
--- a/src/atlasComponents/userAnnotations/module.ts
+++ b/src/atlasComponents/userAnnotations/module.ts
@@ -6,16 +6,14 @@ import {FormsModule, ReactiveFormsModule} from "@angular/forms";
 import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
 import {AnnotationMode} from "src/atlasComponents/userAnnotations/annotationMode/annotationMode.component";
 import {AnnotationList} from "src/atlasComponents/userAnnotations/annotationList/annotationList.component";
-import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
 import { UserAnnotationToolModule } from "./tools/module";
 import {AnnotationSwitch} from "src/atlasComponents/userAnnotations/directives/annotationSwitch.directive";
-import {ExportAnnotation} from "src/atlasComponents/userAnnotations/directives/exportAnnotation.directive";
-import {ImportAnnotation} from "src/atlasComponents/userAnnotations/directives/importAnnotation.directive";
-import {KeyListener} from "src/atlasComponents/userAnnotations/directives/keyListener.directive";
 import {CoordinateInputTextPipe} from "src/atlasComponents/userAnnotations/annotationList/coordinateInputText.pipe";
 import { UtilModule } from "src/util";
 import { SingleAnnotationClsIconPipe, SingleAnnotationNamePipe, SingleAnnotationUnit } from "./singleAnnotationUnit/singleAnnotationUnit.component";
 import { AnnotationVisiblePipe } from "./annotationVisible.pipe";
+import { FileInputModule } from "src/getFileInput/module";
+import { ZipFilesOutputModule } from "src/zipFilesOutput/module";
 
 @NgModule({
   imports: [
@@ -27,23 +25,19 @@ import { AnnotationVisiblePipe } from "./annotationVisible.pipe";
     AngularMaterialModule,
     UserAnnotationToolModule,
     UtilModule,
+    FileInputModule,
+    ZipFilesOutputModule,
   ],
   declarations: [
     AnnotationMode,
     AnnotationList,
     AnnotationSwitch,
-    ImportAnnotation,
-    ExportAnnotation,
-    KeyListener,
     CoordinateInputTextPipe,
     SingleAnnotationUnit,
     SingleAnnotationNamePipe,
     SingleAnnotationClsIconPipe,
     AnnotationVisiblePipe,
   ],
-  providers: [
-    AnnotationService
-  ],
   exports: [
     AnnotationMode,
     AnnotationList,
diff --git a/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.template.html b/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.template.html
index 9dfe60e8dcf6249b1ac16053e87c5c9bbaea8632..e03b3068ebc2360cc9e6a08c537c73c750c4ece9 100644
--- a/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.template.html
+++ b/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.template.html
@@ -32,7 +32,7 @@
   </mat-form-field>
 </form>
 
-<mat-divider class="m-2"></mat-divider>
+<mat-divider class="m-2 d-block position-relative"></mat-divider>
 
 <ng-template #editAnnotationVCRef>
 </ng-template>
diff --git a/src/atlasComponents/userAnnotations/tools/delete.ts b/src/atlasComponents/userAnnotations/tools/delete.ts
index f3141900788a0dbe1a512bc610db5ab51fee2323..ecf04a10d3e7dabed9b5094fe5cb59443fde0c3a 100644
--- a/src/atlasComponents/userAnnotations/tools/delete.ts
+++ b/src/atlasComponents/userAnnotations/tools/delete.ts
@@ -4,7 +4,7 @@ import { filter, switchMapTo, takeUntil, withLatestFrom } from "rxjs/operators";
 import { Point } from "./point";
 import { AbsToolClass, IAnnotationEvents, IAnnotationGeometry, IAnnotationTools, TAnnotationEvent, TCallbackFunction, TNgAnnotationPoint, TToolType } from "./type";
 
-export class ToolDelete extends AbsToolClass implements IAnnotationTools, OnDestroy {
+export class ToolDelete extends AbsToolClass<Point> implements IAnnotationTools, OnDestroy {
 
   public subs: Subscription[] = []
   toolType: TToolType = 'deletion'
@@ -15,6 +15,9 @@ export class ToolDelete extends AbsToolClass implements IAnnotationTools, OnDest
     return []
   }
 
+  // eslint-disable-next-line @typescript-eslint/no-empty-function
+  addAnnotation(){}
+  
   // eslint-disable-next-line @typescript-eslint/no-empty-function
   removeAnnotation(){}
 
diff --git a/src/atlasComponents/userAnnotations/tools/line.ts b/src/atlasComponents/userAnnotations/tools/line.ts
index 5df04a845515df59cab72a4d96e9ada3885a281a..6dcf2e1c436530a658cb9930655ebfe04ec5cccc 100644
--- a/src/atlasComponents/userAnnotations/tools/line.ts
+++ b/src/atlasComponents/userAnnotations/tools/line.ts
@@ -19,7 +19,7 @@ import { getUuid } from "src/util/fn";
 
 type TLineJsonSpec = {
   '@type': 'siibra-ex/annotation/line'
-  points: TPointJsonSpec[]
+  points: (TPointJsonSpec|Point)[]
 } & TBaseAnnotationGeomtrySpec
 
 export class Line extends IAnnotationGeometry{
@@ -39,7 +39,7 @@ export class Line extends IAnnotationGeometry{
       ? p
       : new Point({
         id: `${this.id}_${getUuid()}`,
-        "@type": 'siibra-ex/annotatoin/point',
+        "@type": 'siibra-ex/annotation/point',
         space: this.space,
         ...p
       })
@@ -111,10 +111,54 @@ export class Line extends IAnnotationGeometry{
     return new Line(json)
   }
 
+  static fromSANDS(json: TSandsLine): Line{
+    const {
+      "@id": id,
+      "@type": type,
+      coordinateSpace,
+      coordinatesFrom,
+      coordinatesTo
+    } = json
+    if (type !== 'tmp/line') throw new Error(`cannot parse line from sands`)
+    const fromPt = coordinatesFrom.map(c => {
+      if (c.unit["@id"] !== 'id.link/mm') throw new Error(`Cannot parse unit`)
+      return c.value * 1e6
+    })
+    const toPoint = coordinatesTo.map(c => {
+      if (c.unit["@id"] !== 'id.link/mm') throw new Error(`Cannot parse unit`)
+      return c.value * 1e6
+    })
+    const line = new Line({
+      id,
+      "@type": "siibra-ex/annotation/line",
+      points: [
+        new Point({
+          "@type": 'siibra-ex/annotation/point',
+          x: fromPt[0],
+          y: fromPt[1],
+          z: fromPt[2],
+          space: coordinateSpace
+        }),
+        new Point({
+          '@type': "siibra-ex/annotation/point",
+          x: toPoint[0],
+          y: toPoint[1],
+          z: toPoint[2],
+          space: coordinateSpace
+        })
+      ],
+      space: coordinateSpace
+    })
+    return line
+  }
+
   constructor(spec?: TLineJsonSpec){
     super(spec)
     const { points = [] } = spec || {}
-    this.points = points.map(Point.fromJSON)
+    this.points = points.map(p => {
+      if (p instanceof Point) return p
+      return Point.fromJSON(p)
+    })
   }
 
   public translate(x: number, y: number, z: number) {
@@ -131,7 +175,7 @@ export class Line extends IAnnotationGeometry{
 
 export const LINE_ICON_CLASS = 'fas fa-slash'
 
-export class ToolLine extends AbsToolClass implements IAnnotationTools, OnDestroy {
+export class ToolLine extends AbsToolClass<Line> implements IAnnotationTools, OnDestroy {
   static PREVIEW_ID='tool_line_preview'
   public name = 'Line'
   public toolType: TToolType = 'drawing'
@@ -277,6 +321,14 @@ export class ToolLine extends AbsToolClass implements IAnnotationTools, OnDestro
     this.subs.forEach(s => s.unsubscribe())
   }
 
+  addAnnotation(line: Line) {
+    const idx = this.managedAnnotations.findIndex(ann => ann.id === line.id)
+    if (idx >= 0) throw new Error(`Line annotation has already been added`)
+    this.managedAnnotations.push(line)
+    this.managedAnnotations$.next(this.managedAnnotations)
+    this.forceRefreshAnnotations$.next(null)
+  }
+
   removeAnnotation(id: string){
     const idx = this.managedAnnotations.findIndex(ann => ann.id === id)
     if (idx < 0) {
diff --git a/src/atlasComponents/userAnnotations/tools/line/line.style.css b/src/atlasComponents/userAnnotations/tools/line/line.style.css
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3cf6a85959217c0d3217a794e9dd0a1a7cbc460a 100644
--- a/src/atlasComponents/userAnnotations/tools/line/line.style.css
+++ b/src/atlasComponents/userAnnotations/tools/line/line.style.css
@@ -0,0 +1,5 @@
+:host
+{
+  display: flex;
+  flex-direction: column;
+}
\ No newline at end of file
diff --git a/src/atlasComponents/userAnnotations/tools/line/line.template.html b/src/atlasComponents/userAnnotations/tools/line/line.template.html
index ad1246b245e8acaf7799853eaa40439e5197f471..7b05ff79b4780f4d6858ec4ec2b6e51683fbd727 100644
--- a/src/atlasComponents/userAnnotations/tools/line/line.template.html
+++ b/src/atlasComponents/userAnnotations/tools/line/line.template.html
@@ -12,7 +12,7 @@
   </mat-chip>
 </mat-chip-list>
 
-<mat-divider class="m-2"></mat-divider>
+<mat-divider class="m-2 d-block position-relative"></mat-divider>
 
 <!-- actions -->
 
@@ -39,15 +39,6 @@
   <div class="iv-custom-comp card text"
     iav-stop="click">
 
-    <div class="d-flex">
-      <button *ngFor="let format of viableFormats"
-        (click)="setFormat(format)"
-        mat-flat-button
-        [color]="useFormat === format ? 'primary' : ''">
-        {{ format }}
-      </button>
-    </div>
-
     <div class="iv-custom-comp text">
       <mat-form-field>
         <mat-label>
diff --git a/src/atlasComponents/userAnnotations/tools/module.ts b/src/atlasComponents/userAnnotations/tools/module.ts
index 3576af312ea3851571ebc27f1ddac12947497252..cfc25b90f3e6262f80c777bb5942930372346c57 100644
--- a/src/atlasComponents/userAnnotations/tools/module.ts
+++ b/src/atlasComponents/userAnnotations/tools/module.ts
@@ -9,6 +9,12 @@ import { PolyUpdateCmp } from "./poly/poly.component";
 import { ModularUserAnnotationToolService } from "./service";
 import { ToFormattedStringPipe } from "./toFormattedString.pipe";
 import { ANNOTATION_EVENT_INJ_TOKEN } from "./type";
+import {Line, ToolLine} from "src/atlasComponents/userAnnotations/tools/line";
+
+import { Point, ToolPoint } from "./point";
+import { ToolSelect } from "./select";
+import { ToolDelete } from "./delete";
+import { Polygon, ToolPolygon } from "./poly";
 
 @NgModule({
   imports: [
@@ -38,6 +44,32 @@ import { ANNOTATION_EVENT_INJ_TOKEN } from "./type";
 
 export class UserAnnotationToolModule {
 
-  // eslint-disable-next-line @typescript-eslint/no-empty-function
-  constructor(_svc: ModularUserAnnotationToolService){}
+  constructor(svc: ModularUserAnnotationToolService){
+    const selTool = svc.registerTool({
+      toolCls: ToolSelect
+    })
+    svc.defaultTool = selTool
+
+    svc.registerTool({
+      toolCls: ToolPoint,
+      target: Point,
+      editCmp: PointUpdateCmp,
+    })
+
+    svc.registerTool({
+      toolCls: ToolLine,
+      target: Line,
+      editCmp: LineUpdateCmp,
+    })
+
+    svc.registerTool({
+      toolCls: ToolPolygon,
+      target: Polygon,
+      editCmp: PolyUpdateCmp,
+    })
+
+    svc.registerTool({
+      toolCls: ToolDelete
+    })
+  }
 }
diff --git a/src/atlasComponents/userAnnotations/tools/point.ts b/src/atlasComponents/userAnnotations/tools/point.ts
index 0b7d51d5e604dd3fbbf9a432436ea813bccd1884..233413921fd8b1317f098db99e02dd00023a98b1 100644
--- a/src/atlasComponents/userAnnotations/tools/point.ts
+++ b/src/atlasComponents/userAnnotations/tools/point.ts
@@ -7,7 +7,7 @@ export type TPointJsonSpec = {
   x: number
   y: number
   z: number
-  '@type': 'siibra-ex/annotatoin/point'
+  '@type': 'siibra-ex/annotation/point'
 } & TBaseAnnotationGeomtrySpec
 
 export class Point extends IAnnotationGeometry {
@@ -31,7 +31,7 @@ export class Point extends IAnnotationGeometry {
   }
   toJSON(): TPointJsonSpec{
     const { id, x, y, z, space, name, desc } = this
-    return { id, x, y, z, space, name, desc, '@type': 'siibra-ex/annotatoin/point' }
+    return { id, x, y, z, space, name, desc, '@type': 'siibra-ex/annotation/point' }
   }
 
   getNgAnnotationIds(){
@@ -48,6 +48,33 @@ export class Point extends IAnnotationGeometry {
     return new Point(json)
   }
 
+  static fromSANDS(sands: TSandsPoint): Point {
+    const {
+      "@id": id,
+      "@type": type,
+      coordinateSpace,
+      coordinates
+    } = sands
+    if (type === 'https://openminds.ebrains.eu/sands/CoordinatePoint') {
+      const parsedCoordinate = coordinates.map(coord => {
+        const { value, unit } = coord
+        if (unit["@id"] !== 'id.link/mm') throw new Error(`Unit does not parse`)
+        return value * 1e6
+      })
+      const point = new Point({
+        id,
+        space: coordinateSpace,
+        "@type": 'siibra-ex/annotation/point',
+        x: parsedCoordinate[0],
+        y: parsedCoordinate[1],
+        z: parsedCoordinate[2],
+      })
+      return point
+    }
+
+    throw new Error(`cannot parse sands for points, @type mismatch`)
+  }
+
   toString(){
     return `${(this.x / 1e6).toFixed(2)}mm, ${(this.y / 1e6).toFixed(2)}mm, ${(this.z / 1e6).toFixed(2)}mm`
   }
@@ -74,7 +101,7 @@ export class Point extends IAnnotationGeometry {
 
 export const POINT_ICON_CLASS='fas fa-circle'
 
-export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestroy {
+export class ToolPoint extends AbsToolClass<Point> implements IAnnotationTools, OnDestroy {
   static PREVIEW_ID='tool_point_preview'
   public name = 'Point'
   public toolType: TToolType = 'drawing'
@@ -113,7 +140,7 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
         const pt = new Point({
           x, y, z,
           space,
-          '@type': 'siibra-ex/annotatoin/point'
+          '@type': 'siibra-ex/annotation/point'
         })
         const { id } = pt
         pt.remove = () => this.removeAnnotation(id)
@@ -135,7 +162,7 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
        */
       this.dragHoveredAnnotationsDelta$.subscribe(ev => {
         const { ann, deltaX, deltaY, deltaZ } = ev
-        const { pickedAnnotationId, pickedOffset } = ann.detail
+        const { pickedAnnotationId } = ann.detail
         const foundAnn = this.managedAnnotations.find(ann => ann.id === pickedAnnotationId)
         if (foundAnn) {
           foundAnn.translate(deltaX, deltaY, deltaZ)
@@ -148,7 +175,6 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
       merge(
         this.forceRefresh$,
       ).subscribe(() => {
-        console.log('emit... here?')
         let out: INgAnnotationTypes['point'][] = []
         for (const managedAnn of this.managedAnnotations) {
           if (managedAnn.space['@id'] === this.space['@id']) {
@@ -160,15 +186,27 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
     )
   }
 
+  addAnnotation(point: Point){
+    const found = this.managedAnnotations.find(p => p.id === point.id)
+    if (found) throw new Error(`Point annotation already added`)
+    this.managedAnnotations.push(point)
+    this.managedAnnotations$.next(this.managedAnnotations)
+    this.forceRefresh$.next(null)
+  }
+
   /**
    * @description remove managed annotation via id
    * @param id id of annotation
    */
   removeAnnotation(id: string) {
     const idx = this.managedAnnotations.findIndex(ann => id === ann.id)
-
+    if (idx < 0){
+      throw new Error(`cannot find point idx ${idx}`)
+      return
+    }
     this.managedAnnotations.splice(idx, 1)
     this.managedAnnotations$.next(this.managedAnnotations)
+    this.forceRefresh$.next(null)
   }
 
   onMouseMoveRenderPreview(pos: [number, number, number]) {
diff --git a/src/atlasComponents/userAnnotations/tools/point/point.template.html b/src/atlasComponents/userAnnotations/tools/point/point.template.html
index 1de69ecc26e2e7837758892f0c2d165ab87ab3bc..2eeccd57ca5afa1f41e15e20be332b9f6c90a274 100644
--- a/src/atlasComponents/userAnnotations/tools/point/point.template.html
+++ b/src/atlasComponents/userAnnotations/tools/point/point.template.html
@@ -11,7 +11,7 @@
   </mat-chip>
 </mat-chip-list>
 
-<mat-divider class="m-2"></mat-divider>
+<mat-divider class="m-2 d-block position-relative"></mat-divider>
 
 <!-- actions -->
 
@@ -38,15 +38,6 @@
   <div class="iv-custom-comp card text"
     iav-stop="click">
 
-    <div class="d-flex">
-      <button *ngFor="let format of viableFormats"
-        (click)="setFormat(format)"
-        mat-flat-button
-        [color]="useFormat === format ? 'primary' : ''">
-        {{ format }}
-      </button>
-    </div>
-
     <div class="iv-custom-comp text">
       <mat-form-field>
         <mat-label>
diff --git a/src/atlasComponents/userAnnotations/tools/poly.ts b/src/atlasComponents/userAnnotations/tools/poly.ts
index ccd48017600d98b202028d69cb7b9f4670556ff6..8594e7213f2345698dd078dc02f0151ff6741a53 100644
--- a/src/atlasComponents/userAnnotations/tools/poly.ts
+++ b/src/atlasComponents/userAnnotations/tools/poly.ts
@@ -6,7 +6,7 @@ import { filter, switchMapTo, takeUntil, withLatestFrom } from "rxjs/operators";
 import { getUuid } from "src/util/fn";
 
 type TPolyJsonSpec = {
-  points: TPointJsonSpec[]
+  points: (TPointJsonSpec|Point)[]
   edges: [number, number][]
   '@type': 'siibra-ex/annotation/polyline'
 } & TBaseAnnotationGeomtrySpec
@@ -49,7 +49,7 @@ export class Polygon extends IAnnotationGeometry{
       : new Point({
         id: `${this.id}_${getUuid()}`,
         space: this.space,
-        '@type': 'siibra-ex/annotatoin/point',
+        '@type': 'siibra-ex/annotation/point',
         ...p
       })
     
@@ -99,14 +99,11 @@ export class Polygon extends IAnnotationGeometry{
       coordinateSpace: {
         '@id': this.space["@id"],
       },
-      coordinatesPairs: this.edges.map(([ idx1, idx2 ]) => {
-        const { x: x1, y: y1, z: z1 } = this.points[idx1]
-        const { x: x2, y: y2, z: z2 } = this.points[idx2]
-        return [
-          [getCoord(x1), getCoord(y1), getCoord(z1)],
-          [getCoord(x2), getCoord(y2), getCoord(z2)]
-        ]
-      })
+      coordinates: this.points.map(p => {
+        const { x, y, z } = p
+        return [getCoord(x/1e6), getCoord(y/1e6), getCoord(z/1e6)]
+      }),
+      closed: true
     }
   }
 
@@ -161,10 +158,54 @@ export class Polygon extends IAnnotationGeometry{
     return new Polygon(json)
   }
 
+  static fromSANDS(sands: TSandsPolyLine): Polygon {
+    const {
+      "@id": id,
+      "@type": type,
+      coordinateSpace,
+      coordinates
+    } = sands
+    if (type === 'tmp/poly') {
+      const points: Point[] = []
+      const edges: [number, number][] = []
+      for (const coordinate of coordinates) {
+        const parsedValue = coordinate.map(c => {
+          if (c.unit["@id"] !== 'id.link/mm') throw new Error(`Unit does not parse`)
+          return c.value * 1e6
+        })
+        const p = new Point({
+          space: coordinateSpace,
+          x: parsedValue[0],
+          y: parsedValue[1],
+          z:  parsedValue[2],
+          "@type": "siibra-ex/annotation/point"
+        })
+        const newIdx = points.push(p)
+        if (newIdx > 1) {
+          edges.push([ newIdx - 2, newIdx - 1 ])
+        }
+      }
+
+      const poly = new Polygon({
+        id,
+        "@type": 'siibra-ex/annotation/polyline',
+        space: coordinateSpace,
+        points,
+        edges
+      })
+      return poly
+    }
+
+    throw new Error(`cannot import sands`)
+  }
+
   constructor(spec?: TPolyJsonSpec){
     super(spec)
     const { points = [], edges = [] } = spec || {}
-    this.points = points.map(Point.fromJSON)
+    this.points = points.map(p => {
+      if (p instanceof Point) return p
+      return Point.fromJSON(p)
+    })
     this.edges = edges
   }
 
@@ -182,7 +223,7 @@ export class Polygon extends IAnnotationGeometry{
 
 export const POLY_ICON_CLASS = 'fas fa-draw-polygon'
 
-export class ToolPolygon extends AbsToolClass implements IAnnotationTools, OnDestroy {
+export class ToolPolygon extends AbsToolClass<Polygon> implements IAnnotationTools, OnDestroy {
   static PREVIEW_ID='tool_poly_preview'
 
   public name = 'polygon'
@@ -292,7 +333,6 @@ export class ToolPolygon extends AbsToolClass implements IAnnotationTools, OnDes
           const { id } = this.selectedPoly
           this.selectedPoly.remove = () => this.removeAnnotation(id)
           this.managedAnnotations.push(this.selectedPoly)
-          this.managedAnnotations$.next(this.managedAnnotations)
         } else {
 
           if (ann.detail) {
@@ -318,6 +358,11 @@ export class ToolPolygon extends AbsToolClass implements IAnnotationTools, OnDes
           this.lastAddedPoint
         )
         this.lastAddedPoint = addedPoint
+
+        /**
+         * always emit new annotation onclick
+         */
+        this.managedAnnotations$.next(this.managedAnnotations)
       }),
 
       /**
@@ -372,6 +417,14 @@ export class ToolPolygon extends AbsToolClass implements IAnnotationTools, OnDes
     )
   }
 
+  addAnnotation(poly: Polygon){
+    const idx = this.managedAnnotations.findIndex(ann => ann.id === poly.id)
+    if (idx >= 0) throw new Error(`Polygon already added.`)
+    this.managedAnnotations.push(poly)
+    this.managedAnnotations$.next(this.managedAnnotations)
+    this.forceRefreshAnnotations$.next(null)
+  }
+
   removeAnnotation(id: string) {
     const idx = this.managedAnnotations.findIndex(ann => ann.id === id)
     if (idx < 0) {
diff --git a/src/atlasComponents/userAnnotations/tools/poly/poly.template.html b/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
index 9340263fb28b89db4df5750b8b46170f85875822..07fa279961fce101fff2075de6ce0eb5588d022f 100644
--- a/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
+++ b/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
@@ -12,7 +12,7 @@
   </mat-chip>
 </mat-chip-list>
 
-<mat-divider class="m-2"></mat-divider>
+<mat-divider class="m-2 d-block position-relative"></mat-divider>
 
 <!-- actions -->
 
@@ -39,15 +39,6 @@
   <div class="iv-custom-comp card text"
     iav-stop="click">
 
-    <div class="d-flex">
-      <button *ngFor="let format of viableFormats"
-        (click)="setFormat(format)"
-        mat-flat-button
-        [color]="useFormat === format ? 'primary' : ''">
-        {{ format }}
-      </button>
-    </div>
-
     <div class="iv-custom-comp text">
       <mat-form-field>
         <mat-label>
diff --git a/src/atlasComponents/userAnnotations/tools/select.ts b/src/atlasComponents/userAnnotations/tools/select.ts
index ea2bea2b5b54ee8fcd3e81a582b497c82650bfab..2c10e4fe0a46c725a77666d5f621d3101c82a3b0 100644
--- a/src/atlasComponents/userAnnotations/tools/select.ts
+++ b/src/atlasComponents/userAnnotations/tools/select.ts
@@ -4,7 +4,7 @@ import { filter } from 'rxjs/operators'
 import { Point } from "./point";
 import { AbsToolClass, IAnnotationEvents, IAnnotationGeometry, IAnnotationTools, TAnnotationEvent, TCallbackFunction, TNgAnnotationPoint, TToolType } from "./type";
 
-export class ToolSelect extends AbsToolClass implements IAnnotationTools, OnDestroy {
+export class ToolSelect extends AbsToolClass<Point> implements IAnnotationTools, OnDestroy {
 
   public subs: Subscription[] = []
   toolType: TToolType = 'selecting'
@@ -15,6 +15,9 @@ export class ToolSelect extends AbsToolClass implements IAnnotationTools, OnDest
     return []
   }
 
+  // eslint-disable-next-line @typescript-eslint/no-empty-function
+  addAnnotation(){}
+
   // eslint-disable-next-line @typescript-eslint/no-empty-function
   removeAnnotation(){}
 
diff --git a/src/atlasComponents/userAnnotations/tools/service.ts b/src/atlasComponents/userAnnotations/tools/service.ts
index 9cc72aa5ad507cda981c4a9ada6fda416ecebab4..d80d959f8a5da6134f14343892949be7a6ac8da1 100644
--- a/src/atlasComponents/userAnnotations/tools/service.ts
+++ b/src/atlasComponents/userAnnotations/tools/service.ts
@@ -7,16 +7,12 @@ import { map, switchMap, filter, shareReplay, pairwise } from "rxjs/operators";
 import { viewerStateSelectedTemplatePureSelector, viewerStateViewerModeSelector } from "src/services/state/viewerState/selectors";
 import { NehubaViewerUnit } from "src/viewerModule/nehuba";
 import { NEHUBA_INSTANCE_INJTKN } from "src/viewerModule/nehuba/util";
-import { Polygon, ToolPolygon } from "./poly";
-import { AbsToolClass, ANNOTATION_EVENT_INJ_TOKEN, IAnnotationEvents, IAnnotationGeometry, INgAnnotationTypes, INJ_ANNOT_TARGET, TAnnotationEvent, ClassInterface, TExportFormats, TCallbackFunction } from "./type";
+import { AbsToolClass, ANNOTATION_EVENT_INJ_TOKEN, IAnnotationEvents, IAnnotationGeometry, INgAnnotationTypes, INJ_ANNOT_TARGET, TAnnotationEvent, ClassInterface, TExportFormats, TCallbackFunction, TSandsPolyLine, TSandsPoint, TSandsLine } from "./type";
 import { switchMapWaitFor } from "src/util/fn";
-import {Line, ToolLine} from "src/atlasComponents/userAnnotations/tools/line";
-import { PolyUpdateCmp } from './poly/poly.component'
-import { Point, ToolPoint } from "./point";
-import { PointUpdateCmp } from "./point/point.component";
-import { LineUpdateCmp } from "./line/line.component";
-import { ToolSelect } from "./select";
-import { ToolDelete } from "./delete";
+import { Polygon } from "./poly";
+import { Line } from "./line";
+import { Point } from "./point";
+
 
 const IAV_VOXEL_SIZES_NM = {
   'minds/core/referencespace/v1.0.0/265d32a0-3d84-40a5-926f-bf89f68212b9': [25000, 25000, 25000],
@@ -96,7 +92,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
   private registeredTools: {
     name: string
     iconClass: string
-    toolInsance: AbsToolClass
+    toolInstance: AbsToolClass<any>
     target?: ClassInterface<IAnnotationGeometry>
     editCmp?: ClassInterface<any>
     onDestoryCallBack: () => void
@@ -125,13 +121,13 @@ export class ModularUserAnnotationToolService implements OnDestroy{
    *   editCmp?: ClassInterface<any>
    * }} arg 
    */
-  private registerTool<T extends AbsToolClass>(arg: {
+  public registerTool<T extends AbsToolClass<any>>(arg: {
     toolCls: ClassInterface<T>
     target?: ClassInterface<IAnnotationGeometry>
     editCmp?: ClassInterface<any>
-  }): AbsToolClass{
+  }): AbsToolClass<any>{
     const { toolCls: Cls, target, editCmp } = arg
-    const newTool = new Cls(this.annotnEvSubj, arg => this.handleToolCallback(arg)) as AbsToolClass & { ngOnDestroy?: Function }
+    const newTool = new Cls(this.annotnEvSubj, arg => this.handleToolCallback(arg)) as T & { ngOnDestroy?: Function }
     const { name, iconClass, onMouseMoveRenderPreview } = newTool
     
     this.moduleAnnotationTypes.push({
@@ -178,7 +174,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
       iconClass,
       target,
       editCmp,
-      toolInsance: newTool,
+      toolInstance: newTool,
       onDestoryCallBack: () => {
         newTool.ngOnDestroy && newTool.ngOnDestroy()
         this.managedAnnotationsStream$.next({
@@ -214,33 +210,6 @@ export class ModularUserAnnotationToolService implements OnDestroy{
     @Optional() @Inject(NEHUBA_INSTANCE_INJTKN) nehubaViewer$: Observable<NehubaViewerUnit>,
   ){
 
-    const selTool = this.registerTool({
-      toolCls: ToolSelect
-    })
-    this.defaultTool = selTool
-
-    this.registerTool({
-      toolCls: ToolPoint,
-      target: Point,
-      editCmp: PointUpdateCmp,
-    })
-
-    this.registerTool({
-      toolCls: ToolLine,
-      target: Line,
-      editCmp: LineUpdateCmp,
-    })
-
-    this.registerTool({
-      toolCls: ToolPolygon,
-      target: Polygon,
-      editCmp: PolyUpdateCmp,
-    })
-
-    this.registerTool({
-      toolCls: ToolDelete
-    })
-
     /**
      * listen to mouse event on nehubaViewer, and emit as TAnnotationEvent
      */
@@ -369,9 +338,9 @@ export class ModularUserAnnotationToolService implements OnDestroy{
           console.warn(`cannot find tool ${selectedToolName}`)
           return
         }
-        const { toolInsance } = selectedTool
-        const previewNgAnnotation = toolInsance.onMouseMoveRenderPreview
-          ? toolInsance.onMouseMoveRenderPreview([ngMouseEvent.x, ngMouseEvent.y, ngMouseEvent.z])
+        const { toolInstance } = selectedTool
+        const previewNgAnnotation = toolInstance.onMouseMoveRenderPreview
+          ? toolInstance.onMouseMoveRenderPreview([ngMouseEvent.x, ngMouseEvent.y, ngMouseEvent.z])
           : []
 
         if (this.previewNgAnnIds.length !== previewNgAnnotation.length) {
@@ -548,7 +517,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
     }
   }
 
-  private defaultTool: AbsToolClass
+  public defaultTool: AbsToolClass<any>
   public deselectTools(){
 
     this.activeToolName = null
@@ -560,6 +529,29 @@ export class ModularUserAnnotationToolService implements OnDestroy{
     })
   }
 
+  parseAnnotationObject(json: TSandsPolyLine | TSandsPoint | TSandsLine): IAnnotationGeometry{
+    if (json['@type'] === 'tmp/poly') {
+      return Polygon.fromSANDS(json)
+    }
+    if (json['@type'] === 'tmp/line') {
+      return Line.fromSANDS(json)
+    }
+    if (json['@type'] === 'https://openminds.ebrains.eu/sands/CoordinatePoint') {
+      return Point.fromSANDS(json)
+    }
+    throw new Error(`cannot parse annotation object`)
+  }
+
+  importAnnotation(annotationObj: IAnnotationGeometry){
+    for (const tool of this.registeredTools) {
+      const { toolInstance, target } = tool
+      if (!!target && annotationObj instanceof target) {
+        toolInstance.addAnnotation(annotationObj)
+        return
+      }
+    }
+  }
+
   ngOnDestroy(){
     while(this.subscription.length > 0) this.subscription.pop().unsubscribe()
   }
diff --git a/src/atlasComponents/userAnnotations/tools/type.ts b/src/atlasComponents/userAnnotations/tools/type.ts
index e8be6598144c0d30b90a4f883bd81f254d67d6d2..3f1ccf1f1294a0c5d855c577c185f6b6b2d11f7d 100644
--- a/src/atlasComponents/userAnnotations/tools/type.ts
+++ b/src/atlasComponents/userAnnotations/tools/type.ts
@@ -8,13 +8,14 @@ import { getUuid } from "src/util/fn"
  * TODO perhaps split into drawing subclass/utility subclass
  */
 
-export abstract class AbsToolClass {
+export abstract class AbsToolClass<T extends IAnnotationGeometry> {
 
   public abstract name: string
   public abstract iconClass: string
 
+  public abstract addAnnotation(annotation: T): void
   public abstract removeAnnotation(id: string): void
-  public abstract managedAnnotations$: Observable<IAnnotationGeometry[]>
+  public abstract managedAnnotations$: Observable<T[]>
 
   abstract subs: Subscription[]
   protected space: TBaseAnnotationGeomtrySpec['space']
@@ -202,7 +203,8 @@ type TSandsQValue = {
 type TSandsCoord = [TSandsQValue, TSandsQValue] | [TSandsQValue, TSandsQValue, TSandsQValue]
 
 export type TSandsPolyLine = {
-  coordinatesPairs: [TSandsCoord, TSandsCoord][]
+  coordinates: TSandsCoord[]
+  closed: boolean
   coordinateSpace: {
     '@id': string
   }
diff --git a/src/atlasViewer/atlasViewer.apiService.service.ts b/src/atlasViewer/atlasViewer.apiService.service.ts
index 7fd34675da7020d4ca8230a6965a9c6cf6113b19..dbe633e67022d391826067b9d7d0004e627548bf 100644
--- a/src/atlasViewer/atlasViewer.apiService.service.ts
+++ b/src/atlasViewer/atlasViewer.apiService.service.ts
@@ -87,7 +87,7 @@ export class AtlasViewerAPIServices implements OnDestroy{
 
   private s: Subscription[] = []
 
-  private onMouseClick(ev: any) {
+  private onMouseClick(ev: any): boolean {
     const { rs, spec } = this.getNextUserRegionSelectHandler() || {}
     if (!!rs) {
 
@@ -116,10 +116,11 @@ export class AtlasViewerAPIServices implements OnDestroy{
                 mousePositionReal = floatArr && Array.from(floatArr).map((val: number) => val / 1e6)
               })
           }
-          return rs({
+          rs({
             type: spec.type,
             payload: mousePositionReal
           })
+          return false
         }
 
         /**
@@ -129,10 +130,11 @@ export class AtlasViewerAPIServices implements OnDestroy{
 
           if (!!moSegments && Array.isArray(moSegments) && moSegments.length > 0) {
             this.popUserRegionSelectHandler()
-            return rs({
+            rs({
               type: spec.type,
               payload: moSegments
             })
+            return false
           }
         }
       } else {
@@ -142,7 +144,8 @@ export class AtlasViewerAPIServices implements OnDestroy{
          */
         if (!!moSegments && Array.isArray(moSegments) && moSegments.length > 0) {
           this.popUserRegionSelectHandler()
-          return rs(moSegments[0])
+          rs(moSegments[0])
+          return false
         }
       }
     }
diff --git a/src/util/directives/dragDrop.directive.ts b/src/dragDropFile/dragDrop.directive.ts
similarity index 93%
rename from src/util/directives/dragDrop.directive.ts
rename to src/dragDropFile/dragDrop.directive.ts
index 4f2689b7bfa41878098fa1c6d87c15c45c20e7be..0427836c4a369ddf3fd7ced09358639d206cdcf1 100644
--- a/src/util/directives/dragDrop.directive.ts
+++ b/src/dragDropFile/dragDrop.directive.ts
@@ -4,15 +4,16 @@ import { debounceTime, map, scan, switchMap } from "rxjs/operators";
 import {MatSnackBar, MatSnackBarRef, SimpleSnackBar} from "@angular/material/snack-bar";
 
 @Directive({
-  selector: '[drag-drop]',
+  selector: '[drag-drop-file]',
+  exportAs: 'dragDropFile'
 })
 
-export class DragDropDirective implements OnInit, OnDestroy {
+export class DragDropFileDirective implements OnInit, OnDestroy {
 
   @Input()
   public snackText: string
 
-  @Output('drag-drop')
+  @Output('drag-drop-file')
   public dragDropOnDrop: EventEmitter<File[]> = new EventEmitter()
 
   @HostBinding('style.transition')
diff --git a/src/dragDropFile/module.ts b/src/dragDropFile/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e3b77d44dc37541f55f62beed2ab213af43c4d77
--- /dev/null
+++ b/src/dragDropFile/module.ts
@@ -0,0 +1,17 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { DragDropFileDirective } from "./dragDrop.directive";
+
+@NgModule({
+  imports: [
+    CommonModule
+  ],
+  declarations: [
+    DragDropFileDirective
+  ],
+  exports: [
+    DragDropFileDirective
+  ]
+})
+
+export class DragDropFileModule{}
\ No newline at end of file
diff --git a/src/getFileInput/fileInputModal/fileInputModal.component.ts b/src/getFileInput/fileInputModal/fileInputModal.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b402c272261e01cf13047a0d9c3c65776ada7850
--- /dev/null
+++ b/src/getFileInput/fileInputModal/fileInputModal.component.ts
@@ -0,0 +1,119 @@
+import { Component, ElementRef, EventEmitter, Inject, Input, Optional, TemplateRef, ViewChild } from "@angular/core";
+import { MAT_DIALOG_DATA } from "@angular/material/dialog";
+import { IFileInputConfig, TFileInputEvent } from "../type";
+
+const FILEINPUT_DEFAULT_LABEL = 'File input'
+
+@Component({
+  selector: 'file-input-modal',
+  templateUrl: './fileInputModal.template.html',
+  styleUrls: [
+    './fileInputModal.style.css'
+  ]
+})
+
+export class FileInputModal implements IFileInputConfig{
+  
+  @Input('file-input-directive-title')
+  title = 'Import'
+
+  @Input('file-input-directive-text')
+  allowText = false
+
+  @Input('file-input-directive-file')
+  allowFile = true
+
+  @Input('file-input-directive-message')
+  messageTmpl: TemplateRef<any>
+
+  @ViewChild('fileInput', { read: ElementRef })
+  private fileInputEl: ElementRef<HTMLInputElement>
+
+  constructor(
+    @Optional() @Inject(MAT_DIALOG_DATA) data: IFileInputConfig
+  ){
+    if (data) {
+      const { allowFile, allowText, messageTmpl, title } = data
+      this.allowFile = allowFile
+      this.allowText = allowText
+      this.messageTmpl = messageTmpl
+      this.title = title || this.title
+    }
+  }
+
+  public hasInput = false
+
+  private _textInput = ''
+  set textInput(val: string) {
+    this._textInput = val
+    this.checkImportable()
+  }
+  get textInput(){
+    return this._textInput
+  }
+
+  public fileInputLabel: string = FILEINPUT_DEFAULT_LABEL
+  public hasFileInput = false
+
+  private _fileInput: File
+  set fileInput(val: File){
+    this._fileInput = val
+    this.hasFileInput = !!this.fileInput
+    this.fileInputLabel = this.hasFileInput
+      ? this._fileInput.name
+      : FILEINPUT_DEFAULT_LABEL
+
+    this.checkImportable()
+  }
+  get fileInput(){
+    return this._fileInput
+  }
+  handleFileInputChange(ev: InputEvent){
+    const target = ev.target as HTMLInputElement
+    this.fileInput = target.files[0]
+  }
+
+  handleFileDrop(files: File[]){
+    this.fileInput = files[0]
+  }
+
+  public importable = false
+  checkImportable(){
+    if (this._textInput.length > 0) {
+      this.importable = true
+      return
+    }
+    if (this.hasFileInput){
+      this.importable = true
+      return
+    }
+    this.importable = false
+  }
+
+  clear(){
+    this.textInput = ''
+    this.fileInput = null
+  }
+
+  public evtEmitter = new EventEmitter<TFileInputEvent<'text' | 'file'>>()
+
+  runImport(){
+    if (this._textInput !== '') {
+      this.evtEmitter.emit({
+        type: 'text',
+        payload: {
+          input: this._textInput
+        }
+      })
+      return
+    }
+    if (this.hasFileInput) {
+      const files = [this.fileInput]
+      this.evtEmitter.emit({
+        type: 'file',
+        payload: { files }
+      })
+      return
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/getFileInput/fileInputModal/fileInputModal.style.css b/src/getFileInput/fileInputModal/fileInputModal.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..3326ccd216c00e08bf82bdf311be32f86cefae46
--- /dev/null
+++ b/src/getFileInput/fileInputModal/fileInputModal.style.css
@@ -0,0 +1,22 @@
+.file-input-label-container
+{
+  box-sizing: border-box;
+  padding: 1rem;
+}
+
+.file-input-label
+{
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 1rem;
+  border: 2px dashed rgba(128,128,128,0.4);
+  opacity: 0.7;
+  transition: opacity 200ms ease-in-out;
+}
+
+.file-input-label:hover
+{
+  cursor: pointer;
+  opacity: 1.0;
+}
\ No newline at end of file
diff --git a/src/getFileInput/fileInputModal/fileInputModal.template.html b/src/getFileInput/fileInputModal/fileInputModal.template.html
new file mode 100644
index 0000000000000000000000000000000000000000..4fdc365d5169260206961acf60c0e117f29ce582
--- /dev/null
+++ b/src/getFileInput/fileInputModal/fileInputModal.template.html
@@ -0,0 +1,55 @@
+<h2 mat-dialog-title>
+  {{ title }}
+</h2>
+<mat-dialog-content>
+  <ng-template [ngIf]="messageTmpl" [ngIfElse]="defaultMessageTmpl" [ngTemplateOutlet]="messageTmpl">
+  </ng-template>
+
+  <ng-template #defaultMessageTmpl>
+    Please select a file to import.
+  </ng-template>
+
+  <div class="w-100 d-flex">
+
+    <!-- text input -->
+    <mat-form-field *ngIf="allowText"
+      class="flex-grow-1 flex-shrink-1 w-0">
+      <mat-label>
+        Text Input
+      </mat-label>
+      <textarea matInput
+        [(ngModel)]="textInput"
+        rows="5"
+        placeholder="Text Input"></textarea>
+    </mat-form-field>
+
+    <!-- file-input -->
+    <div class="file-input-label-container flex-grow-1 flex-shrink-1 w-0 position-relative"
+      (drag-drop-file)="handleFileDrop($event)">
+      <label for="file-input" class="file-input-label w-100 h-100">
+        <i [ngClass]="hasFileInput ? 'fa-file' : 'fa-folder-open'" class="fas"></i>
+        <span class="ml-2">
+          {{ fileInputLabel }}
+        </span>
+      </label>
+      <input (change)="handleFileInputChange($event)"
+        type="file"
+        class="position-absolute left-0 top-0 w-0 h-0 invisible"
+        name="file-input"
+        id="file-input"
+        #fileInput>
+    </div>
+  </div>
+</mat-dialog-content>
+
+<mat-dialog-actions align="end">
+  <button mat-raised-button
+    (click)="runImport()"
+    [disabled]="!importable"
+    color="primary">
+    Import
+  </button>
+  <button mat-button mat-dialog-close>
+    Close
+  </button>
+</mat-dialog-actions>
diff --git a/src/getFileInput/getFileInput.directive.ts b/src/getFileInput/getFileInput.directive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d1158cdac9de4598957793bec83f2c90761edb2f
--- /dev/null
+++ b/src/getFileInput/getFileInput.directive.ts
@@ -0,0 +1,68 @@
+import { Directive, EventEmitter, HostListener, Input, Output, TemplateRef } from "@angular/core";
+import { MatDialog, MatDialogRef } from "@angular/material/dialog";
+import { FileInputModal } from "./fileInputModal/fileInputModal.component";
+import { IFileInputConfig, TFileInputEvent } from "./type";
+
+@Directive({
+  selector: '[file-input-directive]',
+  exportAs: 'fileInputDirective'
+})
+
+export class FileInputDirective implements IFileInputConfig{
+
+  @Input('file-input-directive-title')
+  title = 'Import'
+
+  @Input('file-input-directive-text')
+  allowText = false
+
+  @Input('file-input-directive-file')
+  allowFile = true
+
+  @Input('file-input-directive-message')
+  messageTmpl: TemplateRef<any>
+
+  @Output('file-input-directive')
+  evtEmitter = new EventEmitter<TFileInputEvent<'text' | 'file'>>()
+
+  private dialogRef: MatDialogRef<FileInputModal>
+
+  @HostListener('click')
+  handleClick(){
+    const { title, allowText, allowFile, messageTmpl } = this
+    this.dialogRef = this.dialog.open(FileInputModal, {
+      width: '65vw',
+      data: {
+        allowText,
+        allowFile,
+        title,
+        messageTmpl,
+      }
+    })
+    const evSub = this.dialogRef.componentInstance.evtEmitter.subscribe(
+      (ev: TFileInputEvent<"text" | "file">) => this.evtEmitter.emit(ev)
+    )
+    this.dialogRef.afterClosed().subscribe(() => {
+      this.dialogRef = null
+      evSub.unsubscribe()
+    })
+  }
+
+  constructor(
+    private dialog: MatDialog
+  ){
+    
+  }
+
+  clear(){
+    if (this.dialogRef) {
+      this.dialogRef.componentInstance.clear()
+    }
+  }
+
+  dismiss(){
+    if (this.dialogRef) {
+      this.dialogRef.close()
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/getFileInput/index.ts b/src/getFileInput/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/getFileInput/module.ts b/src/getFileInput/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..77610abdb95357e856f20d9d59a13ee98ee515ed
--- /dev/null
+++ b/src/getFileInput/module.ts
@@ -0,0 +1,30 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { FileInputDirective } from "./getFileInput.directive";
+import { MatDialogModule } from '@angular/material/dialog';
+import { FileInputModal } from "./fileInputModal/fileInputModal.component";
+import { FormsModule } from "@angular/forms";
+import { MatInputModule } from '@angular/material/input';
+import { MatButtonModule } from '@angular/material/button';
+import { DragDropFileModule } from "src/dragDropFile/module";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    MatDialogModule,
+    FormsModule,
+    MatInputModule,
+    MatButtonModule,
+    DragDropFileModule,
+  ],
+  declarations: [
+    FileInputDirective,
+    FileInputModal,
+  ],
+  exports: [
+    FileInputDirective,
+    FileInputModal,
+  ],
+})
+
+export class FileInputModule{}
\ No newline at end of file
diff --git a/src/getFileInput/type.ts b/src/getFileInput/type.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6b95f06956c8dc9b9dc64798f9a5df1e8d7e3faa
--- /dev/null
+++ b/src/getFileInput/type.ts
@@ -0,0 +1,18 @@
+import { TemplateRef } from "@angular/core";
+
+export interface IFileInputConfig {
+  title: string
+  allowText: boolean
+  allowFile: boolean
+  messageTmpl?: TemplateRef<any>
+}
+
+export type TFileInput = {
+  text: { input: string }
+  file: { files: File[] }
+}
+
+export type TFileInputEvent<Evt extends keyof TFileInput> = {
+  type: Evt
+  payload: TFileInput[Evt]
+}
\ No newline at end of file
diff --git a/src/main.module.ts b/src/main.module.ts
index 90c7080be8366e2e1e3ecc7f4784c77f6321fbb1..3d47b99f720a655bc63cc94f3f11d08caec175ab 100644
--- a/src/main.module.ts
+++ b/src/main.module.ts
@@ -29,7 +29,6 @@ import { UIService } from "./services/uiService.service";
 import { DatabrowserModule, OVERRIDE_IAV_DATASET_PREVIEW_DATASET_FN, DataBrowserFeatureStore, GET_KGDS_PREVIEW_INFO_FROM_ID_FILENAME, DatabrowserService } from "src/atlasComponents/databrowserModule";
 import { ViewerStateControllerUseEffect } from "src/state";
 import { DockedContainerDirective } from "./util/directives/dockedContainer.directive";
-import { DragDropDirective } from "./util/directives/dragDrop.directive";
 import { FloatingContainerDirective } from "./util/directives/floatingContainer.directive";
 import { FloatingMouseContextualContainerDirective } from "./util/directives/floatingMouseContextualContainer.directive";
 import { NewViewerDisctinctViewToLayer } from "./util/pipes/newViewerDistinctViewToLayer.pipe";
@@ -134,7 +133,6 @@ export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
     DockedContainerDirective,
     FloatingContainerDirective,
     FloatingMouseContextualContainerDirective,
-    DragDropDirective,
 
     /* pipes */
     GetNamesPipe,
diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css
index e98f09941fcc99b2a721c892167f806adf681137..d55624cb78aa1a54e114edcea645ede26c4c56a0 100644
--- a/src/res/css/extra_styles.css
+++ b/src/res/css/extra_styles.css
@@ -843,3 +843,10 @@ mat-list.sm mat-list-item
 {
   color: inherit!important;
 }
+
+.sidenav-cover-header-container
+{
+  padding: 16px;
+  margin: -16px!important;
+  padding-top: 6rem;
+}
\ No newline at end of file
diff --git a/src/viewerModule/viewerCmp/viewerCmp.template.html b/src/viewerModule/viewerCmp/viewerCmp.template.html
index 5ae2b7d4c0e22f7713fabe456b59f735c34ab882..23e6e4b16bad4e0a8ffce83c9fba2c2c536816c0 100644
--- a/src/viewerModule/viewerCmp/viewerCmp.template.html
+++ b/src/viewerModule/viewerCmp/viewerCmp.template.html
@@ -11,12 +11,12 @@
       [hasBackdrop]="false">
       <mat-drawer #annotationDrawer
         [mode]="'push'"
+        [autoFocus]="false"
         [disableClose]="true"
-        class="box-shadow-none border-0 pe-all col-10 col-sm-10 col-md-5 col-lg-4 col-xl-3 col-xxl-2">
+        class="p-0 pe-all col-10 col-sm-10 col-md-5 col-lg-4 col-xl-3 col-xxl-2">
         <annotation-list></annotation-list>
       </mat-drawer>
 
-
       <mat-drawer-content class="visible position-relative pe-none">
 
         <iav-layout-fourcorners>
diff --git a/src/zipFilesOutput/module.ts b/src/zipFilesOutput/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..59e58e22483dfc9a2509fbee93ea5331ed60f8f2
--- /dev/null
+++ b/src/zipFilesOutput/module.ts
@@ -0,0 +1,19 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { ZipFilesOutput } from "./zipFilesOutput.directive";
+
+@NgModule({
+  imports: [
+    CommonModule,
+  ],
+  declarations: [
+    ZipFilesOutput
+  ],
+  exports: [
+    ZipFilesOutput
+  ]
+})
+
+export class ZipFilesOutputModule{}
+
+export { TZipFileConfig } from './type'
\ No newline at end of file
diff --git a/src/zipFilesOutput/type.ts b/src/zipFilesOutput/type.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f5e986b36848cd8cea94cad3e4d54dbd17fa495e
--- /dev/null
+++ b/src/zipFilesOutput/type.ts
@@ -0,0 +1,5 @@
+export type TZipFileConfig = {
+  filename: string
+  filecontent: string
+  base64?: boolean
+}
\ No newline at end of file
diff --git a/src/zipFilesOutput/zipFilesOutput.directive.ts b/src/zipFilesOutput/zipFilesOutput.directive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bcf70bddfaf8e3e84ab97f887ae93ae8e95fcfc6
--- /dev/null
+++ b/src/zipFilesOutput/zipFilesOutput.directive.ts
@@ -0,0 +1,55 @@
+import { Directive, HostListener, Inject, Input } from "@angular/core";
+import { TZipFileConfig } from "./type";
+import * as JSZip from "jszip";
+import { DOCUMENT } from "@angular/common";
+
+@Directive({
+  selector: '[zip-files-output]',
+  exportAs: 'zipFilesOutput'
+})
+
+export class ZipFilesOutput {
+  @Input('zip-files-output')
+  zipFiles: TZipFileConfig[] = []
+
+  @Input('zip-files-output-zip-filename')
+  zipFilename = 'archive.zip'
+
+  @HostListener('click')
+  async onClick(){
+    const zip = new JSZip()
+    for (const zipFile of this.zipFiles) {
+      const { filecontent, filename, base64 } = zipFile
+      zip.file(filename, filecontent, { base64 })
+    }
+    const blob = await zip.generateAsync({ type: 'blob' })
+    const anchor = this.doc.createElement('a')
+    anchor.href = URL.createObjectURL(blob)
+    anchor.download = this.zipFilename
+
+    this.doc.body.appendChild(anchor)
+    anchor.click()
+    this.doc.body.removeChild(anchor)
+    URL.revokeObjectURL(anchor.href)
+  }
+  constructor(
+    @Inject(DOCUMENT) private doc: Document
+  ){
+
+  }
+}
+
+export async function unzip(file: File): Promise<TZipFileConfig[]>{
+  const zip = new JSZip()
+  const loadedAsync = await zip.loadAsync(file)
+  
+  const out: TZipFileConfig[] = []
+  for (const filename in loadedAsync.files) {
+    const filecontent = await loadedAsync.files[filename].async('string')
+    out.push({
+      filename,
+      filecontent
+    })
+  }
+  return out
+}