diff --git a/src/atlasComponents/sapiViews/features/receptors/autoradiography/autoradiography.component.ts b/src/atlasComponents/sapiViews/features/receptors/autoradiography/autoradiography.component.ts
index 95d301d3e4addf1bdd3406be35167d0b5b47d017..ecd059f0a8fd1411e9a5c7b211c7aac78cff91ae 100644
--- a/src/atlasComponents/sapiViews/features/receptors/autoradiography/autoradiography.component.ts
+++ b/src/atlasComponents/sapiViews/features/receptors/autoradiography/autoradiography.component.ts
@@ -53,6 +53,7 @@ export class Autoradiography extends BaseReceptor implements OnChanges, AfterVie
   }
 
   rerender(){
+    this.dataBlobAvailable = false
     if (!this.el || !this.renderBuffer) {
       this.pleaseRender = true
       return
@@ -71,6 +72,11 @@ export class Autoradiography extends BaseReceptor implements OnChanges, AfterVie
     const imgData = ctx.createImageData(this.width, this.height)
     imgData.data.set(this.renderBuffer)
     ctx.putImageData(imgData, 0, 0)
+
+    canvas.toBlob(blob => {
+      this.dataBlobAvailable = true
+      this.dataBlob$.next(blob)
+    })
     this.pleaseRender = false
   }
 }
diff --git a/src/atlasComponents/sapiViews/features/receptors/base.ts b/src/atlasComponents/sapiViews/features/receptors/base.ts
index cbcd75fc2460c847e907d4c312eb0eb9ea19b081..2428c72f6e315c97f98a5914c867d7c6c7560af8 100644
--- a/src/atlasComponents/sapiViews/features/receptors/base.ts
+++ b/src/atlasComponents/sapiViews/features/receptors/base.ts
@@ -1,4 +1,5 @@
 import { Directive, Input, SimpleChanges } from "@angular/core";
+import { BehaviorSubject } from "rxjs";
 import { SAPI, SapiAtlasModel, SapiParcellationModel, SapiRegionModel, SapiSpaceModel } from "src/atlasComponents/sapi";
 import { SapiRegionalFeatureReceptorModel } from "src/atlasComponents/sapi/type";
 
