Skip to content

Commit

Permalink
Implement Enhanced Background Subtraction Method in Fluorescence Imag…
Browse files Browse the repository at this point in the history
…ing Analysis (#169)

* Update quick_start notebook with additional functionality

The quick_start notebook has been updated with more in-depth functionality, including executing code cells and importing additional libraries. The changes also involve modifying the output, providing visual data clarification, and changing the sample path to retrieve other data. The adjustments aim to enhance the user's analytical experience.

* Add code for delta calculations in astrocast notebook

The changes includes importing necessary modules and adding code chunks for performing delta calculations, implementation of interpolation functions, data downsampling measures and peak removal operations. Added new function for delta calculation: get_subtracted, get_interpolated, and remove_peaks. The code edits are focused on handling and processing 3D datasets.

* feat: Implement enhanced background subtraction in fluorescence imaging

This commit introduces a `_subtract_delta_rbf`, designed to significantly improve background subtraction in time-series fluorescence imaging recordings. The primary objective is to enhance the signal-to-noise ratio and mitigate the effects of photo-bleaching.

Key features of the function include:
- Subdivision of video data into manageable chunks for efficient processing.
- Identification and treatment of significant signal fluctuations (peaks) as missing data (NaN), which are then excluded from background calculations.
- Utilization of the remaining pixels to interpolate the background, subsequently subtracting this from the original dataset to isolate the fluorescence signal from the near-static background.
- Inclusion of operations like Gaussian blurring for noise reduction, scaled downsizing for computational efficiency, and 3D RBF interpolation for smoother data transitions.
- Reassembly of processed chunks into a cohesive array, maintaining the original video dimensions and data type.

* officially replacing _calculate_delta_min_filter with subtract_delta_rbf

- add: testing the new delta subtraction
- fix: switched function call and arguments in Delta.run
- fix: updated documentation

* Integration of new delta functionality into quick_start notebook

* Updated CLI interface to include changes to Delta subtraction

* removed Delta from the GUI. Needs to be updated with new subtraction function before it can be re-enabled

* removed superfluous parameter max_tries

* - fix: default parameter for rbf smoothing needs to be 0 in client as well

* - refactor TestLocalCache

* increase flakyness of subtraction performance testing

* - add check if tensorflow is not available during import of denoising

* moved another tensorflow import into try-except-clause

* - fix: test functions for local caching

* convert todo to GitHub issues

* now adhere to PEP

* rename 'Analysis GUI' to 'Exploratory Analysis GUI'

* - fix: fix random output generator

* reformat

* move keras imports into tensorflow available try-except-clause
  • Loading branch information
janreising authored Dec 13, 2023
1 parent 1ed7e52 commit c79d335
Show file tree
Hide file tree
Showing 16 changed files with 6,833 additions and 5,382 deletions.
1,058 changes: 565 additions & 493 deletions astrocast/analysis.py

Large diffs are not rendered by default.

2,862 changes: 1,550 additions & 1,312 deletions astrocast/app_analysis.py

Large diffs are not rendered by default.

696 changes: 359 additions & 337 deletions astrocast/app_preparation.py

Large diffs are not rendered by default.

996 changes: 525 additions & 471 deletions astrocast/cli_interfaces.py

Large diffs are not rendered by default.

1,372 changes: 703 additions & 669 deletions astrocast/denoising.py

Large diffs are not rendered by default.

686 changes: 344 additions & 342 deletions astrocast/helper.py

Large diffs are not rendered by default.

1,580 changes: 961 additions & 619 deletions astrocast/preparation.py

Large diffs are not rendered by default.

Binary file not shown.
622 changes: 622 additions & 0 deletions notebooks/exploring_delta.ipynb

Large diffs are not rendered by default.

196 changes: 130 additions & 66 deletions notebooks/quick_start.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
"id": "initial_id",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T13:23:02.649268383Z",
"start_time": "2023-11-15T13:23:00.374557839Z"
"end_time": "2023-12-13T01:46:47.302299673Z",
"start_time": "2023-12-13T01:46:46.489652956Z"
}
},
"outputs": [],
"source": [
"import shutil\n",
"import os\n",
"from pathlib import Path\n",
"from astrocast.analysis import IO, Video, Events, Plotting\n",
"\n",
"from astrocast.analysis import IO, Video, Events\n",
"\n",
"from pathlib import Path"
"astroPlot = Plotting(None)"
]
},
{
Expand Down Expand Up @@ -45,13 +45,13 @@
"id": "1332388990b34934",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T13:23:05.045991906Z",
"start_time": "2023-11-15T13:23:02.848390645Z"
"end_time": "2023-12-13T01:40:46.705246932Z",
"start_time": "2023-12-13T01:40:44.377908284Z"
}
},
"outputs": [],
"source": [
"sample_path = Path(\"../testdata/sample_2.h5\")\n",
"sample_path = Path(\"../testdata/bigger_data.h5\")\n",
"assert sample_path.exists()\n",
"\n",
"# we can use the visualize_h5 function from the command line interface (CLI)\n",
Expand All @@ -65,8 +65,8 @@
"id": "530f135c103b42fa",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T13:28:59.870710Z",
"start_time": "2023-11-15T13:28:58.958705846Z"
"end_time": "2023-12-13T01:40:47.555619679Z",
"start_time": "2023-12-13T01:40:46.698974442Z"
}
},
"outputs": [],
Expand Down Expand Up @@ -100,14 +100,13 @@
"id": "d29cde6734185ae9",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:49:27.209811383Z",
"start_time": "2023-11-15T12:49:23.887395678Z"
"end_time": "2023-12-13T01:40:47.559949780Z",
"start_time": "2023-12-13T01:40:47.555929675Z"
}
},
"outputs": [],
"source": [
"from astrocast.preparation import MotionCorrection, Input, Delta\n",
"from astrocast.denoising import SubFrameGenerator\n"
"from astrocast.preparation import MotionCorrection, Input, Delta"
]
},
{
Expand All @@ -126,8 +125,8 @@
"id": "df78f685eac21f86",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T13:23:46.867382844Z",
"start_time": "2023-11-15T13:23:46.800282852Z"
"end_time": "2023-12-13T01:46:56.243495252Z",
"start_time": "2023-12-13T01:46:56.191593542Z"
}
},
"outputs": [],
Expand All @@ -141,8 +140,8 @@
"id": "c1fd2411849c47f8",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:49:38.290035837Z",
"start_time": "2023-11-15T12:49:27.214509032Z"
"end_time": "2023-12-13T01:40:53.014833707Z",
"start_time": "2023-12-13T01:40:47.566361818Z"
}
},
"outputs": [],
Expand All @@ -156,7 +155,10 @@
"assert not test_path.exists()\n",
"\n",
"inp = Input()\n",
"inp.run(input_path=sample_path, output_path=test_path, loc_in=\"data/ch0\", loc_out=\"data/ch0\", compression=\"gzip\", infer_strategy=\"Z\")\n",
"inp.run(input_path=sample_path, output_path=test_path, loc_in=\"data/ch0\", loc_out=\"data\", compression=\"gzip\",\n",
" chunk_strategy=\"Z\")\n",
"\n",
"!astrocast visualize-h5 {test_path.as_posix()}\n",
"\n",
"# alternatively with CLI:\n",
"# !astrocast convert-h5 --output-path {test_path.as_posix()} --h5-loc-in data/ch0 --h5-loc-out data/ch0 --compression gzip --infer-chunks {sample_path.as_posix()}"
Expand All @@ -178,15 +180,15 @@
"id": "963ae00bcfbff3b1",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:03.346591303Z",
"start_time": "2023-11-15T12:49:38.271208670Z"
"end_time": "2023-12-13T01:41:34.337019648Z",
"start_time": "2023-12-13T01:40:53.027503559Z"
}
},
"outputs": [],
"source": [
"MC = MotionCorrection()\n",
"MC.run(input_=test_path, loc=\"data/ch0\")\n",
"MC.save(output=test_path, loc=\"mc/ch0\", infer_strategy=\"Z\", compression=\"gzip\")"
"MC.run(path=test_path, loc=\"data/ch0\")\n",
"MC.save(output=test_path, loc=\"mc/ch0\", chunk_strategy=\"Z\", compression=\"gzip\")"
]
},
{
Expand All @@ -195,8 +197,8 @@
"id": "6e2cbe26589901b0",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:05.838657729Z",
"start_time": "2023-11-15T12:50:03.350712941Z"
"end_time": "2023-12-13T01:41:36.566852402Z",
"start_time": "2023-12-13T01:41:34.338136605Z"
}
},
"outputs": [],
Expand All @@ -210,8 +212,8 @@
"id": "e4ce35cc81668fe2",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:05.844972520Z",
"start_time": "2023-11-15T12:50:05.840285718Z"
"end_time": "2023-12-13T01:41:36.601313254Z",
"start_time": "2023-12-13T01:41:36.574445364Z"
}
},
"outputs": [],
Expand All @@ -229,58 +231,109 @@
"## 1.3 Denoising"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3f51ba37a0e325fe",
"metadata": {
"ExecuteTime": {
"end_time": "2023-12-13T01:41:39.990036691Z",
"start_time": "2023-12-13T01:41:36.592564785Z"
}
},
"outputs": [],
"source": [
"from astrocast.denoising import SubFrameDataset, PyTorchNetwork"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7958c8bd4688fe47",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:05.852536566Z",
"start_time": "2023-11-15T12:50:05.843728331Z"
"end_time": "2023-12-13T01:41:39.994116932Z",
"start_time": "2023-12-13T01:41:39.990334737Z"
}
},
"outputs": [],
"source": [
"# Download pretrained models\n",
"# !astrocast download-models \"./models\"--"
"# Optional: Download pretrained models\n",
"# !astrocast download-models \"./models\"\n",
"# for f in os.listdir(\"./models\"):\n",
"# print(f)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6e40311858f09759",
"id": "c4714c207508281",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:05.859394523Z",
"start_time": "2023-11-15T12:50:05.850467828Z"
"end_time": "2023-12-13T01:43:43.875067711Z",
"start_time": "2023-12-13T01:41:39.997752373Z"
}
},
"outputs": [],
"source": [
"# data_generator = SubFrameGenerator(paths=test_path, input_size=(64, 64), pre_post_frame=5, gap_frames=0, batch_size=64, loc=\"mc/ch0\",\n",
"# overlap=5, padding=\"edge\",normalize=\"global\")\n",
"# \n",
"# denoising_model = Path(\"./models/1p_exvivo_input_size_64_64-pre_post_frame_5-gap_frames_0-train_rotation_1_2_3-architecture_3_64.h5\")\n",
"# assert denoising_model.exists()\n",
"# \n",
"# data_generator.infer(model=denoising_model, output=test_path, out_loc=\"dn/ch0\")"
"# Inference dataset\n",
"input_size = (128, 128)\n",
"loc_in = \"mc/ch0\"\n",
"loc_out = \"inf/ch0\"\n",
"use_cpu = True # switch to False, if cuda is available\n",
"\n",
"infer_dataset = SubFrameDataset(paths=test_path, loc=loc_in, input_size=input_size, allowed_rotation=0, allowed_flip=-1,\n",
" shuffle=False, normalize=\"global\", overlap=10, padding=\"edge\")\n",
"\n",
"# Model parameters\n",
"model_path = \"../denoiser_models/1p_exvivo_input_size_128_128_pre_post_frame_5-gap_frames_0-train_rotation_1_2_3-architecture_3_64_epochs-50.pth\"\n",
"pre_post_frames = 5\n",
"gap_frames = 0\n",
"n_stacks, kernels = (3, 64)\n",
"\n",
"net = PyTorchNetwork(infer_dataset, load_model=model_path, val_dataset=None, batch_size=16, n_stacks=n_stacks,\n",
" kernels=kernels, kernel_size=3, batch_normalize=False,\n",
" use_cpu=use_cpu)\n",
"\n",
"# Denoise data\n",
"net.infer(dataset=infer_dataset, output=test_path, out_loc=loc_out, batch_size=1, dtype=float)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8a3975f809e908a8",
"id": "9ef7a72fa7b0e090",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:05.859744528Z",
"start_time": "2023-11-15T12:50:05.855818082Z"
"end_time": "2023-12-13T01:43:43.876766363Z",
"start_time": "2023-12-13T01:43:43.874772842Z"
}
},
"outputs": [],
"source": [
"# !astrocast visualize-h5 {test_path.as_posix()}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a001a57eddab48ad",
"metadata": {
"ExecuteTime": {
"end_time": "2023-12-13T01:43:47.243894852Z",
"start_time": "2023-12-13T01:43:43.874895648Z"
}
},
"outputs": [],
"source": [
"frame = 100\n",
"pixels = [(167, 153), (199, 306), (214, 109), (337, 72)]\n",
"\n",
"fig, axx = astroPlot.compare_pixels(pixels=pixels, frame=frame,\n",
" data_1=test_path, loc_1=\"mc/ch0\", loc_2=\"inf/ch0\",\n",
" title_1=\"before denoising\", title_2=\"after denoising\")"
]
},
{
"cell_type": "markdown",
"id": "c6652771275a017a",
Expand All @@ -297,15 +350,21 @@
"id": "412edb17d8d727dc",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:41.175675394Z",
"start_time": "2023-11-15T12:50:05.862139165Z"
"end_time": "2023-12-13T01:49:01.439766400Z",
"start_time": "2023-12-13T01:47:15.902855457Z"
}
},
"outputs": [],
"source": [
"delta = Delta(test_path, loc=\"mc/ch0\")\n",
"delta.run(window=10, method=\"dF\")\n",
"delta.save(output_path=test_path, loc=\"df/ch0\", infer_strategy=\"balanced\", compression=\"gzip\")\n",
"import astrocast.preparation as prep\n",
"import importlib\n",
"\n",
"importlib.reload(prep)\n",
"\n",
"delta = prep.Delta(test_path, loc=\"inf/ch0\")\n",
"res_delta = delta.run(method=\"dF\", scale_factor=0.25, neighbors=100, wlen=50, distance=5,\n",
" max_chunk_size_mb=10, width=5)\n",
"delta.save(output_path=test_path, loc=\"df/ch0\", chunk_strategy=\"balanced\", compression=\"gzip\")\n",
"\n",
"# TODO add terminal command"
]
Expand All @@ -316,13 +375,13 @@
"id": "2b1f6630279f1fae",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:43.678537712Z",
"start_time": "2023-11-15T12:50:41.170915936Z"
"end_time": "2023-12-13T01:45:25.051079053Z",
"start_time": "2023-12-13T01:45:25.043322800Z"
}
},
"outputs": [],
"source": [
"!astrocast visualize-h5 {test_path.as_posix()}"
"# !astrocast visualize-h5 {test_path.as_posix()}"
]
},
{
Expand All @@ -331,13 +390,18 @@
"id": "4ee9f2f2330388f2",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T12:50:43.684872030Z",
"start_time": "2023-11-15T12:50:43.680606803Z"
"end_time": "2023-12-13T01:49:11.858719123Z",
"start_time": "2023-12-13T01:49:09.002787740Z"
}
},
"outputs": [],
"source": [
"# TODO visualize results"
"frame = 100\n",
"pixels = [(167, 153), (199, 306), (214, 109), (337, 72)]\n",
"\n",
"fig, axx = astroPlot.compare_pixels(pixels=pixels, frame=frame,\n",
" data_1=test_path, loc_1=\"inf/ch0\", loc_2=\"df/ch0\",\n",
" title_1=\"before subtraction\", title_2=\"after subtraction\")"
]
},
{
Expand All @@ -356,8 +420,8 @@
"id": "8f41c647cdca684e",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T13:23:19.067051711Z",
"start_time": "2023-11-15T13:23:19.058555477Z"
"end_time": "2023-12-13T01:49:26.794352561Z",
"start_time": "2023-12-13T01:49:26.725874694Z"
}
},
"outputs": [],
Expand All @@ -372,8 +436,8 @@
"id": "c7161fbc46920ef",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T13:25:36.386913586Z",
"start_time": "2023-11-15T13:23:53.540520527Z"
"end_time": "2023-12-13T01:50:48.088514635Z",
"start_time": "2023-12-13T01:49:28.543331996Z"
}
},
"outputs": [],
Expand All @@ -392,14 +456,15 @@
"id": "d9122fa8153591c9",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T13:25:36.645356453Z",
"start_time": "2023-11-15T13:25:36.386641275Z"
"end_time": "2023-12-13T01:50:48.252272039Z",
"start_time": "2023-12-13T01:50:48.090799508Z"
}
},
"outputs": [],
"source": [
"assert event_path.exists()\n",
"!ls -lthv {event_path.as_posix()}\n",
"for f in os.listdir(event_path):\n",
" print(f)\n",
"\n",
"events = Events(event_path)\n",
"events"
Expand All @@ -411,13 +476,12 @@
"id": "c8840eb4703e630c",
"metadata": {
"ExecuteTime": {
"end_time": "2023-11-15T13:27:40.344269093Z",
"start_time": "2023-11-15T13:25:36.647233721Z"
"start_time": "2023-12-13T01:45:25.060165539Z"
}
},
"outputs": [],
"source": [
"#!astrocast view-detection-results --video-path {test_path.as_posix()} --h5-loc df/ch0 {event_path.as_posix()}"
"#!astrocast view-detection-results --video-path {test_path.as_posix()} --loc df/ch0 {event_path.as_posix()}"
]
}
],
Expand Down
Loading

0 comments on commit c79d335

Please sign in to comment.