diff --git a/README.md b/README.md index 4e3a19d..318a52b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,65 @@ -# C-DARTS -A Ca2+ microdomain analysis pipeline for spatio-temporal microscopy imaging of T cells +# DARTS +![overview](/docs/assets/img/Figure_1_dart.png) + +## About +**DARTS** is an integrated tool for the analysis of Ca2+ microdomains in immune cells (Jurkat T cells, primary murine cells, NK). +For detailed information, see the [Documentation](https://ipmi-icns-uke.github.io/DARTS/). + +It combines the following modules: + +- Postprocessing + - channel registration + - background subtraction + - cell detection and tracking + - deconvolution + - bleaching correction + - ratio computation +- Shape Normalization +- Hotspot Detection and Dartboard visualization (based on [2]) + + + +## Installation +We recommend using [anaconda](https://www.anaconda.com/download) to install the necessary packages. + +Download and install anaconda and python and either clone the DARTS code with +`` +git clone https://github.com/IPMI-ICNS-UKE/DARTS.git +`` + +or download the .zip file via the download button. Before continuing, please check the prerequisites on the Installation page in the [Documentation](https://ipmi-icns-uke.github.io/DARTS/General/Installation.html). + +Navigate to the folder containing the `DARTS.yml` file and run + +``` +conda env create -f DARTS.yml +conda activate DARTS +``` + +in the command line. + +For more information regarding the installation, see the [Documentation](https://ipmi-icns-uke.github.io/DARTS/) + + +## Usage +1. Store raw image files in a source directory. All common microscopy image formats can be opened, e.g. ics- or tif-files. +2. Run `python main.py` in the terminal/ shell/ powershell or IDE of your choice. +3. Enter relevant information in the GUI. +4. If necessary, define the bead contacts for each cell of interest in each image file. + +![Main](https://github.com/IPMI-ICNS-UKE/DARTS/assets/127941319/3549d0d5-5f8d-4d47-bf8c-096202c99bb0) +![Bead contacts](https://github.com/IPMI-ICNS-UKE/DARTS/assets/127941319/d145d44f-f154-4125-b15d-3b82a40c788a) + + + +## License +This code runs under the Apache 2.0 license. + +## References and Citing +If DARTS is useful for a project that leads to publication, please acknowledge DARTS by citing it. + +[1] DARTS: an open-source Python pipeline for Ca2+ microdomain analysis in live cell imaging data + +[2] Diercks BP, Werner R, Schetelig D, Wolf IMA, Guse AH. High-Resolution Calcium Imaging Method for Local Calcium Signaling. Methods Mol Biol. 2019;1929:27-39. doi: [https://doi.org/10.1007/978-1-4939-9030-6_3](https://doi.org/10.1007/978-1-4939-9030-6_3) diff --git a/batch_postprocessing.py b/batch_postprocessing.py deleted file mode 100644 index fff157d..0000000 --- a/batch_postprocessing.py +++ /dev/null @@ -1,201 +0,0 @@ -from pathlib import Path - -import matplotlib.pyplot as plt -import tomli -import os -import json -import time -from stardist.models import StarDist2D -import argparse -import skimage.io as io -from general.processing import ImageProcessor -from GUI import TDarts_GUI -from general.logger import Logger -from analysis.Bead_Contact_GUI import BeadContactGUI -from analysis.MeanDartboard import MeanDartboardGenerator -import pandas as pd -import numpy as np - - -logger = Logger() - -#%% - -def list_files(directory, extension): - filenames = [] - for filename in os.listdir(directory): - if filename.endswith(extension): - filenames.append(os.path.splitext(filename)[0]) - return filenames - -#%% -bead_contact_times_KO = pd.read_csv("bead_contact_times_KO.csv") -bead_contact_times_WT = pd.read_csv("bead_contact_times_WT.csv") -ko_data_path = "/Users/lwoelk/ICNScloud/PythonPipeline_Testfiles/HN1L/K2 OKT3" -wt_data_path = "/Users/lwoelk/ICNScloud/PythonPipeline_Testfiles/HN1L/WT OKT3" - - -#%% -parameters = tomli.loads(Path("config.toml").read_text(encoding="utf-8")) - -#parameters["inputoutput"]["start_frame"] = bead_contact_times_KO.loc[0, 'von_min'] -#parameters["inputoutput"]["end_frame"] = bead_contact_times_KO.loc[0, 'end'] -parameters["inputoutput"]["start_frame"] = 0 -parameters["inputoutput"]["end_frame"] = 5000 - -parameters["properties"]["list_of_bead_contacts"] = 0 -#%% - -celltype = "ko" - -if celltype == "ko": - nb_files = len(bead_contact_times_KO) - savepath_ko = "results_batch/HN1L/K2/" - os.makedirs(savepath_ko, exist_ok=True) -elif celltype == "wt": - nb_files = len(bead_contact_times_WT) - savepath_wt = "results_batch/HN1L/WT/" - os.makedirs(savepath_wt, exist_ok=True) -else: - nb_files = 0 - -logger.info("Program started") -for i in range(nb_files): - - start_time = time.time() - if celltype == "ko": - basename = bead_contact_times_KO.loc[i, 'fname'] - filename = ko_data_path + '/' + basename + '.tif' - elif celltype == "wt": - basename = bead_contact_times_WT.loc[i, 'fname'] - filename = wt_data_path + '/' + basename + '.tif' - else: - basename = None - - Processor = ImageProcessor.fromfilename(filename, parameters) - - # channel registration - Processor.channel2 = Processor.registration.channel_registration(Processor.channel1, Processor.channel2, - Processor.parameters["properties"][ - "registration_framebyframe"]) - - # background subtraction - Processor.channel1, Processor.channel2 = Processor.background_subtraction(Processor.channel1, Processor.channel2) - - # segmentation of cells, tracking - Processor.segmentation_result_dict = {} - Processor.segmentation_result_dict = Processor.select_rois() - - nb_rois = len(Processor.segmentation_result_dict) - for n in range(nb_rois): - try: - roi_dict = Processor.segmentation_result_dict[n] - roi_ch1 = roi_dict[0] - roi_ch2 = roi_dict[1] - except Exception as E: - print(E) - continue - - subpath = basename + "/" + "cell" + str(n) + "/" - - if celltype == "ko": - savepath_cell = savepath_ko + subpath - elif celltype == "wt": - savepath_cell = savepath_wt + subpath - os.makedirs(savepath_cell, exist_ok=True) - io.imsave(savepath_cell + "0_channel1_beforedecon.tif", roi_ch1) - io.imsave(savepath_cell + "0_channel2_beforedecon.tif", roi_ch2) - - - # deconvolution - #Processor.deconvolution_result_dict = {} - Processor.segmentation_result_dict = Processor.deconvolve_cell_images(Processor.segmentation_result_dict) - - nb_rois = len(Processor.segmentation_result_dict) - for n in range(nb_rois): - try: - roi_dict = Processor.segmentation_result_dict[n] - roi_ch1 = roi_dict[0] - roi_ch2 = roi_dict[1] - except Exception as E: - print(E) - continue - - subpath = basename + "/" + "cell" + str(n) + "/" - if celltype == "ko": - savepath_cell = savepath_ko + subpath - elif celltype == "wt": - savepath_cell = savepath_wt + subpath - os.makedirs(savepath_cell, exist_ok=True) - io.imsave(savepath_cell + "1_channel1_afterdecon.tif", roi_ch1) - io.imsave(savepath_cell + "1_channel2_afterdecon.tif", roi_ch2) - - # cell images - Processor.create_cell_images(Processor.segmentation_result_dict) - - # bleaching correction - Processor.bleaching_correction() - - for n, cell in enumerate(Processor.cell_list): - subpath = basename + "/" + "cell" + str(n) + "/" - if celltype == "ko": - savepath_cell = savepath_ko + subpath - elif celltype == "wt": - savepath_cell = savepath_wt + subpath - os.makedirs(savepath_cell, exist_ok=True) - io.imsave(savepath_cell + "2_channel1_afterbleaching.tif", cell.channel1.image) - io.imsave(savepath_cell + "2_channel2_afterbleaching.tif", cell.channel2.image) - - # first median filter - Processor.medianfilter("channels") - for n, cell in enumerate(Processor.cell_list): - subpath = basename + "/" + "cell" + str(n) + "/" - if celltype == "ko": - savepath_cell = savepath_ko + subpath - elif celltype == "wt": - savepath_cell = savepath_wt + subpath - os.makedirs(savepath_cell, exist_ok=True) - io.imsave(savepath_cell + "3_channel1_aftermedian1.tif", cell.channel1.image) - io.imsave(savepath_cell + "3_channel2_aftermedian1.tif", cell.channel2.image) - - # generation of ratio images - Processor.generate_ratio_images() - for n, cell in enumerate(Processor.cell_list): - subpath = basename + "/" + "cell" + str(n) + "/" - if celltype == "ko": - savepath_cell = savepath_ko + subpath - elif celltype == "wt": - savepath_cell = savepath_wt + subpath - os.makedirs(savepath_cell, exist_ok=True) - io.imsave(savepath_cell + "4_ratio_beforemedian2.tif", cell.ratio) - - # second median filter - Processor.medianfilter("ratio") - for n, cell in enumerate(Processor.cell_list): - subpath = basename + "/" + "cell" + str(n) + "/" - if celltype == "ko": - savepath_cell = savepath_ko + subpath - elif celltype == "wt": - savepath_cell = savepath_wt + subpath - os.makedirs(savepath_cell, exist_ok=True) - io.imsave(savepath_cell + "5_ratio_aftermedian2.tif", cell.ratio) - - # clear area outside the cells - Processor.clear_outside_of_cells(Processor.segmentation_result_dict) - for n,cell in enumerate(Processor.cell_list): - subpath = basename + "/" + "cell" + str(n) + "/" - if celltype == "ko": - savepath_cell = savepath_ko + subpath - elif celltype == "wt": - savepath_cell = savepath_wt + subpath - os.makedirs(savepath_cell, exist_ok=True) - io.imsave(savepath_cell + "6_ratio_final.tif", cell.ratio) - - end_time = time.time() - # execution time - elapsed_time = end_time - start_time - print("\n") - logger.log_and_print(message=f'Execution time: {float(elapsed_time):.1f}, seconds', - level=logger.logging.INFO, logger=logger) - -logger.info("Program finished") diff --git a/beadcontacts.py b/beadcontacts.py deleted file mode 100644 index bd875b7..0000000 --- a/beadcontacts.py +++ /dev/null @@ -1,49 +0,0 @@ -import pandas as pd -import os - -#%% -def list_files(directory, extension): - filenames = [] - for filename in os.listdir(directory): - if filename.endswith(extension): - filenames.append(os.path.splitext(filename)[0]) - return filenames - -#%% -ko_file = "/Users/lwoelk/ICNScloud/PythonPipeline_Testfiles/Bead Kontakte/161209_HN1L-KO.xlsx" -wt_file = "/Users/lwoelk/ICNScloud/PythonPipeline_Testfiles/Bead Kontakte/161209_WT.xlsx" -KO_excel = pd.read_excel(ko_file, header=3) -WT_excel = pd.read_excel(wt_file, header=3) - -#%% - -ko_data_path = "/Users/lwoelk/ICNScloud/PythonPipeline_Testfiles/HN1L/K2 OKT3" -wt_data_path = "/Users/lwoelk/ICNScloud/PythonPipeline_Testfiles/HN1L/WT OKT3" - -ko_files = list_files(ko_data_path, '.tif') -wt_files = list_files(wt_data_path, '.tif') - - -#%% -KO_excel['fname'] = KO_excel['Name'].str.split('_', n=1).str[0] -KO_excel['fname'] = KO_excel['fname'].str.split('-', n=1).str[0] -WT_excel['fname'] = WT_excel['Name'].str.split('_', n=1).str[0] -WT_excel['fname'] = WT_excel['fname'].str.split('-', n=1).str[0] - -#%% -KO_info = KO_excel[KO_excel['fname'].isin(ko_files)] -WT_info = WT_excel[WT_excel['fname'].isin(wt_files)] - -#%% -aggregated_KO = KO_info.groupby('fname').agg({'von': ['min', 'max']}) -aggregated_KO.columns = ['_'.join(col).strip() for col in aggregated_KO.columns.values] -aggregated_KO = aggregated_KO.reset_index() -aggregated_KO['end'] = aggregated_KO['von_max']+600 - -aggregated_WT = WT_info.groupby('fname').agg({'von': ['min', 'max']}) -aggregated_WT.columns = ['_'.join(col).strip() for col in aggregated_WT.columns.values] -aggregated_WT = aggregated_WT.reset_index() -aggregated_WT['end'] = aggregated_WT['von_max']+600 - -aggregated_KO.to_csv('bead_contact_times_KO.csv', index=False) -aggregated_WT.to_csv('bead_contact_times_WT.csv', index=False) diff --git a/concept.md b/concept.md deleted file mode 100644 index eb703a7..0000000 --- a/concept.md +++ /dev/null @@ -1,73 +0,0 @@ -```mermaid ---- -title: Ca2+ Postprocessing ---- -classDiagram - - class BaseCaImageProcessor{ - string path_to_image - array image - dict parameters - list cell_list[cells] - list ratio_list[images] - list processing_steps[Decon, Bleaching, ...] - segment_cells() - start_processing() - return ratios() - } - - - class ImageROI{ - array image - float wavelength - return_image() - } - - - class BaseCell{ - ImageROI channel1 - ImageROI channel2 - array ratio - list processing steps - process_channels() - give_ratio() - } - - BaseCell <|-- Cell_cAMP :erbt - - class CaImageProcessor_cAMP{ - - } - - BaseCaImageProcessor <|-- CaImageProcessor_cAMP :erbt - - class BaseDecon{ - - } - class LRDecon{ - - } - class TDEDecon{ - - } - BaseDecon <|-- LRDecon :erbt - BaseDecon <|-- TDEDecon :erbt - - BaseBleaching <|-- Bleaching1 :erbt - BaseBleaching <|-- Bleaching2 :erbt - - BaseCell <-- ImageROI: lebt in - BaseCaImageProcessor <-- BaseCell: lebt in - BaseCaImageProcessor <-- BaseDecon: lebt in - BaseCaImageProcessor <-- BaseBleaching: lebt in - CaImageProcessor_cAMP <-- Cell_cAMP: lebt in - Cell_cAMP <-- ImageROI: lebt in - - BaseSegmentation <|-- Seg1 :erbt - BaseSegmentation <|-- Seg2 :erbt - BaseRegistration <|-- Reg1 :erbt - BaseRegistration <|-- Reg2 :erbt - BaseCaImageProcessor <-- BaseSegmentation: lebt in - BaseCaImageProcessor <-- BaseRegistration: lebt in - -``` \ No newline at end of file diff --git a/docs/Analysis/Analysis.md b/docs/Analysis/Analysis.md new file mode 100644 index 0000000..188f485 --- /dev/null +++ b/docs/Analysis/Analysis.md @@ -0,0 +1,13 @@ +--- +layout: default +title: Analysis +nav_order: 5 +has_children: true +--- + +# Microdomain Analysis + + +The analysis consists of two steps: Hotspot detection and dartboard visualization. It is based on Diercks et al. 2019. + +During the hotspot detection, information about the Calcium Microdomains in each cell of interest and each time frame such as the localization, time of occurrence and size are being measured. After that, the microdomains can be assigend to different areas in a virtual dartboard. This allows to create various dartboards for different time spans and cells. diff --git a/docs/Analysis/Dartboards.md b/docs/Analysis/Dartboards.md new file mode 100644 index 0000000..f089edb --- /dev/null +++ b/docs/Analysis/Dartboards.md @@ -0,0 +1,46 @@ +--- +layout: default +title: Dartboards +parent: Analysis +nav_order: 2 +--- + +# Dartboards + +## Explanation +This method was described earlier in Diercks et al. (2019). It aims to assign detected Calcium Microdomains to areas on +a dartboard. It provides an easy-to-understand overview of the distribution of signals and allows to compare whole sets of +cells with each other. + +## How it works +In order to assign the detected signals to certain dartboard areas, the (1) relative distance of the signal from the centroid coordinates (of the frame) and (2) the angle relative to the centroid coordinates are measured. This enables to project each signal onto a normalized dartboard. Signals close to the edge are projected to an outer area on the dartbaord, for example. Preservation of the signal distribution requires the normalization of the signal information to the bead contact position. +We chose the position "2 o'clock" as the normalized bead contact position. If a cell has the bead contact at 10 o'clock, for example, then all the signal information will be normalized to the contact site, so that superposition of multiple information from different cells and frames leads to a correct dartboard representation. + + +## Illustration +24 cells have been processed with our pipeline. For each cell and frame, there is a dartboard representation that is normalized to the specific bead contact site of the cell. All the dartboard information for the frames within the first 5 seconds after bead contact were cumulated and divided by 5 to obtain the mean number and distribution of signals within the first 5 seconds. +
+![example_dartboard](https://github.com/IPMI-ICNS-UKE/DARTS/assets/127941319/b1753f83-e811-49e9-834b-4d7aa9f6940d) +
+## Representation and usage +After running the script, you can find Excel-files for each cell saved on your computer. +
+Bildschirmfoto 2023-09-22 um 14 36 26 +
+The Excel files contain information for each frame and each dartboard area, leading to a 2D-Matrix/table. There are 37 dartboard areas. The bullseye in the middle is 12.5 times larger than all the other dartbaord areas, which are equal in size. Outside of the bullseye, there are three rings - each consisting of 12 areas. The bead contact site is defined as 2 o'clock. +
+
+Example: +
+
+Bildschirmfoto 2023-09-22 um 14 35 53 +
+ +Based on this, you can create various dartboards depending on (1) the chosen time interval (e.g. bead contact (0 seconds) to 5 seconds after bead contact) and (2) the selected subset of cells. +After running the main-script, you need to run the script "DartboardPlotGUI.py" in order to create your dartboards. You can either choose the "per-frame"- or the "per-second"-representation. +
+Bildschirmfoto 2023-09-22 um 14 40 34 + + + + diff --git a/docs/Analysis/Hotspot Detection.md b/docs/Analysis/Hotspot Detection.md new file mode 100644 index 0000000..a4fa0f9 --- /dev/null +++ b/docs/Analysis/Hotspot Detection.md @@ -0,0 +1,22 @@ +--- +layout: default +title: Hotspot Detection +parent: Analysis +nav_order: 1 +--- + +# Hotspot Detection + +## Explanation +Calcium microdomains are defined as "small, compact connected sets of pixels with high [Ca2+] values." (Diercks et al., 2019). Each cell image series consists of multiples frames or ratio images. The threshold for the detection of Calcium Microdomains is based on the cell type and the frame-specific mean ratio value (Diercks et al., 2019). Every pixel surpassing the threshold value is considered as a potential member of a connected set of pixels (hotspot). If the area of connected pixels is within a certain range (e.g. 4 to 20 pixels), then a hotspot has been detected. + +## Illustration +This ratio image shows hotspots in the center. + +Bildschirmfoto 2023-09-22 um 14 14 10 + +For illustration purposes, the following image shows the potential Calcium microdomains after application of an arbitrary signal threshold. +Bildschirmfoto 2023-09-22 um 14 14 24 + +Some of these hotspots might be considered as Calcium Microdomains based on their area, others might be excluded. + diff --git a/docs/Gemfile b/docs/Gemfile new file mode 100644 index 0000000..df086a8 --- /dev/null +++ b/docs/Gemfile @@ -0,0 +1,7 @@ +source 'https://rubygems.org' + +gem "jekyll", "~> 4.3.2" # installed by `gem jekyll` +# gem "webrick" # required when using Ruby >= 3 and Jekyll <= 4.2.2 + +gem "just-the-docs", "0.4.0.rc4" # currently the latest pre-release +# gem "just-the-docs" # always download the latest release diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock new file mode 100644 index 0000000..504b415 --- /dev/null +++ b/docs/Gemfile.lock @@ -0,0 +1,86 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.4) + public_suffix (>= 2.0.2, < 6.0) + colorator (1.1.0) + concurrent-ruby (1.2.2) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + eventmachine (1.2.7) + ffi (1.15.5) + forwardable-extended (2.6.0) + google-protobuf (3.23.2-x64-mingw-ucrt) + google-protobuf (3.23.2-x86_64-darwin) + google-protobuf (3.23.2-x86_64-linux) + http_parser.rb (0.8.0) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + jekyll (4.3.2) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (>= 2.0, < 4.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.3, >= 2.3.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (>= 0.3.6, < 0.5) + pathutil (~> 0.9) + rouge (>= 3.0, < 5.0) + safe_yaml (~> 1.0) + terminal-table (>= 1.8, < 4.0) + webrick (~> 1.7) + jekyll-sass-converter (3.0.0) + sass-embedded (~> 1.54) + jekyll-seo-tag (2.8.0) + jekyll (>= 3.8, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + just-the-docs (0.4.0.rc4) + jekyll (>= 3.8.5) + jekyll-seo-tag (>= 2.0) + rake (>= 12.3.1) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.8.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.4.0) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (5.0.1) + rake (13.0.6) + rb-fsevent (0.11.2) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.5) + rouge (4.1.2) + safe_yaml (1.0.5) + sass-embedded (1.62.1-x64-mingw-ucrt) + google-protobuf (~> 3.21) + sass-embedded (1.62.1-x86_64-darwin) + google-protobuf (~> 3.21) + sass-embedded (1.62.1-x86_64-linux-gnu) + google-protobuf (~> 3.21) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.4.2) + webrick (1.8.1) + +PLATFORMS + x64-mingw-ucrt + x86_64-darwin-22 + x86_64-linux + +DEPENDENCIES + jekyll (~> 4.3.2) + just-the-docs (= 0.4.0.rc4) + +BUNDLED WITH + 2.3.26 diff --git a/docs/General/Getting Started.md b/docs/General/Getting Started.md new file mode 100644 index 0000000..7dc70ca --- /dev/null +++ b/docs/General/Getting Started.md @@ -0,0 +1,16 @@ +--- +layout: default +title: Getting Started +nav_order: 2 +has_children: true +--- + +# **Getting Started** + +This program was designed to facilitate postprocessing and analysis of live cell fluorescence microscopy imaging data. +It is meant primarily as a tool for experimentalists. +We have included a graphical user interface (GUI) to make usage as easy as possible, but the installation process +is at the moment still only possible by downloading the code and installing the necessary packages. + + +For further support or issues regarding installation, feel free to submit an [issue](https://github.com/IPMI-ICNS-UKE/DARTS/issues) or contact us directly. diff --git a/docs/General/Installation.md b/docs/General/Installation.md new file mode 100644 index 0000000..456d516 --- /dev/null +++ b/docs/General/Installation.md @@ -0,0 +1,97 @@ +--- +layout: default +title: Installation +parent: Getting Started +nav_order: 1 +warning: true +--- + +# Installation + +We recommend using [anaconda](https://www.anaconda.com/download) to install python and the necessary packages. +Make sure to install correctly and to include the correct python executable in your path. +For more information, see for example [here](https://docs.anaconda.com/free/anaconda/install/index.html). + + +Make sure git is installed on your system, then clone the repository by running + +`` +git clone https://github.com/IPMI-ICNS-UKE/DARTS.git +`` + +in your command line. + +## Installation with bioformats + +Verify you are in the folder containing the `DARTS.yml` file and run + +``` +conda env create -f DARTS.yml +conda activate DARTS +``` + +This includes the [bioformats library](http://www.openmicroscopy.org/bio-formats/), which allows processing of common microscopy imaging formats. + +For this, the following prerequisites also need to be fulfilled: +1. Java Development Kit (JDK) needs to be installed. +You can download the JDK from the official Oracle website or use OpenJDK. + +2. The `JAVA_HOME` environment variable needs to be set correctly to point to the directory of your JDK installation. +On Linux or MacOS you can set it temporarily with +``` + export JAVA_HOME=/path/to/your/jdk +``` +On Windows, you'd set it via the System Properties > Environment Variables dialog. To point to a specific version: +Make sure to point to the correct version of jdk, since newer ones are not compatible. We tested successfully using v8. + +### Complete example installation on MacOS using homebrew + +As an example, we provide here a step-by-step guide to install the java dependencies for bioformats using [homebrew](https://brew.sh/). + +We were successfull using v8 of JDK. Install it by running + +``` + brew install adoptopenjdk/openjdk/adoptopenjdk8 +``` + +You can check which versions of Java you have installed by running +``` +/usr/libexec/java_home -V +``` +To set JAVA_HOME for a particular version, you can use the following +``` +export JAVA_HOME=$(/usr/libexec/java_home -v 8) +``` +Or add the above line to your shell configuration file (e.g., ~/.bashrc, ~/.bash_profile, ~/.zshrc) to make the change persistent across sessions. + +Alternatively, you can install `jenv` to switch between java versions. + +Install by +``` +brew install jenv +``` +Then integrate into shell (Use ~/.zshrc if you're using the Zsh shell.) +``` +echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bash_profile +echo 'eval "$(jenv init -)"' >> ~/.bash_profile +source ~/.bash_profile +``` + +Add java versions to `jenv` +``` +jenv add $(/usr/libexec/java_home -v 8) +``` +Now you can switch with +``` +jenv global 8 +``` + +## Installation without bioformats + +If the image data you are working with is in `.tif` format, or you convert it beforehand, for example using ImageJ, +you don't need to install bioformats and java. In this case, install the packages by + +`` +conda env create -f DARTS_without_bioformats.yml +conda activate DARTS +`` \ No newline at end of file diff --git a/docs/General/Usage.md b/docs/General/Usage.md new file mode 100644 index 0000000..73599e4 --- /dev/null +++ b/docs/General/Usage.md @@ -0,0 +1,88 @@ +--- +layout: default +title: Usage +parent: Getting Started +nav_order: 2 +--- + +# Usage + +## Starting the script +After installing the necessary packages, activate the environment + +`` +conda activate DARTS +`` + +and then run + +``` +python main.py +``` + +Depending on the python versions you have installed, it might be `python3 main.py`. + +## First GUI: Initial information +This initiates the first GUI, prompting for general information. In the top left corner, you must specify whether the raw data is in dual-channel format (two channels in one file) or single-channel format (both channels separated in individual files), along with setting the source and results directories. An example of a source directory can be found below the GUI. + +In the bottom left, provide measurement properties like scale (pixels per micron) and frame rate. This data is critical for accurate Calcium Microdomains measurements. Additionally, specifying the correct cell type is crucial as the internal calibration depends on it. + +In the top right corner, input information regarding the post-processing pipeline, shape normalization, and analysis. It's essential to specify: + +1. Whether registration should be calculated frame-by-frame (not recommended) or only in the first frame (recommended, refer to the 'Registration' section). +2. The choice of deconvolution algorithm (LR or TDE, consult the 'Deconvolution' section). +3. Selection of the appropriate bleaching correction algorithm (additive no fit, multiplicative simple ratio, biexponential fit additive). + +In the bottom right corner, you can initiate or cancel the analysis. +![Bildschirmfoto 2023-10-21 um 16 20 19](https://github.com/IPMI-ICNS-UKE/DARTS/assets/127941319/49a83945-a0ea-4254-981b-fc4b600569e4) + +An example for a source directory: + +Bildschirmfoto 2023-09-23 um 13 02 31 + + +Example image: + +Bildschirmfoto 2023-09-23 um 13 03 31 + +## Test file +You can try out the script by yourself using the test file that was uploaded to the DARTS-Repo. You can find the file in the following folder: https://github.com/IPMI-ICNS-UKE/DARTS/tree/main/DARTS_test_file. + +The bottom cell has a bead contact at approximately frame 45: + +Bildschirmfoto 2023-09-27 um 11 33 07 + + +## Definition of bead contacts +After clicking on "Start", there will appear a GUI for each image file, so that the bead contacts can be defined. A bead contact is defined as the contact of a (stimulatory) with the cells of interest. Internally, it consists of (1) the bead contact time, e.g. frame 300 and (2) the bead contact position relative to the center of the cell, e.g. 1 o'clock or 12 o'clock. In order to define bead contacts, the user needs to enter information regarding each bead contact manually. Use the following procedure to define bead contacts: + +1. Have a look at the whole image sequence to identify bead contacts. Beads usually appear in the first couple seconds of the addition, depending on the time of addition. +2. Click on "Bead contact position/time of bead contact" in the option menu below the "Add bead contact"-button. +3. In the left channel, click on the bead contact site between the cell of interest and the bead. Alternatively, use the text field. In the example below, the bead contacts are marked with a yellow cross. The correct definition of the bead contact time and position is crucial for useful results. +4. Click on "Position inside cell" in the option menu. +5. In the left channel, click on the cell, that interacts with the bead. Alternatively, you can type the coordinates in the text field. Ideally, you aim for the center. This will facilitate the assignment of the bead contact to the cell. In the example below, the cells of interest are marked with a red cross. +6. Repeat the steps 2. to 5. for each bead contact in the image sequence. +7. Once you have described every bead contact for this measurement, click on the button in the bottom right ("continue with next image or processing, respectively"). Repeat the steps 1. to 7. for every following image file or file pair in case of single file setup. + +![Bildschirmfoto 2023-10-21 um 16 30 45](https://github.com/IPMI-ICNS-UKE/DARTS/assets/127941319/1ae79491-7ae9-49c6-a37c-3679a0590a82) + + +## Output of running the script +After the definition of bead contacts, the script processes the image files by itself (postprocessing, shape normalization, analysis). Depending on the input data, this can take up to +hours to complete. + +The output of the script consists of various files: +1. for each image file, each detected cell image is saved as a ratio image and a corresponding normalized ratio image. If there have been detected Calcium microdomains in the cells, then the corresponding excel files will be saved to the same directories. +2. On the top layer of the results directory, you will find a text-file with all the defined bead contacts (Bead_contact_information.txt). +3. Based on the microdomain-measurement, you will find information regarding the number of responding cells (percentage of cells, that have at least one Calcium microdomain after the bead contact) and the mean amplitude of the responding cells (mean amplitude of the calcium signals in the responding cells) +4. In the Excel-file "microdomain_data", you can find the number of signals in each detected cell in each frame from 1 second before until 15s seconds after bead contact. +5. Finally, in the directory "Dartboards/Dartboard_data", you can find excel sheets for each detected cells, displaying the number of microdomains in each dartboard area and each frame (see below). These excel files can be used to generate dartboards (see section Analysis > Dartboards). + +Example for output: + +Bildschirmfoto 2023-09-23 um 13 51 10 + +Example for dartboard data table for one cell: + +Bildschirmfoto 2023-09-23 um 13 52 43 + diff --git a/docs/LICENSE b/docs/LICENSE new file mode 100644 index 0000000..7d510d0 --- /dev/null +++ b/docs/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 just-the-docs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/docs/Postprocessing/Background Subtraction.md b/docs/Postprocessing/Background Subtraction.md new file mode 100644 index 0000000..b8037e3 --- /dev/null +++ b/docs/Postprocessing/Background Subtraction.md @@ -0,0 +1,29 @@ +--- +layout: default +title: Background Subtraction +parent: Postprocessing +nav_order: 3 +--- + +# Background Subtraction + +## Explanation +Background signal can obscure or interefere with the relevant biological structures. That is why it is important to remove the background. Background correction methods aim to enhance the quality of the image. One possible method to correct the background is to apply a background subtraction algorithm, that we also used in our script. + + +## How it works +The mean intensity of the background is measured in the first and in the last frame. Next, a linear interpolation is used +to estimate the mean background intensity in the frames in between. The frame-specific mean background value is then subtracted from the whole image. In order to avoid integer-overflow, the maximum subtraction only sets pixels to zero. Otherwise, the subtraction could result in very large intensity values, if the subtrahend > pixel value. + +The background was separated from the cells using a threshold function from skimage and creating a mask for the background. In the next step, the mean intensity was measured with the regionprops-function. + +## Example +A channel image before background subtraction: + +Bildschirmfoto 2023-09-23 um 12 30 44 + + +The same image, but after background subtraction: + +Bildschirmfoto 2023-09-23 um 12 30 04 + diff --git a/docs/Postprocessing/Bleaching Correction.md b/docs/Postprocessing/Bleaching Correction.md new file mode 100644 index 0000000..f441c0d --- /dev/null +++ b/docs/Postprocessing/Bleaching Correction.md @@ -0,0 +1,49 @@ +--- +layout: default +title: Bleaching Correction +parent: Postprocessing +nav_order: 6 +--- + +# **Bleaching Correction** + +## General information + +Photobleaching is a common problem in fluorescence microscopy. It leads to a gradual decrease in +fluorescence signal intensity over time and results in intensity decay, loss of information and - if not corrected - to +false interpretations. Therefore it is crucial to compensate for signal intensity loss. There are several Bleaching correction approaches available. +
+ +## Offered algorithms +In the framework of this project, we work on **Calcium Microdomains** (see reference paper: [Diercks et al. - 2019 - +High-resolution calcium imaging method for local calcium signaling](https://pubmed.ncbi.nlm.nih.gov/30710265/)). This program was developed to automatically process calcium imaging data. Similar to the reference paper, +we carry out an **additive frame-by-frame bleaching correction** algorithm. Local calcium imaging employs the two dyes +Fura-Red and Fluo-4. Given the negligible bleaching of Fluo-4 in comparison to Fura-Red, only the bleaching +characteristics of Fura-Red are considered. Alternatively, we offer two more bleaching correction algorithms: simple multiplicative correction (based on the ratio of Frame 0 and Frame i) and a bi-exponential fit with additive correction (using a curve-fit-function from scipy). +
+
+ +## Bleaching correction Algorithm (additive frame-by-frame, no fit): Pseudocode + +Here is an exemplified code of the bleaching correction: + +```markdown +# ref_i: reference image series (Fura_Red) +reference_mean_intensity = measure_mean_intensity(ref_i[frame_0]) +for frame_n in ref_i: + mean_intensity = measure_mean_intensity(ref_i[frame]) + difference = reference_mean_intensity - mean_intensity + for pixel in ref_i[frame_n]: + if pixel_value > 0: + pixel_intensity += difference +``` +
+
+ +## Example of a bleaching corrected intensity timeline: + +Blue = correction
+Red = without correction + +![Bleaching_correction](https://github.com/IPMI-ICNS-UKE/DARTS/assets/127941319/fe42281a-c0df-4b57-a68c-c805beb38b83) + diff --git a/docs/Postprocessing/Deconvolution.md b/docs/Postprocessing/Deconvolution.md new file mode 100644 index 0000000..27c64bc --- /dev/null +++ b/docs/Postprocessing/Deconvolution.md @@ -0,0 +1,77 @@ +--- +layout: default +title: Deconvolution +parent: Postprocessing +nav_order: 5 +--- + +# Deconvolution + +## General information + +If the illumination time is increased when trying to generate high-resolution images of experimental data, +undesirable side effects may occur: Live cells can cause motion artifacts, and rapid intensity fluctuations might +not be captured. At the same time, longer exposure can lead to photobleaching and phototoxicity. +Too short an exposure time, however, can result in noisy images. +This is where deconvolution comes in to equalize images, reduce noise, and increase resolution. + +## Background information + +When images are captured, various physical factors such as lenses and light incidence can cause +the original "ground truth" image to change. This effect is known as "convolution." Deconvolution aims to reverse this +process. It is based on the assumption that a real point of light (can be understood as a pixel in this case) +has effects on neighboring points (or pixels) when the image is captured. +This relationship is called the "point spread function" or "PSF", and Deconvolution attempts to reverse the effects +of this PSF. Using Deconvolution, images with short exposure time (and thus orignally poorer image quality) can still +produce data with high image quality, without the negative effects of longer light exposure. + + +## Lucy-Richardson Deconvolution + +A commonly used method is the "Lucy-Richardson deconvolution" (LR) (Richardson WH, "Bayesian-Based Iterative Method +of Image Restoration",doi:10.1364/JOSA.62.000055, and Lucy LB, "An iterative technique for the rectification of +observed distributions", doi:10.1086/111605), which was originally +developed in astronomy for star and planet images. +It uses iterative steps in combination with PSF to produce realistic results. +LR is often considered a starting point against which newer methods are compared. +However, it can lead to artifacts at edge transitions and poor results when the Signal-to-Noise Ratio (SNR) is low. + + +## Time-Dependent Entropy Deconvolution + +An alternative approach is Timedependent Entropy Deconvolution (TDE) by Woelk et al. (https://pubmed.ncbi.nlm.nih.gov/34769223/). +This method captures temporal components as well as spatial components, which is particularly +advantageous for video data. The biggest advantage of TDE is its ability to process +highly noisy images with low SNR - Where LR deconvolution might produce poor results, +TDE can separate and recover the signal from noise. +However, smoothing effects may occur at high intensity levels. + +## Parameters for Deconvolution + +{: .highlight } +>General Parameters for PSF calculation: +>- type: Type of the used microscope; "confocal" or "widefield" +>- lambdaEx_ch1: Excitation wavelength of the first channel (in nm) +>- lambdaEm_ch1: Emission wavelength of the first channel (in nm) +>- lambdaEx_ch2: Excitation wavelength of the second channel (in nm) +>- lambdaEm_ch2: Emission wavelength of the first channel (in nm) +>- numAper: Numerical Aperture of the objective +>- magObj: Magnification of the objective +>- rindexObj: Refractive index of the immersion Medium +>- rindexSp: Refractive index of the specimen medium +>- ccdSize: Pixel dimension of the CCD (in the plane of the camera) + +{: .highlight } +>Additional Parameters for TDE: +>- lambda: Spatial Lagrange parameter to weigh the regularization terms; needs to be determined empirically and can be widely +> different dependent on the type of data; normally in the range of 0.1 to 3 +>- lambda t: Temporal Lagrange parameter to weigh the regularization terms; Works best when of a similar order of magnitude as lambda + +## Example +> ![](decon.png) +> _Comparison of deconvolution methods for TPC2- +> R.GECO.1.2 images captured with different +> exposure times; Standard deconvolution corresponds to LR._ + +{: .important } +>In summary, deconvolution is based on the idea of correcting the effects of lenses and other optical factors on images. Different methods such as Lucy-Richardson deconvolution and timedependent entropy deconvolution are used to achieve image deconvolution, noise reduction, and resolution enhancement, with each method having its advantages and disadvantages. diff --git a/docs/Postprocessing/Postprocessing Components.md b/docs/Postprocessing/Postprocessing Components.md new file mode 100644 index 0000000..9576950 --- /dev/null +++ b/docs/Postprocessing/Postprocessing Components.md @@ -0,0 +1,12 @@ +--- +layout: default +title: Postprocessing +nav_order: 3 +has_children: true +--- + +# **Postprocessing** +In order to enhance the image quality, we use a postprocessing pipeline that consists of various steps, such as the deconvolution or the bleaching correction. +
+ +For more information, feel free to click on the respective Component in the table of contents below. diff --git a/docs/Postprocessing/ROI Selection.md b/docs/Postprocessing/ROI Selection.md new file mode 100644 index 0000000..dae6653 --- /dev/null +++ b/docs/Postprocessing/ROI Selection.md @@ -0,0 +1,39 @@ +--- +layout: default +title: Segmentation/ Cell tracking +parent: Postprocessing +nav_order: 4 +--- + +# Segmentation/ Cell tracking (ROI Selection) + +## Motivation +Defining regions of interest in microscopy images can be a time-consuming process. In order to automate this +step, we decided to combine the advantages of (1) automated cell segmentation and (2) cell tracking over time. + +## How it works + +The cells are segmented in each frame of the microscopy images using the StarDist-algorithm for star-convex objects. The segmentation creates labels for each detected cell. +For each cell label in each frame, relevant data is measured (coordinates, edge, bounding box, ...) by the skimage.regionprops +function. +The trackpy-package is used to connect the cell labels in each frame so that each cell will later consist of a time series +of cell images in both channels. Variables such as the memory, the maximum positional alteration between two frames and others can be modified by the user. +After identifying the cells, the cell-specific information regarding the position and the bounding boxes are used to crop an image series out of the channel images (same size as raw data). +Because of the fact, that in our case, the beads are mostly prominent in the first channel, we apply the cell selection algorithm only onto the second channel. After that, the bounding boxes can be used in the first channel for cropping out the cells, too. + +## Example + +In each frame, the StarDist-algorithm tries to detect cells and creates a labelled image: + +Bildschirmfoto 2023-09-23 um 12 48 59 + +The trackpy algorithm associates labels, enabling the generation of cell traces that can then be used to crop individual cell images from each frame, resulting in a series of smaller images for each cell. + +Bildschirmfoto 2023-09-23 um 12 48 09 + + +## References + +For segmentation, we use **[StarDist](https://github.com/stardist/stardist)** + +For cell tracking, we use **[Trackpy](http://soft-matter.github.io/trackpy/v0.6.1/)** diff --git a/docs/Postprocessing/Registration.md b/docs/Postprocessing/Registration.md new file mode 100644 index 0000000..353d9d5 --- /dev/null +++ b/docs/Postprocessing/Registration.md @@ -0,0 +1,56 @@ +--- +layout: default +title: Registration +parent: Postprocessing +nav_order: 2 +--- + +# **Registration** + +## What is registration? + +Image registration involves estimating a transformation that aligns points from one image to their corresponding points +in another image. This transformation establishes a mapping between the coordinate systems of the fixed and moving +images. In the context of fluorescence microscopy, image registration is relevant because in dual-channel imaging, the channels often are not aligned perfectly. This could cause unwanted alterations of the signal. +
+
+ + +## What kind of approaches exist? + +Various approaches exist for image registration, including: +- feature-based methods +- intensity-based methods +- phase correlation +- elastic registration +- affine registration +- non-affine registration +
+ + +## Which approach did we use? + +Since we are working with low signal-to-noise ratio images, feature based methods may be less effective +because the presence of noise can affect the detection and matching of distinct features and can therefore +lead to suboptimal registration results. + +We utilized the **[SimpleITK](https://simpleitk.readthedocs.io/en/master/about.html)** Python package that was installed +with **`pip install SimpleITK`**. +SimpleITK, built on top of ITK (Insight Segmentation and Registration Toolkit), is an open-source library. +SimpleITK offers a user-friendly interface for common operations such as filtering, registration, segmentation, +and feature extraction. +In the context of registration, it offers different types type of transformations, global and local ones. +The available transformations are listed [here](https://simpleitk.readthedocs.io/en/master/registrationOverview.html). +We applied the `affine` transformation to define the mapping between images. + +Below, you can find an example image. As shown, SITK with affine transformation works really well on our low signal-to-noise +ratio images: + +![sitk_registration_example](https://github.com/IPMI-ICNS-UKE/DARTS/assets/127941319/058d7b73-0ea2-44f7-8ed7-571b6872576e) + + +We offer the user the option to choose whether to employ the registration method frame by frame or not. As the latter option +is much more time-efficient and provides good results, we recommend not to use the registration frame-by-frame. Instead, +letting the script calculate the transformation in the first frame and using it for the following frames is recommended. + +For more code details, please visit our [Github page](https://github.com/IPMI-ICNS-UKE/T-DARTS/blob/main/postprocessing/registration.py) diff --git a/docs/Postprocessing/Shape Normalization.md b/docs/Postprocessing/Shape Normalization.md new file mode 100644 index 0000000..83a2c51 --- /dev/null +++ b/docs/Postprocessing/Shape Normalization.md @@ -0,0 +1,40 @@ +--- +layout: default +title: Shape normalization +nav_order: 4 +has_children: false +math: katex +--- + + +# Shape Normalization +## About + +This part of the program takes a cell of arbitrary (reasonably convex) shape and returns the same cell normalized onto +a circle, making it easier to compare and analyse multiple cells of different shapes. + +Crucial for this step is the correct segmentation of the cell outline, +since this determines the transformation. + +Our implementation was inspired by the approach used by [Möhl et. al 2012](https://doi.org/10.1242/jcs.090746). + + + +## Usage + +The shape normalization takes as input image data containing a single cell. +Neccessary information for the normalization: +1. the edge around the cell as a list of discrete points (x,y) +2. the coordinates of the cell centroid (x,y) +If this information is not supplied, the function will try to segment the cell using the StarDist algorithm. + + +The algorithm is purely two dimensional, time-dependent input will be processed frame-by-frame. + +## Background + +The normalization process can be described in three parts: + +1. converting the edge coordinates from cartesian to polar coordinates $$(r, \theta)$$ +2. normalizing the radii from the edge coordinates onto a fixed value, thus transforming the shape into a circle +3. interpolating the transformation of the edge onto the entire image using nearest neighbor interpolation \ No newline at end of file diff --git a/docs/Postprocessing/decon.png b/docs/Postprocessing/decon.png new file mode 100644 index 0000000..2d97a33 Binary files /dev/null and b/docs/Postprocessing/decon.png differ diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..2233092 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,32 @@ +title: DARTS +logo: assets/img/Logo.png +description: Python pipeline for Ca2+ microdomain analysis +theme: just-the-docs +show_downloads: true +google_analytics: +url: https://ipmi-icns-uke.github.io/DARTS/ +baseurl: /docs + +favicon_ico: favicon.ico +color_scheme: foo + +math: katex + +callouts_opacity: 0.3 + +callouts_level: quiet # or loud +callouts: + highlight: + color: yellow + important: + title: Important + color: blue + new: + title: New + color: green + note: + title: Note + color: grey-dk + warning: + title: Warning + color: red diff --git a/docs/_includes/head_custom.html b/docs/_includes/head_custom.html new file mode 100644 index 0000000..a6e632c --- /dev/null +++ b/docs/_includes/head_custom.html @@ -0,0 +1,27 @@ +{%- comment -%} + When you include the following code in `_includes/head_custom.html`, you can + render TeX/LaTeX math formula in web pages using KaTeX or MathJax. + + To render math using KaTeX on individual pages, set `math: katex` in their + front matter. + + To add a preamble (defining new commands and environments) for some pages, + set `layout: katex` (instead of `math: katex`) in their front matter, and + insert the preamble in `_layouts/katex.html`. + + To render math using KaTeX on all pages, either set `math: katex` in + `_config.yml`, or use front-matter defaults for `math: katex` or `layout: katex`. + + To render math using MathJax instead of KaTeX, set to `mathjax` instead of `katex`. + + You can use KaTeX and MathJax on different pages (but not on the same page). +{%- endcomment -%} + +{% assign math = page.math | default: layout.math | default: site.math %} + +{% case math %} + {% when "katex" %} + {% include katex.html %} + {% when "mathjax" %} + {% include mathjax.html %} +{% endcase %} \ No newline at end of file diff --git a/docs/_includes/katex.html b/docs/_includes/katex.html new file mode 100644 index 0000000..82bc88b --- /dev/null +++ b/docs/_includes/katex.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + diff --git a/docs/_layouts/katex.html b/docs/_layouts/katex.html new file mode 100644 index 0000000..d22e791 --- /dev/null +++ b/docs/_layouts/katex.html @@ -0,0 +1,12 @@ +--- +layout: default +math: katex +--- +
+ \( + + \) +
+ +{{ content }} diff --git a/docs/_sass/color_schemes/foo.scss b/docs/_sass/color_schemes/foo.scss new file mode 100644 index 0000000..80c1e0f --- /dev/null +++ b/docs/_sass/color_schemes/foo.scss @@ -0,0 +1,8 @@ +$link-color: #CA776C; +$body-heading-color: #CA776C; +$base-button-color: #CA776C; +$sidebar-color: #FFFAF8; +$nav-child-link-color: #CA776C; +$search-result-preview-color: #FFFEFF; +$feedback-color: #E2D3D0; +//$feedback-color: darken($sidebar-color, 3%) !default; \ No newline at end of file diff --git a/docs/_sass/color_schemes/light.scss b/docs/_sass/color_schemes/light.scss new file mode 100644 index 0000000..f754305 --- /dev/null +++ b/docs/_sass/color_schemes/light.scss @@ -0,0 +1,15 @@ +$body-background-color: $white !default; +$body-heading-color: $grey-dk-300 !default; +$body-text-color: $grey-dk-100 !default; +$link-color: $purple-000 !default; +$nav-child-link-color: $grey-dk-100 !default; +$sidebar-color: $grey-lt-000 !default; +$base-button-color: #f7f7f7 !default; +$btn-primary-color: $purple-100 !default; +$code-background-color: $grey-lt-000 !default; +$feedback-color: darken($sidebar-color, 3%) !default; +$table-background-color: $white !default; +$search-background-color: $white !default; +$search-result-preview-color: $grey-dk-000 !default; + +//@import "./vendor/OneLightJekyll/syntax"; diff --git a/docs/_sass/custom/setup.scss b/docs/_sass/custom/setup.scss new file mode 100644 index 0000000..4e21ad5 --- /dev/null +++ b/docs/_sass/custom/setup.scss @@ -0,0 +1,5 @@ +// custom setup code goes here +$pink-000: #f77ef1; +$pink-100: #f967f1; +$pink-200: #e94ee1; +$pink-300: #dd2cd4; diff --git a/docs/_sass/support/_variables.scss b/docs/_sass/support/_variables.scss new file mode 100644 index 0000000..044a8a4 --- /dev/null +++ b/docs/_sass/support/_variables.scss @@ -0,0 +1,119 @@ +// Typography + +// prettier-ignore +//$body-font-family: system-ui, -apple-system, blinkmacsystemfont, "Segoe UI", + //roboto, "Helvetica Neue", arial, sans-serif !default; +$body-font-family: 'Barlow Semi Condensed', sans-serif; +$mono-font-family: 'Barlow Semi Condensed', sans-serif; +//$mono-font-family: "SFMono-Regular", menlo, consolas, monospace !default; +$root-font-size: 16px !default; // DEPRECATED: previously base font-size for rems +$body-line-height: 1.4 !default; +$content-line-height: 1.6 !default; +$body-heading-line-height: 1.25 !default; + +// Font size +// `-sm` suffix is the size at the small (and above) media query + +$font-size-1: 0.5625rem !default; +$font-size-1-sm: 0.625rem !default; +$font-size-2: 0.6875rem !default; // h4 - uppercased!, h6 not uppercased, text-small +$font-size-3: 0.75rem !default; // h5 +$font-size-4: 0.875rem !default; +$font-size-5: 1rem !default; // h3 +$font-size-6: 1.125rem !default; // h2 +$font-size-7: 1.5rem !default; +$font-size-8: 2rem !default; // h1 +$font-size-9: 2.25rem !default; +$font-size-10: 2.625rem !default; +$font-size-10-sm: 3rem !default; + +// Colors + +$white: #fff !default; +$grey-dk-000: #959396 !default; +$grey-dk-100: #5c5962 !default; +$grey-dk-200: #44434d !default; +$grey-dk-250: #302d36 !default; +$grey-dk-300: #27262b !default; +$grey-lt-000: #f5f6fa !default; +$grey-lt-100: #eeebee !default; +$grey-lt-200: #ecebed !default; +$grey-lt-300: #e6e1e8 !default; +$purple-000: #7253ed !default; +$purple-100: #5e41d0 !default; +$purple-200: #4e26af !default; +$purple-300: #381885 !default; +$blue-000: #2c84fa !default; +$blue-100: #2869e6 !default; +$blue-200: #264caf !default; +$blue-300: #183385 !default; +$green-000: #41d693 !default; +$green-100: #11b584 !default; +$green-200: #009c7b !default; +$green-300: #026e57 !default; +$yellow-000: #ffeb82 !default; +$yellow-100: #fadf50 !default; +$yellow-200: #f7d12e !default; +$yellow-300: #e7af06 !default; +$red-000: #f77e7e !default; +$red-100: #f96e65 !default; +$red-200: #e94c4c !default; +$red-300: #dd2e2e !default; + +// Spacing + +$spacing-unit: 1rem; // 1rem == 16px + +$spacers: ( + sp-0: 0, + sp-1: $spacing-unit * 0.25, + sp-2: $spacing-unit * 0.5, + sp-3: $spacing-unit * 0.75, + sp-4: $spacing-unit, + sp-5: $spacing-unit * 1.5, + sp-6: $spacing-unit * 2, + sp-7: $spacing-unit * 2.5, + sp-8: $spacing-unit * 3, + sp-9: $spacing-unit * 3.5, + sp-10: $spacing-unit * 4, +) !default; +$sp-1: map-get($spacers, sp-1) !default; // 0.25 rem == 4px +$sp-2: map-get($spacers, sp-2) !default; // 0.5 rem == 8px +$sp-3: map-get($spacers, sp-3) !default; // 0.75 rem == 12px +$sp-4: map-get($spacers, sp-4) !default; // 1 rem == 16px +$sp-5: map-get($spacers, sp-5) !default; // 1.5 rem == 24px +$sp-6: map-get($spacers, sp-6) !default; // 2 rem == 32px +$sp-7: map-get($spacers, sp-7) !default; // 2.5 rem == 40px +$sp-8: map-get($spacers, sp-8) !default; // 3 rem == 48px +$sp-9: map-get($spacers, sp-9) !default; // 3.5 rem == 56px +$sp-10: map-get($spacers, sp-10) !default; // 4 rem == 64px + +// Borders + +$border: 1px solid !default; +$border-radius: 4px !default; +$border-color: $grey-lt-100 !default; + +// Grid system + +$gutter-spacing: $sp-6 !default; +$gutter-spacing-sm: $sp-4 !default; +$nav-width: 16.5rem !default; +$nav-width-md: 15.5rem !default; +$nav-list-item-height: $sp-6 !default; +$nav-list-item-height-sm: $sp-8 !default; +$nav-list-expander-right: true; +$content-width: 50rem !default; +$header-height: 3.75rem !default; +$search-results-width: $content-width - $nav-width !default; +$transition-duration: 400ms; + +// Media queries in pixels + +$media-queries: ( + xs: 20rem, + sm: 31.25rem, + md: $content-width, + lg: $content-width + $nav-width, + xl: 87.5rem, +) !default; diff --git a/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.14.10.png b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.14.10.png new file mode 100644 index 0000000..793c80d Binary files /dev/null and b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.14.10.png differ diff --git a/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.14.24.png b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.14.24.png new file mode 100644 index 0000000..6d73072 Binary files /dev/null and b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.14.24.png differ diff --git a/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.35.53.png b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.35.53.png new file mode 100644 index 0000000..ac8db88 Binary files /dev/null and b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.35.53.png differ diff --git a/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.36.26.png b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.36.26.png new file mode 100644 index 0000000..87ed3ab Binary files /dev/null and b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.36.26.png differ diff --git a/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.40.34.png b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.40.34.png new file mode 100644 index 0000000..a7199fd Binary files /dev/null and b/docs/assets/img/Bildschirmfoto 2023-09-22 um 14.40.34.png differ diff --git a/docs/assets/img/Bleaching_correction.PNG b/docs/assets/img/Bleaching_correction.PNG new file mode 100644 index 0000000..08be49a Binary files /dev/null and b/docs/assets/img/Bleaching_correction.PNG differ diff --git a/docs/assets/img/CDARTS.png b/docs/assets/img/CDARTS.png new file mode 100644 index 0000000..75b9528 Binary files /dev/null and b/docs/assets/img/CDARTS.png differ diff --git a/docs/assets/img/Figure_1_dart.png b/docs/assets/img/Figure_1_dart.png new file mode 100644 index 0000000..36ee888 Binary files /dev/null and b/docs/assets/img/Figure_1_dart.png differ diff --git a/docs/assets/img/Logo.png b/docs/assets/img/Logo.png new file mode 100644 index 0000000..21f7b16 Binary files /dev/null and b/docs/assets/img/Logo.png differ diff --git a/docs/assets/img/analysis_overview.png b/docs/assets/img/analysis_overview.png new file mode 100644 index 0000000..488da73 Binary files /dev/null and b/docs/assets/img/analysis_overview.png differ diff --git a/docs/assets/img/example_dartboard.png b/docs/assets/img/example_dartboard.png new file mode 100644 index 0000000..40df1bb Binary files /dev/null and b/docs/assets/img/example_dartboard.png differ diff --git a/docs/assets/img/general_overview.PNG b/docs/assets/img/general_overview.PNG new file mode 100644 index 0000000..2e40a89 Binary files /dev/null and b/docs/assets/img/general_overview.PNG differ diff --git a/docs/assets/img/headerlogo.png b/docs/assets/img/headerlogo.png new file mode 100644 index 0000000..628e3d3 Binary files /dev/null and b/docs/assets/img/headerlogo.png differ diff --git a/docs/assets/img/postprocessing_components_overview.PNG b/docs/assets/img/postprocessing_components_overview.PNG new file mode 100644 index 0000000..2bee8fe Binary files /dev/null and b/docs/assets/img/postprocessing_components_overview.PNG differ diff --git a/docs/assets/img/screenshot_beadGUI.png b/docs/assets/img/screenshot_beadGUI.png new file mode 100644 index 0000000..e9f9e01 Binary files /dev/null and b/docs/assets/img/screenshot_beadGUI.png differ diff --git a/docs/assets/img/screenshot_main.png b/docs/assets/img/screenshot_main.png new file mode 100644 index 0000000..cfb26be Binary files /dev/null and b/docs/assets/img/screenshot_main.png differ diff --git a/docs/assets/img/shape_normalization_overview.PNG b/docs/assets/img/shape_normalization_overview.PNG new file mode 100644 index 0000000..ed786e6 Binary files /dev/null and b/docs/assets/img/shape_normalization_overview.PNG differ diff --git a/docs/assets/img/sitk_registration_example.PNG b/docs/assets/img/sitk_registration_example.PNG new file mode 100644 index 0000000..ab11915 Binary files /dev/null and b/docs/assets/img/sitk_registration_example.PNG differ diff --git a/docs/assets/js/mathtex-script-type.js b/docs/assets/js/mathtex-script-type.js new file mode 100644 index 0000000..4e3f9c1 --- /dev/null +++ b/docs/assets/js/mathtex-script-type.js @@ -0,0 +1,34 @@ +// Mostly copied from https://github.com/KaTeX/KaTeX/tree/main/contrib/mathtex-script-type +// Options for global command definitions added by @pdmosses + +// import katex from "katex"; + +const macros = {}; + +let scripts = document.body.getElementsByTagName("script"); +scripts = Array.prototype.slice.call(scripts); +scripts.forEach(function(script) { + if (!script.type || !script.type.match(/math\/tex/i)) { + return -1; + } + const display = + (script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null); + + const katexElement = document.createElement(display ? "div" : "span"); + katexElement.setAttribute("class", + display ? "equation" : "inline-equation"); + try { + katex.render(script.text, katexElement, { + displayMode: display, + globalGroup: true, + trust: true, + strict: false, + throwOnError: false, + macros + }); + } catch (err) { + //console.error(err); linter doesn't like this + katexElement.textContent = script.text; + } + script.parentNode.replaceChild(katexElement, script); +}); diff --git a/docs/favicon.ico b/docs/favicon.ico new file mode 100644 index 0000000..02991e9 Binary files /dev/null and b/docs/favicon.ico differ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..dc2ed11 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,53 @@ +--- +layout: home +title: Welcome +nav_order: 1 +--- + +# **DARTS**:
**An open-source Python pipeline for Ca2+ microdomain analysis in live cell imaging data** + +
+
+ +## General Information + +DARTS is a pipeline for Ca2+ microdomain analysis in live cell imaging data written in Python 3 by Lena-Marie Woelk, Dejan Kovacevic, Hümeyra Husseini and Fritz Förster. +For support, please open an [issue](https://github.com/IPMI-ICNS-UKE/DARTS/issues) or contact us directly. + +This pipeline is part of the sfb1328 [A02 project](https://www.sfb1328.de/index.php?id=29). + + +[View it on GitHub](https://github.com/IPMI-ICNS-UKE/DARTS){: .btn .btn-outline } +
+
+ + +## Program Structure + +![](assets/img/Figure_1_dart.png) + +The pipeline can be roughly divided into three parts: + +1. [Postprocessing Components]({% link Postprocessing/Postprocessing Components.md %}#Postprocessing Components) +2. [Shape normalization]({% link Postprocessing/Shape Normalization.md %}#Shape Normalization) +3. [Analysis]({% link Analysis/Analysis.md %}#Analysis) + +### General postprocessing + +These components include segmentation and cell tracking to identify regions of interest (ROI), image improvement by bleaching +correction, deconvolution and denoising, background subtraction and ratiometric image handling, i.e. registration of two input channels +and ratio computation. + +### Shape Normalization + +This part normalizes arbitrary cell shapes (within certain convexity constraints) onto a circle with a well-defined radius +to facilitate comparison of Ca2+ microdomains across multiple cells with differing morphologies. + +### Analysis + +The normalized cells are then analyzed to detect Ca2+ hotspots and the results given as data tables and visualized either on an +individual basis or across multiple cells on a dartboard shape, where hotspot frequency and location can be analyzed for different time +frames. + + + diff --git a/shapenormalization_consistency.py b/shapenormalization_consistency.py deleted file mode 100644 index 1ec11da..0000000 --- a/shapenormalization_consistency.py +++ /dev/null @@ -1,32 +0,0 @@ -import time -import matplotlib.pyplot as plt -from pathlib import Path -import tomli -from postprocessing.processing import ImageProcessor -from pystackreg import StackReg -import SimpleITK as sitk -import numpy as np -from stardist.models import StarDist2D -from csbdeep.utils import normalize -from postprocessing.shapenormalization import ShapeNormalization -import os - -#%% - -folder = "/Users/lwoelk/PycharmProjects/T-DARTS/Data/K2" - - - - -parameters = tomli.loads(Path("config.toml").read_text(encoding="utf-8")) - -for file in os.listdir(folder): - filename = os.fsdecode(file) - if filename.endswith(".tif") or filename.endswith(".tiff"): - parameters["inputoutput"]["path_to_input_combined"] = folder + "/" + filename - print("processing image ", parameters["inputoutput"]["path_to_input_combined"]) - - Processor = ImageProcessor(parameters) - - Processor.start_postprocessing() - diff --git a/test_file/test_file.py b/test_file/test_file.py deleted file mode 100644 index e69de29..0000000 diff --git a/test_postprocessing.py b/test_postprocessing.py deleted file mode 100644 index e69de29..0000000