diff --git a/common/constants.js b/common/constants.js
index d9d3e6c4ff1bf4558e08aeb977d988beaed47a54..5a7066902a523a337cd27ab40065d8a64db0df31 100644
--- a/common/constants.js
+++ b/common/constants.js
@@ -64,10 +64,10 @@
     USER_ANNOTATION_LIST: 'user annotations footer',
     USER_ANNOTATION_IMPORT: 'user annotations import',
     USER_ANNOTATION_EXPORT: 'user annotations export',
-    USER_ANNOTATION_EXPORT_SINGLE: 'user annotations export single',
+    USER_ANNOTATION_EXPORT_SINGLE: 'Export annotation',
     USER_ANNOTATION_HIDE: 'user annotations hide',
     USER_ANNOTATION_DELETE: 'user annotations delete',
-    GOTO_ANNOTATION_ROI: 'Navigate to annotation location of interest.'
+    GOTO_ANNOTATION_ROI: 'Navigate to annotation location of interest'
 
   }
 
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
index 141c36903dd66dcdfcef381542fdfe2a4c537446..0dccb54111b0b663098701fe5275fe305cb62e62 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
@@ -4,34 +4,34 @@ import {viewerStateChangeNavigation} from "src/services/state/viewerState/action
 import {Store} from "@ngrx/store";
 import {ARIA_LABELS} from "common/constants";
 import { ModularUserAnnotationToolService } from "../tools/service";