@@ -83,6 +84,15 @@ export abstract class BaseReceptor{
 
   abstract rerender(): void
 
+  /**
+   * flag to indicate that getDataBlob() can be called.
+   */
+  dataBlobAvailable = false
+  /**
+   * blob object observable, representing the data of the component. This allows the data to be downloaded.
+   */
+  dataBlob$ = new BehaviorSubject<Blob>(null)
+
   constructor(
     protected sapi: SAPI
   ){
diff --git a/src/atlasComponents/sapiViews/features/receptors/entry/entry.component.ts b/src/atlasComponents/sapiViews/features/receptors/entry/entry.component.ts
index 25ee164f8e3f99cd9e2ee4944276224097e8dbc1..3f6a756c1b26a15d26a93c4900347072cd79be27 100644
--- a/src/atlasComponents/sapiViews/features/receptors/entry/entry.component.ts
+++ b/src/atlasComponents/sapiViews/features/receptors/entry/entry.component.ts
@@ -1,6 +1,5 @@
-import { ChangeDetectorRef, Component, Input, OnChanges, SimpleChanges } from "@angular/core";
+import { ChangeDetectorRef, Component, OnChanges, SimpleChanges } from "@angular/core";
 import { SAPI } from "src/atlasComponents/sapi";
-import { SapiRegionalFeatureReceptorModel } from "src/atlasComponents/sapi/type";
 import { BaseReceptor } from "../base";
 
 @Component({
@@ -37,4 +36,8 @@ export class Entry extends BaseReceptor implements OnChanges {
   setSelectedSymbol(select: string){
     this.selectedSymbol = select
   }
+
+  getDataBlob(): Promise<Blob> {
+    throw new Error(`cannot get blob of entry component`)
+  }
 }
diff --git a/src/atlasComponents/sapiViews/features/receptors/entry/entry.template.html b/src/atlasComponents/sapiViews/features/receptors/entry/entry.template.html
index 33636fa42ac00bee0b0e9e29a9caa54d200f8453..e88ce49a8da4549d21f77e950af2c9a1361a4fb1 100644
--- a/src/atlasComponents/sapiViews/features/receptors/entry/entry.template.html
+++ b/src/atlasComponents/sapiViews/features/receptors/entry/entry.template.html
@@ -1,9 +1,17 @@
 <mat-card>
   <spinner-cmp *ngIf="loading"></spinner-cmp>
 
+  <ng-template [ngTemplateOutlet]="downloadBtn"
+    [ngTemplateOutletContext]="{
+      label: 'fingerprint.tsv',
+      filename: 'fingerprint.tsv',
+      receptorCmp: fp
+    }">
+  </ng-template>
   <sxplr-sapiviews-features-receptor-fingerprint
     [sxplr-sapiviews-features-receptor-data]="receptorData"
     (sxplr-sapiviews-features-receptor-fingerprint-receptor-selected)="setSelectedSymbol($event)"
+    #fp="sxplrSapiViewsFeaturesReceptorFP"
   >
   </sxplr-sapiviews-features-receptor-fingerprint>
 
@@ -22,16 +30,51 @@
 
   <ng-template [ngIf]="selectedSymbol">
     
+    <ng-template [ngTemplateOutlet]="downloadBtn"
+      [ngTemplateOutletContext]="{
+        label: 'profile.tsv',
+        filename: 'profile.tsv',
+        receptorCmp: profile
+      }">
+    </ng-template>
     <sxplr-sapiviews-features-receptor-profile
       [sxplr-sapiviews-features-receptor-data]="receptorData"
-      [sxplr-sapiviews-features-receptor-profile-selected-symbol]="selectedSymbol">
+      [sxplr-sapiviews-features-receptor-profile-selected-symbol]="selectedSymbol"
+      #profile="sxplrSapiViewsFeaturesReceptorProfile">
     </sxplr-sapiviews-features-receptor-profile>
 
+
+    <ng-template [ngTemplateOutlet]="downloadBtn"
+      [ngTemplateOutletContext]="{
+        label: 'autoradiograph.png',
+        filename: 'autoradiograph.png',
+        receptorCmp: ar
+      }">
+    </ng-template>
     <sxplr-sapiviews-features-receptor-autoradiograph
       [sxplr-sapiviews-features-receptor-data]="receptorData"
       [sxplr-sapiviews-features-receptor-autoradiograph-selected-symbol]="selectedSymbol"
+      #ar="sxplrSapiViewsFeaturesReceptorAR"
     >
     </sxplr-sapiviews-features-receptor-autoradiograph>
   </ng-template>
 
 </mat-card>
+
+
+<!-- download data button template -->
+<ng-template #downloadBtn
+  let-label="label"
+  let-filename="filename"
+  let-receptorCmp="receptorCmp">
+  <button mat-button
+    *ngIf="receptorCmp.dataBlobAvailable"
+    single-file-output
+    [single-file-output-blob]="receptorCmp.dataBlob$ | async"
+    [single-file-output-filename]="filename">
+    <i class="fas fa-download"></i>
+    <span>
+      {{ label }}
+    </span>
+  </button>
+</ng-template>
diff --git a/src/atlasComponents/sapiViews/features/receptors/fingerprint/fingerprint.component.ts b/src/atlasComponents/sapiViews/features/receptors/fingerprint/fingerprint.component.ts
index 1a9bd2b0142aecbacb4cff82818e5df17faf5471..98c5b0076da0350cd0a30fdc01633ee57b6e3bab 100644
--- a/src/atlasComponents/sapiViews/features/receptors/fingerprint/fingerprint.component.ts
+++ b/src/atlasComponents/sapiViews/features/receptors/fingerprint/fingerprint.component.ts
@@ -45,7 +45,8 @@ function transformRadar(input: SapiRegionalFeatureReceptorModel['data']['fingerp
   templateUrl: './fingerprint.template.html',
   styleUrls: [
     './fingerprint.style.css'
-  ]
+  ],
+  exportAs: "sxplrSapiViewsFeaturesReceptorFP"
 })
 
 export class Fingerprint extends BaseReceptor implements OnChanges, AfterViewInit, OnDestroy{
@@ -105,6 +106,23 @@ export class Fingerprint extends BaseReceptor implements OnChanges, AfterViewIni
     this.dumbRadarCmp.metaBs = this.receptorData.data.receptor_symbols
     this.dumbRadarCmp.radar= transformRadar(this.receptorData.data.fingerprints)
 
-    this.setDumbRadarPlease = false   
+    this.dataBlob$.next(this.getDataBlob())
+    this.dataBlobAvailable = true
+    this.setDumbRadarPlease = false
+  }
+
+  private getDataBlob(): Blob {
+    if (!this.receptorData?.data?.fingerprints) throw new Error(`raw data unavailable. Try again later.`)
+    const fingerprints = this.receptorData.data.fingerprints
+    const output: string[] = []
+    output.push(
+      ["name", "mean", "std"].join("\t")
+    )
+    for (const key in fingerprints) {
+      output.push(
+        [key, fingerprints[key].mean, fingerprints[key].std].join("\t")
+      )
+    }
+    return new Blob([output.join("\n")], { type: 'text/tab-separated-values' })
   }
 }