-import { EXPORT_FORMAT_INJ_TOKEN, TExportFormats } from "../tools/type";
+import { TExportFormats } from "../tools/type";
+import { ComponentStore } from "src/viewerModule/componentStore";
 
 
 @Component({
   selector: 'annotation-list',
   templateUrl: './annotationList.template.html',
   styleUrls: ['./annotationList.style.css'],
-  providers: [{
-    provide: EXPORT_FORMAT_INJ_TOKEN,
-    useFactory: (svc: ModularUserAnnotationToolService) => svc.exportFormat$,
-    deps: [
-      ModularUserAnnotationToolService
-    ]
-  }]
+  providers: [
+    ComponentStore,
+  ]
 })
 export class AnnotationList {
 
   public ARIA_LABELS = ARIA_LABELS
   public identifier = (index: number, item: any) => item.id
 
-  public availableFormat: TExportFormats[] = ['json', 'sands', 'string']
-  public exportFromat$ = this.annotSvc.exportFormat$
-  public selectExportFormat(format: TExportFormats) {
-    this.exportFromat$.next(format)
-  }
-
   public managedAnnotations$ = this.annotSvc.managedAnnotations$
-  constructor(private store$: Store<any>, public ans: AnnotationService, private annotSvc: ModularUserAnnotationToolService) {}
+  constructor(
+    private store$: Store<any>,
+    public ans: AnnotationService,
+    private annotSvc: ModularUserAnnotationToolService,
+    cStore: ComponentStore<{ useFormat: TExportFormats }>,
+  ) {
+    cStore.setState({
+      useFormat: 'json'
+    })
+  }
 
   toggleAnnotationVisibility(annotation) {
     if (annotation.type === 'polygon') {
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
index 5433e233e676d3177b710741a7c7c2eb4e2923fd..2b06e3ade5695a9937016e92e724b2dc69929e23 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
@@ -37,22 +37,6 @@
 
         </div>
 
-        <!-- select export format -->
-        <button mat-icon-button [matMenuTriggerFor]="exportFormatMenu">
-            <i class="fas fa-code"></i>
-        </button>
-
-        <mat-menu #exportFormatMenu="matMenu">
-            <button *ngFor="let format of availableFormat"
-                mat-menu-item
-                (click)="selectExportFormat(format)">
-                <span class="iv-custom-comp text"
-                    [ngClass]="{'primary': (exportFromat$ | async) === format}">
-                    {{ format }}
-                </span>
-            </button>
-        </mat-menu>
-
         <div class="d-flex flex-column">
             <small [ngClass]="[ans.annotationFilter !== 'all'? 'text-muted' : '']"
                    class="cursor-pointer" (click)="ans.refreshFinalAnnotationList('all')">
diff --git a/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts b/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
index e69df14b0f8bf8106cd266a3289b6511d6aee265..299e8ccf558d42e793637ff2a3d95ff3f1e12b77 100644
--- a/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
+++ b/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
@@ -1,13 +1,14 @@
 import { AfterViewInit, Component, ComponentFactoryResolver, Inject, Injector, Input, OnDestroy, Optional, Pipe, PipeTransform, ViewChild, ViewContainerRef } from "@angular/core";
-import { EXPORT_FORMAT_INJ_TOKEN, IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../tools/type";
+import { IAnnotationGeometry, UDPATE_ANNOTATION_TOKEN } from "../tools/type";
 import { Point } from '../tools/point'
 import { Polygon } from '../tools/poly'
 import { FormControl, FormGroup } from "@angular/forms";
-import { Observable, Subscription } from "rxjs";
+import { Subscription } from "rxjs";
 import { select, Store } from "@ngrx/store";
 import { viewerStateFetchedAtlasesSelector } from "src/services/state/viewerState/selectors";
 import { ModularUserAnnotationToolService } from "../tools/service";
 import { MatSnackBar } from "@angular/material/snack-bar";
+import { Line } from "../tools/line";
 
 @Component({
   selector: 'single-annotation-unit',
@@ -59,7 +60,7 @@ export class SingleAnnotationUnit implements OnDestroy, AfterViewInit{
     private snackbar: MatSnackBar,
     private svc: ModularUserAnnotationToolService,
     private cfr: ComponentFactoryResolver,
-    @Optional() @Inject(EXPORT_FORMAT_INJ_TOKEN) private useFormat$: Observable<TExportFormats>,
+    private injector: Injector,
   ){
     this.subs.push(
       store.pipe(
@@ -81,18 +82,19 @@ export class SingleAnnotationUnit implements OnDestroy, AfterViewInit{
     if (this.managedAnnotation && this.editAnnotationVCR) {
       const editCmp = this.svc.getEditAnnotationCmp(this.managedAnnotation)
       if (!editCmp) {
-        this.snackbar.open(`Update component not found!`)
+        this.snackbar.open(`Update component not found!`, 'Dismiss', {
+          duration: 3000
+        })
         throw new Error(`Edit component not found!`)
       }
       const cf = this.cfr.resolveComponentFactory(editCmp)
+      
       const injector = Injector.create({
         providers: [{
           provide: UDPATE_ANNOTATION_TOKEN,
           useValue: this.managedAnnotation
-        }, {
-          provide: EXPORT_FORMAT_INJ_TOKEN,
-          useValue: this.useFormat$
-        }]
+        }],
+        parent: this.injector
       })
       this.editAnnotationVCR.createComponent(cf, null, injector)
     }
@@ -114,6 +116,7 @@ export class SingleAnnotationNamePipe implements PipeTransform{
     if (name) return name
     if (ann instanceof Polygon) return `Unnamed Polygon`
     if (ann instanceof Point) return `Unname Point`
+    if (ann instanceof Line) return `Unnamed Line`
     return `Unnamed geometry`
   }
 }
@@ -127,6 +130,7 @@ export class SingleAnnotationClsIconPipe implements PipeTransform{
   public transform(ann: IAnnotationGeometry): string{
     if (ann instanceof Polygon) return `fas fa-draw-polygon`
     if (ann instanceof Point) return `fas fa-circle`
+    if (ann instanceof Line) return `fas fa-slash`
     return `fas fa-mouse-pointer`
   }
 }
\ No newline at end of file
diff --git a/src/atlasComponents/userAnnotations/tools/line.ts b/src/atlasComponents/userAnnotations/tools/line.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e74cbf1b6054b7bbee6bd5492e6d9e0b71ed8ae9
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/tools/line.ts
@@ -0,0 +1,282 @@
+import {
+  IAnnotationTools,
+  IAnnotationGeometry,
+  TAnnotationEvent,
+  IAnnotationEvents,
+  AbsToolClass,
+  INgAnnotationTypes,
+  TToolType,
+  TSandsLine,
+  getCoord,
+  TBaseAnnotationGeomtrySpec,
+  TCallbackFunction,
+} from "./type";
+import { Point, TPointJsonSpec } from './point'
+import { OnDestroy } from "@angular/core";
+import { merge, Observable, Subject, Subscription } from "rxjs";
+import { filter, switchMapTo, takeUntil } from "rxjs/operators";
+import { getUuid } from "src/util/fn";
+
+type TLineJsonSpec = {
+  '@type': 'siibra-ex/annotation/line'
+  points: TPointJsonSpec[]
+} & TBaseAnnotationGeomtrySpec
+
+export class Line extends IAnnotationGeometry{
+  public id: string
+
+  public points: Point[] = []
+
+  public hasPoint(p: Point) {
+    return this.points.indexOf(p) >= 0
+  }
+
+  public addLinePoints(p: Point | {x: number, y: number, z: number}): Point {
+    if (this.checkComplete()) {
+      throw new Error(`This line is already complete!`)
+    }
+    const point = p instanceof Point
+      ? p
+      : new Point({
+        id: `${this.id}_${getUuid()}`,
+        "@type": 'siibra-ex/annotatoin/point',
+        space: this.space,
+        ...p
+      })
+    if (!this.points[0]) this.points[0] = point
+    else this.points[1] = point
+    this.sendUpdateSignal()
+    return point
+  }
+
+  getNgAnnotationIds() {
+    return [this.id]
+  }
+
+  private checkComplete(){
+    return this.points.length >= 2
+  }
+
+  toString(): string {
+    if (!this.checkComplete()) {
+      return `Line incomplete.`
+    } 
+    
+    return `Line from ${this.points[0].toString()} to ${this.points[1].toString()}`
+  }
+
+  toSands(): TSandsLine {
+    if (!this.checkComplete()) {
+      return null
+    }
+    const {
+      x: x0, y: y0, z: z0
+    } = this.points[0]
+
+    const {
+      x: x1, y: y1, z: z1
+    } = this.points[1]
+
+    return {
+      '@id': this.id,
+      '@type': "tmp/line",
+      coordinateSpace: {
+        '@id': this.space["@id"]
+      },
+      coordinatesFrom: [getCoord(x0/1e6), getCoord(y0/1e6), getCoord(z0/1e6)],
+      coordinatesTo: [getCoord(x1/1e6), getCoord(y1/1e6), getCoord(z1/1e6)],
+    }
+  }
+
+  toNgAnnotation(): INgAnnotationTypes['line'][] {
+    if (!this.checkComplete()) return []
+    const pt1 = this.points[0]
+    const pt2 = this.points[1]
+    return [{
+      id: this.id,
+      pointA: [pt1.x, pt1.y, pt1.z],
+      pointB: [pt2.x, pt2.y, pt2.z],
+      type: 'line',
+      description: ''
+    }]
+
+  }
+
+  toJSON(){
+    const { id, points } = this
+    return { id, points }
+  }
+
+  static fromJSON(json: TLineJsonSpec){
+    return new Line(json)
+  }
+
+  constructor(spec?: TLineJsonSpec){
+    super(spec)
+    const { points = [] } = spec || {}
+    this.points = points.map(Point.fromJSON)
+  }
+
+  public translate(x: number, y: number, z: number) {
+    for (const p of this.points){
+      p.translate(x, y, z)
+    }
+    this.sendUpdateSignal()
+  }
+
+  private sendUpdateSignal(){
+    this.updateSignal$.next(this.toString())
+  }
+}
+
+export const LINE_ICON_CLASS = 'fas fa-slash'
+
+export class ToolLine extends AbsToolClass implements IAnnotationTools, OnDestroy {
+  static PREVIEW_ID='tool_line_preview'
+  public name = 'Line'
+  public toolType: TToolType = 'drawing'
+  public iconClass = LINE_ICON_CLASS
+
+  private selectedLine: Line
+  
+  subs: Subscription[] = []
+
+  private forceRefreshAnnotations$ = new Subject()
+  private managedAnnotations: Line[] = []
+  public managedAnnotations$ = new Subject<Line[]>()
+  public allNgAnnotations$ = new Subject<INgAnnotationTypes[keyof INgAnnotationTypes][]>()
+
+
+  onMouseMoveRenderPreview(pos: [number, number, number]) {
+    if (this.selectedLine && !!this.selectedLine.points[0]) {
+      const { x, y, z } = this.selectedLine.points[0]
+      return [{
+        id: `${ToolLine.PREVIEW_ID}_0`,
+        pointA: [ x, y, z ],
+        pointB: pos,
+        type: 'line',
+        description: ''
+      }] as INgAnnotationTypes['line'][]
+    }
+    return [{
+      id: `${ToolLine.PREVIEW_ID}_0`,
+      point: pos,
+      type: 'point',
+      description: ''
+    }] as INgAnnotationTypes['point'][]
+  }
+
+
+  constructor(
+    annotationEv$: Observable<TAnnotationEvent<keyof IAnnotationEvents>>,
+    callback?: TCallbackFunction
+  ){
+    super(annotationEv$, callback)
+
+    this.init()
+    
+    const toolDeselect$ = this.toolSelected$.pipe(
+      filter(flag => !flag)
+    )
+    const toolSelThenClick$ = this.toolSelected$.pipe(
+      filter(flag => !!flag),
+      switchMapTo(this.mouseClick$.pipe(
+        takeUntil(toolDeselect$)
+      ))
+    )
+
+    this.subs.push(
+      /**
+       * on end tool select
+       */
+      toolDeselect$.subscribe(() => {
+        this.selectedLine = null
+      }),
+      /**
+       * on tool selected
+       * on mouse down
+       * until tool deselected
+       */
+      toolSelThenClick$.pipe(
+      ).subscribe(mouseev => {
+        const crd = mouseev.detail.ngMouseEvent
+        if (!this.selectedLine) {
+          this.selectedLine = new Line({
+            space: this.space,
+            "@type": 'siibra-ex/annotation/line',
+            points: []
+          })
+          this.selectedLine.addLinePoints(crd)
+          this.managedAnnotations.push(this.selectedLine)
+          this.managedAnnotations$.next(this.managedAnnotations)
+        } else {
+
+          // ToDo Tool Should Be Deselected.
+          this.selectedLine.addLinePoints(crd)
+          this.selectedLine = null
+
+          if (this.callback) {
+            this.callback({ type: 'paintingEnd' })
+          }
+        }
+      }),
+
+      /**
+       * conditions by which ng annotations are refreshed
+       */
+      merge(
+        toolDeselect$,
+        toolSelThenClick$,
+        this.forceRefreshAnnotations$,
+      ).pipe(
+
+      ).subscribe(() => {
+        let out: INgAnnotationTypes['line'][] = []
+        for (const managedAnn of this.managedAnnotations) {
+          out = out.concat(...managedAnn.toNgAnnotation())
+        }
+
+        this.allNgAnnotations$.next(out)
+      }),
+
+      /**
+       * emit on init, and reset on mouseup$
+       * otherwise, pairwise confuses last drag event and first drag event
+       */
+      this.dragHoveredAnnotationsDelta$.subscribe(val => {
+        
+        const { ann, deltaX, deltaY, deltaZ } = val
+        const { pickedAnnotationId, pickedOffset } = ann.detail
+
+        const annotation = this.managedAnnotations.find(an => an.id === pickedAnnotationId)
+        if (!annotation) {
+          return null
+        }
+        
+        if (pickedOffset === 2) {
+          annotation.points[1].translate(deltaX, deltaY, deltaZ)
+        } else if (pickedOffset === 1) {
+          annotation.points[0].translate(deltaX, deltaY, deltaZ)
+        } else {
+          annotation.translate(deltaX, deltaY, deltaZ)
+        }
+        this.forceRefreshAnnotations$.next(null)
+      })
+    )
+  }
+
+  ngOnDestroy(){
+    this.subs.forEach(s => s.unsubscribe())
+  }
+
+  removeAnnotation(id: string){
+    const idx = this.managedAnnotations.findIndex(ann => ann.id === id)
+    if (idx < 0) {
+      return
+    }
+    this.managedAnnotations.splice(idx, 1)
+    this.managedAnnotations$.next(this.managedAnnotations)
+    this.forceRefreshAnnotations$.next(null)
+  }
+
+}
diff --git a/src/atlasComponents/userAnnotations/tools/line/line.component.ts b/src/atlasComponents/userAnnotations/tools/line/line.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e99984bbb5bd5d22b19022c60b76aaa22d939d87
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/tools/line/line.component.ts
@@ -0,0 +1,115 @@
+import { Component, ElementRef, Inject, Input, OnDestroy, Optional, ViewChild } from "@angular/core";
+import { MatSnackBar } from "@angular/material/snack-bar";
+import { Store } from "@ngrx/store";
+import { Subscription } from "rxjs";
+import { Line, LINE_ICON_CLASS } from "../line";
+import { ToolCmpBase } from "../toolCmp.base";
+import { IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
+import { Clipboard } from "@angular/cdk/clipboard";
+import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
+import { Point } from "../point";
+import { ARIA_LABELS } from 'common/constants'
+import { ComponentStore } from "src/viewerModule/componentStore";
+
+@Component({
+  selector: 'line-update-cmp',
+  templateUrl: './line.template.html',
+  styleUrls: [
+    './line.style.css'
+  ]
+})
+
+export class LineUpdateCmp extends ToolCmpBase implements OnDestroy{
+  @Input('update-annotation')
+  public updateAnnotation: Line
+
+  public ARIA_LABELS = ARIA_LABELS
+
+  public annotationLabel = 'Line'
+  public LINE_ICON_CLASS = LINE_ICON_CLASS
+
+  @ViewChild('copyTarget', { read: ElementRef, static: false })
+  copyTarget: ElementRef
+
+  public useFormat: TExportFormats = 'json'
+  private sub: Subscription[] = []
+
+  constructor(
+    private store: Store<any>,
+    snackbar: MatSnackBar,
+    clipboard: Clipboard,
+    private cStore: ComponentStore<{ useFormat: TExportFormats }>,
+    @Optional() @Inject(UDPATE_ANNOTATION_TOKEN) updateAnnotation: IAnnotationGeometry,
+  ){
+    super(clipboard, snackbar)
+    if (this.cStore) {
+      this.sub.push(
+        this.cStore.select(store => store.useFormat).subscribe((val: TExportFormats) => {
+          this.useFormat = val
+        })
+      )
+    }
+
+    if (updateAnnotation) {
+      if (updateAnnotation instanceof Line) {
+        this.updateAnnotation = updateAnnotation
+      }
+    }
+  }
+
+  public viableFormats: TExportFormats[] = ['json', 'sands']
+
+  setFormat(format: TExportFormats){
+    if (this.cStore) {
+      this.cStore.setState({
+        useFormat: format
+      })
+    }
+  }
+
+  ngOnDestroy(){
+    while (this.sub.length > 0) this.sub.pop().unsubscribe()
+  }
+
+  get copyValue(){
+    return this.copyTarget && this.copyTarget.nativeElement.value
+  }
+
+  gotoRoi(roi?: IAnnotationGeometry){
+    if (!this.updateAnnotation && !roi) {
+      throw new Error(`updateAnnotation undefined`)
+    }
+    if (this.updateAnnotation.points.length < 1) {
+      this.snackbar.open('No points added to polygon yet.', 'Dismiss', {
+        duration: 3000
+      })
+      return
+    }
+    const { x, y, z } = this.updateAnnotation.points[0]
+    
+    this.store.dispatch(
+      viewerStateChangeNavigation({
+        navigation: {
+          position: [x, y, z],
+          positionReal: true,
+          animation: {}
+        }
+      })
+    )
+  }
+
+  gotoPoint(point: Point){
+    if (!point) throw new Error(`Point is not defined.`)
+    const { x, y, z } = point
+
+    this.store.dispatch(
+      viewerStateChangeNavigation({
+        navigation: {
+          position: [x, y, z],
+          positionReal: true,
+          animation: {}
+        }
+      })
+    )
+  }
+}
diff --git a/src/atlasComponents/userAnnotations/tools/line/line.style.css b/src/atlasComponents/userAnnotations/tools/line/line.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/atlasComponents/userAnnotations/tools/line/line.template.html b/src/atlasComponents/userAnnotations/tools/line/line.template.html
new file mode 100644
index 0000000000000000000000000000000000000000..d65b06ef8c1a6e4c3ed767fcc055fed689b3813f
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/tools/line/line.template.html
@@ -0,0 +1,62 @@
+<!-- actions -->
+
+<span class="m-2 text-muted">
+  Endpoints
+</span>
+
+<mat-chip-list>
+  <mat-chip *ngFor="let point of (updateAnnotation?.points || []) ; let i = index"
+    (click)="gotoPoint(point)">
+    {{ i }}
+  </mat-chip>
+</mat-chip-list>
+
+<mat-divider class="m-2"></mat-divider>
+
+<div class="d-flex">
+
+  <!-- export -->
+  <button mat-icon-button
+    [attr.aria-label]="ARIA_LABELS.USER_ANNOTATION_EXPORT_SINGLE"
+    [matTooltip]="ARIA_LABELS.USER_ANNOTATION_EXPORT_SINGLE"
+    [matMenuTriggerFor]="exportMenu">
+    <i class="fas fa-file-export"></i>
+  </button>
+</div>
+
+<mat-menu #exportMenu="matMenu" xPosition="before">
+  <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>
+          {{ useFormat }}
+        </mat-label>
+        <textarea
+          disabled="true"
+          matInput
+          #exportTarget>{{ updateAnnotation.updateSignal$ | async | toFormattedStringPipe : updateAnnotation : useFormat }}</textarea>
+
+        <button mat-icon-button
+          matSuffix
+          iav-stop="click"
+          aria-label="Copy to clipboard"
+          matTooltip="Copy to clipboard."
+          (click)="copyToClipboard(exportTarget.value)"
+          color="basic">
+          <i class="fas fa-copy"></i>
+        </button>
+      </mat-form-field>
+    </div>
+  </div>
+</mat-menu>
diff --git a/src/atlasComponents/userAnnotations/tools/module.ts b/src/atlasComponents/userAnnotations/tools/module.ts
index d68658dbe2de34be90eae56127baa6dec4f21ed8..3576af312ea3851571ebc27f1ddac12947497252 100644
--- a/src/atlasComponents/userAnnotations/tools/module.ts
+++ b/src/atlasComponents/userAnnotations/tools/module.ts
@@ -3,6 +3,7 @@ import { NgModule } from "@angular/core";
 import { Subject } from "rxjs";
 import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
 import { UtilModule } from "src/util";
+import { LineUpdateCmp } from "./line/line.component";
 import { PointUpdateCmp } from "./point/point.component";
 import { PolyUpdateCmp } from "./poly/poly.component";
 import { ModularUserAnnotationToolService } from "./service";
@@ -16,11 +17,13 @@ import { ANNOTATION_EVENT_INJ_TOKEN } from "./type";
     UtilModule,
   ],
   declarations: [
+    LineUpdateCmp,
     PolyUpdateCmp,
     PointUpdateCmp,
     ToFormattedStringPipe,
   ],
   exports: [
+    LineUpdateCmp,
     PolyUpdateCmp,
     PointUpdateCmp,
   ],
diff --git a/src/atlasComponents/userAnnotations/tools/point.ts b/src/atlasComponents/userAnnotations/tools/point.ts
index 23649b38e1be13f4d4fc0d0cfcbb6fcf3a804322..713c3c6cc4c6c315eb0ed478b4e33f04c37f5e18 100644
--- a/src/atlasComponents/userAnnotations/tools/point.ts
+++ b/src/atlasComponents/userAnnotations/tools/point.ts
@@ -79,10 +79,8 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
   public name = 'Point'
   public toolType: TToolType = 'drawing'
   public iconClass = POINT_ICON_CLASS
-
-  private space: TBaseAnnotationGeomtrySpec['space']
   
-  private subs: Subscription[] = []
+  public subs: Subscription[] = []
   private managedAnnotations: Point[] = []
   public managedAnnotations$ = new Subject<Point[]>()
   public allNgAnnotations$ = new Subject<INgAnnotationTypes[keyof INgAnnotationTypes][]>()
@@ -92,7 +90,7 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
     annotationEv$: Observable<TAnnotationEvent<keyof IAnnotationEvents>>
   ){
     super(annotationEv$)
-
+    this.init()
     const toolDeselect$ = this.toolSelected$.pipe(
       filter(flag => !flag)
     )
@@ -105,12 +103,6 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
     )
 
     this.subs.push(
-      /**
-       * subscribe to space event space info
-       */
-      this.metadataEv$.subscribe(ev => {
-        this.space = ev.detail.space
-      }),
       /**
        * listen to click ev, add point when it occurrs
        */
@@ -157,8 +149,15 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
     )
   }
 
+  /**
+   * @description remove managed annotation via id
+   * @param id id of annotation
+   */
   removeAnnotation(id: string) {
+    const idx = this.managedAnnotations.findIndex(ann => id === ann.id)
 
+    this.managedAnnotations.splice(idx, 1)
+    this.managedAnnotations$.next(this.managedAnnotations)
   }
 
   onMouseMoveRenderPreview(pos: [number, number, number]) {
@@ -170,10 +169,6 @@ export class ToolPoint extends AbsToolClass implements IAnnotationTools, OnDestr
     }] as INgAnnotationTypes['point'][]
   }
 
-  ngAnnotationIsRelevant(annotation: TNgAnnotationEv){
-    return this.managedAnnotations.some(p => p.id === annotation.pickedAnnotationId)
-  }
-
   ngOnDestroy(){
     while (this.subs.length > 0) this.subs.pop().unsubscribe()
   }
diff --git a/src/atlasComponents/userAnnotations/tools/point/point.component.ts b/src/atlasComponents/userAnnotations/tools/point/point.component.ts
index 869a2c497bdfe169cf0f39589df4abea04fb546b..9e08437b5b803a17486bf84d6fc0ee0a80598cf3 100644
--- a/src/atlasComponents/userAnnotations/tools/point/point.component.ts
+++ b/src/atlasComponents/userAnnotations/tools/point/point.component.ts
@@ -1,12 +1,12 @@
 import { Component, ElementRef, Inject, Input, OnDestroy, Optional, ViewChild } from "@angular/core";
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { Point, POINT_ICON_CLASS } from "../point";
-import { EXPORT_FORMAT_INJ_TOKEN, IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
+import { IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
 import { Clipboard } from "@angular/cdk/clipboard";
 import { ToolCmpBase } from "../toolCmp.base";
 import { Store } from "@ngrx/store";
 import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
-import { Observable, Subscription } from "rxjs";
+import { Subscription } from "rxjs";
 
 @Component({
   selector: 'point-update-cmp',
@@ -39,18 +39,10 @@ export class PointUpdateCmp extends ToolCmpBase implements OnDestroy{
     private store: Store<any>,
     snackbar: MatSnackBar,
     clipboard: Clipboard,
-    @Optional() @Inject(EXPORT_FORMAT_INJ_TOKEN) useFormat$: Observable<TExportFormats>,
     @Optional() @Inject(UDPATE_ANNOTATION_TOKEN) updateAnnotation: IAnnotationGeometry,
   ){
     super(clipboard, snackbar)
     
-    if (useFormat$) {
-      this.sub.push(
-        useFormat$.subscribe(val => {
-          this.useFormat = val
-        })
-      )
-    }
     if (updateAnnotation) {
       if (updateAnnotation instanceof Point) {
         this.updateAnnotation = updateAnnotation
diff --git a/src/atlasComponents/userAnnotations/tools/point/point.template.html b/src/atlasComponents/userAnnotations/tools/point/point.template.html
index 2fd1334d2f77af8dc16ed69754528891f4ed157b..c5fdf78056fa36c8011f50ce97e2c14d27715951 100644
--- a/src/atlasComponents/userAnnotations/tools/point/point.template.html
+++ b/src/atlasComponents/userAnnotations/tools/point/point.template.html
@@ -6,7 +6,7 @@
     <i [class]="POINT_ICON_CLASS"></i>
   </button>
 
-  <form class="flex-grow-1 flex-shrink-1">
+  <div class="flex-grow-1 flex-shrink-1">
     <mat-form-field class="w-100">
       <mat-label>
         {{ annotationLabel }}
@@ -28,5 +28,5 @@
         <i class="fas fa-copy"></i>
       </button>
     </mat-form-field>
-  </form>
+  </div>
 </div>
diff --git a/src/atlasComponents/userAnnotations/tools/poly.ts b/src/atlasComponents/userAnnotations/tools/poly.ts
index bbf19d6cdfed0ded3bdfe94fd7cc636ea814a8b1..42780797a569d548d7f6f73d466a88328f068118 100644
--- a/src/atlasComponents/userAnnotations/tools/poly.ts
+++ b/src/atlasComponents/userAnnotations/tools/poly.ts
@@ -47,11 +47,11 @@ export class Polygon extends IAnnotationGeometry{
     const pointToBeAdded = p instanceof Point
       ? p
       : new Point({
-          id: `${this.id}_${getUuid()}`,
-          space: this.space,
-          '@type': 'siibra-ex/annotatoin/point',
-          ...p
-        })
+        id: `${this.id}_${getUuid()}`,
+        space: this.space,
+        '@type': 'siibra-ex/annotatoin/point',
+        ...p
+      })
     
     if (!this.hasPoint(pointToBeAdded)) {
       this.points.push(pointToBeAdded)
@@ -189,15 +189,13 @@ export class ToolPolygon extends AbsToolClass implements IAnnotationTools, OnDes
   public iconClass = POLY_ICON_CLASS
   public toolType: TToolType = 'drawing'
 
-  private space: TBaseAnnotationGeomtrySpec['space']
-
   private selectedPoly: Polygon
   private lastAddedPoint: Point
 
   private managedAnnotations: Polygon[] = []
   public managedAnnotations$ = new Subject<Polygon[]>()
 
-  private subs: Subscription[] = []
+  public subs: Subscription[] = []
   private forceRefreshAnnotations$ = new Subject()
   public allNgAnnotations$ = new Subject<INgAnnotationTypes[keyof INgAnnotationTypes][]>()
 
@@ -224,7 +222,7 @@ export class ToolPolygon extends AbsToolClass implements IAnnotationTools, OnDes
     annotationEv$: Observable<TAnnotationEvent<keyof IAnnotationEvents>>
   ){
     super(annotationEv$)
-
+    this.init()
     const toolDeselect$ = this.toolSelected$.pipe(
       filter(flag => !flag)
     )
@@ -342,11 +340,6 @@ export class ToolPolygon extends AbsToolClass implements IAnnotationTools, OnDes
     this.forceRefreshAnnotations$.next(null)
   }
 
-  ngAnnotationIsRelevant(annotation: TNgAnnotationEv): boolean {
-    // perhaps use more advanced way to track if annotation is a part of polygon?
-    return this.managedAnnotations.some(poly => poly.id.indexOf(annotation.pickedAnnotationId) >= 0)
-  }
-
   ngOnDestroy(){
     if (this.subs.length > 0) this.subs.pop().unsubscribe()
   }
diff --git a/src/atlasComponents/userAnnotations/tools/poly/poly.component.ts b/src/atlasComponents/userAnnotations/tools/poly/poly.component.ts
index e6c7347301d8dbf82c4ade5f00f38374655e3c39..3621c2d25717a64aa8b3cb85aaafd491dc5bb43b 100644
--- a/src/atlasComponents/userAnnotations/tools/poly/poly.component.ts
+++ b/src/atlasComponents/userAnnotations/tools/poly/poly.component.ts
@@ -2,11 +2,11 @@ import { Component, ElementRef, Inject, Input, OnDestroy, Optional, ViewChild }
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { Polygon, POLY_ICON_CLASS } from "../poly";
 import { ToolCmpBase } from "../toolCmp.base";
-import { EXPORT_FORMAT_INJ_TOKEN, IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
+import { IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
 import { Clipboard } from "@angular/cdk/clipboard";
 import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
 import { Store } from "@ngrx/store";
-import { Observable, Subscription } from "rxjs";
+import { Subscription } from "rxjs";
 
 @Component({
   selector: 'poly-update-cmp',
@@ -33,17 +33,9 @@ export class PolyUpdateCmp extends ToolCmpBase implements OnDestroy{
     private store: Store<any>,
     snackbar: MatSnackBar,
     clipboard: Clipboard,
-    @Optional() @Inject(EXPORT_FORMAT_INJ_TOKEN) useFormat$: Observable<TExportFormats>,
     @Optional() @Inject(UDPATE_ANNOTATION_TOKEN) updateAnnotation: IAnnotationGeometry,
   ){
     super(clipboard, snackbar)
-    if (useFormat$) {
-      this.sub.push(
-        useFormat$.subscribe(val => {
-          this.useFormat = val
-        })
-      )
-    }
 
     if (updateAnnotation) {
       if (updateAnnotation instanceof Polygon) {
diff --git a/src/atlasComponents/userAnnotations/tools/poly/poly.template.html b/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
index a26ca35b991873e871be7a9663672a64f012f399..52dab491ec667660bf73c783f24d6b97dff5c93c 100644
--- a/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
+++ b/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
@@ -6,7 +6,7 @@
     <i [class]="POLY_ICON_CLASS"></i>
   </button>
 
-  <form class="flex-grow-1 flex-shrink-1">
+  <div class="flex-grow-1 flex-shrink-1">
     <mat-form-field class="w-100">
       <mat-label>
         {{ annotationLabel }}
@@ -26,7 +26,7 @@
         <i class="fas fa-copy"></i>
       </button>
     </mat-form-field>
-  </form>
+  </div>
 </div>
 
 <point-update-cmp
diff --git a/src/atlasComponents/userAnnotations/tools/service.ts b/src/atlasComponents/userAnnotations/tools/service.ts
index b4f302ad8e4a97b6ce7fa75a956690e78ab1a388..a48049574a75e15fadc82f9b01a9126ea3968a3b 100644
--- a/src/atlasComponents/userAnnotations/tools/service.ts
+++ b/src/atlasComponents/userAnnotations/tools/service.ts
@@ -8,11 +8,13 @@ import { viewerStateSelectedTemplatePureSelector, viewerStateViewerModeSelector
 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 } from "./type";
+import { AbsToolClass, ANNOTATION_EVENT_INJ_TOKEN, IAnnotationEvents, IAnnotationGeometry, INgAnnotationTypes, INJ_ANNOT_TARGET, TAnnotationEvent, ClassInterface, TExportFormats, TCallbackFunction } 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";
 
 const IAV_VOXEL_SIZES_NM = {
   'minds/core/referencespace/v1.0.0/265d32a0-3d84-40a5-926f-bf89f68212b9': [25000, 25000, 25000],
@@ -91,14 +93,23 @@ export class ModularUserAnnotationToolService implements OnDestroy{
 
   private registeredTools: {
     name: string
-    iconClass: string,
-    target?: ClassInterface<IAnnotationGeometry>,
-    editCmp?: ClassInterface<any>,
+    iconClass: string
+    target?: ClassInterface<IAnnotationGeometry>
+    editCmp?: ClassInterface<any>
     onMouseMoveRenderPreview: (pos: [number, number, number]) => INgAnnotationTypes[keyof INgAnnotationTypes][]
     onDestoryCallBack: () => void
   }[] = []
   private mousePosReal: [number, number, number]
 
+  private handleToolCallback: TCallbackFunction = arg => {
+    switch (arg.type) {
+    case 'paintingEnd': {
+      this.deselectTools()
+      return
+    }
+    }
+  }
+
   /**
    * @description register new annotation tool
    * Some tools (deletion / dragging) may not have target and editCmp 
@@ -110,12 +121,12 @@ export class ModularUserAnnotationToolService implements OnDestroy{
    * }} arg 
    */
   private registerTool<T extends AbsToolClass>(arg: {
-    toolCls: ClassInterface<T>,
-    target?: ClassInterface<IAnnotationGeometry>,
+    toolCls: ClassInterface<T>
+    target?: ClassInterface<IAnnotationGeometry>
     editCmp?: ClassInterface<any>
   }){
     const { toolCls: Cls, target, editCmp } = arg
-    const newTool = new Cls(this.annotnEvSubj) as AbsToolClass & { ngOnDestroy?: Function }
+    const newTool = new Cls(this.annotnEvSubj, arg => this.handleToolCallback(arg)) as AbsToolClass & { ngOnDestroy?: Function }
     const { name, iconClass, onMouseMoveRenderPreview } = newTool
     
     this.moduleAnnotationTypes.push({
@@ -167,7 +178,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
   }
 
   /**
-   * 
+   *
    * @description deregister tool. Calls any necessary clean up function
    * @param name name of the tool to be deregistered
    * @returns void
@@ -181,8 +192,6 @@ export class ModularUserAnnotationToolService implements OnDestroy{
     }
   }
 
-  public exportFormat$ = new BehaviorSubject<TExportFormats>('string')
-
   constructor(
     store: Store<any>,
     @Inject(INJ_ANNOT_TARGET) annotTarget$: Observable<HTMLElement>,
@@ -196,6 +205,12 @@ export class ModularUserAnnotationToolService implements OnDestroy{
       editCmp: PointUpdateCmp,
     })
 
+    this.registerTool({
+      toolCls: ToolLine,
+      target: Line,
+      editCmp: LineUpdateCmp,
+    })
+
     this.registerTool({
       toolCls: ToolPolygon,
       target: Polygon,
@@ -210,7 +225,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
         switchMap(el => {
           if (!el) return of(null)
           return merge(...(
-            ['mousedown', 'mouseup', 'mousemove'].map(type => 
+            ['mousedown', 'mouseup', 'mousemove'].map(type =>
               fromEvent(el, type, { capture: true }).pipe(
                 map((ev: MouseEvent) => {
                   return {
@@ -290,7 +305,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
         switchMap(v => v?.mousePosInReal$ || of(null))
       ).subscribe(v => this.mousePosReal = v)
     )
-    
+
     /**
      * on mouse move, render preview annotation
      */
@@ -316,7 +331,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
             })
           )
         })
-      ).subscribe((ev: { 
+      ).subscribe((ev: {
         selectedToolName: string
         ngMouseEvent: {x: number, y: number, z: number}
       }) => {
@@ -332,7 +347,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
         }
         const { onMouseMoveRenderPreview } = selectedTool
         const previewNgAnnotation = onMouseMoveRenderPreview([ngMouseEvent.x, ngMouseEvent.y, ngMouseEvent.z])
-  
+
         if (this.previewNgAnnIds.length !== previewNgAnnotation.length) {
           this.clearAllPreviewAnnotations()
         }
@@ -433,7 +448,7 @@ export class ModularUserAnnotationToolService implements OnDestroy{
         } else {
           if (this.ngAnnotationLayer) this.ngAnnotationLayer.setVisible(false)
         }
-      })  
+      })
     )
 
     /**
diff --git a/src/atlasComponents/userAnnotations/tools/type.ts b/src/atlasComponents/userAnnotations/tools/type.ts
index d90d40ea836b1b5ee3593cac2224aa65fe8844fa..06f715bcbbeb6342f73228b49b89f12da0438265 100644
--- a/src/atlasComponents/userAnnotations/tools/type.ts
+++ b/src/atlasComponents/userAnnotations/tools/type.ts
@@ -1,5 +1,5 @@
 import { InjectionToken } from "@angular/core"
-import { merge, Observable, of, Subject } from "rxjs"
+import { merge, Observable, of, Subject, Subscription } from "rxjs"
 import { filter, map, mapTo, pairwise, switchMap, switchMapTo, takeUntil, withLatestFrom } from 'rxjs/operators'
 import { getUuid } from "src/util/fn"
 
@@ -14,12 +14,8 @@ export abstract class AbsToolClass {
   public abstract removeAnnotation(id: string): void
   public abstract managedAnnotations$: Observable<IAnnotationGeometry[]>
 
-  /**
-   * @description to be overwritten by subclass. Check if a given annotation is relevant to the tool. Used for filtering annotations.
-   * @param {TNgAnnotationEv} annotation
-   * @returns {boolean} if annotation is relevant to this tool
-   */
-  public abstract ngAnnotationIsRelevant(hoverEv: TNgAnnotationEv): boolean
+  abstract subs: Subscription[]
+  protected space: TBaseAnnotationGeomtrySpec['space']
 
   /**
    * @description to be overwritten by subclass. Emit the latest representation of NgAnnotations from the tool.
@@ -27,18 +23,27 @@ export abstract class AbsToolClass {
   public abstract allNgAnnotations$: Observable<INgAnnotationTypes[keyof INgAnnotationTypes][]>
 
   /**
-   * @description to be overwritten by subclass. Called once every mousemove event, if the tool is active. 
-   * @param {[number, number, number]} mousepos 
+   * @description to be overwritten by subclass. Called once every mousemove event, if the tool is active.
+   * @param {[number, number, number]} mousepos
    * @returns {INgAnnotationTypes[keyof INgAnnotationTypes][]} Array of NgAnnotation to be rendered.
    */
   public abstract onMouseMoveRenderPreview(mousepos: [number, number, number]): INgAnnotationTypes[keyof INgAnnotationTypes][]
 
   constructor(
-    protected annotationEv$: Observable<TAnnotationEvent<keyof IAnnotationEvents>>
+    protected annotationEv$: Observable<TAnnotationEvent<keyof IAnnotationEvents>>,
+    protected callback?: TCallbackFunction
   ){
 
   }
 
+  init(){
+    this.subs.push(
+      this.metadataEv$.subscribe(ev => {
+        this.space = ev.detail.space
+      })
+    )
+  }
+
   public toolSelected$ = this.annotationEv$.pipe(
     filter(ev => ev.type === 'toolSelect'),
     map(ev => (ev as TAnnotationEvent<'toolSelect'>).detail.name === this.name)
@@ -75,10 +80,10 @@ export abstract class AbsToolClass {
    * on mouseover, then drag annotation
    * use mousedown as obs src, since hoverAnnotation$ is a bit trigger happy
    * check if there is a hit on mousedown trigger
-   * 
+   *
    * if true - stop mousedown propagation, switchmap to mousemove
-   * if false - 
-   * 
+   * if false -
+   *
    */
   protected dragHoveredAnnotation$: Observable<{
     startNgX: number
@@ -120,9 +125,9 @@ export abstract class AbsToolClass {
    * otherwise, pairwise confuses last drag event and first drag event
    */
   protected dragHoveredAnnotationsDelta$: Observable<{
-    ann: TAnnotationEvent<"hoverAnnotation">,
-    deltaX: number,
-    deltaY: number,
+    ann: TAnnotationEvent<"hoverAnnotation">
+    deltaX: number
+    deltaY: number
     deltaZ: number
   }> = merge(
     of(null),
@@ -150,6 +155,15 @@ export abstract class AbsToolClass {
 
 export type TToolType = 'translation' | 'drawing' | 'deletion'
 
+export type TCallback = {
+  paintingEnd: {
+    callArg: {}
+    returns: void
+  }
+}
+
+export type TCallbackFunction = <T extends keyof TCallback>(arg: TCallback[T]['callArg'] & { type: T }) => TCallback[T] | void
+
 export type TBaseAnnotationGeomtrySpec = {
   id?: string
   space?: {
@@ -322,7 +336,3 @@ export interface ClassInterface<T> {
 }
 
 export type TExportFormats = 'sands' | 'json' | 'string'
-
-export const EXPORT_FORMAT_INJ_TOKEN = new InjectionToken<
-  Observable<TExportFormats>
->('EXPORT_FORMAT_INJ_TOKEN')
diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css
index a295e3f09f7c6c710e41a6686dbf6beaf64289c6..e98f09941fcc99b2a721c892167f806adf681137 100644
--- a/src/res/css/extra_styles.css
+++ b/src/res/css/extra_styles.css
@@ -370,6 +370,11 @@ markdown-dom p
   pointer-events: all;
 }
 
+.t-a-ease-200
+{
+  transition: all ease 200ms;
+}
+
 .t-a-ease-500
 {
   transition: all ease 500ms;