diff --git a/src/atlasComponents/sapiViews/features/receptors/module.ts b/src/atlasComponents/sapiViews/features/receptors/module.ts
index ca559de014f96f1e54dd38a6313ec1f6bcf3b69c..d5bd04dc6b11f71c1646b4c8b2892c6ddf372f6b 100644
--- a/src/atlasComponents/sapiViews/features/receptors/module.ts
+++ b/src/atlasComponents/sapiViews/features/receptors/module.ts
@@ -5,6 +5,7 @@ import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 import { SpinnerModule } from "src/components/spinner";
 import { AngularMaterialModule } from "src/sharedModules";
 import { APPEND_SCRIPT_TOKEN } from "src/util/constants";
+import { ZipFilesOutputModule } from "src/zipFilesOutput/module";
 import { Autoradiography } from "./autoradiography/autoradiography.component";
 import { Entry } from "./entry/entry.component";
 import { Fingerprint } from "./fingerprint/fingerprint.component"
@@ -17,6 +18,7 @@ import { Profile } from "./profile/profile.component"
     FormsModule,
     BrowserAnimationsModule,
     SpinnerModule,
+    ZipFilesOutputModule,
   ],
   declarations: [
     Autoradiography,
diff --git a/src/atlasComponents/sapiViews/features/receptors/profile/profile.component.ts b/src/atlasComponents/sapiViews/features/receptors/profile/profile.component.ts
index a50b2a5be99f761546ae90d22c9d55285496b44c..864584597568df263ed93be923f757bcd585f125 100644
--- a/src/atlasComponents/sapiViews/features/receptors/profile/profile.component.ts
+++ b/src/atlasComponents/sapiViews/features/receptors/profile/profile.component.ts
@@ -10,7 +10,8 @@ import { BaseReceptor } from "../base";
   templateUrl: './profile.template.html',
   styleUrls: [
     './profile.style.css'
-  ]
+  ],
+  exportAs: "sxplrSapiViewsFeaturesReceptorProfile"
 })
 
 export class Profile extends BaseReceptor implements AfterViewInit, OnChanges{
@@ -46,6 +47,7 @@ export class Profile extends BaseReceptor implements AfterViewInit, OnChanges{
   }
 
   async rerender() {
+    this.dataBlobAvailable = false
     if (!this.dumbLineCmp) {
       this.pleaseRender = true
       return
@@ -67,7 +69,23 @@ export class Profile extends BaseReceptor implements AfterViewInit, OnChanges{
       for (const idx in prof) {
         this.dumbLineData[idx] = prof[idx]
       }
+      this.dataBlob$.next(this.getDataBlob())
+      this.dataBlobAvailable = true
       this.dumbLineCmp.profileBs = this.dumbLineData
     }
   }
+
+  private getDataBlob(): Blob {
+    if (!this.dumbLineData) throw new Error(`data has not been populated. Perhaps wait until render finishes?`)
+    const output: string[] = []
+    output.push(
+      ["cortical depth (%)", "receptor density (fmol/mg)"].join("\t")
+    )
+    for (const key in this.dumbLineData) {
+      output.push(
+        [key, this.dumbLineData[key]].join("\t")
+      )
+    }
+    return new Blob([output.join("\n")], { type: 'text/tab-separated-values' })
+  }
 }
diff --git a/src/zipFilesOutput/downloadSingleFile.directive.ts b/src/zipFilesOutput/downloadSingleFile.directive.ts
index 80d8eef4a2f05a32f068da4d15d9061dd5f45bf3..d23f0dad79766203bba582003d39208a609f5505 100644
--- a/src/zipFilesOutput/downloadSingleFile.directive.ts
+++ b/src/zipFilesOutput/downloadSingleFile.directive.ts
@@ -12,12 +12,18 @@ export class SingleFileOutput {
   @Input('single-file-output')
   singleFile: TZipFileConfig
 
+  @Input('single-file-output-filename')
+  singleFileFileName: string
+
+  @Input('single-file-output-blob')
+  singleFileBlob: Blob
+
   @HostListener('click')
   onClick(): void{
     const anchor = this.doc.createElement('a')
-    const blob = new Blob([this.singleFile.filecontent], { type: 'text/plain' })
+    const blob = this.singleFileBlob || new Blob([this.singleFile.filecontent], { type: 'text/plain' })
     anchor.href = URL.createObjectURL(blob)
-    anchor.download = this.singleFile.filename
+    anchor.download = this.singleFileFileName || this.singleFile.filename
 
     this.doc.body.appendChild(anchor)
     anchor.click()