├── .bumpversion.cfg ├── .gitignore ├── BUILD.md ├── CONTRIBUTING.md ├── Jenkinsfile ├── LICENSE.txt ├── README.md ├── aicssegmentation ├── __init__.py ├── __init__.pyc ├── bin │ ├── 3.0.0 │ ├── =0.4.3, │ ├── __init__.py │ ├── batch_processing.py │ ├── run_toolkit.bat │ └── run_toolkit.sh ├── cli │ └── to_analysis.py ├── core │ ├── MO_threshold.py │ ├── __init__.py │ ├── __init__.pyc │ ├── hessian.py │ ├── output_utils.py │ ├── pre_processing_utils.py │ ├── seg_dot.py │ ├── utils.py │ ├── vessel.py │ ├── visual.py │ └── visual.pyc ├── setting.txt ├── structure_wrapper │ ├── __init__.py │ ├── seg_actb.py │ ├── seg_actn1.py │ ├── seg_atp2a2.py │ ├── seg_cardio_actn2.py │ ├── seg_cardio_atp2a2.py │ ├── seg_cardio_fbl.py │ ├── seg_cardio_fbl_100x.py │ ├── seg_cardio_myl7.py │ ├── seg_cardio_npm1.py │ ├── seg_cardio_npm1_100x.py │ ├── seg_cardio_tnni1.py │ ├── seg_cardio_ttn.py │ ├── seg_cetn2.py │ ├── seg_ctnnb1.py │ ├── seg_drug_npm1.py │ ├── seg_dsp.py │ ├── seg_fbl.py │ ├── seg_fbl_bright_v3.py │ ├── seg_fbl_comb.py │ ├── seg_fbl_labelfree_4dn.py │ ├── seg_gja1.py │ ├── seg_h2b.py │ ├── seg_lamp1.py │ ├── seg_lmnb1_interphase.py │ ├── seg_lmnb1_mitotic.py │ ├── seg_myh10.py │ ├── seg_npm1.py │ ├── seg_npm1_SR.py │ ├── seg_npm1_bright_v3.py │ ├── seg_npm1_comb.py │ ├── seg_npm_labelfree_4dn.py │ ├── seg_nup153.py │ ├── seg_pxn.py │ ├── seg_rab5a.py │ ├── seg_sec61b.py │ ├── seg_sec61b_dual.py │ ├── seg_slc25a17.py │ ├── seg_smc1a.py │ ├── seg_son.py │ ├── seg_st6gal1.py │ ├── seg_template.py │ ├── seg_tjp1.py │ ├── seg_tomm20.py │ ├── seg_tuba1b.py │ ├── seg_ubtf.py │ └── structure_segmenter.py ├── tests │ ├── __init__.py │ └── dummy_test.py ├── version.py └── version.pyc ├── build.gradle ├── demo_data ├── RAB5_demo_data.tif ├── TNNI1_demo_data.tif ├── TOM20_demo_data.tif ├── TOMM20_pipeline_example_cell_segmentation.tiff ├── TOMM20_pipeline_example_nucleus_segmentation.tiff └── TOMM20_pipeline_example_structure_segmentation.tiff ├── docs ├── API.md ├── conda_why.md ├── doc.rst ├── full.jpg ├── full_doc.md ├── full_mem.jpg ├── full_str.jpg ├── installation_linux.md ├── installation_mac.md ├── installation_windows.md ├── jupyter_lookup_table.md ├── object_identification.md ├── rab5a_raw.jpg ├── step1.jpg ├── step2.jpg ├── step3_p1.jpg ├── step3_p2.jpg ├── toolkit_paper_SI_vFinalForBioRxiv.pdf └── toolkit_paper_lookup_table_20181206.pdf ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lookup_table_demo ├── README.md ├── bridging_the_gap_between_binary_image_and_analysis.ipynb ├── demo_NUP153.ipynb ├── demo_TNNI1.ipynb ├── playground_Sec61_dual.ipynb ├── playground_Sec61b.ipynb ├── playground_curvi.ipynb ├── playground_curvi_WorkshopOct2019.ipynb ├── playground_dots.ipynb ├── playground_filament3d.ipynb ├── playground_gja1.ipynb ├── playground_lamp1.ipynb ├── playground_npm1.ipynb ├── playground_shell.ipynb ├── playground_spotty-Copy1.ipynb ├── playground_spotty.ipynb ├── playground_st6gal1.ipynb ├── test_segmentation_TNNI1.tiff └── test_viewer.ipynb ├── settings.gradle ├── setup.cfg └── setup.py /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.1.21.dev1 3 | parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\.((?P[a-z]*)(?P\d*)))? 4 | serialize = 5 | {major}.{minor}.{patch}.{release}{devbuild} 6 | {major}.{minor}.{patch} 7 | 8 | [bumpversion:part:release] 9 | optional_value = rel 10 | values = 11 | dev 12 | rel 13 | 14 | [bumpversion:file:aicssegmentation/version.py] 15 | search = MODULE_VERSION={current_version} 16 | replace = {new_version} 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | .gradle/ 3 | .idea/ 4 | *.iml 5 | .*.swp 6 | .*.swo 7 | *~ 8 | *.ipynb_checkpoints 9 | .project 10 | .settings 11 | 12 | # Generated by build 13 | build/ 14 | dist/ 15 | venv/ 16 | .eggs/ 17 | *.egg-info 18 | **/__pycache__/ 19 | .pyc 20 | .pytest_cache/ 21 | activate 22 | .coverage 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Allen Institute Contribution Agreement 2 | 3 | ## Contribution Status 4 | We use this for internal purpose and are currently not accepting pull requests. We are releasing it to the community AS IS. 5 | 6 | 24 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | parameters { booleanParam(name: 'create_release', defaultValue: false, 3 | description: 'If true, create a release artifact and publish to ' + 4 | 'the artifactory release PyPi or public PyPi.') } 5 | options { 6 | timeout(time: 1, unit: 'HOURS') 7 | } 8 | agent { 9 | node { 10 | label "python-gradle" 11 | } 12 | } 13 | environment { 14 | PATH = "/home/jenkins/.local/bin:$PATH" 15 | REQUESTS_CA_BUNDLE = "/etc/ssl/certs" 16 | } 17 | stages { 18 | stage ("create virtualenv") { 19 | steps { 20 | this.notifyBB("INPROGRESS") 21 | sh "./gradlew -i cleanAll installCIDependencies" 22 | } 23 | } 24 | 25 | stage ("bump version pre-build") { 26 | when { 27 | expression { return params.create_release } 28 | } 29 | steps { 30 | // This will drop the dev suffix if we are releasing 31 | // X.Y.Z.devN -> X.Y.Z 32 | sh "./gradlew -i bumpVersionRelease" 33 | } 34 | } 35 | 36 | stage ("test/build distribution") { 37 | steps { 38 | sh "./gradlew -i build" 39 | } 40 | } 41 | 42 | stage ("report on tests") { 43 | steps { 44 | junit "build/test_report.xml" 45 | 46 | cobertura autoUpdateHealth: false, 47 | autoUpdateStability: false, 48 | coberturaReportFile: 'build/coverage.xml', 49 | failUnhealthy: false, 50 | failUnstable: false, 51 | maxNumberOfBuilds: 0, 52 | onlyStable: false, 53 | sourceEncoding: 'ASCII', 54 | zoomCoverageChart: false 55 | 56 | 57 | } 58 | } 59 | 60 | stage ("publish release") { 61 | when { 62 | branch 'master' 63 | expression { return params.create_release } 64 | } 65 | steps { 66 | sh "./gradlew -i publishRelease" 67 | sh "./gradlew -i gitTagCommitPush" 68 | sh "./gradlew -i bumpVersionPostRelease gitCommitPush" 69 | } 70 | } 71 | 72 | stage ("publish snapshot") { 73 | when { 74 | branch 'master' 75 | not { expression { return params.create_release } } 76 | } 77 | steps { 78 | sh "./gradlew -i publishSnapshot" 79 | script { 80 | def ignoreAuthors = ["jenkins", "Jenkins User", "Jenkins Builder"] 81 | if (!ignoreAuthors.contains(gitAuthor())) { 82 | sh "./gradlew -i bumpVersionDev gitCommitPush" 83 | } 84 | } 85 | } 86 | } 87 | 88 | } 89 | post { 90 | always { 91 | notifyBuildOnSlack(currentBuild.result, currentBuild.previousBuild?.result) 92 | this.notifyBB(currentBuild.result) 93 | } 94 | cleanup { 95 | deleteDir() 96 | } 97 | } 98 | } 99 | 100 | def notifyBB(String state) { 101 | // on success, result is null 102 | state = state ?: "SUCCESS" 103 | 104 | if (state == "SUCCESS" || state == "FAILURE") { 105 | currentBuild.result = state 106 | } 107 | 108 | notifyBitbucket commitSha1: "${GIT_COMMIT}", 109 | credentialsId: 'aea50792-dda8-40e4-a683-79e8c83e72a6', 110 | disableInprogressNotification: false, 111 | considerUnstableAsSuccess: true, 112 | ignoreUnverifiedSSLPeer: false, 113 | includeBuildNumberInKey: false, 114 | prependParentProjectKey: false, 115 | projectKey: 'SW', 116 | stashServerBaseUrl: 'https://aicsbitbucket.corp.alleninstitute.org' 117 | } 118 | 119 | def notifyBuildOnSlack(String buildStatus = 'STARTED', String priorStatus) { 120 | // build status of null means successful 121 | buildStatus = buildStatus ?: 'SUCCESS' 122 | 123 | // Override default values based on build status 124 | if (buildStatus != 'SUCCESS') { 125 | slackSend ( 126 | color: '#FF0000', 127 | message: "${buildStatus}: '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})" 128 | ) 129 | } else if (priorStatus != 'SUCCESS') { 130 | slackSend ( 131 | color: '#00FF00', 132 | message: "BACK_TO_NORMAL: '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})" 133 | ) 134 | } 135 | } 136 | 137 | def gitAuthor() { 138 | sh(returnStdout: true, script: 'git log -1 --format=%an').trim() 139 | } 140 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Allen Institute Software License – This software license is the 2-clause BSD license 2 | plus clause a third clause that prohibits redistribution for commercial purposes without further permission. 3 | 4 | Copyright © 2017. Allen Institute. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the 10 | following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 13 | following disclaimer in the documentation and/or other materials provided with the distribution. 14 | 15 | 3. Redistributions for commercial purposes are not permitted without the Allen Institute’s written permission. 16 | For purposes of this license, commercial purposes is the incorporation of the Allen Institute's software into 17 | anything for which you will charge fees or other compensation. Contact terms@alleninstitute.org for commercial 18 | licensing opportunities. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 21 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 26 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /aicssegmentation/__init__.py: -------------------------------------------------------------------------------- 1 | from .version import MODULE_VERSION 2 | 3 | __version__ = MODULE_VERSION 4 | 5 | 6 | def get_module_version(): 7 | return MODULE_VERSION 8 | 9 | 10 | -------------------------------------------------------------------------------- /aicssegmentation/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/__init__.pyc -------------------------------------------------------------------------------- /aicssegmentation/bin/=0.4.3,: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/bin/=0.4.3, -------------------------------------------------------------------------------- /aicssegmentation/bin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/bin/__init__.py -------------------------------------------------------------------------------- /aicssegmentation/bin/run_toolkit.bat: -------------------------------------------------------------------------------- 1 | set WFNAME=lmnb1_interphase 2 | set INPUTCH=0 3 | set OUTPUTDIR="C:\\Users\\Foo Yoo\\Desktop\\LMNB1_images\\out\\" 4 | set INPUTFILE_TYPE=.tiff 5 | : script for processing a whole folder (ENV_name is the name of your conda environment) 6 | set INPUTDIR="C:\\Users\\Calysta Yan\\Desktop\\Allen Institute\\FISH_CAAX_images\\BMPER\\" 7 | activate ENV_name && python batch_processing.py --d --workflow_name %WFNAME% --struct_ch %INPUTCH% --output_dir %OUTPUTDIR% per_dir --input_dir %INPUTDIR% --data_type %INPUTFILE_TYPE% && pause || pause 8 | -------------------------------------------------------------------------------- /aicssegmentation/bin/run_toolkit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | WFNAME=lamin_interphase 4 | INPUTCH=0 5 | OUTPUTDIR="/home/data/structures/$WFNAME/result/" 6 | INPUTFILE_TYPE='.czi' 7 | 8 | # script for processing a whole folder 9 | INPUTDIR="../../data/structures/$WFNAME/original/" 10 | 11 | python batch_pipeline.py \ 12 | --d \ 13 | --workflow_name $WFNAME \ 14 | --struct_ch $INPUTCH \ 15 | --output_dir $OUTPUTDIR \ 16 | per_dir \ 17 | --input_dir $INPUTDIR \ 18 | --data_type $INPUTFILE_TYPE 19 | -------------------------------------------------------------------------------- /aicssegmentation/cli/to_analysis.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | import pandas as pd 4 | from scipy.ndimage.measurements import label 5 | 6 | def simple_builder(bw, se=None, return_dataframe=False): 7 | 8 | if se is None: 9 | obj_label, obj_num = label(bw>0) 10 | else: 11 | obj_label, obj_num = label(bw>0, structure=se) 12 | 13 | if return_dataframe: 14 | import pandas as pd 15 | obj_df = pd.DataFrame(np.arange(1,obj_num+1,1), columns=['object_index']) 16 | return obj_label, obj_df 17 | else: 18 | return obj_label 19 | 20 | def masked_builder(bw, mask_label): 21 | 22 | assert mask_label.max()>0 23 | 24 | if mask_label.max()==1: 25 | mask_label, num_label = label(mask_label>0) 26 | label_list = np.arange(1, num_label+1, 1) 27 | else: 28 | label_list = np.unique(mask_label[mask_label>0]) 29 | 30 | counter_offset = 0 31 | obj_label = np.zeros_like(mask_label) 32 | multi_index_list = [] 33 | for ii, val in enumerate(label_list): 34 | single_mask = mask_label==val 35 | valid_bw = bw.copy() 36 | valid_bw[single_mask==0]=0 37 | valid_label, valid_label_num = label(valid_bw>0) 38 | for valid_index in range(valid_label_num): 39 | index_plus = valid_index + 1 40 | this_obj_index = index_plus + counter_offset 41 | this_obj = valid_label==index_plus 42 | obj_label[this_obj] = this_obj_index 43 | multi_index_list.append([val,this_obj_index, this_obj.sum()]) 44 | counter_offset = counter_offset + valid_label_num 45 | 46 | obj_df = pd.DataFrame(multi_index_list) 47 | obj_df.columns=['mask_id', 'obj_id', 'vol'] 48 | 49 | return obj_label, obj_df.set_index(['mask_id', 'obj_id']) 50 | 51 | def hierachical_builder(img_list): 52 | print('under construction') 53 | pass 54 | -------------------------------------------------------------------------------- /aicssegmentation/core/MO_threshold.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from skimage.morphology import remove_small_objects, binary_closing, ball , dilation 3 | from skimage.filters import threshold_triangle, threshold_otsu 4 | from skimage.measure import label 5 | 6 | def MO(structure_img_smooth, global_thresh_method, object_minArea, extra_criteria=False, local_adjust=0.98, return_object=False): 7 | 8 | if global_thresh_method=='tri' or global_thresh_method=='triangle': 9 | th_low_level = threshold_triangle(structure_img_smooth) 10 | elif global_thresh_method=='med' or global_thresh_method=='median': 11 | th_low_level = np.percentile(structure_img_smooth,50) 12 | elif global_thresh_method=='ave' or global_thresh_method=='ave_tri_med': 13 | global_tri = threshold_triangle(structure_img_smooth) 14 | global_median = np.percentile(structure_img_smooth,50) 15 | th_low_level = (global_tri + global_median)/2 16 | 17 | bw_low_level = structure_img_smooth > th_low_level 18 | bw_low_level = remove_small_objects(bw_low_level, min_size=object_minArea, connectivity=1, in_place=True) 19 | bw_low_level = dilation(bw_low_level, selem=ball(2)) 20 | 21 | bw_high_level = np.zeros_like(bw_low_level) 22 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 23 | if extra_criteria: 24 | local_cutoff = 0.333 * threshold_otsu(structure_img_smooth) 25 | for idx in range(num_obj): 26 | single_obj = lab_low==(idx+1) 27 | local_otsu = threshold_otsu(structure_img_smooth[single_obj>0]) 28 | if local_otsu > local_cutoff: 29 | bw_high_level[np.logical_and(structure_img_smooth>local_otsu*local_adjust, single_obj)]=1 30 | else: 31 | for idx in range(num_obj): 32 | single_obj = lab_low==(idx+1) 33 | local_otsu = threshold_otsu(structure_img_smooth[single_obj>0]) 34 | bw_high_level[np.logical_and(structure_img_smooth>local_otsu*local_adjust, single_obj)]=1 35 | 36 | if return_object: 37 | return bw_high_level>0, bw_low_level 38 | else: 39 | return bw_high_level>0 40 | -------------------------------------------------------------------------------- /aicssegmentation/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/core/__init__.py -------------------------------------------------------------------------------- /aicssegmentation/core/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/core/__init__.pyc -------------------------------------------------------------------------------- /aicssegmentation/core/hessian.py: -------------------------------------------------------------------------------- 1 | from itertools import combinations_with_replacement 2 | 3 | import numpy as np 4 | from scipy import ndimage as ndi 5 | 6 | from .utils import absolute_eigenvaluesh 7 | 8 | 9 | def compute_3d_hessian_matrix(nd_array, sigma=1, scale=True, whiteonblack=True): 10 | """ 11 | Computes the hessian matrix for an nd_array. 12 | This can be used to detect vesselness as well as other features. 13 | In 3D the first derivative will contain three directional gradients at each index: 14 | [ gx, gy, gz ] 15 | The Hessian matrix at each index will then be equal to the second derivative: 16 | [ gxx, gxy, gxz] 17 | [ gyx, gyy, gyz] 18 | [ gzx, gzy, gzz] 19 | The Hessian matrix is symmetrical, so gyx == gxy, gzx == gxz, and gyz == gzy. 20 | :param nd_array: n-dimensional array from which to compute the hessian matrix. 21 | :param sigma: gaussian smoothing to perform on the array. 22 | :param scale: if True, the hessian elements will be scaled by sigma squared. 23 | :return: hessian array of shape (..., ndim, ndim) 24 | """ 25 | ndim = nd_array.ndim 26 | 27 | # smooth the nd_array 28 | smoothed = ndi.gaussian_filter(nd_array, sigma=sigma, mode='nearest', truncate=3.0) 29 | 30 | # compute the first order gradients 31 | gradient_list = np.gradient(smoothed) 32 | 33 | # compute the hessian elements 34 | hessian_elements = [np.gradient(gradient_list[ax0], axis=ax1) 35 | for ax0, ax1 in combinations_with_replacement(range(ndim), 2)] 36 | 37 | if sigma > 0 and scale: 38 | # scale the elements of the hessian matrix 39 | if whiteonblack: 40 | hessian_elements = [(sigma ** 2) * element for element in hessian_elements] 41 | else: 42 | hessian_elements = [-1 * (sigma ** 2) * element for element in hessian_elements] 43 | 44 | # create hessian matrix from hessian elements 45 | hessian_full=[[()] * ndim for x in range(ndim)] 46 | #hessian_full = [[None] * ndim] * ndim 47 | 48 | for index, (ax0, ax1) in enumerate(combinations_with_replacement(range(ndim), 2)): 49 | element = hessian_elements[index] 50 | hessian_full[ax0][ax1] = element 51 | if ax0 != ax1: 52 | hessian_full[ax1][ax0] = element 53 | 54 | hessian_rows = list() 55 | for row in hessian_full: 56 | #print(row.shape) 57 | hessian_rows.append(np.stack(row, axis=-1)) 58 | 59 | hessian = np.stack(hessian_rows, axis=-2) 60 | return hessian 61 | 62 | 63 | def absolute_3d_hessian_eigenvalues(nd_array, sigma=1, scale=True, whiteonblack=True): 64 | """ 65 | Eigenvalues of the hessian matrix calculated from the input array sorted by absolute value. 66 | :param nd_array: input array from which to calculate hessian eigenvalues. 67 | :param sigma: gaussian smoothing parameter. 68 | :param scale: if True hessian values will be scaled according to sigma squared. 69 | :return: list of eigenvalues [eigenvalue1, eigenvalue2, ...] 70 | """ 71 | return absolute_eigenvaluesh(compute_3d_hessian_matrix(nd_array, sigma=sigma, scale=scale, whiteonblack=whiteonblack)) 72 | -------------------------------------------------------------------------------- /aicssegmentation/core/pre_processing_utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.stats import norm 3 | from scipy.ndimage import gaussian_filter 4 | 5 | 6 | def intensity_normalization(struct_img, scaling_param): 7 | 8 | ''' 9 | Mode 1: scaling_param = [0] 10 | Mode 2: scaling_param = [lower std range, upper std range] 11 | Mode 3: scaling_param = [lower std range, upper std range, lower abs intensity, higher abs intensity] 12 | ''' 13 | assert len(scaling_param) > 0 14 | 15 | if len(scaling_param) == 1: 16 | if scaling_param[0] < 1: 17 | print('intensity normalization: using min-max normalization with NO absolute intensity upper bound') 18 | else: 19 | print(f'intensity normalization: using min-max normalization with absolute intensity upper bound {scaling_param[0]}') 20 | struct_img[struct_img > scaling_param[0]] = struct_img.min() 21 | strech_min = struct_img.min() 22 | strech_max = struct_img.max() 23 | struct_img = (struct_img - strech_min + 1e-8)/(strech_max - strech_min + 1e-8) 24 | elif len(scaling_param) == 2: 25 | # print(f'intensity normalization: normalize into [mean - {scaling_param[0]} x std, mean + {scaling_param[1]} x std] ') 26 | m, s = norm.fit(struct_img.flat) 27 | # print(m,s) 28 | # import numpy as np 29 | # import pdb; pdb.set_trace() 30 | strech_min = max(m - scaling_param[0] * s, struct_img.min()) 31 | strech_max = min(m + scaling_param[1] * s, struct_img.max()) 32 | struct_img[struct_img > strech_max] = strech_max 33 | struct_img[struct_img < strech_min] = strech_min 34 | struct_img = (struct_img - strech_min + 1e-8)/(strech_max - strech_min + 1e-8) 35 | elif len(scaling_param) == 4: 36 | img_valid = struct_img[np.logical_and(struct_img > scaling_param[2], struct_img < scaling_param[3])] 37 | m, s = norm.fit(img_valid.flat) 38 | strech_min = max(scaling_param[2] - scaling_param[0] * s, struct_img.min()) 39 | strech_max = min(scaling_param[3] + scaling_param[1] * s, struct_img.max()) 40 | struct_img[struct_img > strech_max] = strech_max 41 | struct_img[struct_img < strech_min] = strech_min 42 | struct_img = (struct_img - strech_min + 1e-8)/(strech_max - strech_min + 1e-8) 43 | 44 | # print('intensity normalization completes') 45 | return struct_img 46 | 47 | 48 | def image_smoothing_gaussian_3d(struct_img, sigma, truncate_range=3.0): 49 | 50 | structure_img_smooth = gaussian_filter(struct_img, sigma=sigma, mode='nearest', truncate=truncate_range) 51 | 52 | return structure_img_smooth 53 | 54 | 55 | def image_smoothing_gaussian_slice_by_slice(struct_img, sigma, truncate_range=3.0): 56 | 57 | structure_img_smooth = np.zeros_like(struct_img) 58 | for zz in range(struct_img.shape[0]): 59 | structure_img_smooth[zz, :, :] = gaussian_filter(struct_img[zz, :, :], sigma=sigma, mode='nearest', 60 | truncate=truncate_range) 61 | 62 | return structure_img_smooth 63 | 64 | 65 | def edge_preserving_smoothing_3d(struct_img, numberOfIterations=10, conductance=1.2, timeStep=0.0625): 66 | import itk 67 | # numberOfIteration was 5 68 | 69 | itk_img = itk.GetImageFromArray(struct_img.astype(np.float32)) 70 | 71 | gradientAnisotropicDiffusionFilter = itk.GradientAnisotropicDiffusionImageFilter.New(itk_img) 72 | gradientAnisotropicDiffusionFilter.SetNumberOfIterations(numberOfIterations) 73 | gradientAnisotropicDiffusionFilter.SetTimeStep(timeStep) 74 | gradientAnisotropicDiffusionFilter.SetConductanceParameter(conductance) 75 | gradientAnisotropicDiffusionFilter.Update() 76 | 77 | itk_img_smooth = gradientAnisotropicDiffusionFilter.GetOutput() 78 | 79 | img_smooth_ag = itk.GetArrayFromImage(itk_img_smooth) 80 | 81 | return img_smooth_ag 82 | 83 | 84 | def suggest_normalization_param(structure_img0): 85 | m, s = norm.fit(structure_img0.flat) 86 | print(f'mean intensity of the stack: {m}') 87 | print(f'the standard deviation of intensity of the stack: {s}') 88 | 89 | p99 = np.percentile(structure_img0, 99.99) 90 | print(f'0.9999 percentile of the stack intensity is: {p99}') 91 | 92 | pmin = structure_img0.min() 93 | print(f'minimum intensity of the stack: {pmin}') 94 | 95 | pmax = structure_img0.max() 96 | print(f'maximum intensity of the stack: {pmax}') 97 | 98 | up_ratio = 0 99 | for up_i in np.arange(0.5, 1000, 0.5): 100 | if m+s * up_i > p99: 101 | if m+s * up_i > pmax: 102 | print(f'suggested upper range is {up_i-0.5}, which is {m+s*(up_i-0.5)}') 103 | up_ratio = up_i-0.5 104 | else: 105 | print(f'suggested upper range is {up_i}, which is {m+s*up_i}') 106 | up_ratio = up_i 107 | break 108 | 109 | low_ratio = 0 110 | for low_i in np.arange(0.5, 1000, 0.5): 111 | if m-s*low_i < pmin: 112 | print(f'suggested lower range is {low_i-0.5}, which is {m-s*(low_i-0.5)}') 113 | low_ratio = low_i-0.5 114 | break 115 | 116 | print(f'So, suggested parameter for normalization is [{low_ratio}, {up_ratio}]') 117 | print('To further enhance the contrast: You may increase the first value (may loss some dim parts), or decrease the second value' + 118 | '(may loss some texture in super bright regions)') 119 | print('To slightly reduce the contrast: You may decrease the first value, or increase the second value') 120 | -------------------------------------------------------------------------------- /aicssegmentation/core/seg_dot.py: -------------------------------------------------------------------------------- 1 | from scipy import ndimage as ndi 2 | import numpy as np 3 | from scipy.ndimage.filters import gaussian_laplace, minimum_filter, convolve 4 | 5 | 6 | def dot_3d(struct_img, log_sigma): 7 | assert len(struct_img.shape) == 3 8 | responce = -1*(log_sigma**2)*ndi.filters.gaussian_laplace(struct_img, log_sigma) 9 | return responce 10 | 11 | def dot_3d_wrapper(struct_img, s3_param): 12 | bw = np.zeros(struct_img.shape, dtype=bool) 13 | for fid in range(len(s3_param)): 14 | log_sigma = s3_param[fid][0] 15 | responce = -1*(log_sigma**2)*ndi.filters.gaussian_laplace(struct_img, log_sigma) 16 | bw = np.logical_or(bw, responce>s3_param[fid][1]) 17 | return bw 18 | 19 | def dot_2d(struct_img, log_sigma): 20 | assert len(struct_img.shape) == 2 21 | responce = -1*(log_sigma**2)*ndi.filters.gaussian_laplace(struct_img, log_sigma) 22 | return responce 23 | 24 | def logSlice(image, sigma_list, threshold): 25 | 26 | gl_images = [-gaussian_laplace(image, s) * (s ** 2) for s in sigma_list] 27 | 28 | # get the mask 29 | seg = np.zeros_like(image) 30 | for zi in range(len(sigma_list)): 31 | seg = np.logical_or(seg, gl_images[zi]>threshold) 32 | 33 | return seg 34 | 35 | 36 | def dot_slice_by_slice(struct_img, log_sigma): 37 | res = np.zeros_like(struct_img) 38 | for zz in range(struct_img.shape[0]): 39 | res[zz, :, :] = -1*(log_sigma**2)*ndi.filters.gaussian_laplace(struct_img[zz, :, :], log_sigma) 40 | return res 41 | 42 | def dot_2d_slice_by_slice_wrapper(struct_img, s2_param): 43 | bw = np.zeros(struct_img.shape, dtype=bool) 44 | for fid in range(len(s2_param)): 45 | log_sigma = s2_param[fid][0] 46 | responce = np.zeros_like(struct_img) 47 | for zz in range(struct_img.shape[0]): 48 | responce[zz, :, :] = -1*(log_sigma**2)*ndi.filters.gaussian_laplace(struct_img[zz, :, :], log_sigma) 49 | bw = np.logical_or(bw, responce>s2_param[fid][1]) 50 | return bw -------------------------------------------------------------------------------- /aicssegmentation/core/visual.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | import ipywidgets as widgets 5 | from ipywidgets import interact, fixed 6 | from IPython.display import display 7 | 8 | def sliceViewer(im, zz): 9 | plt.imshow(im[zz,:,:]) 10 | plt.show() 11 | 12 | def random_colormap(nn=10000): 13 | from matplotlib import cm 14 | viridis = cm.get_cmap('viridis', nn) 15 | for ii in range(nn): 16 | for jj in range(3): 17 | viridis.colors[ii][jj] = np.random.rand() 18 | viridis.colors[0][0]=0 19 | viridis.colors[0][1]=0 20 | viridis.colors[0][2]=0 21 | 22 | return viridis 23 | 24 | def explore_dot_3d(img, sigma, th, roi=[-1]): 25 | # roi = [x0, y0, x1, y1] 26 | if roi[0]<0: 27 | roi = [0,0,img.shape[1],img.shape[2]] 28 | 29 | im = img[:,roi[1]:roi[3],roi[0]:roi[2]] 30 | 31 | from aicssegmentation.core.seg_dot import dot_3d 32 | 33 | response = dot_3d(im, log_sigma=sigma) 34 | bw = response > th 35 | 36 | out = img_seg_combine(im,bw) 37 | return out 38 | 39 | def explore_vesselness_3d(im, sigma, th, roi=[-1]): 40 | # roi = [x0, y0, x1, y1] 41 | if roi[0]<0: 42 | roi = [0,0,im.shape[1],im.shape[2]] 43 | 44 | from aicssegmentation.core.vessel import vesselness3D 45 | 46 | response = vesselness3D(im, sigmas=sigma, tau=1, whiteonblack=True) 47 | bw = response > th 48 | 49 | out = img_seg_combine(im,bw, roi) 50 | return out 51 | 52 | def explore_vesselness_2d(im, sigma, th, roi=[-1]): 53 | # roi = [x0, y0, x1, y1] 54 | if roi[0]<0: 55 | roi = [0,0,im.shape[1],im.shape[2]] 56 | 57 | from aicssegmentation.core.vessel import vesselnessSliceBySlice 58 | 59 | response = vesselnessSliceBySlice(im, sigmas=sigma, tau=1, whiteonblack=True) 60 | bw = response > th 61 | 62 | out = img_seg_combine(im,bw, roi) 63 | return out 64 | 65 | def blob2dExplorer_single(im, sigma, th): 66 | from .seg_dot import logSlice 67 | 68 | bw = logSlice(im,(sigma[0],sigma[1],1) , th) 69 | plt.imshow(im) 70 | plt.show() 71 | plt.imshow(bw) 72 | plt.show() 73 | 74 | def fila2dExplorer_single(im, sigma, th): 75 | from .vessel import vesselness2D 76 | 77 | tmp = vesselness2D(im, [sigma], tau=1, whiteonblack=True) 78 | plt.imshow(im) 79 | plt.show() 80 | plt.imshow(tmp>th) 81 | plt.show() 82 | 83 | def blob2dExplorer_stack(im_stack, zz, sigma, th): 84 | from .seg_dot import logSlice 85 | im = im_stack[zz,:,:] 86 | 87 | print(im.shape) 88 | 89 | bw = logSlice(im,(sigma[0],sigma[1],1) , th) 90 | plt.imshow(im) 91 | plt.show() 92 | plt.imshow(bw) 93 | plt.show() 94 | 95 | def vesselness2dExplorer(im, zz, sigma, th): 96 | from .vessel import vesselness2D_range 97 | 98 | mip= np.amax(im,axis=0) 99 | tmp = np.concatenate((im[zz,:,:],mip),axis=1) 100 | tmp = vesselness2D_range(tmp, scale_range=(sigma[0],sigma[1]+0.5,0.5), scale_step=1, tau=1, whiteonblack=True) 101 | ves = np.zeros_like(mip) 102 | ves[:,:im.shape[2]-2]= tmp[:,:im.shape[2]-2] 103 | plt.imshow(im[zz,:,:]) 104 | plt.show() 105 | plt.imshow(ves>th) 106 | plt.show() 107 | 108 | def mipView(im): 109 | mip= np.amax(im,axis=0) 110 | plt.imshow(mip) 111 | plt.show() 112 | 113 | def img_seg_combine(img, seg, roi=['Full',None]): 114 | 115 | # normalize to 0~1 116 | img = img.astype(np.float32) 117 | img = (img-img.min())/(img.max()-img.min()) 118 | seg = seg.astype(np.float32) 119 | seg[seg>0]=1 120 | 121 | if roi[0]=='ROI' or roi[0]=='roi': 122 | img = img[roi[1]] 123 | seg = seg[roi[1]] 124 | elif roi[0]=='manual' or roi[0]=='M': 125 | img = img[:,roi[1][1]:roi[1][3],roi[1][0]:roi[1][2]] 126 | seg = seg[:,roi[1][1]:roi[1][3],roi[1][0]:roi[1][2]] 127 | 128 | # combine 129 | combined = np.concatenate((seg, img), axis=2) 130 | 131 | ## overlay 132 | #ovelay = img.copy() 133 | #ovelay[seg>0]=1 134 | #combined = np.concatenate((combined, ovelay), axis=2) 135 | 136 | # view 137 | return combined 138 | 139 | def segmentation_quick_view(seg): 140 | valid_pxl = np.unique(seg[seg>0]) 141 | if len(valid_pxl)<1: 142 | print('segmentation is empty') 143 | return 144 | 145 | seg = seg>0 146 | seg = seg.astype(np.uint8) 147 | seg[seg>0]=255 148 | 149 | return seg 150 | 151 | def single_fluorescent_view(im): 152 | 153 | assert len(im.shape)==3 154 | 155 | im = im.astype(np.float32) 156 | im = (im - im.min())/(im.max()-im.min()) 157 | 158 | return im 159 | 160 | def seg_fluo_side_by_side(im, seg, roi=['Full',None]): 161 | 162 | out = img_seg_combine(im, seg, roi) 163 | 164 | return out 165 | -------------------------------------------------------------------------------- /aicssegmentation/core/visual.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/core/visual.pyc -------------------------------------------------------------------------------- /aicssegmentation/setting.txt: -------------------------------------------------------------------------------- 1 | fbl_bright 2 | intensity_norm_param = [1, 15] 3 | 4 | gaussian_smoothing_sigma = 0.3 5 | 6 | gaussian_smoothing_truncate_range = 3.0 7 | 8 | dot_2d_sigma = 2 9 | 10 | dot_2d_sigma_extra = 3 11 | 12 | dot_2d_cutoff = 0.010 13 | 14 | minArea = 5 15 | 16 | low_level_min_size = 200 17 | 18 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/structure_wrapper/__init__.py -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_actb.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from ..core.vessel import vesselness3D 6 | from aicssegmentation.core.output_utils import save_segmentation, ACTB_output, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | 10 | def Workflow_actb(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [3, 15] 17 | vesselness_sigma_1 = [2] 18 | vesselness_cutoff_1 = 0.1 19 | vesselness_sigma_2 = [1] 20 | vesselness_cutoff_2 = 0.04 21 | minArea = 15 22 | ########################################################################## 23 | 24 | out_img_list = [] 25 | out_name_list = [] 26 | 27 | ################### 28 | # PRE_PROCESSING 29 | ################### 30 | # intenisty normalization 31 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 32 | 33 | out_img_list.append(struct_img.copy()) 34 | out_name_list.append('im_norm') 35 | 36 | # rescale if needed 37 | if rescale_ratio > 0: 38 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 39 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 40 | 41 | # smoothing with gaussian filter 42 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 43 | 44 | out_img_list.append(structure_img_smooth.copy()) 45 | out_name_list.append('im_smooth') 46 | 47 | ################### 48 | # core algorithm 49 | ################### 50 | 51 | # vesselness 3d 52 | response_1 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma_1, tau=1, whiteonblack=True) 53 | response_2 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma_2, tau=1, whiteonblack=True) 54 | bw = np.logical_or(response_1 > vesselness_cutoff_1, response_2 > vesselness_cutoff_2) 55 | 56 | ################### 57 | # POST-PROCESSING 58 | ################### 59 | seg = remove_small_objects(bw, min_size=minArea, connectivity=1, in_place=False) 60 | 61 | # output 62 | seg = seg>0 63 | seg = seg.astype(np.uint8) 64 | seg[seg>0]=255 65 | 66 | out_img_list.append(seg.copy()) 67 | out_name_list.append('bw_final') 68 | 69 | if output_type == 'default': 70 | # the default final output 71 | save_segmentation(seg, False, output_path, fn) 72 | elif output_type == 'AICS_pipeline': 73 | # pre-defined output function for pipeline data 74 | save_segmentation(seg, True, output_path, fn) 75 | elif output_type == 'customize': 76 | # the hook for passing in a customized output function 77 | #output_fun(out_img_list, out_name_list, output_path, fn) 78 | print('please provide custom output function') 79 | elif output_type == 'array': 80 | return seg 81 | elif output_type == 'array_with_contour': 82 | return (seg, generate_segmentation_contour(seg)) 83 | else: 84 | # the hook for pre-defined RnD output functions (AICS internal) 85 | img_list, name_list = ACTB_output(out_img_list, out_name_list, output_type, output_path, fn) 86 | if output_type == 'QCB': 87 | return img_list, name_list 88 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_actn1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from ..core.vessel import vesselness3D 6 | from aicssegmentation.core.output_utils import save_segmentation, ACTN1_output, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | def Workflow_atcn1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 10 | # there was a typo, reproduced here to keep any code relying on the typo working 11 | return Workflow_actn1(struct_img, rescale_ratio, output_type, output_path, fn, output_func) 12 | 13 | def Workflow_actn1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 14 | ########################################################################## 15 | # PARAMETERS: 16 | # note that these parameters are supposed to be fixed for the structure 17 | # and work well accross different datasets 18 | 19 | intensity_norm_param = [3, 15] 20 | vesselness_sigma_1 = [2] 21 | vesselness_cutoff_1 = 0.15 22 | vesselness_sigma_2 = [1] 23 | vesselness_cutoff_2 = 0.05 24 | minArea = 5 25 | ########################################################################## 26 | 27 | out_img_list = [] 28 | out_name_list = [] 29 | 30 | ################### 31 | # PRE_PROCESSING 32 | ################### 33 | # intenisty normalization 34 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 35 | 36 | out_img_list.append(struct_img.copy()) 37 | out_name_list.append('im_norm') 38 | 39 | # rescale if needed 40 | if rescale_ratio>0: 41 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 42 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 43 | 44 | # smoothing 45 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 46 | 47 | out_img_list.append(structure_img_smooth.copy()) 48 | out_name_list.append('im_smooth') 49 | 50 | ################### 51 | # core algorithm 52 | ################### 53 | 54 | # vesselness 3d 55 | response_1 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma_1, tau=1, whiteonblack=True) 56 | response_2 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma_2, tau=1, whiteonblack=True) 57 | bw = np.logical_or(response_1 > vesselness_cutoff_1, response_2 > vesselness_cutoff_2) 58 | 59 | ################### 60 | # POST-PROCESSING 61 | ################### 62 | seg = remove_small_objects(bw, min_size=minArea, connectivity=1, in_place=False) 63 | 64 | # output 65 | seg = seg>0 66 | seg = seg.astype(np.uint8) 67 | seg[seg>0]=255 68 | 69 | out_img_list.append(seg.copy()) 70 | out_name_list.append('bw_final') 71 | 72 | if output_type == 'default': 73 | # the default final output 74 | save_segmentation(seg, False, output_path, fn) 75 | elif output_type == 'AICS_pipeline': 76 | # pre-defined output function for pipeline data 77 | save_segmentation(seg, True, output_path, fn) 78 | elif output_type == 'customize': 79 | # the hook for passing in a customized output function 80 | # output_fun(out_img_list, out_name_list, output_path, fn) 81 | print('please provide custom output function') 82 | elif output_type == 'array': 83 | return seg 84 | elif output_type == 'array_with_contour': 85 | return (seg, generate_segmentation_contour(seg)) 86 | else: 87 | # the hook for pre-defined RnD output functions (AICS internal) 88 | img_list, name_list = ACTN1_output(out_img_list, out_name_list, output_type, output_path, fn) 89 | if output_type == 'QCB': 90 | return img_list, name_list 91 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_atp2a2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from ..core.vessel import vesselnessSliceBySlice 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from scipy import ndimage as ndi 6 | from skimage.morphology import remove_small_objects 7 | from aicssegmentation.core.output_utils import save_segmentation, SEC61B_output, generate_segmentation_contour 8 | from aicsimageprocessing import resize 9 | 10 | def Workflow_atp2a2(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [2.5, 9.0] 17 | vesselness_sigma = [1] 18 | vesselness_cutoff = 0.25 19 | minArea = 15 20 | ########################################################################## 21 | 22 | out_img_list = [] 23 | out_name_list = [] 24 | 25 | ################### 26 | # PRE_PROCESSING 27 | ################### 28 | # intenisty normalization (min/max) 29 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 30 | 31 | out_img_list.append(struct_img.copy()) 32 | out_name_list.append('im_norm') 33 | 34 | # rescale if needed 35 | if rescale_ratio>0: 36 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 37 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 38 | 39 | # smoothing with boundary preserving smoothing 40 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 41 | 42 | out_img_list.append(structure_img_smooth.copy()) 43 | out_name_list.append('im_smooth') 44 | 45 | ################### 46 | # core algorithm 47 | ################### 48 | 49 | # 2d vesselness slice by slice 50 | response = vesselnessSliceBySlice(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 51 | bw = response > vesselness_cutoff 52 | 53 | ################### 54 | # POST-PROCESSING 55 | ################### 56 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 57 | for zz in range(bw.shape[0]): 58 | bw[zz,:,:] = remove_small_objects(bw[zz,:,:], min_size=3, connectivity=1, in_place=False) 59 | 60 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 61 | 62 | # output 63 | seg = seg>0 64 | seg = seg.astype(np.uint8) 65 | seg[seg>0]=255 66 | 67 | out_img_list.append(seg.copy()) 68 | out_name_list.append('bw_final') 69 | 70 | if output_type == 'default': 71 | # the default final output 72 | save_segmentation(seg, False, output_path, fn) 73 | elif output_type == 'AICS_pipeline': 74 | # pre-defined output function for pipeline data 75 | save_segmentation(seg, True, output_path, fn) 76 | elif output_type == 'customize': 77 | # the hook for passing in a customized output function 78 | output_fun(out_img_list, out_name_list, output_path, fn) 79 | elif output_type == 'array': 80 | return seg 81 | elif output_type == 'array_with_contour': 82 | return (seg, generate_segmentation_contour(seg)) 83 | else: 84 | # the hook for pre-defined RnD output functions (AICS internal) 85 | img_list, name_list = SEC61B_output(out_img_list, out_name_list, output_type, output_path, fn) 86 | if output_type == 'QCB': 87 | return img_list, name_list 88 | 89 | 90 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_cardio_actn2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from ..core.vessel import vesselness3D 6 | from aicssegmentation.core.output_utils import save_segmentation, ACTN2_Cardio_output, generate_segmentation_contour 7 | 8 | def Workflow_cardio_actn2(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 9 | ########################################################################## 10 | # PARAMETERS: 11 | # note that these parameters are supposed to be fixed for the structure 12 | # and work well accross different datasets 13 | 14 | intensity_norm_param = [1, 19] 15 | vesselness_sigma = [1] 16 | vesselness_cutoff = 0.02 17 | minArea = 15 18 | ########################################################################## 19 | 20 | out_img_list = [] 21 | out_name_list = [] 22 | 23 | ################### 24 | # PRE_PROCESSING 25 | ################### 26 | # intenisty normalization (min/max) 27 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 28 | 29 | out_img_list.append(struct_img.copy()) 30 | out_name_list.append('im_norm') 31 | 32 | # rescale if needed 33 | if rescale_ratio>0: 34 | struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 35 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 36 | 37 | # smoothing with gaussian filter 38 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 39 | 40 | out_img_list.append(structure_img_smooth.copy()) 41 | out_name_list.append('im_smooth') 42 | 43 | ################### 44 | # core algorithm 45 | ################### 46 | 47 | # vesselness 3d 48 | response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 49 | bw = response > vesselness_cutoff 50 | 51 | ################### 52 | # POST-PROCESSING 53 | ################### 54 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 55 | 56 | # output 57 | seg = seg>0 58 | seg = seg.astype(np.uint8) 59 | seg[seg>0]=255 60 | 61 | out_img_list.append(seg.copy()) 62 | out_name_list.append('bw_final') 63 | 64 | if output_type == 'default': 65 | # the default final output 66 | save_segmentation(seg, False, output_path, fn) 67 | elif output_type == 'AICS_pipeline': 68 | # pre-defined output function for pipeline data 69 | save_segmentation(seg, True, output_path, fn) 70 | elif output_type == 'customize': 71 | # the hook for passing in a customized output function 72 | output_fun(out_img_list, out_name_list, output_path, fn) 73 | elif output_type == 'array': 74 | return seg 75 | elif output_type == 'array_with_contour': 76 | return (seg, generate_segmentation_contour(seg)) 77 | else: 78 | # the hook for other pre-defined RnD output functions (AICS internal) 79 | ACTN2_Cardio_output(out_img_list, out_name_list, output_type, output_path, fn) 80 | 81 | 82 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_cardio_atp2a2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from ..core.vessel import vesselness3D 6 | from aicssegmentation.core.output_utils import save_segmentation, ATP2A2_Cardio_output, generate_segmentation_contour 7 | 8 | 9 | def Workflow_cardio_atp2a2(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 10 | ########################################################################## 11 | # PARAMETERS: 12 | # note that these parameters are supposed to be fixed for the structure 13 | # and work well accross different datasets 14 | 15 | intensity_norm_param = [1, 20] 16 | vesselness_sigma = [1] 17 | vesselness_cutoff = 0.002 18 | minArea = 15 19 | ########################################################################## 20 | 21 | out_img_list = [] 22 | out_name_list = [] 23 | 24 | ################### 25 | # PRE_PROCESSING 26 | ################### 27 | # intenisty normalization (min/max) 28 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 29 | 30 | out_img_list.append(struct_img.copy()) 31 | out_name_list.append('im_norm') 32 | 33 | # rescale if needed 34 | if rescale_ratio>0: 35 | struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 36 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 37 | 38 | # smoothing with gaussian filter 39 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 40 | 41 | out_img_list.append(structure_img_smooth.copy()) 42 | out_name_list.append('im_smooth') 43 | 44 | ################### 45 | # core algorithm 46 | ################### 47 | 48 | # vesselness 3d 49 | response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 50 | bw = response > vesselness_cutoff 51 | 52 | ################### 53 | # POST-PROCESSING 54 | ################### 55 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 56 | 57 | # output 58 | seg = seg>0 59 | seg = seg.astype(np.uint8) 60 | seg[seg>0]=255 61 | 62 | out_img_list.append(seg.copy()) 63 | out_name_list.append('bw_final') 64 | 65 | if output_type == 'default': 66 | # the default final output 67 | save_segmentation(seg, False, output_path, fn) 68 | elif output_type == 'AICS_pipeline': 69 | # pre-defined output function for pipeline data 70 | save_segmentation(seg, True, output_path, fn) 71 | elif output_type == 'customize': 72 | # the hook for passing in a customized output function 73 | output_fun(out_img_list, out_name_list, output_path, fn) 74 | elif output_type == 'array': 75 | return seg 76 | elif output_type == 'array_with_contour': 77 | return (seg, generate_segmentation_contour(seg)) 78 | else: 79 | # the hook for other pre-defined RnD output functions (AICS internal) 80 | ATP2A2_Cardio_output(out_img_list, out_name_list, output_type, output_path, fn) 81 | 82 | 83 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_cardio_fbl.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_slice_by_slice 6 | from skimage.filters import threshold_triangle, threshold_otsu 7 | from skimage.measure import label 8 | from aicssegmentation.core.output_utils import save_segmentation, FBL_output, generate_segmentation_contour 9 | from aicsimageprocessing import resize 10 | from skimage.io import imsave 11 | 12 | 13 | def Workflow_cardio_fbl(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 14 | ########################################################################## 15 | # PARAMETERS: 16 | # note that these parameters are supposed to be fixed for the structure 17 | # and work well accross different datasets 18 | 19 | intensity_norm_param = [0.5, 140] 20 | gaussian_smoothing_sigma = 1 21 | gaussian_smoothing_truncate_range = 3.0 22 | dot_2d_sigma = 1 23 | dot_2d_cutoff = 0.015 24 | minArea = 1 25 | low_level_min_size = 1000 26 | ########################################################################## 27 | 28 | out_img_list = [] 29 | out_name_list = [] 30 | 31 | ################### 32 | # PRE_PROCESSING 33 | ################### 34 | # intenisty normalization (min/max) 35 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 36 | 37 | out_img_list.append(struct_img.copy()) 38 | out_name_list.append('im_norm') 39 | 40 | # rescale if needed 41 | if rescale_ratio>0: 42 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 43 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 44 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 45 | 46 | # smoothing with gaussian filter 47 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 48 | 49 | out_img_list.append(structure_img_smooth.copy()) 50 | out_name_list.append('im_smooth') 51 | 52 | ################### 53 | # core algorithm 54 | ################### 55 | 56 | # step 1: low level thresholding 57 | #global_otsu = threshold_otsu(structure_img_smooth) 58 | global_tri = threshold_triangle(structure_img_smooth) 59 | global_median = np.percentile(structure_img_smooth,50) 60 | 61 | th_low_level = (global_tri + global_median)/2 62 | bw_low_level = structure_img_smooth > th_low_level 63 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 64 | 65 | # step 2: high level thresholding 66 | local_cutoff = 0.333 * threshold_otsu(structure_img_smooth) 67 | bw_high_level = np.zeros_like(bw_low_level) 68 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 69 | for idx in range(num_obj): 70 | single_obj = (lab_low==(idx+1)) 71 | local_otsu = threshold_otsu(structure_img_smooth[single_obj]) 72 | if local_otsu > local_cutoff: 73 | bw_high_level[np.logical_and(structure_img_smooth>local_otsu, single_obj)]=1 74 | 75 | out_img_list.append(bw_high_level.copy()) 76 | out_name_list.append('interm_high') 77 | 78 | # step 3: finer segmentation 79 | response2d = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) 80 | 81 | bw_finer = remove_small_objects(response2d>dot_2d_cutoff, min_size=minArea, connectivity=1, in_place=True) 82 | 83 | out_img_list.append(bw_finer.copy()) 84 | out_name_list.append('bw_fine') 85 | 86 | # merge finer level detection into high level coarse segmentation to include outside dim parts 87 | bw_high_level[bw_finer>0]=1 88 | 89 | ################### 90 | # POST-PROCESSING 91 | ################### 92 | seg = remove_small_objects(bw_high_level>0, min_size=minArea, connectivity=1, in_place=False) 93 | 94 | # output 95 | seg = seg>0 96 | seg = seg.astype(np.uint8) 97 | seg[seg>0]=255 98 | 99 | out_img_list.append(seg.copy()) 100 | out_name_list.append('bw_coarse') 101 | 102 | if output_type == 'default': 103 | # the default final output 104 | save_segmentation(seg, False, output_path, fn) 105 | elif output_type == 'AICS_pipeline': 106 | # pre-defined output function for pipeline data 107 | save_segmentation(seg, True, output_path, fn) 108 | elif output_type == 'customize': 109 | # the hook for passing in a customized output function 110 | output_fun(out_img_list, out_name_list, output_path, fn) 111 | elif output_type == 'array': 112 | return seg 113 | elif output_type == 'array_with_contour': 114 | return (seg, generate_segmentation_contour(seg)) 115 | else: 116 | # the hook for pre-defined RnD output functions (AICS internal) 117 | img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) 118 | if output_type == 'QCB': 119 | return img_list, name_list 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_cardio_fbl_100x.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_slice_by_slice 6 | from skimage.filters import threshold_triangle, threshold_otsu 7 | from skimage.measure import label 8 | from aicssegmentation.core.output_utils import save_segmentation, FBL_output, generate_segmentation_contour 9 | from aicsimageprocessing import resize 10 | from skimage.io import imsave 11 | 12 | 13 | def Workflow_cardio_fbl_100x(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 14 | ########################################################################## 15 | # PARAMETERS: 16 | # note that these parameters are supposed to be fixed for the structure 17 | # and work well accross different datasets 18 | 19 | intensity_norm_param = [0.5, 3] 20 | gaussian_smoothing_sigma = 1 21 | gaussian_smoothing_truncate_range = 3.0 22 | dot_2d_sigma = 1 23 | dot_2d_cutoff = 0.015 24 | minArea = 1 25 | low_level_min_size = 600 26 | ########################################################################## 27 | 28 | out_img_list = [] 29 | out_name_list = [] 30 | 31 | ################### 32 | # PRE_PROCESSING 33 | ################### 34 | # intenisty normalization (min/max) 35 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 36 | 37 | out_img_list.append(struct_img.copy()) 38 | out_name_list.append('im_norm') 39 | 40 | # rescale if needed 41 | if rescale_ratio>0: 42 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 43 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 44 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 45 | 46 | # smoothing with gaussian filter 47 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 48 | 49 | out_img_list.append(structure_img_smooth.copy()) 50 | out_name_list.append('im_smooth') 51 | 52 | ################### 53 | # core algorithm 54 | ################### 55 | 56 | # step 1: low level thresholding 57 | #global_otsu = threshold_otsu(structure_img_smooth) 58 | global_tri = threshold_triangle(structure_img_smooth) 59 | global_median = np.percentile(structure_img_smooth,50) 60 | 61 | th_low_level = (global_tri + global_median)/2 62 | bw_low_level = structure_img_smooth > th_low_level 63 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 64 | 65 | # step 2: high level thresholding 66 | local_cutoff = 0.333 * threshold_otsu(structure_img_smooth) 67 | bw_high_level = np.zeros_like(bw_low_level) 68 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 69 | for idx in range(num_obj): 70 | single_obj = (lab_low==(idx+1)) 71 | local_otsu = threshold_otsu(structure_img_smooth[single_obj]) 72 | if local_otsu > local_cutoff: 73 | bw_high_level[np.logical_and(structure_img_smooth>1.1*local_otsu, single_obj)]=1 74 | 75 | out_img_list.append(bw_high_level.copy()) 76 | out_name_list.append('interm_high') 77 | 78 | # step 3: finer segmentation 79 | response2d = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) 80 | 81 | bw_finer = remove_small_objects(response2d>dot_2d_cutoff, min_size=minArea, connectivity=1, in_place=True) 82 | 83 | out_img_list.append(bw_finer.copy()) 84 | out_name_list.append('bw_fine') 85 | 86 | # merge finer level detection into high level coarse segmentation to include outside dim parts 87 | bw_high_level[bw_finer>0]=1 88 | 89 | ################### 90 | # POST-PROCESSING 91 | ################### 92 | seg = remove_small_objects(bw_high_level>0, min_size=minArea, connectivity=1, in_place=False) 93 | 94 | # output 95 | seg = seg>0 96 | seg = seg.astype(np.uint8) 97 | seg[seg>0]=255 98 | 99 | out_img_list.append(seg.copy()) 100 | out_name_list.append('bw_coarse') 101 | 102 | if output_type == 'default': 103 | # the default final output 104 | save_segmentation(seg, False, output_path, fn) 105 | elif output_type == 'AICS_pipeline': 106 | # pre-defined output function for pipeline data 107 | save_segmentation(seg, True, output_path, fn) 108 | elif output_type == 'customize': 109 | # the hook for passing in a customized output function 110 | output_fun(out_img_list, out_name_list, output_path, fn) 111 | elif output_type == 'array': 112 | return seg 113 | elif output_type == 'array_with_contour': 114 | return (seg, generate_segmentation_contour(seg)) 115 | else: 116 | # the hook for pre-defined RnD output functions (AICS internal) 117 | img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) 118 | if output_type == 'QCB': 119 | return img_list, name_list 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_cardio_myl7.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from ..core.vessel import vesselness3D 6 | from aicssegmentation.core.output_utils import save_segmentation, MYL7_Cardio_output, generate_segmentation_contour 7 | 8 | def Workflow_cardio_myl7(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 9 | ########################################################################## 10 | # PARAMETERS: 11 | # note that these parameters are supposed to be fixed for the structure 12 | # and work well accross different datasets 13 | 14 | intensity_norm_param = [8, 15.5] 15 | vesselness_sigma = [1] 16 | vesselness_cutoff = 0.01 17 | minArea = 15 18 | ########################################################################## 19 | 20 | out_img_list = [] 21 | out_name_list = [] 22 | 23 | ################### 24 | # PRE_PROCESSING 25 | ################### 26 | # intenisty normalization (min/max) 27 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 28 | 29 | out_img_list.append(struct_img.copy()) 30 | out_name_list.append('im_norm') 31 | 32 | # rescale if needed 33 | if rescale_ratio>0: 34 | struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 35 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 36 | 37 | # smoothing with gaussian filter 38 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 39 | 40 | out_img_list.append(structure_img_smooth.copy()) 41 | out_name_list.append('im_smooth') 42 | 43 | ################### 44 | # core algorithm 45 | ################### 46 | 47 | # vesselness 3d 48 | response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 49 | bw = response > vesselness_cutoff 50 | 51 | ################### 52 | # POST-PROCESSING 53 | ################### 54 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 55 | 56 | # output 57 | seg = seg>0 58 | seg = seg.astype(np.uint8) 59 | seg[seg>0]=255 60 | 61 | out_img_list.append(seg.copy()) 62 | out_name_list.append('bw_final') 63 | 64 | if output_type == 'default': 65 | # the default final output 66 | save_segmentation(seg, False, output_path, fn) 67 | elif output_type == 'AICS_pipeline': 68 | # pre-defined output function for pipeline data 69 | save_segmentation(seg, True, output_path, fn) 70 | elif output_type == 'customize': 71 | # the hook for passing in a customized output function 72 | output_fun(out_img_list, out_name_list, output_path, fn) 73 | elif output_type == 'array': 74 | return seg 75 | elif output_type == 'array_with_contour': 76 | return (seg, generate_segmentation_contour(seg)) 77 | else: 78 | # the hook for other pre-defined RnD output functions (AICS internal) 79 | MYL7_Cardio_output(out_img_list, out_name_list, output_type, output_path, fn) 80 | 81 | 82 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_cardio_tnni1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from ..core.vessel import vesselness3D 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from skimage.morphology import remove_small_objects 6 | from aicssegmentation.core.output_utils import save_segmentation, TNNI1_Cardio_output, generate_segmentation_contour 7 | 8 | 9 | def Workflow_cardio_tnni1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 10 | ########################################################################## 11 | # PARAMETERS: 12 | # note that these parameters are supposed to be fixed for the structure 13 | # and work well accross different datasets 14 | 15 | intensity_norm_param = [2, 11] 16 | vesselness_sigma = [1] 17 | vesselness_cutoff = 0.01 18 | minArea = 15 19 | ########################################################################## 20 | 21 | out_img_list = [] 22 | out_name_list = [] 23 | 24 | ################### 25 | # PRE_PROCESSING 26 | ################### 27 | # intenisty normalization (min/max) 28 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 29 | 30 | out_img_list.append(struct_img.copy()) 31 | out_name_list.append('im_norm') 32 | 33 | # rescale if needed 34 | if rescale_ratio>0: 35 | struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 36 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 37 | 38 | # smoothing 39 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 40 | 41 | out_img_list.append(structure_img_smooth.copy()) 42 | out_name_list.append('im_smooth') 43 | 44 | ################### 45 | # core algorithm 46 | ################### 47 | 48 | # vesselness 3d 49 | response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 50 | bw = response > vesselness_cutoff 51 | 52 | ################### 53 | # POST-PROCESSING 54 | ################### 55 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 56 | 57 | # output 58 | seg = seg>0 59 | seg = seg.astype(np.uint8) 60 | seg[seg>0]=255 61 | 62 | out_img_list.append(seg.copy()) 63 | out_name_list.append('bw_final') 64 | 65 | if output_type == 'default': 66 | # the default final output 67 | save_segmentation(seg, False, output_path, fn) 68 | elif output_type == 'AICS_pipeline': 69 | # pre-defined output function for pipeline data 70 | save_segmentation(seg, True, output_path, fn) 71 | elif output_type == 'customize': 72 | # the hook for passing in a customized output function 73 | output_fun(out_img_list, out_name_list, output_path, fn) 74 | elif output_type == 'array': 75 | return seg 76 | elif output_type == 'array_with_contour': 77 | return (seg, generate_segmentation_contour(seg)) 78 | else: 79 | # the hook for other pre-defined RnD output functions (AICS internal) 80 | TNNI1_Cardio_output(out_img_list, out_name_list, output_type, output_path, fn) 81 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_cardio_ttn.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from ..core.vessel import vesselness3D 6 | from aicssegmentation.core.output_utils import save_segmentation, TTN_Cardio_output, generate_segmentation_contour 7 | 8 | 9 | def Workflow_cardio_ttn(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 10 | ########################################################################## 11 | # PARAMETERS: 12 | # note that these parameters are supposed to be fixed for the structure 13 | # and work well accross different datasets 14 | 15 | intensity_norm_param = [8, 15.5] 16 | vesselness_sigma = [1] 17 | vesselness_cutoff = 0.02 18 | minArea = 15 19 | ########################################################################## 20 | 21 | out_img_list = [] 22 | out_name_list = [] 23 | 24 | ################### 25 | # PRE_PROCESSING 26 | ################### 27 | # intenisty normalization (min/max) 28 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 29 | 30 | out_img_list.append(struct_img.copy()) 31 | out_name_list.append('im_norm') 32 | 33 | # rescale if needed 34 | if rescale_ratio>0: 35 | struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 36 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 37 | 38 | 39 | # smoothing with gaussian filter 40 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 41 | 42 | out_img_list.append(structure_img_smooth.copy()) 43 | out_name_list.append('im_smooth') 44 | 45 | ################### 46 | # core algorithm 47 | ################### 48 | 49 | # vesselness 3d 50 | response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 51 | bw = response > vesselness_cutoff 52 | 53 | ################### 54 | # POST-PROCESSING 55 | ################### 56 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 57 | 58 | # output 59 | seg = seg>0 60 | seg = seg.astype(np.uint8) 61 | seg[seg>0]=255 62 | 63 | out_img_list.append(seg.copy()) 64 | out_name_list.append('bw_final') 65 | 66 | if output_type == 'default': 67 | # the default final output 68 | save_segmentation(seg, False, output_path, fn) 69 | elif output_type == 'AICS_pipeline': 70 | # pre-defined output function for pipeline data 71 | save_segmentation(seg, True, output_path, fn) 72 | elif output_type == 'customize': 73 | # the hook for passing in a customized output function 74 | output_fun(out_img_list, out_name_list, output_path, fn) 75 | elif output_type == 'array': 76 | return seg 77 | elif output_type == 'array_with_contour': 78 | return (seg, generate_segmentation_contour(seg)) 79 | else: 80 | # the hook for other pre-defined RnD output functions (AICS internal) 81 | TTN_Cardio_output(out_img_list, out_name_list, output_type, output_path, fn) 82 | 83 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_cetn2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_slice_by_slice 5 | from ..core.seg_dot import dot_3d 6 | from skimage.feature import peak_local_max 7 | from scipy.ndimage import distance_transform_edt 8 | from skimage.measure import label 9 | from aicssegmentation.core.output_utils import save_segmentation, CETN2_output, generate_segmentation_contour 10 | from aicsimageprocessing import resize 11 | 12 | 13 | def Workflow_cetn2(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 14 | ########################################################################## 15 | # PARAMETERS: 16 | # note that these parameters are supposed to be fixed for the structure 17 | # and work well accross different datasets 18 | 19 | intensity_norm_param_seg = [12, 160, 300, 2000] 20 | intensity_norm_param_peak = [5000] 21 | gaussian_smoothing_sigma = 1 22 | gaussian_smoothing_truncate_range = 3.0 23 | dot_3d_sigma = 1 24 | dot_3d_cutoff = 0.04 25 | minArea = 3 26 | ########################################################################## 27 | 28 | out_img_list = [] 29 | out_name_list = [] 30 | 31 | ################### 32 | # PRE_PROCESSING 33 | ################### 34 | # intenisty normalization (min/max) 35 | struct_img_for_seg = intensity_normalization(struct_img.copy(), scaling_param=intensity_norm_param_seg) 36 | struct_img_for_peak = intensity_normalization(struct_img.copy(), scaling_param=intensity_norm_param_peak) 37 | 38 | out_img_list.append(struct_img_for_seg.copy()) 39 | out_name_list.append('im_norm') 40 | 41 | # rescale if needed 42 | if rescale_ratio>0: 43 | struct_img_for_seg = resize(struct_img_for_seg, [1, rescale_ratio, rescale_ratio], method="cubic") 44 | struct_img_for_seg = (struct_img_for_seg - struct_img_for_seg.min() + 1e-8)/(struct_img_for_seg.max() - struct_img_for_seg.min() + 1e-8) 45 | struct_img_for_peak = resize(struct_img_for_peak, [1, rescale_ratio, rescale_ratio], method="cubic") 46 | struct_img_for_peak = (struct_img_for_peak - struct_img_for_peak.min() + 1e-8)/(struct_img_for_peak.max() - struct_img_for_peak.min() + 1e-8) 47 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 48 | 49 | # smoothing with gaussian filter 50 | structure_img_smooth_for_seg = image_smoothing_gaussian_slice_by_slice(struct_img_for_seg, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 51 | 52 | out_img_list.append(structure_img_smooth_for_seg.copy()) 53 | out_name_list.append('im_smooth') 54 | 55 | ################### 56 | # core algorithm 57 | ################### 58 | 59 | # step 1: LOG 3d 60 | response = dot_3d(structure_img_smooth_for_seg, log_sigma=dot_3d_sigma) 61 | bw = response > dot_3d_cutoff 62 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 63 | 64 | out_img_list.append(bw.copy()) 65 | out_name_list.append('interm_mask') 66 | 67 | # step 2: 'local_maxi + watershed' for cell cutting 68 | local_maxi = peak_local_max(struct_img_for_peak, labels=label(bw), min_distance=2, indices=False) 69 | 70 | out_img_list.append(local_maxi.copy()) 71 | out_name_list.append('interm_local_max') 72 | 73 | distance = distance_transform_edt(bw) 74 | im_watershed = watershed(-distance, label(dilation(local_maxi, selem=ball(1))), mask=bw, watershed_line=True) 75 | 76 | ################### 77 | # POST-PROCESSING 78 | ################### 79 | seg = remove_small_objects(im_watershed, min_size=minArea, connectivity=1, in_place=False) 80 | 81 | # output 82 | seg = seg>0 83 | seg = seg.astype(np.uint8) 84 | seg[seg>0]=255 85 | 86 | out_img_list.append(seg.copy()) 87 | out_name_list.append('bw_final') 88 | 89 | if output_type == 'default': 90 | # the default final output 91 | save_segmentation(seg, False, output_path, fn) 92 | elif output_type == 'AICS_pipeline': 93 | # pre-defined output function for pipeline data 94 | save_segmentation(seg, True, output_path, fn) 95 | elif output_type == 'customize': 96 | # the hook for passing in a customized output function 97 | output_fun(out_img_list, out_name_list, output_path, fn) 98 | elif output_type == 'array': 99 | return seg 100 | elif output_type == 'array_with_contour': 101 | return (seg, generate_segmentation_contour(seg)) 102 | else: 103 | # the hook for pre-defined RnD output functions (AICS internal) 104 | img_list, name_list = CETN2_output(out_img_list, out_name_list, output_type, output_path, fn) 105 | if output_type == 'QCB': 106 | return img_list, name_list -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_ctnnb1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_slice_by_slice 6 | from aicssegmentation.core.output_utils import save_segmentation, CTNNB1_output, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | 10 | def Workflow_ctnnb1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [4, 27] 17 | gaussian_smoothing_sigma = 1 18 | gaussian_smoothing_truncate_range = 3.0 19 | dot_2d_sigma = 1.5 20 | dot_2d_cutoff = 0.01 21 | minArea = 10 22 | ########################################################################## 23 | 24 | out_img_list = [] 25 | out_name_list = [] 26 | 27 | ################### 28 | # PRE_PROCESSING 29 | ################### 30 | # intenisty normalization (min/max) 31 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 32 | 33 | out_img_list.append(struct_img.copy()) 34 | out_name_list.append('im_norm') 35 | 36 | # rescale if needed 37 | if rescale_ratio>0: 38 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 39 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 40 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 41 | 42 | # smoothing 43 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 44 | 45 | out_img_list.append(structure_img_smooth.copy()) 46 | out_name_list.append('im_smooth') 47 | 48 | ################### 49 | # core algorithm 50 | ################### 51 | 52 | response = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) 53 | bw = response > dot_2d_cutoff 54 | 55 | ################### 56 | # POST-PROCESSING 57 | ################### 58 | seg = remove_small_objects(bw, min_size=minArea, connectivity=1, in_place=False) 59 | 60 | # output 61 | seg = seg>0 62 | seg = seg.astype(np.uint8) 63 | seg[seg>0]=255 64 | 65 | out_img_list.append(seg.copy()) 66 | out_name_list.append('bw_final') 67 | 68 | if output_type == 'default': 69 | # the default final output 70 | save_segmentation(seg, False, output_path, fn) 71 | elif output_type == 'AICS_pipeline': 72 | # pre-defined output function for pipeline data 73 | save_segmentation(seg, True, output_path, fn) 74 | elif output_type == 'customize': 75 | # the hook for passing in a customized output function 76 | output_fun(out_img_list, out_name_list, output_path, fn) 77 | elif output_type == 'array': 78 | return seg 79 | elif output_type == 'array_with_contour': 80 | return (seg, generate_segmentation_contour(seg)) 81 | else: 82 | # the hook for pre-defined RnD output functions (AICS internal) 83 | img_list, name_list = CTNNB1_output(out_img_list, out_name_list, output_type, output_path, fn) 84 | if output_type == 'QCB': 85 | return img_list, name_list -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_drug_npm1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_slice_by_slice 6 | from skimage.filters import threshold_triangle, threshold_otsu 7 | from skimage.measure import label 8 | from aicssegmentation.core.output_utils import save_segmentation, FBL_output, generate_segmentation_contour 9 | from aicsimageprocessing import resize 10 | from aicssegmentation.core.seg_dot import dot_3d_wrapper 11 | 12 | def Workflow_drug_npm1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 13 | ########################################################################## 14 | # PARAMETERS: 15 | # note that these parameters are supposed to be fixed for the structure 16 | # and work well accross different datasets 17 | 18 | intensity_norm_param = [0.5, 25] 19 | gaussian_smoothing_sigma = 1 20 | gaussian_smoothing_truncate_range = 3.0 21 | dot_2d_sigma = 1 22 | dot_2d_cutoff = 0.01 23 | minArea = 5 24 | low_level_min_size = 700 25 | ########################################################################## 26 | 27 | out_img_list = [] 28 | out_name_list = [] 29 | 30 | ################### 31 | # PRE_PROCESSING 32 | ################### 33 | # intenisty normalization (min/max) 34 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 35 | 36 | out_img_list.append(struct_img.copy()) 37 | out_name_list.append('im_norm') 38 | 39 | # rescale if needed 40 | if rescale_ratio>0: 41 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 42 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 43 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 44 | 45 | # smoothing with gaussian filter 46 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 47 | 48 | out_img_list.append(structure_img_smooth.copy()) 49 | out_name_list.append('im_smooth') 50 | 51 | ################### 52 | # core algorithm 53 | ################### 54 | 55 | # step 1: low level thresholding 56 | #global_otsu = threshold_otsu(structure_img_smooth) 57 | global_tri = threshold_triangle(structure_img_smooth) 58 | global_median = np.percentile(structure_img_smooth,50) 59 | 60 | th_low_level = (global_tri + global_median)/2 61 | bw_low_level = structure_img_smooth > th_low_level 62 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 63 | 64 | # step 2: high level thresholding 65 | bw_high_level = np.zeros_like(bw_low_level) 66 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 67 | for idx in range(num_obj): 68 | single_obj = (lab_low==(idx+1)) 69 | local_otsu = threshold_otsu(structure_img_smooth[single_obj]) 70 | bw_high_level[np.logical_and(structure_img_smooth>local_otsu, single_obj)]=1 71 | 72 | out_img_list.append(bw_high_level.copy()) 73 | out_name_list.append('interm_high') 74 | 75 | # step 3: finer segmentation 76 | # response2d = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) 77 | # bw_finer = remove_small_objects(response2d>dot_2d_cutoff, min_size=minArea, connectivity=1, in_place=True) 78 | bw_finer = dot_3d_wrapper(structure_img_smooth, s3_param = [[1, 0.015]]) 79 | 80 | out_img_list.append(bw_finer.copy()) 81 | out_name_list.append('bw_fine') 82 | 83 | # merge finer level detection into high level coarse segmentation to include outside dim parts 84 | bw_high_level[bw_finer>0]=1 85 | 86 | ################### 87 | # POST-PROCESSING 88 | ################### 89 | seg = remove_small_objects(bw_high_level>0, min_size=minArea, connectivity=1, in_place=False) 90 | 91 | # output 92 | seg = seg>0 93 | seg = seg.astype(np.uint8) 94 | seg[seg>0]=255 95 | 96 | out_img_list.append(seg.copy()) 97 | out_name_list.append('bw_coarse') 98 | 99 | if output_type == 'default': 100 | # the default final output 101 | save_segmentation(seg, False, output_path, fn) 102 | elif output_type == 'AICS_pipeline': 103 | # pre-defined output function for pipeline data 104 | save_segmentation(seg, True, output_path, fn) 105 | elif output_type == 'customize': 106 | # the hook for passing in a customized output function 107 | output_fun(out_img_list, out_name_list, output_path, fn) 108 | elif output_type == 'array': 109 | return seg 110 | elif output_type == 'array_with_contour': 111 | return (seg, generate_segmentation_contour(seg)) 112 | else: 113 | # the hook for pre-defined RnD output functions (AICS internal) 114 | img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) 115 | if output_type == 'QCB': 116 | return img_list, name_list 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_dsp.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_slice_by_slice 5 | from ..core.seg_dot import dot_3d 6 | from skimage.feature import peak_local_max 7 | from scipy.ndimage import distance_transform_edt 8 | from skimage.measure import label 9 | from aicssegmentation.core.output_utils import save_segmentation, DSP_output, generate_segmentation_contour 10 | from aicsimageprocessing import resize 11 | 12 | 13 | def Workflow_dsp(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 14 | ########################################################################## 15 | # PARAMETERS: 16 | # note that these parameters are supposed to be fixed for the structure 17 | # and work well accross different datasets 18 | 19 | intensity_norm_param = [8000] 20 | gaussian_smoothing_sigma = 1 21 | gaussian_smoothing_truncate_range = 3.0 22 | dot_3d_sigma = 1 23 | dot_3d_cutoff = 0.012 24 | minArea = 4 25 | ########################################################################## 26 | 27 | out_img_list = [] 28 | out_name_list = [] 29 | 30 | ################### 31 | # PRE_PROCESSING 32 | ################### 33 | # intenisty normalization (min/max) 34 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 35 | 36 | out_img_list.append(struct_img.copy()) 37 | out_name_list.append('im_norm') 38 | 39 | # rescale if needed 40 | if rescale_ratio>0: 41 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 42 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 43 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 44 | 45 | # smoothing with gaussian filter 46 | structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 47 | 48 | out_img_list.append(structure_img_smooth.copy()) 49 | out_name_list.append('im_smooth') 50 | 51 | ################### 52 | # core algorithm 53 | ################### 54 | 55 | # step 1: LOG 3d 56 | response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) 57 | bw = response > dot_3d_cutoff 58 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 59 | 60 | out_img_list.append(bw.copy()) 61 | out_name_list.append('interm_mask') 62 | 63 | # step 2: 'local_maxi + watershed' for cell cutting 64 | local_maxi = peak_local_max(struct_img,labels=label(bw), min_distance=2, indices=False) 65 | 66 | out_img_list.append(local_maxi.copy()) 67 | out_name_list.append('interm_local_max') 68 | 69 | distance = distance_transform_edt(bw) 70 | im_watershed = watershed(-distance, label(dilation(local_maxi, selem=ball(1))), mask=bw, watershed_line=True) 71 | 72 | ################### 73 | # POST-PROCESSING 74 | ################### 75 | seg = remove_small_objects(im_watershed, min_size=minArea, connectivity=1, in_place=False) 76 | 77 | # output 78 | seg = seg>0 79 | seg = seg.astype(np.uint8) 80 | seg[seg>0]=255 81 | 82 | out_img_list.append(seg.copy()) 83 | out_name_list.append('bw_final') 84 | 85 | if output_type == 'default': 86 | # the default final output 87 | save_segmentation(seg, False, output_path, fn) 88 | elif output_type == 'AICS_pipeline': 89 | # pre-defined output function for pipeline data 90 | save_segmentation(seg, True, output_path, fn) 91 | elif output_type == 'customize': 92 | # the hook for passing in a customized output function 93 | output_fun(out_img_list, out_name_list, output_path, fn) 94 | elif output_type == 'array': 95 | return seg 96 | elif output_type == 'array_with_contour': 97 | return (seg, generate_segmentation_contour(seg)) 98 | else: 99 | # the hook for pre-defined RnD output functions (AICS internal) 100 | img_list, name_list = DSP_output(out_img_list, out_name_list, output_type, output_path, fn) 101 | if output_type == 'QCB': 102 | return img_list, name_list 103 | 104 | 105 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_fbl.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_slice_by_slice 6 | from skimage.filters import threshold_triangle, threshold_otsu 7 | from skimage.measure import label 8 | from aicssegmentation.core.output_utils import save_segmentation, FBL_output, generate_segmentation_contour 9 | from aicsimageprocessing import resize 10 | 11 | 12 | def Workflow_fbl(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 13 | ########################################################################## 14 | # PARAMETERS: 15 | # note that these parameters are supposed to be fixed for the structure 16 | # and work well accross different datasets 17 | 18 | intensity_norm_param = [0.5, 18] 19 | gaussian_smoothing_sigma = 1 20 | gaussian_smoothing_truncate_range = 3.0 21 | dot_2d_sigma = 1 22 | dot_2d_cutoff = 0.01 # 0.01 as default 23 | minArea = 5 24 | low_level_min_size = 700 25 | ########################################################################## 26 | 27 | out_img_list = [] 28 | out_name_list = [] 29 | 30 | ################### 31 | # PRE_PROCESSING 32 | ################### 33 | # intenisty normalization (min/max) 34 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 35 | 36 | out_img_list.append(struct_img.copy()) 37 | out_name_list.append('im_norm') 38 | 39 | # rescale if needed 40 | if rescale_ratio>0: 41 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 42 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 43 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 44 | 45 | # smoothing with gaussian filter 46 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 47 | 48 | out_img_list.append(structure_img_smooth.copy()) 49 | out_name_list.append('im_smooth') 50 | 51 | ################### 52 | # core algorithm 53 | ################### 54 | 55 | # step 1: low level thresholding 56 | #global_otsu = threshold_otsu(structure_img_smooth) 57 | global_tri = threshold_triangle(structure_img_smooth) 58 | global_median = np.percentile(structure_img_smooth,50) 59 | 60 | th_low_level = (global_tri + global_median)/2 61 | bw_low_level = structure_img_smooth > th_low_level 62 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 63 | 64 | # step 2: high level thresholding 65 | bw_high_level = np.zeros_like(bw_low_level) 66 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 67 | for idx in range(num_obj): 68 | single_obj = (lab_low==(idx+1)) 69 | local_otsu = threshold_otsu(structure_img_smooth[single_obj]) 70 | bw_high_level[np.logical_and(structure_img_smooth>local_otsu, single_obj)]=1 71 | 72 | out_img_list.append(bw_high_level.copy()) 73 | out_name_list.append('interm_high') 74 | 75 | # step 3: finer segmentation 76 | response2d = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) 77 | bw_finer = remove_small_objects(response2d>dot_2d_cutoff, min_size=minArea, connectivity=1, in_place=True) 78 | 79 | out_img_list.append(bw_finer.copy()) 80 | out_name_list.append('bw_fine') 81 | 82 | # merge finer level detection into high level coarse segmentation to include outside dim parts 83 | bw_high_level[bw_finer>0]=1 84 | 85 | ################### 86 | # POST-PROCESSING 87 | ################### 88 | seg = remove_small_objects(bw_high_level>0, min_size=minArea, connectivity=1, in_place=False) 89 | 90 | # output 91 | seg = seg>0 92 | seg = seg.astype(np.uint8) 93 | seg[seg>0]=255 94 | 95 | out_img_list.append(seg.copy()) 96 | out_name_list.append('bw_coarse') 97 | 98 | if output_type == 'default': 99 | # the default final output 100 | save_segmentation(seg, False, output_path, fn) 101 | elif output_type == 'AICS_pipeline': 102 | # pre-defined output function for pipeline data 103 | save_segmentation(seg, True, output_path, fn) 104 | elif output_type == 'customize': 105 | # the hook for passing in a customized output function 106 | output_fun(out_img_list, out_name_list, output_path, fn) 107 | elif output_type == 'array': 108 | return seg 109 | elif output_type == 'array_with_contour': 110 | return (seg, generate_segmentation_contour(seg)) 111 | else: 112 | # the hook for pre-defined RnD output functions (AICS internal) 113 | img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) 114 | if output_type == 'QCB': 115 | return img_list, name_list 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_fbl_labelfree_4dn.py: -------------------------------------------------------------------------------- 1 | ###### import functions #### 2 | import numpy as np 3 | import os 4 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 5 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 6 | from ..core.seg_dot import dot_slice_by_slice, dot_2d_slice_by_slice_wrapper 7 | from skimage.filters import threshold_triangle, threshold_otsu 8 | from skimage.measure import label 9 | from aicsimageprocessing import resize 10 | 11 | #### do not remove #### 12 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour 13 | 14 | def Workflow_fbl_labelfree_4dn(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): 15 | ########################################################################## 16 | # PARAMETERS: 17 | minArea = 5 18 | low_level_min_size = 7000 19 | s2_param = [[0.5, 0.1]] 20 | intensity_scaling_param = [0.5, 19.5] 21 | gaussian_smoothing_sigma = 1 22 | 23 | ########################################################################## 24 | 25 | ################### 26 | # PRE_PROCESSING 27 | ################### 28 | # intenisty normalization 29 | struct_norm = intensity_normalization(struct_img, scaling_param=intensity_scaling_param) 30 | 31 | # smoothing 32 | struct_smooth = image_smoothing_gaussian_3d(struct_norm, sigma=gaussian_smoothing_sigma) 33 | 34 | ################### 35 | # core algorithm 36 | ################### 37 | # step 1: low level thresholding 38 | #global_otsu = threshold_otsu(structure_img_smooth) 39 | global_tri = threshold_triangle(struct_smooth) 40 | global_median = np.percentile(struct_smooth,50) 41 | 42 | th_low_level = (global_tri + global_median)/2 43 | bw_low_level = struct_smooth > th_low_level 44 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 45 | 46 | # step 2: high level thresholding 47 | bw_high_level = np.zeros_like(bw_low_level) 48 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 49 | for idx in range(num_obj): 50 | single_obj = (lab_low==(idx+1)) 51 | local_otsu = threshold_otsu(struct_smooth[single_obj]) 52 | bw_high_level[np.logical_and(struct_smooth>local_otsu*1.2, single_obj)]=1 53 | 54 | # step 3: finer segmentation 55 | response2d = dot_2d_slice_by_slice_wrapper(struct_smooth, s2_param) 56 | bw_finer = remove_small_objects(response2d, min_size=minArea, connectivity=1, in_place=True) 57 | 58 | # merge finer level detection into high level coarse segmentation to include outside dim parts 59 | bw_high_level[bw_finer>0]=1 60 | 61 | ################### 62 | # POST-PROCESSING 63 | # make sure the variable name of final segmentation is 'seg' 64 | ################### 65 | seg = remove_small_objects(bw_high_level, min_size=minArea, connectivity=1, in_place=True) 66 | 67 | # output 68 | seg = seg>0 69 | seg = seg.astype(np.uint8) 70 | seg[seg>0]=255 71 | 72 | if output_type == 'default': 73 | # the default final output 74 | save_segmentation(seg, False, output_path, fn) 75 | elif output_type == 'array': 76 | return seg 77 | elif output_type == 'array_with_contour': 78 | return (seg, generate_segmentation_contour(seg)) 79 | else: 80 | print('your can implement your output hook here, but not yet') 81 | quit() 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_gja1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_slice_by_slice 5 | from ..core.seg_dot import dot_3d, dot_slice_by_slice 6 | from skimage.measure import label 7 | from aicssegmentation.core.output_utils import save_segmentation, GJA1_output, generate_segmentation_contour 8 | from aicsimageprocessing import resize 9 | 10 | def Workflow_gja1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | ########################################################################## 13 | # PARAMETERS: 14 | # note that these parameters are supposed to be fixed for the structure 15 | # and work well accross different datasets 16 | 17 | intensity_norm_param = [1, 40] 18 | gaussian_smoothing_sigma = 1 19 | gaussian_smoothing_truncate_range = 3.0 20 | dot_3d_sigma = 1 21 | dot_3d_cutoff = 0.031 # 0.025 22 | dot_2d_cutoff = 0.0175 23 | minArea = 5 24 | ########################################################################## 25 | 26 | out_img_list = [] 27 | out_name_list = [] 28 | 29 | ################### 30 | # PRE_PROCESSING 31 | ################### 32 | # intenisty normalization (min/max) 33 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 34 | 35 | out_img_list.append(struct_img.copy()) 36 | out_name_list.append('im_norm') 37 | 38 | # rescale if needed 39 | if rescale_ratio>0: 40 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 41 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 42 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 43 | 44 | # smoothing with gaussian filter 45 | structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 46 | 47 | out_img_list.append(structure_img_smooth.copy()) 48 | out_name_list.append('im_smooth') 49 | 50 | ################### 51 | # core algorithm 52 | ################### 53 | 54 | # step 1: LOG 3d 55 | response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) 56 | bw = response > dot_3d_cutoff 57 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 58 | 59 | ################### 60 | # POST-PROCESSING 61 | ################### 62 | seg = remove_small_objects(bw, min_size=minArea, connectivity=1, in_place=False) 63 | 64 | # output 65 | seg = seg>0 66 | seg = seg.astype(np.uint8) 67 | seg[seg>0]=255 68 | 69 | out_img_list.append(seg.copy()) 70 | out_name_list.append('bw_final') 71 | 72 | if output_type == 'default': 73 | # the default final output 74 | save_segmentation(seg, False, output_path, fn) 75 | elif output_type == 'AICS_pipeline': 76 | # pre-defined output function for pipeline data 77 | save_segmentation(seg, True, output_path, fn) 78 | elif output_type == 'customize': 79 | # the hook for passing in a customized output function 80 | output_fun(out_img_list, out_name_list, output_path, fn) 81 | elif output_type == 'array': 82 | return seg 83 | elif output_type == 'array_with_contour': 84 | return (seg, generate_segmentation_contour(seg)) 85 | else: 86 | # the hook for pre-defined RnD output functions (AICS internal) 87 | img_list, name_list = GJA1_output(out_img_list, out_name_list, output_type, output_path, fn) 88 | if output_type == 'QCB': 89 | return img_list, name_list 90 | 91 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_h2b.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 4 | from ..core.seg_dot import dot_2d_slice_by_slice_wrapper 5 | from skimage.morphology import remove_small_objects 6 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | 10 | def Workflow_h2b(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [1.0, 14] 17 | s2_param = [[1, 0.014], [2, 0.039]] 18 | minArea = 3 19 | ########################################################################## 20 | 21 | out_img_list = [] 22 | out_name_list = [] 23 | 24 | ################### 25 | # PRE_PROCESSING 26 | ################### 27 | # intenisty normalization (min/max) 28 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 29 | 30 | out_img_list.append(struct_img.copy()) 31 | out_name_list.append('im_norm') 32 | 33 | # rescale if needed 34 | if rescale_ratio>0: 35 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 36 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 37 | 38 | # smoothing with gaussian filter 39 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 40 | 41 | out_img_list.append(structure_img_smooth.copy()) 42 | out_name_list.append('im_smooth') 43 | 44 | ################### 45 | # core algorithm 46 | ################### 47 | 48 | bw = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param) 49 | 50 | ################### 51 | # POST-PROCESSING 52 | ################### 53 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 54 | 55 | # output 56 | seg = seg>0 57 | seg = seg.astype(np.uint8) 58 | seg[seg>0]=255 59 | 60 | out_img_list.append(seg.copy()) 61 | out_name_list.append('bw_final') 62 | 63 | if output_type == 'default': 64 | # the default final output 65 | save_segmentation(seg, False, output_path, fn) 66 | elif output_type == 'AICS_pipeline': 67 | # pre-defined output function for pipeline data 68 | save_segmentation(seg, True, output_path, fn) 69 | elif output_type == 'customize': 70 | # the hook for passing in a customized output function 71 | output_fun(out_img_list, out_name_list, output_path, fn) 72 | elif output_type == 'array': 73 | return seg 74 | elif output_type == 'array_with_contour': 75 | return (seg, generate_segmentation_contour(seg)) 76 | else: 77 | # the hook for pre-defined RnD output functions (AICS internal) 78 | img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) 79 | if output_type == 'QCB': 80 | return img_list, name_list 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_lamp1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from skimage.measure import label 5 | from ..core.vessel import vesselnessSliceBySlice 6 | from ..core.seg_dot import dot_slice_by_slice 7 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_slice_by_slice 8 | from aicssegmentation.core.output_utils import save_segmentation, LAMP1_output, generate_segmentation_contour 9 | from aicsimageprocessing import resize 10 | 11 | 12 | def Workflow_lamp1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 13 | ########################################################################## 14 | # PARAMETERS: 15 | # note that these parameters are supposed to be fixed for the structure 16 | # and work well accross different datasets 17 | intensity_scaling_param = [3, 19] 18 | gaussian_smoothing_sigma = 1 19 | gaussian_smoothing_truncate_range = 3.0 20 | 21 | minArea = 15 22 | ves_th_2d =0.1 23 | 24 | vesselness_sigma = [1] 25 | vesselness_cutoff = 0.15 26 | 27 | #hole_min = 60 28 | hole_max = 1600 29 | 30 | log_sigma_1 = 5 31 | log_cutoff_1 = 0.09 32 | log_sigma_2 = 2.5 33 | log_cutoff_2 = 0.07 34 | log_sigma_3 = 1 35 | log_cutoff_3 = 0.01 36 | ########################################################################## 37 | 38 | out_img_list = [] 39 | out_name_list = [] 40 | 41 | # intenisty normalization 42 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_scaling_param) 43 | 44 | out_img_list.append(struct_img.copy()) 45 | out_name_list.append('im_norm') 46 | 47 | if rescale_ratio>0: 48 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 49 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 50 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 51 | 52 | structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 53 | 54 | out_img_list.append(structure_img_smooth.copy()) 55 | out_name_list.append('im_smooth') 56 | 57 | # spot detection 58 | response1 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_1) 59 | bw1 = response1> log_cutoff_1 60 | response2 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_2) 61 | bw2 = response2> log_cutoff_2 62 | bw_spot = np.logical_or(bw1, bw2) 63 | response3 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_3) 64 | bw3 = response3> log_cutoff_3 65 | bw_spot = np.logical_or(bw_spot, bw3) 66 | 67 | # ring/filament detection 68 | ves = vesselnessSliceBySlice(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 69 | bw_ves = ves> vesselness_cutoff 70 | 71 | # fill holes 72 | partial_fill = np.logical_or(bw_spot, bw_ves) 73 | 74 | out_img_list.append(partial_fill.copy()) 75 | out_name_list.append('interm_before_hole') 76 | 77 | holes = np.zeros_like(partial_fill) 78 | for zz in range(partial_fill.shape[0]): 79 | background_lab = label(~partial_fill[zz,:,:], connectivity=1) 80 | 81 | out = np.copy(background_lab) 82 | component_sizes = np.bincount(background_lab.ravel()) 83 | too_big = component_sizes >hole_max 84 | too_big_mask = too_big[background_lab] 85 | out[too_big_mask] = 0 86 | #too_small = component_sizes 0 98 | seg = seg.astype(np.uint8) 99 | seg[seg>0]=255 100 | 101 | 102 | out_img_list.append(seg.copy()) 103 | out_name_list.append('bw_final') 104 | 105 | if output_type == 'default': 106 | # the default final output 107 | save_segmentation(seg, False, output_path, fn) 108 | elif output_type == 'AICS_pipeline': 109 | # pre-defined output function for pipeline data 110 | save_segmentation(seg, True, output_path, fn) 111 | elif output_type == 'customize': 112 | # the hook for passing in a customized output function 113 | output_fun(out_img_list, out_name_list, output_path, fn) 114 | elif output_type == 'array': 115 | return seg 116 | elif output_type == 'array_with_contour': 117 | return (seg, generate_segmentation_contour(seg)) 118 | else: 119 | # the hook for pre-defined RnD output functions (AICS internal) 120 | img_list, name_list = LAMP1_output(out_img_list, out_name_list, output_type, output_path, fn) 121 | if output_type == 'QCB': 122 | return img_list, name_list 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_lmnb1_interphase.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | # package for io 4 | from aicsimageio import AICSImage 5 | 6 | # function for core algorithm 7 | from aicssegmentation.core.vessel import filament_2d_wrapper 8 | from aicssegmentation.core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 9 | from aicssegmentation.core.utils import get_middle_frame, hole_filling, get_3dseed_from_mid_frame 10 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 11 | from skimage.segmentation import find_boundaries 12 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour 13 | from aicsimageprocessing import resize 14 | 15 | def Workflow_lmnb1_interphase(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 16 | ########################################################################## 17 | # PARAMETERS: 18 | # note that these parameters are supposed to be fixed for the structure 19 | # and work well accross different datasets 20 | 21 | intensity_norm_param = [4000] 22 | gaussian_smoothing_sigma = 1 23 | gaussian_smoothing_truncate_range = 3.0 24 | f2_param = [[1, 0.01],[2, 0.01],[3, 0.01]] 25 | hole_max = 40000 26 | hole_min = 400 27 | ########################################################################## 28 | 29 | out_img_list = [] 30 | out_name_list = [] 31 | 32 | ################### 33 | # PRE_PROCESSING 34 | ################### 35 | # intenisty normalization (min/max) 36 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 37 | 38 | out_img_list.append(struct_img.copy()) 39 | out_name_list.append('im_norm') 40 | 41 | # rescale if needed 42 | if rescale_ratio>0: 43 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 44 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 45 | 46 | # smoothing with boundary preserving smoothing 47 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 48 | 49 | out_img_list.append(structure_img_smooth.copy()) 50 | out_name_list.append('im_smooth') 51 | 52 | ################### 53 | # core algorithm 54 | ################### 55 | 56 | # get the mid frame 57 | mid_z = get_middle_frame(structure_img_smooth, method='intensity') 58 | 59 | # 2d filament filter on the middle frame 60 | bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z,:,:], f2_param) 61 | 62 | # hole filling 63 | bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max) 64 | seed = get_3dseed_from_mid_frame(np.logical_xor(bw_fill_mid_z, bw_mid_z), struct_img.shape, mid_z, hole_min, bg_seed = True) 65 | seg_filled = watershed(struct_img, seed.astype(int), watershed_line=True)>1 # in watershed result, 1 is for background 66 | 67 | # get the actual shell 68 | seg = find_boundaries(seg_filled, connectivity=1, mode='thick') 69 | 70 | # output 71 | seg = seg.astype(np.uint8) 72 | seg[seg>0]=255 73 | 74 | out_img_list.append(seg.copy()) 75 | out_name_list.append('bw_final') 76 | 77 | if output_type == 'default': 78 | # the default final output 79 | save_segmentation(seg, False, output_path, fn) 80 | elif output_type == 'array': 81 | return seg 82 | elif output_type == 'array_with_contour': 83 | return (seg, generate_segmentation_contour(seg)) 84 | else: 85 | print('your can implement your output hook here, but not yet') 86 | quit() -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_lmnb1_mitotic.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | # package for io 4 | from aicsimageio import AICSImage 5 | 6 | # function for core algorithm 7 | from aicssegmentation.core.vessel import filament_2d_wrapper 8 | from aicssegmentation.core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 9 | from aicssegmentation.core.utils import get_middle_frame, hole_filling, get_3dseed_from_mid_frame 10 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 11 | from skimage.segmentation import find_boundaries 12 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour 13 | from aicsimageprocessing import resize 14 | 15 | 16 | def Workflow_lmnb1_mitotic(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 17 | ########################################################################## 18 | # PARAMETERS: 19 | # note that these parameters are supposed to be fixed for the structure 20 | # and work well accross different datasets 21 | 22 | intensity_norm_param = [4000] 23 | gaussian_smoothing_sigma = 1 24 | gaussian_smoothing_truncate_range = 3.0 25 | f2_param = [[0.5, 0.01]] 26 | minArea = 5 27 | ########################################################################## 28 | 29 | out_img_list = [] 30 | out_name_list = [] 31 | 32 | ################### 33 | # PRE_PROCESSING 34 | ################### 35 | # intenisty normalization (min/max) 36 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 37 | 38 | out_img_list.append(struct_img.copy()) 39 | out_name_list.append('im_norm') 40 | 41 | # rescale if needed 42 | if rescale_ratio>0: 43 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 44 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 45 | 46 | # smoothing with boundary preserving smoothing 47 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 48 | 49 | out_img_list.append(structure_img_smooth.copy()) 50 | out_name_list.append('im_smooth') 51 | 52 | ################### 53 | # core algorithm 54 | ################### 55 | 56 | # 2d filament filter on the middle frame 57 | bw = filament_2d_wrapper(structure_img_smooth, f2_param) 58 | 59 | ################### 60 | # POST-PROCESSING 61 | ################### 62 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 63 | 64 | # output 65 | seg = bw>0 66 | seg = seg.astype(np.uint8) 67 | seg[seg>0]=255 68 | 69 | out_img_list.append(seg.copy()) 70 | out_name_list.append('bw_final') 71 | 72 | if output_type == 'default': 73 | # the default final output 74 | save_segmentation(seg, False, output_path, fn) 75 | elif output_type == 'array': 76 | return seg 77 | elif output_type == 'array_with_contour': 78 | return (seg, generate_segmentation_contour(seg)) 79 | else: 80 | print('your can implement your output hook here, but not yet') 81 | quit() -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_myh10.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from ..core.vessel import vesselness3D 6 | from aicssegmentation.core.output_utils import save_segmentation, MYH10_output, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | 10 | def Workflow_myh10(struct_img,rescale_ratio,output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [2.5, 17] 17 | vesselness_sigma_1 = [2] 18 | vesselness_cutoff_1 = 0.2 19 | vesselness_sigma_2 = [1] 20 | vesselness_cutoff_2 = 0.015 21 | minArea = 16 22 | ########################################################################## 23 | 24 | out_img_list = [] 25 | out_name_list = [] 26 | 27 | ################### 28 | # PRE_PROCESSING 29 | ################### 30 | # intenisty normalization 31 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 32 | 33 | out_img_list.append(struct_img.copy()) 34 | out_name_list.append('im_norm') 35 | 36 | # rescale if needed 37 | if rescale_ratio>0: 38 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 39 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 40 | 41 | # smoothing 42 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 43 | 44 | out_img_list.append(structure_img_smooth.copy()) 45 | out_name_list.append('im_smooth') 46 | 47 | ################### 48 | # core algorithm 49 | ################### 50 | 51 | # vesselness 3d 52 | response_1 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma_1, tau=1, whiteonblack=True) 53 | response_2 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma_2, tau=1, whiteonblack=True) 54 | bw = np.logical_or(response_1 > vesselness_cutoff_1, response_2 > vesselness_cutoff_2) 55 | 56 | ################### 57 | # POST-PROCESSING 58 | ################### 59 | seg = remove_small_objects(bw, min_size=minArea, connectivity=1, in_place=False) 60 | 61 | # output 62 | seg = seg>0 63 | seg = seg.astype(np.uint8) 64 | seg[seg>0]=255 65 | 66 | out_img_list.append(seg.copy()) 67 | out_name_list.append('bw_final') 68 | 69 | if output_type == 'default': 70 | # the default final output 71 | save_segmentation(seg, False, output_path, fn) 72 | elif output_type == 'AICS_pipeline': 73 | # pre-defined output function for pipeline data 74 | save_segmentation(seg, True, output_path, fn) 75 | elif output_type == 'customize': 76 | # the hook for passing in a customized output function 77 | output_fun(out_img_list, out_name_list, output_path, fn) 78 | elif output_type == 'array': 79 | return seg 80 | elif output_type == 'array_with_contour': 81 | return (seg, generate_segmentation_contour(seg)) 82 | else: 83 | # the hook for pre-defined RnD output functions (AICS internal) 84 | img_list, name_list = MYH10_output(out_img_list, out_name_list, output_type, output_path, fn) 85 | if output_type == 'QCB': 86 | return img_list, name_list 87 | 88 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_npm1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, erosion, ball, dilation 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_slice_by_slice 6 | from skimage.filters import threshold_triangle, threshold_otsu 7 | from skimage.measure import label 8 | from scipy.ndimage.morphology import binary_fill_holes 9 | from aicssegmentation.core.output_utils import save_segmentation, NPM1_output, generate_segmentation_contour 10 | from aicsimageprocessing import resize 11 | 12 | def Workflow_npm1(struct_img,rescale_ratio,output_type, output_path, fn, output_func=None): 13 | ########################################################################## 14 | # PARAMETERS: 15 | # note that these parameters are supposed to be fixed for the structure 16 | # and work well accross different datasets 17 | 18 | intensity_norm_param = [0.5, 15] 19 | gaussian_smoothing_sigma = 1 20 | gaussian_smoothing_truncate_range = 3.0 21 | dot_2d_sigma = 2 22 | dot_2d_sigma_extra = 1 23 | dot_2d_cutoff = 0.025 24 | minArea = 5 25 | low_level_min_size = 700 26 | ########################################################################## 27 | 28 | out_img_list = [] 29 | out_name_list = [] 30 | 31 | ################### 32 | # PRE_PROCESSING 33 | ################### 34 | # intenisty normalization (min/max) 35 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 36 | 37 | out_img_list.append(struct_img.copy()) 38 | out_name_list.append('im_norm') 39 | 40 | # rescale if needed 41 | if rescale_ratio>0: 42 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 43 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 44 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 45 | 46 | # smoothing with gaussian filter 47 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 48 | 49 | out_img_list.append(structure_img_smooth.copy()) 50 | out_name_list.append('im_smooth') 51 | 52 | ################### 53 | # core algorithm 54 | ################### 55 | 56 | # step 1: low level thresholding 57 | #global_otsu = threshold_otsu(structure_img_smooth) 58 | global_tri = threshold_triangle(structure_img_smooth) 59 | global_median = np.percentile(structure_img_smooth,50) 60 | 61 | th_low_level = (global_tri + global_median)/2 62 | bw_low_level = structure_img_smooth > th_low_level 63 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 64 | bw_low_level = dilation(bw_low_level, selem=ball(2)) 65 | 66 | # step 2: high level thresholding 67 | local_cutoff = 0.333 * threshold_otsu(structure_img_smooth) 68 | bw_high_level = np.zeros_like(bw_low_level) 69 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 70 | for idx in range(num_obj): 71 | single_obj = (lab_low==(idx+1)) 72 | local_otsu = threshold_otsu(structure_img_smooth[single_obj]) 73 | if local_otsu > local_cutoff: 74 | bw_high_level[np.logical_and(structure_img_smooth>0.98*local_otsu, single_obj)]=1 75 | 76 | out_img_list.append(bw_high_level.copy()) 77 | out_name_list.append('bw_coarse') 78 | 79 | response_bright = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) 80 | 81 | response_dark = dot_slice_by_slice(1 - structure_img_smooth, log_sigma=dot_2d_sigma) 82 | response_dark_extra = dot_slice_by_slice(1 - structure_img_smooth, log_sigma=dot_2d_sigma_extra) 83 | 84 | #inner_mask = bw_high_level.copy() 85 | #for zz in range(inner_mask.shape[0]): 86 | # inner_mask[zz,:,:] = binary_fill_holes(inner_mask[zz,:,:]) 87 | 88 | holes = np.logical_or(response_dark>dot_2d_cutoff , response_dark_extra>dot_2d_cutoff) 89 | #holes[~inner_mask] = 0 90 | 91 | bw_extra = response_bright>dot_2d_cutoff 92 | #bw_extra[~bw_high_level]=0 93 | bw_extra[~bw_low_level]=0 94 | 95 | bw_final = np.logical_or(bw_extra, bw_high_level) 96 | bw_final[holes]=0 97 | 98 | ################### 99 | # POST-PROCESSING 100 | ################### 101 | seg = remove_small_objects(bw_final, min_size=minArea, connectivity=1, in_place=True) 102 | 103 | # output 104 | seg = seg>0 105 | seg = seg.astype(np.uint8) 106 | seg[seg>0]=255 107 | 108 | out_img_list.append(seg.copy()) 109 | out_name_list.append('bw_fine') 110 | 111 | if output_type == 'default': 112 | # the default final output 113 | save_segmentation(seg, False, output_path, fn) 114 | elif output_type == 'AICS_pipeline': 115 | # pre-defined output function for pipeline data 116 | save_segmentation(seg, True, output_path, fn) 117 | elif output_type == 'customize': 118 | # the hook for passing in a customized output function 119 | output_fun(out_img_list, out_name_list, output_path, fn) 120 | elif output_type == 'array': 121 | return seg 122 | elif output_type == 'array_with_contour': 123 | return (seg, generate_segmentation_contour(seg)) 124 | else: 125 | # the hook for pre-defined RnD output functions (AICS internal) 126 | img_list, name_list = NPM1_output(out_img_list, out_name_list, output_type, output_path, fn) 127 | if output_type == 'QCB': 128 | return img_list, name_list 129 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_npm1_SR.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_slice_by_slice 6 | from skimage.filters import threshold_triangle, threshold_otsu 7 | from skimage.measure import label 8 | from aicssegmentation.core.output_utils import save_segmentation, NPM1_output, generate_segmentation_contour 9 | from aicsimageprocessing import resize 10 | 11 | 12 | def Workflow_npm1_SR(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 13 | ########################################################################## 14 | # PARAMETERS: 15 | # note that these parameters are supposed to be fixed for the structure 16 | # and work well accross different datasets 17 | 18 | intensity_norm_param = [0.05, 32] 19 | gaussian_smoothing_sigma = 2 20 | gaussian_smoothing_truncate_range = 3.0 21 | dot_2d_sigma = 3 22 | dot_2d_sigma_extra = 1 23 | dot_2d_cutoff = 0.025 24 | minArea = 8 25 | low_level_min_size = 3000 26 | ########################################################################## 27 | 28 | out_img_list = [] 29 | out_name_list = [] 30 | 31 | ################### 32 | # PRE_PROCESSING 33 | ################### 34 | # intenisty normalization (min/max) 35 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 36 | 37 | out_img_list.append(struct_img.copy()) 38 | out_name_list.append('im_norm') 39 | 40 | # rescale if needed 41 | if rescale_ratio>0: 42 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 43 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 44 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 45 | 46 | # smoothing with gaussian filter 47 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 48 | 49 | out_img_list.append(structure_img_smooth.copy()) 50 | out_name_list.append('im_smooth') 51 | 52 | ################### 53 | # core algorithm 54 | ################### 55 | 56 | # step 1: low level thresholding 57 | global_tri = threshold_triangle(structure_img_smooth) 58 | global_median = np.percentile(structure_img_smooth,50) 59 | 60 | th_low_level = (global_tri + global_median)/2 61 | bw_low_level = structure_img_smooth > th_low_level 62 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 63 | bw_low_level = dilation(bw_low_level, selem=ball(2)) 64 | 65 | # step 2: high level thresholding 66 | local_cutoff = 0.333 * threshold_otsu(structure_img_smooth) 67 | bw_high_level = np.zeros_like(bw_low_level) 68 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 69 | for idx in range(num_obj): 70 | single_obj = (lab_low==(idx+1)) 71 | local_otsu = threshold_otsu(structure_img_smooth[single_obj]) 72 | if local_otsu > local_cutoff: 73 | bw_high_level[np.logical_and(structure_img_smooth>0.98*local_otsu, single_obj)]=1 74 | 75 | out_img_list.append(bw_high_level.copy()) 76 | out_name_list.append('bw_coarse') 77 | 78 | response_bright = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) 79 | 80 | response_dark = dot_slice_by_slice(1 - structure_img_smooth, log_sigma=dot_2d_sigma) 81 | response_dark_extra = dot_slice_by_slice(1 - structure_img_smooth, log_sigma=dot_2d_sigma_extra) 82 | 83 | 84 | holes = np.logical_or(response_dark>dot_2d_cutoff , response_dark_extra>dot_2d_cutoff) 85 | 86 | bw_extra = response_bright>dot_2d_cutoff 87 | bw_extra[~bw_low_level]=0 88 | 89 | bw_final = np.logical_or(bw_extra, bw_high_level) 90 | bw_final[holes]=0 91 | 92 | ################### 93 | # POST-PROCESSING 94 | ################### 95 | seg = remove_small_objects(bw_final, min_size=minArea, connectivity=1, in_place=True) 96 | 97 | # output 98 | seg = seg>0 99 | seg = seg.astype(np.uint8) 100 | seg[seg>0]=255 101 | 102 | out_img_list.append(seg.copy()) 103 | out_name_list.append('bw_fine') 104 | 105 | if output_type == 'default': 106 | # the default final output 107 | save_segmentation(seg, False, output_path, fn) 108 | elif output_type == 'AICS_pipeline': 109 | # pre-defined output function for pipeline data 110 | save_segmentation(seg, True, output_path, fn) 111 | elif output_type == 'customize': 112 | # the hook for passing in a customized output function 113 | output_fun(out_img_list, out_name_list, output_path, fn) 114 | elif output_type == 'array': 115 | return seg 116 | elif output_type == 'array_with_contour': 117 | return (seg, generate_segmentation_contour(seg)) 118 | else: 119 | # the hook for pre-defined RnD output functions (AICS internal) 120 | img_list, name_list = NPM1_output(out_img_list, out_name_list, output_type, output_path, fn) 121 | if output_type == 'QCB': 122 | return img_list, name_list 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_npm_labelfree_4dn.py: -------------------------------------------------------------------------------- 1 | ###### import functions #### 2 | import numpy as np 3 | import os 4 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 5 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 6 | from ..core.seg_dot import dot_slice_by_slice, dot_2d_slice_by_slice_wrapper 7 | from skimage.filters import threshold_triangle, threshold_otsu 8 | from skimage.measure import label 9 | from aicsimageprocessing import resize 10 | 11 | #### do not remove #### 12 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour 13 | 14 | def Workflow_npm_labelfree_4dn(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): 15 | ########################################################################## 16 | # PARAMETERS: 17 | minArea = 5 18 | low_level_min_size = 7000 19 | s2_param = [[0.5, 0.12]] 20 | intensity_scaling_param = [2, 16.5] 21 | gaussian_smoothing_sigma = 1 22 | 23 | ########################################################################## 24 | 25 | ################### 26 | # PRE_PROCESSING 27 | ################### 28 | # intenisty normalization 29 | struct_norm = intensity_normalization(struct_img, scaling_param=intensity_scaling_param) 30 | 31 | # smoothing 32 | struct_smooth = image_smoothing_gaussian_3d(struct_norm, sigma=gaussian_smoothing_sigma) 33 | 34 | ################### 35 | # core algorithm 36 | ################### 37 | # step 1: low level thresholding 38 | #global_otsu = threshold_otsu(structure_img_smooth) 39 | global_tri = threshold_triangle(struct_smooth) 40 | global_median = np.percentile(struct_smooth,50) 41 | 42 | th_low_level = (global_tri + global_median)/2 43 | bw_low_level = struct_smooth > th_low_level 44 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 45 | 46 | # step 2: high level thresholding 47 | bw_high_level = np.zeros_like(bw_low_level) 48 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 49 | for idx in range(num_obj): 50 | single_obj = (lab_low==(idx+1)) 51 | local_otsu = threshold_otsu(struct_smooth[single_obj]) 52 | bw_high_level[np.logical_and(struct_smooth>local_otsu*1.2, single_obj)]=1 53 | 54 | # step 3: finer segmentation 55 | response2d = dot_2d_slice_by_slice_wrapper(struct_smooth, s2_param) 56 | bw_finer = remove_small_objects(response2d, min_size=minArea, connectivity=1, in_place=True) 57 | 58 | # merge finer level detection into high level coarse segmentation to include outside dim parts 59 | bw_high_level[bw_finer>0]=1 60 | 61 | ################### 62 | # POST-PROCESSING 63 | # make sure the variable name of final segmentation is 'seg' 64 | ################### 65 | seg = remove_small_objects(bw_high_level, min_size=minArea, connectivity=1, in_place=True) 66 | 67 | # output 68 | seg = seg>0 69 | seg = seg.astype(np.uint8) 70 | seg[seg>0]=255 71 | 72 | if output_type == 'default': 73 | # the default final output 74 | save_segmentation(seg, False, output_path, fn) 75 | elif output_type == 'array': 76 | return seg 77 | elif output_type == 'array_with_contour': 78 | return (seg, generate_segmentation_contour(seg)) 79 | else: 80 | print('your can implement your output hook here, but not yet') 81 | quit() 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_nup153.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_slice_by_slice, edge_preserving_smoothing_3d 5 | from ..core.seg_dot import dot_3d_wrapper, dot_2d_slice_by_slice_wrapper 6 | from skimage.measure import label 7 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour#, NUP153_output 8 | from aicsimageprocessing import resize 9 | 10 | def Workflow_nup153(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | ########################################################################## 13 | # PARAMETERS: 14 | # note that these parameters are supposed to be fixed for the structure 15 | # and work well accross different datasets 16 | 17 | intensity_norm_param = [1, 13.5] 18 | gaussian_smoothing_sigma = 1 19 | gaussian_smoothing_truncate_range = 3.0 20 | s3_param = [[1, 0.07]] 21 | #s2_param = [[1, 0.04]] 22 | minArea = 7 23 | ########################################################################## 24 | 25 | out_img_list = [] 26 | out_name_list = [] 27 | 28 | ################### 29 | # PRE_PROCESSING 30 | ################### 31 | # intenisty normalization (min/max) 32 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 33 | 34 | out_img_list.append(struct_img.copy()) 35 | out_name_list.append('im_norm') 36 | 37 | # rescale if needed 38 | if rescale_ratio>0: 39 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 40 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 41 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 42 | 43 | # smoothing with edge_preserving_smoothing filter 44 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 45 | #structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 46 | 47 | out_img_list.append(structure_img_smooth.copy()) 48 | out_name_list.append('im_smooth') 49 | 50 | ################### 51 | # core algorithm 52 | ################### 53 | 54 | # step 1: LOG 3d 55 | bw = dot_3d_wrapper(structure_img_smooth, s3_param) 56 | 57 | #bw = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param) 58 | 59 | ################### 60 | # POST-PROCESSING 61 | ################### 62 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 63 | 64 | # output 65 | seg = seg>0 66 | seg = seg.astype(np.uint16) 67 | seg[seg>0]=65535 68 | 69 | out_img_list.append(seg.copy()) 70 | out_name_list.append('bw_final') 71 | 72 | if output_type == 'default': 73 | # the default final output 74 | save_segmentation(seg, False, output_path, fn) 75 | elif output_type == 'AICS_pipeline': 76 | # pre-defined output function for pipeline data 77 | save_segmentation(seg, True, output_path, fn) 78 | elif output_type == 'customize': 79 | # the hook for passing in a customized output function 80 | output_fun(out_img_list, out_name_list, output_path, fn) 81 | elif output_type == 'array': 82 | return seg 83 | elif output_type == 'array_with_contour': 84 | return (seg, generate_segmentation_contour(seg)) 85 | else: 86 | pass 87 | # the hook for pre-defined RnD output functions (AICS internal) 88 | #img_list, name_list = GJA1_output(out_img_list, out_name_list, output_type, output_path, fn) 89 | #if output_type == 'QCB': 90 | # return img_list, name_list 91 | 92 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_pxn.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from ..core.vessel import vesselness3D 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from skimage.morphology import remove_small_objects 6 | from aicssegmentation.core.output_utils import save_segmentation, PXN_output, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | 10 | def Workflow_pxn(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | ########################################################################## 13 | # PARAMETERS: 14 | # note that these parameters are supposed to be fixed for the structure 15 | # and work well accross different datasets 16 | 17 | intensity_norm_param = [11, 8] 18 | vesselness_sigma = [1] 19 | vesselness_cutoff = 0.35 20 | minArea3D = 15 21 | minArea2D = 4 22 | ########################################################################## 23 | 24 | out_img_list = [] 25 | out_name_list = [] 26 | 27 | ################### 28 | # PRE_PROCESSING 29 | ################### 30 | # intenisty normalization (min/max) 31 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 32 | 33 | out_img_list.append(struct_img.copy()) 34 | out_name_list.append('im_norm') 35 | 36 | # rescale if needed 37 | if rescale_ratio>0: 38 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 39 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 40 | 41 | # smoothing with boundary preserving smoothing 42 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 43 | 44 | out_img_list.append(structure_img_smooth.copy()) 45 | out_name_list.append('im_smooth') 46 | 47 | ################### 48 | # core algorithm 49 | ################### 50 | 51 | # vesselness 3d 52 | response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 53 | bw = response > vesselness_cutoff 54 | 55 | ################### 56 | # POST-PROCESSING 57 | ################### 58 | 59 | seg = np.zeros_like(bw) 60 | for zz in range(bw.shape[0]): 61 | seg[zz,:,:] = remove_small_objects(bw[zz,:,:]>0, min_size=minArea2D, connectivity=1, in_place=False) 62 | 63 | seg = remove_small_objects(seg>0, min_size=minArea3D, connectivity=1, in_place=False) 64 | 65 | # determine z-range 66 | bw_z = np.zeros(bw.shape[0], dtype=np.uint16) 67 | for zz in range(bw.shape[0]): 68 | bw_z[zz] = np.count_nonzero(seg[zz,:,:]>0) 69 | 70 | mid_z = np.argmax(bw_z) 71 | low_z = 0 72 | high_z = seg.shape[0]-2 73 | for ii in np.arange(mid_z-1,0,-1): 74 | if bw_z[ii]<100: 75 | low_z = ii 76 | break 77 | for ii in range(mid_z+1, bw.shape[0]-1, 1): 78 | if bw_z[ii]<100: 79 | high_z = ii 80 | break 81 | 82 | seg[:low_z,:,:]=0 83 | seg[high_z+1:,:,:]=0 84 | 85 | # output 86 | seg = seg>0 87 | seg = seg.astype(np.uint8) 88 | seg[seg>0]=255 89 | 90 | out_img_list.append(seg.copy()) 91 | out_name_list.append('bw_final') 92 | 93 | if output_type == 'default': 94 | # the default final output 95 | save_segmentation(seg, False, output_path, fn) 96 | elif output_type == 'AICS_pipeline': 97 | # pre-defined output function for pipeline data 98 | save_segmentation(seg, True, output_path, fn) 99 | elif output_type == 'customize': 100 | # the hook for passing in a customized output function 101 | output_fun(out_img_list, out_name_list, output_path, fn) 102 | elif output_type == 'array': 103 | return seg 104 | elif output_type == 'array_with_contour': 105 | return (seg, generate_segmentation_contour(seg)) 106 | else: 107 | # the hook for pre-defined RnD output functions (AICS internal) 108 | img_list, name_list = PXN_output(out_img_list, out_name_list, output_type, output_path, fn) 109 | if output_type == 'QCB': 110 | return img_list, name_list -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_rab5a.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_slice_by_slice 5 | from ..core.seg_dot import dot_3d 6 | from skimage.feature import peak_local_max 7 | from scipy.ndimage import distance_transform_edt 8 | from skimage.measure import label 9 | from aicssegmentation.core.output_utils import save_segmentation, RAB5A_output, generate_segmentation_contour 10 | from aicssegmentation.core.utils import hole_filling 11 | from aicsimageprocessing import resize 12 | 13 | def Workflow_rab5a(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 14 | ########################################################################## 15 | # PARAMETERS: 16 | # note that these parameters are supposed to be fixed for the structure 17 | # and work well accross different datasets 18 | 19 | intensity_norm_param = [1000] 20 | gaussian_smoothing_sigma = 1 21 | gaussian_smoothing_truncate_range = 3.0 22 | dot_3d_sigma = 1 23 | dot_3d_cutoff = 0.03 24 | 25 | hole_min = 0 26 | hole_max= 81 27 | 28 | minArea = 3 29 | ########################################################################## 30 | 31 | out_img_list = [] 32 | out_name_list = [] 33 | 34 | ################### 35 | # PRE_PROCESSING 36 | ################### 37 | # intenisty normalization (min/max) 38 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 39 | 40 | out_img_list.append(struct_img.copy()) 41 | out_name_list.append('im_norm') 42 | 43 | # rescale if needed 44 | if rescale_ratio>0: 45 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 46 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 47 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 48 | 49 | # smoothing with gaussian filter 50 | structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 51 | 52 | out_img_list.append(structure_img_smooth.copy()) 53 | out_name_list.append('im_smooth') 54 | 55 | ################### 56 | # core algorithm 57 | ################### 58 | 59 | # step 1: LOG 3d 60 | response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) 61 | bw = response > dot_3d_cutoff 62 | 63 | # step 2: fill holes and remove small objects 64 | bw_filled = hole_filling(bw, hole_min, hole_max, True) 65 | seg = remove_small_objects(bw_filled, min_size=minArea, connectivity=1, in_place=False) 66 | 67 | # output 68 | seg = seg>0 69 | seg = seg.astype(np.uint8) 70 | seg[seg>0]=255 71 | 72 | out_img_list.append(seg.copy()) 73 | out_name_list.append('bw_final') 74 | 75 | if output_type == 'default': 76 | # the default final output 77 | save_segmentation(seg, False, output_path, fn) 78 | elif output_type == 'AICS_pipeline': 79 | # pre-defined output function for pipeline data 80 | save_segmentation(seg, True, output_path, fn) 81 | elif output_type == 'customize': 82 | # the hook for passing in a customized output function 83 | output_fun(out_img_list, out_name_list, output_path, fn) 84 | elif output_type == 'array': 85 | return seg 86 | elif output_type == 'array_with_contour': 87 | return (seg, generate_segmentation_contour(seg)) 88 | else: 89 | # the hook for pre-defined RnD output functions (AICS internal) 90 | img_list, name_list = RAB5A_output(out_img_list, out_name_list, output_type, output_path, fn) 91 | if output_type == 'QCB': 92 | return img_list, name_list 93 | 94 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_sec61b.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from ..core.vessel import vesselnessSliceBySlice 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from scipy import ndimage as ndi 6 | from skimage.morphology import remove_small_objects 7 | from aicssegmentation.core.output_utils import save_segmentation, SEC61B_output, generate_segmentation_contour 8 | from aicsimageprocessing import resize 9 | 10 | def Workflow_sec61b(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [2.5, 7.5] 17 | vesselness_sigma = [1] 18 | vesselness_cutoff = 0.15 19 | minArea = 15 20 | ########################################################################## 21 | 22 | out_img_list = [] 23 | out_name_list = [] 24 | 25 | ################### 26 | # PRE_PROCESSING 27 | ################### 28 | # intenisty normalization (min/max) 29 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 30 | 31 | out_img_list.append(struct_img.copy()) 32 | out_name_list.append('im_norm') 33 | 34 | # rescale if needed 35 | if rescale_ratio>0: 36 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 37 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 38 | 39 | # smoothing with boundary preserving smoothing 40 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 41 | 42 | out_img_list.append(structure_img_smooth.copy()) 43 | out_name_list.append('im_smooth') 44 | 45 | ################### 46 | # core algorithm 47 | ################### 48 | 49 | # 2d vesselness slice by slice 50 | response = vesselnessSliceBySlice(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 51 | bw = response > vesselness_cutoff 52 | 53 | ################### 54 | # POST-PROCESSING 55 | ################### 56 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 57 | for zz in range(bw.shape[0]): 58 | bw[zz,:,:] = remove_small_objects(bw[zz,:,:], min_size=3, connectivity=1, in_place=False) 59 | 60 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 61 | 62 | # output 63 | seg = seg>0 64 | seg = seg.astype(np.uint8) 65 | seg[seg>0]=255 66 | 67 | out_img_list.append(seg.copy()) 68 | out_name_list.append('bw_final') 69 | 70 | if output_type == 'default': 71 | # the default final output 72 | save_segmentation(seg, False, output_path, fn) 73 | elif output_type == 'AICS_pipeline': 74 | # pre-defined output function for pipeline data 75 | save_segmentation(seg, True, output_path, fn) 76 | elif output_type == 'customize': 77 | # the hook for passing in a customized output function 78 | output_fun(out_img_list, out_name_list, output_path, fn) 79 | elif output_type == 'array': 80 | return seg 81 | elif output_type == 'array_with_contour': 82 | return (seg, generate_segmentation_contour(seg)) 83 | else: 84 | # the hook for pre-defined RnD output functions (AICS internal) 85 | img_list, name_list = SEC61B_output(out_img_list, out_name_list, output_type, output_path, fn) 86 | if output_type == 'QCB': 87 | return img_list, name_list 88 | 89 | 90 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_sec61b_dual.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from ..core.vessel import vesselnessSliceBySlice 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from scipy import ndimage as ndi 6 | from skimage.morphology import remove_small_objects 7 | from aicssegmentation.core.output_utils import save_segmentation, SEC61B_output, generate_segmentation_contour 8 | from aicsimageprocessing import resize 9 | 10 | def Workflow_sec61b_dual(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [2.0, 7.0] 17 | vesselness_sigma = [1] 18 | vesselness_cutoff = 0.17 19 | minArea = 20 20 | ########################################################################## 21 | 22 | out_img_list = [] 23 | out_name_list = [] 24 | 25 | ################### 26 | # PRE_PROCESSING 27 | ################### 28 | # intenisty normalization (min/max) 29 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 30 | 31 | out_img_list.append(struct_img.copy()) 32 | out_name_list.append('im_norm') 33 | 34 | # rescale if needed 35 | if rescale_ratio>0: 36 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 37 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 38 | 39 | # smoothing with boundary preserving smoothing 40 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 41 | 42 | out_img_list.append(structure_img_smooth.copy()) 43 | out_name_list.append('im_smooth') 44 | 45 | ################### 46 | # core algorithm 47 | ################### 48 | 49 | # 2d vesselness slice by slice 50 | response = vesselnessSliceBySlice(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 51 | bw = response > vesselness_cutoff 52 | 53 | ################### 54 | # POST-PROCESSING 55 | ################### 56 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 57 | for zz in range(bw.shape[0]): 58 | bw[zz,:,:] = remove_small_objects(bw[zz,:,:], min_size=3, connectivity=1, in_place=False) 59 | 60 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 61 | 62 | # output 63 | seg = seg>0 64 | seg = seg.astype(np.uint8) 65 | seg[seg>0]=255 66 | 67 | out_img_list.append(seg.copy()) 68 | out_name_list.append('bw_final') 69 | 70 | if output_type == 'default': 71 | # the default final output 72 | save_segmentation(seg, False, output_path, fn) 73 | elif output_type == 'AICS_pipeline': 74 | # pre-defined output function for pipeline data 75 | save_segmentation(seg, True, output_path, fn) 76 | elif output_type == 'customize': 77 | # the hook for passing in a customized output function 78 | output_fun(out_img_list, out_name_list, output_path, fn) 79 | elif output_type == 'array': 80 | return seg 81 | elif output_type == 'array_with_contour': 82 | return (seg, generate_segmentation_contour(seg)) 83 | else: 84 | # the hook for pre-defined RnD output functions (AICS internal) 85 | img_list, name_list = SEC61B_output(out_img_list, out_name_list, output_type, output_path, fn) 86 | if output_type == 'QCB': 87 | return img_list, name_list 88 | 89 | 90 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_slc25a17.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_slice_by_slice 5 | from ..core.seg_dot import dot_3d 6 | from skimage.feature import peak_local_max 7 | from scipy.ndimage import distance_transform_edt 8 | from skimage.measure import label 9 | from aicssegmentation.core.output_utils import save_segmentation, SLC25A17_output, generate_segmentation_contour 10 | from aicsimageprocessing import resize 11 | 12 | 13 | def Workflow_slc25a17(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 14 | ########################################################################## 15 | # PARAMETERS: 16 | # note that these parameters are supposed to be fixed for the structure 17 | # and work well accross different datasets 18 | 19 | intensity_norm_param = [2, 36] 20 | gaussian_smoothing_sigma = 1 21 | gaussian_smoothing_truncate_range = 3.0 22 | dot_3d_sigma = 1 23 | dot_3d_cutoff = 0.045 #0.03 #0.04 24 | minArea = 3 #5 25 | ########################################################################## 26 | 27 | out_img_list = [] 28 | out_name_list = [] 29 | 30 | ################### 31 | # PRE_PROCESSING 32 | ################### 33 | # intenisty normalization (min/max) 34 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 35 | 36 | out_img_list.append(struct_img.copy()) 37 | out_name_list.append('im_norm') 38 | 39 | # rescale if needed 40 | if rescale_ratio>0: 41 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 42 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 43 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 44 | 45 | # smoothing with gaussian filter 46 | structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 47 | 48 | out_img_list.append(structure_img_smooth.copy()) 49 | out_name_list.append('im_smooth') 50 | 51 | ################### 52 | # core algorithm 53 | ################### 54 | 55 | # step 1: LOG 3d 56 | response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) 57 | bw = response > dot_3d_cutoff 58 | 59 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 60 | 61 | out_img_list.append(bw.copy()) 62 | out_name_list.append('interm_mask') 63 | 64 | # step 2: 'local_maxi + watershed' for cell cutting 65 | local_maxi = peak_local_max(struct_img,labels=label(bw), min_distance=2, indices=False) 66 | 67 | out_img_list.append(local_maxi.copy()) 68 | out_name_list.append('interm_local_max') 69 | 70 | distance = distance_transform_edt(bw) 71 | im_watershed = watershed(-1*distance, label(dilation(local_maxi, selem=ball(1))), mask=bw, watershed_line=True) 72 | 73 | ################### 74 | # POST-PROCESSING 75 | ################### 76 | seg = remove_small_objects(im_watershed, min_size=minArea, connectivity=1, in_place=False) 77 | 78 | ###### HACK: Only for 2019 April Release ##### 79 | if np.count_nonzero(seg>0)<50000: 80 | print('FLAG: please check the meta data of the original CZI for QC') 81 | 82 | # output 83 | seg = seg>0 84 | seg = seg.astype(np.uint8) 85 | seg[seg>0]=255 86 | 87 | out_img_list.append(seg.copy()) 88 | out_name_list.append('bw_final') 89 | 90 | if output_type == 'default': 91 | # the default final output 92 | save_segmentation(seg, False, output_path, fn) 93 | elif output_type == 'AICS_pipeline': 94 | # pre-defined output function for pipeline data 95 | save_segmentation(seg, True, output_path, fn) 96 | elif output_type == 'customize': 97 | # the hook for passing in a customized output function 98 | #output_fun(out_img_list, out_name_list, output_path, fn) 99 | print('please provide custom output function') 100 | elif output_type == 'array': 101 | return seg 102 | elif output_type == 'array_with_contour': 103 | return (seg, generate_segmentation_contour(seg)) 104 | else: 105 | # the hook for pre-defined RnD output functions (AICS internal) 106 | img_list, name_list = SLC25A17_output(out_img_list, out_name_list, output_type, output_path, fn) 107 | if output_type == 'QCB': 108 | return img_list, name_list 109 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_smc1a.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 4 | from ..core.seg_dot import dot_2d_slice_by_slice_wrapper 5 | from skimage.morphology import remove_small_objects 6 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | 10 | def Workflow_smc1a(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [2.5, 12] 17 | s2_param = [[1, 0.06]] 18 | minArea = 3 19 | ########################################################################## 20 | 21 | out_img_list = [] 22 | out_name_list = [] 23 | 24 | ################### 25 | # PRE_PROCESSING 26 | ################### 27 | # intenisty normalization (min/max) 28 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 29 | 30 | out_img_list.append(struct_img.copy()) 31 | out_name_list.append('im_norm') 32 | 33 | # rescale if needed 34 | if rescale_ratio>0: 35 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 36 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 37 | 38 | # smoothing with gaussian filter 39 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 40 | 41 | out_img_list.append(structure_img_smooth.copy()) 42 | out_name_list.append('im_smooth') 43 | 44 | ################### 45 | # core algorithm 46 | ################### 47 | 48 | bw = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param) 49 | 50 | ################### 51 | # POST-PROCESSING 52 | ################### 53 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 54 | 55 | # output 56 | seg = seg>0 57 | seg = seg.astype(np.uint8) 58 | seg[seg>0]=255 59 | 60 | out_img_list.append(seg.copy()) 61 | out_name_list.append('bw_final') 62 | 63 | if output_type == 'default': 64 | # the default final output 65 | save_segmentation(seg, False, output_path, fn) 66 | elif output_type == 'AICS_pipeline': 67 | # pre-defined output function for pipeline data 68 | save_segmentation(seg, True, output_path, fn) 69 | elif output_type == 'customize': 70 | # the hook for passing in a customized output function 71 | output_fun(out_img_list, out_name_list, output_path, fn) 72 | elif output_type == 'array': 73 | return seg 74 | elif output_type == 'array_with_contour': 75 | return (seg, generate_segmentation_contour(seg)) 76 | else: 77 | # the hook for pre-defined RnD output functions (AICS internal) 78 | img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) 79 | if output_type == 'QCB': 80 | return img_list, name_list 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_son.py: -------------------------------------------------------------------------------- 1 | # import 2 | import numpy as np 3 | import os 4 | import sys 5 | import glob 6 | import pathlib 7 | 8 | from aicssegmentation.core.vessel import vesselnessSliceBySlice, vesselness3D 9 | from aicssegmentation.core.seg_dot import dot_slice_by_slice, dot_3d 10 | from aicssegmentation.core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 11 | from scipy import ndimage as ndi 12 | from skimage.morphology import remove_small_objects 13 | from aicsimageprocessing import resize 14 | from aicsimageio import AICSImage 15 | from skimage.io import imsave 16 | from argparse import ArgumentParser 17 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour 18 | 19 | 20 | def Workflow_son(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): 21 | ########################################################################## 22 | # PARAMETERS: 23 | # note that these parameters are supposed to be fixed for the structure 24 | # and work well accross different datasets 25 | ########################################################################## 26 | 27 | intensity_norm_param = [2, 30] 28 | vesselness_sigma = [1.2] 29 | vesselness_cutoff = 0.15 30 | minArea = 15 31 | 32 | dot_2d_sigma = 1 33 | dot_3d_sigma = 1.15 34 | ########################################################################## 35 | 36 | ################### 37 | # PRE_PROCESSING 38 | ################### 39 | # intenisty normalization (min/max) 40 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 41 | 42 | # smoothing with boundary preserving smoothing 43 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 44 | 45 | ################### 46 | # core algorithm 47 | ################### 48 | response_f3 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 49 | response_f3 = response_f3 > vesselness_cutoff 50 | 51 | response_s3_1 = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) 52 | response_s3_3 = dot_3d(structure_img_smooth, log_sigma=3) 53 | 54 | bw_small_inverse = remove_small_objects(response_s3_1>0.03, min_size=150) 55 | bw_small = np.logical_xor(bw_small_inverse, response_s3_1>0.02) 56 | 57 | bw_medium = np.logical_or(bw_small, response_s3_1>0.07) 58 | bw_large = np.logical_or(response_s3_3>0.2, response_f3>0.25) 59 | bw = np.logical_or( np.logical_or(bw_small, bw_medium), bw_large) 60 | 61 | ################### 62 | # POST-PROCESSING 63 | ################### 64 | bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 65 | for zz in range(bw.shape[0]): 66 | bw[zz,: , :] = remove_small_objects(bw[zz,:,:], min_size=3, connectivity=1, in_place=False) 67 | 68 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 69 | 70 | seg = seg>0 71 | seg = seg.astype(np.uint8) 72 | seg[seg>0]=255 73 | 74 | if output_type == 'default': 75 | # the default final output 76 | save_segmentation(seg, False, output_path, fn) 77 | elif output_type == 'array': 78 | return seg 79 | elif output_type == 'array_with_contour': 80 | return (seg, generate_segmentation_contour(seg)) 81 | else: 82 | print('your can implement your output hook here, but not yet') 83 | quit() 84 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_st6gal1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, erosion, ball, dilation 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_3d 6 | from skimage.measure import label 7 | from skimage.filters import threshold_triangle, threshold_otsu 8 | from aicssegmentation.core.utils import topology_preserving_thinning 9 | from aicssegmentation.core.output_utils import save_segmentation, ST6GAL1_output, generate_segmentation_contour 10 | from aicsimageprocessing import resize 11 | 12 | def Workflow_st6gal1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 13 | ########################################################################## 14 | # PARAMETERS: 15 | # note that these parameters are supposed to be fixed for the structure 16 | # and work well accross different datasets 17 | 18 | intensity_norm_param = [9, 19] 19 | gaussian_smoothing_sigma = 1 20 | gaussian_smoothing_truncate_range = 3.0 21 | cell_wise_min_area = 1200 22 | dot_3d_sigma = 1.6 23 | dot_3d_cutoff = 0.02 24 | minArea = 10 25 | thin_dist = 1 26 | thin_dist_preserve = 1.6 27 | ########################################################################## 28 | 29 | out_img_list = [] 30 | out_name_list = [] 31 | 32 | ################### 33 | # PRE_PROCESSING 34 | ################### 35 | # intenisty normalization (min/max) 36 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 37 | 38 | out_img_list.append(struct_img.copy()) 39 | out_name_list.append('im_norm') 40 | 41 | # rescale if needed 42 | if rescale_ratio>0: 43 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 44 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 45 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 46 | 47 | # smoothing with gaussian filter 48 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 49 | 50 | out_img_list.append(structure_img_smooth.copy()) 51 | out_name_list.append('im_smooth') 52 | 53 | ################### 54 | # core algorithm 55 | ################### 56 | 57 | # cell-wise local adaptive thresholding 58 | th_low_level = threshold_triangle(structure_img_smooth) 59 | 60 | bw_low_level = structure_img_smooth > th_low_level 61 | bw_low_level = remove_small_objects(bw_low_level, min_size=cell_wise_min_area, connectivity=1, in_place=True) 62 | bw_low_level = dilation(bw_low_level,selem=ball(2)) 63 | 64 | bw_high_level = np.zeros_like(bw_low_level) 65 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 66 | 67 | for idx in range(num_obj): 68 | single_obj = lab_low==(idx+1) 69 | local_otsu = threshold_otsu(structure_img_smooth[single_obj>0]) 70 | bw_high_level[np.logical_and(structure_img_smooth>local_otsu*0.98, single_obj)]=1 71 | 72 | # LOG 3d to capture spots 73 | response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) 74 | bw_extra = response > dot_3d_cutoff 75 | 76 | # thinning 77 | bw_high_level = topology_preserving_thinning(bw_high_level, thin_dist_preserve, thin_dist) 78 | 79 | # combine the two parts 80 | bw = np.logical_or(bw_high_level, bw_extra) 81 | 82 | ################### 83 | # POST-PROCESSING 84 | ################### 85 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 86 | 87 | # output 88 | seg = seg>0 89 | seg = seg.astype(np.uint8) 90 | seg[seg>0]=255 91 | 92 | out_img_list.append(seg.copy()) 93 | out_name_list.append('bw_final') 94 | 95 | if output_type == 'default': 96 | # the default final output 97 | save_segmentation(seg, False, output_path, fn) 98 | elif output_type == 'AICS_pipeline': 99 | # pre-defined output function for pipeline data 100 | save_segmentation(seg, True, output_path, fn) 101 | elif output_type == 'customize': 102 | # the hook for passing in a customized output function 103 | output_fun(out_img_list, out_name_list, output_path, fn) 104 | elif output_type == 'array': 105 | return seg 106 | elif output_type == 'array_with_contour': 107 | return (seg, generate_segmentation_contour(seg)) 108 | else: 109 | # the hook for pre-defined RnD output functions (AICS internal) 110 | img_list, name_list = ST6GAL1_output(out_img_list, out_name_list, output_type, output_path, fn) 111 | if output_type == 'QCB': 112 | return img_list, name_list 113 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_template.py: -------------------------------------------------------------------------------- 1 | ###### import functions #### 2 | 3 | 4 | #### do not remove #### 5 | from aicssegmentation.core.output_utils import save_segmentation, generate_segmentation_contour 6 | 7 | def Workflow_template(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): 8 | ########################################################################## 9 | # PARAMETERS: 10 | 11 | 12 | ########################################################################## 13 | 14 | ################### 15 | # PRE_PROCESSING 16 | # make sure the variable name of original image is 'struct_img' 17 | ################### 18 | # intenisty normalization 19 | 20 | 21 | # smoothing 22 | 23 | 24 | ################### 25 | # core algorithm 26 | ################### 27 | 28 | 29 | ################### 30 | # POST-PROCESSING 31 | # make sure the variable name of final segmentation is 'seg' 32 | ################### 33 | 34 | 35 | 36 | ########################################################################## 37 | ### no need to change below 38 | ########################################################################## 39 | # output 40 | seg = seg>0 41 | seg = seg.astype(np.uint8) 42 | seg[seg>0]=255 43 | 44 | if output_type == 'default': 45 | # the default final output 46 | save_segmentation(seg, False, output_path, fn) 47 | elif output_type == 'array': 48 | return seg 49 | elif output_type == 'array_with_contour': 50 | return (seg, generate_segmentation_contour(seg)) 51 | else: 52 | print('your can implement your output hook here, but not yet') 53 | quit() 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_tjp1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.vessel import vesselness3D 6 | from aicssegmentation.core.output_utils import save_segmentation, TJP1_output, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | 10 | def Workflow_tjp1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | # PARAMETERS: 13 | # note that these parameters are supposed to be fixed for the structure 14 | # and work well accross different datasets 15 | 16 | intensity_norm_param = [3, 17] 17 | gaussian_smoothing_sigma = 1 18 | gaussian_smoothing_truncate_range = 3.0 19 | vesselness_sigma = [1.5] 20 | vesselness_cutoff = 0.2 21 | minArea = 15 22 | ########################################################################## 23 | 24 | out_img_list = [] 25 | out_name_list = [] 26 | 27 | ################### 28 | # PRE_PROCESSING 29 | ################### 30 | # intenisty normalization (min/max) 31 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 32 | 33 | out_img_list.append(struct_img.copy()) 34 | out_name_list.append('im_norm') 35 | 36 | # rescale if needed 37 | if rescale_ratio>0: 38 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 39 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 40 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 41 | 42 | # smoothing with gaussian filter 43 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 44 | 45 | out_img_list.append(structure_img_smooth.copy()) 46 | out_name_list.append('im_smooth') 47 | 48 | ################### 49 | # core algorithm 50 | ################### 51 | 52 | # vesselness 3d 53 | response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 54 | bw = response > vesselness_cutoff 55 | 56 | ################### 57 | # POST-PROCESSING 58 | ################### 59 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 60 | 61 | # output 62 | seg = seg>0 63 | seg = seg.astype(np.uint8) 64 | seg[seg>0]=255 65 | 66 | out_img_list.append(seg.copy()) 67 | out_name_list.append('bw_final') 68 | 69 | if output_type == 'default': 70 | # the default final output 71 | save_segmentation(seg, False, output_path, fn) 72 | elif output_type == 'AICS_pipeline': 73 | # pre-defined output function for pipeline data 74 | save_segmentation(seg, True, output_path, fn) 75 | elif output_type == 'customize': 76 | # the hook for passing in a customized output function 77 | output_fun(out_img_list, out_name_list, output_path, fn) 78 | elif output_type == 'array': 79 | return seg 80 | elif output_type == 'array_with_contour': 81 | return (seg, generate_segmentation_contour(seg)) 82 | else: 83 | # the hook for pre-defined RnD output functions (AICS internal) 84 | img_list, name_list = TJP1_output(out_img_list, out_name_list, output_type, output_path, fn) 85 | if output_type == 'QCB': 86 | return img_list, name_list -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_tomm20.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.vessel import vesselnessSliceBySlice 6 | from skimage.feature import peak_local_max 7 | from scipy.ndimage import distance_transform_edt 8 | from skimage.measure import label 9 | from aicssegmentation.core.output_utils import save_segmentation, TOMM20_output, generate_segmentation_contour 10 | from aicsimageprocessing import resize 11 | 12 | def Workflow_tomm20(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 13 | ########################################################################## 14 | # PARAMETERS: 15 | # note that these parameters are supposed to be fixed for the structure 16 | # and work well accross different datasets 17 | 18 | intensity_norm_param = [3.5, 15] 19 | gaussian_smoothing_sigma = 1 20 | gaussian_smoothing_truncate_range = 3.0 21 | vesselness_sigma = [1.5] 22 | vesselness_cutoff = 0.16 23 | minArea = 10 24 | ########################################################################## 25 | 26 | out_img_list = [] 27 | out_name_list = [] 28 | 29 | ################### 30 | # PRE_PROCESSING 31 | ################### 32 | # intenisty normalization (min/max) 33 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 34 | 35 | out_img_list.append(struct_img.copy()) 36 | out_name_list.append('im_norm') 37 | 38 | # rescale if needed 39 | if rescale_ratio>0: 40 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 41 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 42 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 43 | 44 | # smoothing with gaussian filter 45 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 46 | 47 | out_img_list.append(structure_img_smooth.copy()) 48 | out_name_list.append('im_smooth') 49 | 50 | ################### 51 | # core algorithm 52 | ################### 53 | 54 | # 2d vesselness slice by slice 55 | response = vesselnessSliceBySlice(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 56 | bw = response > vesselness_cutoff 57 | 58 | ################### 59 | # POST-PROCESSING 60 | ################### 61 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 62 | 63 | # output 64 | seg = seg>0 65 | seg = seg.astype(np.uint8) 66 | seg[seg>0]=255 67 | 68 | out_img_list.append(seg.copy()) 69 | out_name_list.append('bw_final') 70 | 71 | if output_type == 'default': 72 | # the default final output 73 | save_segmentation(seg, False, output_path, fn) 74 | elif output_type == 'AICS_pipeline': 75 | # pre-defined output function for pipeline data 76 | save_segmentation(seg, True, output_path, fn) 77 | elif output_type == 'customize': 78 | # the hook for passing in a customized output function 79 | output_fun(out_img_list, out_name_list, output_path, fn) 80 | elif output_type == 'array': 81 | return seg 82 | elif output_type == 'array_with_contour': 83 | return (seg, generate_segmentation_contour(seg)) 84 | else: 85 | # the hook for pre-defined RnD output functions (AICS internal) 86 | img_list, name_list = TOMM20_output(out_img_list, out_name_list, output_type, output_path, fn) 87 | if output_type == 'QCB': 88 | return img_list, name_list 89 | 90 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_tuba1b.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from ..core.vessel import vesselness3D 4 | from ..core.pre_processing_utils import intensity_normalization, edge_preserving_smoothing_3d 5 | from skimage.morphology import remove_small_objects 6 | from aicssegmentation.core.output_utils import save_segmentation, TUBA1B_output, generate_segmentation_contour 7 | from aicsimageprocessing import resize 8 | 9 | 10 | def Workflow_tuba1b(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 11 | ########################################################################## 12 | ########################################################################## 13 | # PARAMETERS: 14 | # note that these parameters are supposed to be fixed for the structure 15 | # and work well accross different datasets 16 | 17 | intensity_norm_param = [1.5, 8.0] 18 | vesselness_sigma = [1] 19 | vesselness_cutoff = 0.01 20 | minArea = 20 21 | ########################################################################## 22 | 23 | out_img_list = [] 24 | out_name_list = [] 25 | 26 | ################### 27 | # PRE_PROCESSING 28 | ################### 29 | # intenisty normalization (min/max) 30 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 31 | 32 | out_img_list.append(struct_img.copy()) 33 | out_name_list.append('im_norm') 34 | 35 | # rescale if needed 36 | if rescale_ratio>0: 37 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 38 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 39 | 40 | # smoothing with boundary preserving smoothing 41 | structure_img_smooth = edge_preserving_smoothing_3d(struct_img) 42 | 43 | out_img_list.append(structure_img_smooth.copy()) 44 | out_name_list.append('im_smooth') 45 | 46 | ################### 47 | # core algorithm 48 | ################### 49 | 50 | # vesselness 3d 51 | response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) 52 | bw = response > vesselness_cutoff 53 | 54 | ################### 55 | # POST-PROCESSING 56 | ################### 57 | seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 58 | 59 | # output 60 | seg = seg>0 61 | seg = seg.astype(np.uint8) 62 | seg[seg>0]=255 63 | 64 | out_img_list.append(seg.copy()) 65 | out_name_list.append('bw_final') 66 | 67 | if output_type == 'default': 68 | # the default final output 69 | save_segmentation(seg, False, output_path, fn) 70 | elif output_type == 'AICS_pipeline': 71 | # pre-defined output function for pipeline data 72 | save_segmentation(seg, True, output_path, fn) 73 | elif output_type == 'customize': 74 | # the hook for passing in a customized output function 75 | output_fun(out_img_list, out_name_list, output_path, fn) 76 | elif output_type == 'array': 77 | return seg 78 | elif output_type == 'array_with_contour': 79 | return (seg, generate_segmentation_contour(seg)) 80 | else: 81 | # the hook for pre-defined RnD output functions (AICS internal) 82 | img_list, name_list = TUBA1B_output(out_img_list, out_name_list, output_type, output_path, fn) 83 | if output_type == 'QCB': 84 | return img_list, name_list -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/seg_ubtf.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | from skimage.morphology import remove_small_objects, watershed, dilation, ball 4 | from ..core.pre_processing_utils import intensity_normalization, image_smoothing_gaussian_3d 5 | from ..core.seg_dot import dot_slice_by_slice 6 | from skimage.filters import threshold_triangle, threshold_otsu 7 | from skimage.measure import label 8 | from aicssegmentation.core.output_utils import save_segmentation, FBL_output, generate_segmentation_contour 9 | from aicsimageprocessing import resize 10 | 11 | 12 | def Workflow_ubtf(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): 13 | ########################################################################## 14 | # PARAMETERS: 15 | # note that these parameters are supposed to be fixed for the structure 16 | # and work well accross different datasets 17 | 18 | intensity_norm_param = [0.5, 30] 19 | gaussian_smoothing_sigma = 1 20 | gaussian_smoothing_truncate_range = 3.0 21 | dot_2d_sigma = 1 22 | dot_2d_cutoff = 0.03 # 0.01 as default 23 | minArea = 5 24 | low_level_min_size = 700 25 | ########################################################################## 26 | 27 | out_img_list = [] 28 | out_name_list = [] 29 | 30 | ################### 31 | # PRE_PROCESSING 32 | ################### 33 | # intenisty normalization (min/max) 34 | struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) 35 | 36 | out_img_list.append(struct_img.copy()) 37 | out_name_list.append('im_norm') 38 | 39 | # rescale if needed 40 | if rescale_ratio>0: 41 | struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") 42 | struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) 43 | gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio 44 | 45 | # smoothing with gaussian filter 46 | structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) 47 | 48 | out_img_list.append(structure_img_smooth.copy()) 49 | out_name_list.append('im_smooth') 50 | 51 | ################### 52 | # core algorithm 53 | ################### 54 | 55 | # step 1: low level thresholding 56 | #global_otsu = threshold_otsu(structure_img_smooth) 57 | global_tri = threshold_triangle(structure_img_smooth) 58 | global_median = np.percentile(structure_img_smooth,50) 59 | 60 | th_low_level = (global_tri + global_median)/2 61 | bw_low_level = structure_img_smooth > th_low_level 62 | bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) 63 | 64 | # step 2: high level thresholding 65 | bw_high_level = np.zeros_like(bw_low_level) 66 | lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) 67 | for idx in range(num_obj): 68 | single_obj = (lab_low==(idx+1)) 69 | local_otsu = threshold_otsu(structure_img_smooth[single_obj]) 70 | bw_high_level[np.logical_and(structure_img_smooth>local_otsu, single_obj)]=1 71 | 72 | out_img_list.append(bw_high_level.copy()) 73 | out_name_list.append('interm_high') 74 | 75 | # step 3: finer segmentation 76 | response2d = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) 77 | bw_finer = remove_small_objects(response2d>dot_2d_cutoff, min_size=minArea, connectivity=1, in_place=True) 78 | 79 | out_img_list.append(bw_finer.copy()) 80 | out_name_list.append('bw_fine') 81 | 82 | if output_type == 'return': 83 | seg = bw_finer>0 84 | seg = seg.astype(np.uint8) 85 | seg[seg>0]=255 86 | return seg 87 | 88 | # merge finer level detection into high level coarse segmentation to include outside dim parts 89 | bw_high_level[bw_finer>0]=1 90 | 91 | ################### 92 | # POST-PROCESSING 93 | ################### 94 | seg = remove_small_objects(bw_high_level>0, min_size=minArea, connectivity=1, in_place=False) 95 | 96 | # output 97 | seg = seg>0 98 | seg = seg.astype(np.uint8) 99 | seg[seg>0]=255 100 | 101 | out_img_list.append(seg.copy()) 102 | out_name_list.append('bw_coarse') 103 | 104 | if output_type == 'default': 105 | # the default final output 106 | save_segmentation(seg, False, output_path, fn) 107 | elif output_type == 'AICS_pipeline': 108 | # pre-defined output function for pipeline data 109 | save_segmentation(seg, True, output_path, fn) 110 | elif output_type == 'customize': 111 | # the hook for passing in a customized output function 112 | output_fun(out_img_list, out_name_list, output_path, fn) 113 | elif output_type == 'array': 114 | return seg 115 | elif output_type == 'array_with_contour': 116 | return (seg, generate_segmentation_contour(seg)) 117 | else: 118 | # the hook for pre-defined RnD output functions (AICS internal) 119 | img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) 120 | if output_type == 'QCB': 121 | return img_list, name_list 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /aicssegmentation/structure_wrapper/structure_segmenter.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | import logging 3 | import numpy as np 4 | 5 | # Defaults cloned from existing ../bin/batch_processing script 6 | DEFAULT_MODULE_PATH = 'aicssegmentation.structure_wrapper.seg_' 7 | DEFAULT_RESCALE_RATIO = -1 8 | 9 | class StructureSegmenter: 10 | 11 | def __init__(self): 12 | self.log = logging.getLogger(__name__) 13 | 14 | def process_img(self, gene:str, 15 | image: np.array, 16 | rescale_ratio=DEFAULT_RESCALE_RATIO , 17 | module_path=DEFAULT_MODULE_PATH )->(np.array, np.array): 18 | lower_gene = gene.lower() 19 | module_name = module_path+lower_gene 20 | try: 21 | logging.info(f'loading module {module_name}') 22 | seg_module = importlib.import_module(module_name) 23 | function_name = 'Workflow_'+ lower_gene 24 | logging.info(f'getting function '+function_name) 25 | SegModuleFunction = getattr(seg_module, function_name) 26 | except Exception as e: 27 | logging.error(f'raising failure while trying to get module/function for {module_name}') 28 | raise e 29 | try: 30 | logging.info('executing') 31 | (array_val, countour_val) = SegModuleFunction(struct_img=image, 32 | rescale_ratio=rescale_ratio, 33 | output_type='array_with_contour', 34 | output_path=None, # these args are used when the output 35 | fn=None) # is a file 36 | return (array_val, countour_val) 37 | except Exception as e: 38 | logging.error('raising failure in dispatch for process_img') 39 | raise e 40 | -------------------------------------------------------------------------------- /aicssegmentation/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/tests/__init__.py -------------------------------------------------------------------------------- /aicssegmentation/tests/dummy_test.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | from datetime import timedelta 3 | 4 | 5 | def test_dummy(): 6 | assert(True) 7 | 8 | -------------------------------------------------------------------------------- /aicssegmentation/version.py: -------------------------------------------------------------------------------- 1 | # Autogenerated file - do NOT edit this by hand 2 | MODULE_VERSION = "0.1.21.dev1" 3 | 4 | # For snapshot, X.Y.Z.devN -> X.Y.Z.devN+1 5 | # bumpversion devbuild 6 | # 7 | # For release, X.Y.Z.devN -> X.Y.Z 8 | # bumpversion release 9 | # DO NOT CALL release on consecutive calls 10 | # DO NOT CALL release on 0.0.0.devN 11 | # 12 | # For preparing for next development cycle after release 13 | # bumpversion patch (X.Y.Z -> X.Y.Z+1.dev0) 14 | # bumpversion minor (X.Y.Z -> X.Y+1.Z.dev0) 15 | # bumpversion major (X.Y.Z -> X+1.Y.Z.dev0) 16 | # 17 | -------------------------------------------------------------------------------- /aicssegmentation/version.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/aicssegmentation/version.pyc -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | def buildScriptPlugins = ['scripts/common/buildscript-5.gradle'] 3 | println "> Applying script plugins in buildscripts:" 4 | for (scriptPlugin in buildScriptPlugins) { 5 | def pluginPath = "${scriptPluginPrefix}${scriptPlugin}${scriptPluginSuffix}${scriptPluginTag}" 6 | println "${pluginPath}" 7 | apply from: pluginPath, to: buildscript 8 | } 9 | } 10 | 11 | ////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | def scriptPlugins = ['scripts/common/gradle-version-5.gradle', 14 | 'scripts/common/common-5.gradle', 15 | 'scripts/python/build.gradle', 16 | 'scripts/python/version.gradle', 17 | 'scripts/python/publish.gradle'] 18 | println "> Applying script plugins:" 19 | for (scriptPlugin in scriptPlugins) { 20 | def pluginPath = "${scriptPluginPrefix}${scriptPlugin}${scriptPluginSuffix}${scriptPluginTag}" 21 | println "${pluginPath}" 22 | apply from: pluginPath 23 | } 24 | 25 | 26 | // Add the environment variable to gradle for coverage report 27 | // Do not add this to setup.cfg since it will break IDE tools 28 | py.env.put("PYTEST_ADDOPTS", "--cov=${rootProject.name} --cov-config=setup.cfg --cov-report=html --cov-report=xml --cov-report=term") 29 | py.uploadToPyPi = true 30 | 31 | 32 | ////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | 34 | project.group = "org.alleninstitute.aics.pypi" 35 | description = "Scripts for structure segmentation" 36 | // Project version will be managed outside of gradle in accordance with PEP 440 37 | // ("https://www.python.org/dev/peps/pep-0440/") 38 | 39 | // To see the gradle plugin for python look at 40 | // http://stash.corp.alleninstitute.org/projects/AICSSW/repos/gradle-script-plugins/browse/scripts/python/ 41 | // Also read BUILD.md 42 | 43 | ////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | -------------------------------------------------------------------------------- /demo_data/RAB5_demo_data.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/demo_data/RAB5_demo_data.tif -------------------------------------------------------------------------------- /demo_data/TNNI1_demo_data.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/demo_data/TNNI1_demo_data.tif -------------------------------------------------------------------------------- /demo_data/TOM20_demo_data.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/demo_data/TOM20_demo_data.tif -------------------------------------------------------------------------------- /demo_data/TOMM20_pipeline_example_cell_segmentation.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/demo_data/TOMM20_pipeline_example_cell_segmentation.tiff -------------------------------------------------------------------------------- /demo_data/TOMM20_pipeline_example_nucleus_segmentation.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/demo_data/TOMM20_pipeline_example_nucleus_segmentation.tiff -------------------------------------------------------------------------------- /demo_data/TOMM20_pipeline_example_structure_segmentation.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/demo_data/TOMM20_pipeline_example_structure_segmentation.tiff -------------------------------------------------------------------------------- /docs/conda_why.md: -------------------------------------------------------------------------------- 1 | # About conda and why we need it 2 | 3 | 4 | [What is conda?](https://conda.io/docs/): Conda is a package that is used to manage many different packages. 5 | 6 | [What is Anaconda?](https://www.anaconda.com/what-is-anaconda/): Anaconda is a platform that includes many standard packages (e.g., conda and python). This is the easiest way to work on Python projects across different operating systems. 7 | 8 | [What is a conda environment?](https://conda.io/docs/user-guide/concepts.html#conda-environments): You can think of a conda environment as a box containing all necessary elements you need for a specific project. It can help avoid potential issues like "cannot find package" or "You need Package A in version X but you have Package A in version Y", which may crash your code. -------------------------------------------------------------------------------- /docs/doc.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/doc.rst -------------------------------------------------------------------------------- /docs/full.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/full.jpg -------------------------------------------------------------------------------- /docs/full_doc.md: -------------------------------------------------------------------------------- 1 | # Full Documentations 2 | 3 | The full documentation for experienced developers is under construction and is expected to be available in early 2019. 4 | 5 | 6 | [scikit-image](http://scikit-image.org/docs/dev/index.html) 7 | 8 | 9 | [ITK in Python](https://itkpythonpackage.readthedocs.io/en/latest/Quick_start_guide.html#usage) -------------------------------------------------------------------------------- /docs/full_mem.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/full_mem.jpg -------------------------------------------------------------------------------- /docs/full_str.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/full_str.jpg -------------------------------------------------------------------------------- /docs/installation_linux.md: -------------------------------------------------------------------------------- 1 | # Installation Instruction for Linux 2 | 3 | (tested on Ubuntu 16.04 and 18.04) 4 | 5 | 6 | ## Step 1: Install conda 7 | 8 | *Go to Step 2 if you have anaconda or miniconda installed* 9 | 10 | Go to [Install conda on Linux](https://docs.conda.io/projects/conda/en/latest/user-guide/install/linux.html), choose Anaconda Installer (for Python 3) and then follow the installation instructions. 11 | 12 | Note: [What is conda and anaconda, and why we need this?](conda_why.md) Because conda can effectively manage environment and package installation, setting up conda will make the following steps straightforward and help avoid future problems (conda itself is also very easy to set up). 13 | 14 | 15 | ## Step 2: Verify requirement and prepare for installing segmenter 16 | 17 | #### Step 2.1: [Start conda](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html#starting-conda) 18 | 19 | All commands below are typed in the Terminal window 20 | 21 | #### Step 2.2: Test conda version 22 | 23 | ```bash 24 | conda info 25 | ``` 26 | 27 | You may see somthing like 28 | ```bash 29 | conda version : 4.6.11 30 | python version : 3.7.3.final.0 31 | ``` 32 | 33 | `conda version > 4.4` is preferred. To update conda, check out [how to update your conda](https://www.anaconda.com/keeping-anaconda-date/). `python version >=3.6` is required. 34 | 35 | #### Step 2.3: Test git 36 | 37 | ```bash 38 | git --version 39 | ``` 40 | 41 | If you don't have git, follow [Git for Linux](https://www.atlassian.com/git/tutorials/install-git#linux) to install. 42 | #### Step 2.4: Test pip 43 | 44 | ```bash 45 | pip show pip 46 | ``` 47 | 48 | A message will be printed out on your screen. If you see a warning, like a newer version is available, you can follow the instruction to upgrade you pip. 49 | 50 | #### Step 2.5: Create a new empty conda environment, which we will name "segmentation" (You can certainly choose a different name.) 51 | 52 | ``` bash 53 | conda create -n segmentation python=3.6 54 | ``` 55 | 56 | ### Step 2.6: Activate your conda environment "segmentation" 57 | 58 | ``` bash 59 | conda activate segmentation 60 | ``` 61 | 62 | (For older version conda, the command is `source activate segmentation`.) 63 | 64 | ### Step 2.7: Install nb_conda (for easy conda environment management in jupyter notebook) 65 | 66 | ```bash 67 | conda install nb_conda 68 | ``` 69 | 70 | ## Step 3: Install segmenter 71 | 72 | #### Step 3.1: Clone aics-segmentation repository from Github (suppose you want to save the folder under '~/Projects') 73 | 74 | ```bash 75 | cd ~/Projects 76 | git clone https://github.com/AllenInstitute/aics-segmentation.git 77 | ``` 78 | 79 | #### Step 3.2: install the packages 80 | 81 | ```bash 82 | cd ~/Projects/aics-segmentation 83 | pip install numpy 84 | pip install itkwidgets==0.14.0 85 | pip install -e .[all] 86 | ``` 87 | 88 | Note 1: Please note that for the users with both python 2 and python 3 installed, use `pip3` instead of `pip` in the commands 89 | 90 | Note 2: We use the packge `itkwidgets` for visualizaiotn within jupyter notebook. Currently, we find version `0.14.0` has slightly better performance in visualizing segmentation results. If you find this viwer keeps crashing in your browser, try `pip uninstall itkwidgets` and then `pip install itkwidgets==0.12.2`. For JupyterLab users, version >= `0.17.1` is needed. 91 | 92 | Note 3: For Jupyter Lab users, the itk viewer requires additionally run: 93 | 94 | ``` 95 | jupyter labextension install @jupyter-widgets/jupyterlab-manager itk-jupyter-widgets 96 | ``` 97 | 98 | Note 4: For advanced user to deploy segmenter on cluster, our package is also [available on PyPi](https://pypi.org/project/aicssegmentation/) 99 | 100 | 101 | #### Step 3.3: Test segmenter 102 | 103 | ``` bash 104 | cd ~/Projects/aics-segmentation/lookup_table_demo 105 | jupyter notebook 106 | ``` 107 | 108 | This will take you to your default browser (e.g., Firefox) and launch Jupyter Notebook App within your browser. Open "test_viewer.ipynb" and test if you can run the notebook from beginning to the end. See more details on [How to use Jupyter Notebook to running the workflow in the Look-up Table](../docs/jupyter_lookup_table.md) -------------------------------------------------------------------------------- /docs/installation_mac.md: -------------------------------------------------------------------------------- 1 | # Installation Instruction for MacOS 2 | 3 | ## Step 0: Install XCode 4 | 5 | *Go to Step 1 if you already have XCode installed (it is very likely that you already have it, if you have done any python or C++ programming on your machine).* 6 | 7 | [Download and install XCode from Apple Developer](https://developer.apple.com/xcode/) 8 | 9 | Note: Depending on the time you access this page, you may be directed to a different page. As effective date of Sep 24 2019, you can find ‘Software Downloads’ at the bottom of the page and follow the download and installation instructions. 10 | 11 | ## Step 1: Install Conda 12 | 13 | *Go to Step 2 if you have anaconda or miniconda installed* 14 | 15 | Go to [Install conda on macOS](https://docs.conda.io/projects/conda/en/latest/user-guide/install/macos.html), choose Anaconda Installer (for Python 3) and then follow the installation instructions. 16 | 17 | Note: [What is conda and anaconda, and why we need this?](conda_why.md) Because conda can effectively manage environment and package installation, setting up conda will make the following steps straightforward and help avoid future problems (conda itself is also very easy to set up). 18 | 19 | ## Step 2: Verify requirement and prepare for installing segmenter 20 | 21 | #### Step 2.1: [Start conda](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html#starting-conda) 22 | 23 | All commands below are typed into the Terminal Window 24 | 25 | #### Step 2.2: Test conda version 26 | 27 | ```bash 28 | conda info 29 | ``` 30 | 31 | You may see somthing like 32 | ```bash 33 | conda version : 4.6.11 34 | python version : 3.7.3.final.0 35 | ``` 36 | 37 | `conda version > 4.4` is preferred. To update conda, check out [how to update your conda](https://www.anaconda.com/keeping-anaconda-date/). `python version >=3.6` is required. 38 | 39 | #### Step 2.3: Test git 40 | 41 | ```bash 42 | git --version 43 | ``` 44 | 45 | If you don't have git, follow [Git for macOS](https://www.atlassian.com/git/tutorials/install-git#mac-os-x) to install and restart conda after installing git. 46 | 47 | #### Step 2.4: Test pip 48 | 49 | ```bash 50 | pip show pip 51 | ``` 52 | 53 | A message will be printed out on your screen. If you see a warning, like a newer version is available, you can follow the instruction to upgrade you pip. 54 | 55 | #### Step 2.5: Create a new empty conda environment, which we will name "segmentation" (You can certainly choose a different name.) 56 | 57 | ``` bash 58 | conda create -n segmentation python=3.6 59 | ``` 60 | 61 | ### Step 2.6: Activate your conda environment "segmentation" 62 | 63 | ``` bash 64 | conda activate segmentation 65 | ``` 66 | 67 | (For older version conda, the command is `source activate segmentation`.) 68 | 69 | ### Step 2.7: Install nb_conda (for easy conda environment management in jupyter notebook) 70 | 71 | ```bash 72 | conda install nb_conda 73 | ``` 74 | 75 | ## Step 3: Install segmenter 76 | 77 | #### Step 3.1: Clone aics-segmentation repository from Github (suppose you want to save the folder under '~/Projects') 78 | 79 | ```bash 80 | cd ~/Projects 81 | git clone https://github.com/AllenInstitute/aics-segmentation.git 82 | ``` 83 | 84 | #### Step 3.2: install the packages 85 | 86 | ```bash 87 | cd ~/Projects/aics-segmentation 88 | pip install numpy 89 | pip install itkwidgets==0.14.0 90 | pip install -e .[all] 91 | ``` 92 | 93 | Note 1: Please note that for the users with both python 2 and python 3 installed, use `pip3` instead of `pip` in the commands 94 | 95 | Note 2: We use the packge `itkwidgets` for visualizaiotn within jupyter notebook. Currently, we find version `0.14.0` has slightly better performance in visualizing segmentation results. If you find this viwer keeps crashing in your browser, try `pip uninstall itkwidgets` and then `pip install itkwidgets==0.12.2`. For JupyterLab users, version >= `0.17.1` is needed. 96 | 97 | Note 3: For Jupyter Lab users, the itk viewer requires additionally run: 98 | 99 | ``` 100 | jupyter labextension install @jupyter-widgets/jupyterlab-manager itk-jupyter-widgets 101 | ``` 102 | 103 | Note 4: For advanced user to deploy segmenter on cluster, our package is also [available on PyPi](https://pypi.org/project/aicssegmentation/) 104 | 105 | 106 | #### Step 3.3: Test segmenter 107 | 108 | ``` bash 109 | cd ~/Projects/aics-segmentation/lookup_table_demo 110 | jupyter notebook 111 | ``` 112 | 113 | This will take you to your default browser (e.g., Safari) and launch Jupyter Notebook App within your browser.Open "test_viwer.ipynb" and test if you can run the notebook from beginning to the end. See more details on [How to use Jupyter Notebook to running the workflow in the Look-up Table](../docs/jupyter_lookup_table.md) 114 | 115 | -------------------------------------------------------------------------------- /docs/installation_windows.md: -------------------------------------------------------------------------------- 1 | # Installation Instruction for Windows 2 | 3 | (tested on Windows 10 with anaconda) 4 | 5 | 6 | ## Step 0: Install Microscoft Build Tools 7 | 8 | *Go to Step 1 if you already have these installed (it is very likely that you already have it, if you have done any python or C++ programming on your machine).* 9 | 10 | 11 | [Download and install the Build Tools from Microsoft](https://visualstudio.microsoft.com/visual-cpp-build-tools/) 12 | 13 | Note 1: Depending on the time you access this page, you may be directed to the download page of "Build Tools for Visual Studio 2017" or "Build Tools for Visual Studio 2018", etc. In general, as long as the version is at least 2015, any subsequent version should work. 14 | 15 | Note 2: When you install the Build Tool, you may be asked to choose what to install. Only the tool for Visual Studio C++ (e.g, pack name: "MSVC v142 - VC 2019 C++") is required for the Allen Cell Segmenter. After installing the Build Tool, make sure to reboot your machine. 16 | 17 | ## Step 1: Install conda 18 | 19 | *Go to Step 2 if you have anaconda or miniconda installed* 20 | 21 | Go to [Install conda on Windows](https://docs.conda.io/projects/conda/en/latest/user-guide/install/windows.html), choose Anaconda Installer (for Python 3) and then follow the installation instructions. 22 | 23 | Note: [What is conda and anaconda, and why we need this?](conda_why.md) Because conda can effectively manage environment and package installation, setting up conda will make the following steps straightforward and help avoid future problems (conda itself is also very easy to set up). 24 | 25 | ## Step 3: Verify requirement and prepare for installing segmenter 26 | 27 | 28 | #### Step 3.1: [Start conda](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html#starting-conda) 29 | 30 | All commands below are typed into Anaconda Prompt window 31 | 32 | #### Step 2.2: Test conda version 33 | 34 | ```bash 35 | conda info 36 | ``` 37 | 38 | You may see somthing like 39 | ```bash 40 | conda version : 4.6.11 41 | python version : 3.7.3.final.0 42 | ``` 43 | 44 | `conda version > 4.4` is preferred. To update conda, check out [how to update your conda](https://www.anaconda.com/keeping-anaconda-date/). `python version >=3.6` is required. 45 | 46 | #### Step 2.3: Test git 47 | 48 | ```bash 49 | git --version 50 | ``` 51 | 52 | If you don't have git, follow [Git for Windows](https://www.atlassian.com/git/tutorials/install-git#windows) to install. It is okay to just use default installation settings. You will need to restart Anaconda Prompt after installing Git. 53 | 54 | #### Step 2.4: Test pip 55 | 56 | ```bash 57 | pip show pip 58 | ``` 59 | 60 | A message will be printed out on your screen. If you see a warning, like a newer version is available, you can follow the instruction to upgrade you pip. 61 | 62 | #### Step 2.5: Create a new empty conda environment, which we will name "segmentation" (You can certainly choose a different name.) 63 | 64 | ``` bash 65 | conda create -n segmentation python=3.6 66 | ``` 67 | 68 | ### Step 2.6: Activate your conda environment "segmentation" 69 | 70 | ``` bash 71 | conda activate segmentation 72 | ``` 73 | 74 | ### Step 2.7: Install nb_conda (for easy conda environment management in jupyter notebook) 75 | 76 | ```bash 77 | conda install nb_conda 78 | ``` 79 | 80 | ## Step 3: Install segmenter 81 | 82 | #### Step 3.1: Clone aics-segmentation repository from Github (suppose you want to save the folder under 'C:\Projects') 83 | 84 | ```bash 85 | cd C:\Projects 86 | git clone https://github.com/AllenInstitute/aics-segmentation.git 87 | ``` 88 | 89 | 90 | #### Step 3.2: install the packages 91 | 92 | ```bash 93 | cd ~/Projects/aics-segmentation 94 | pip install numpy 95 | pip install itkwidgets==0.14.0 96 | pip install -e .[all] 97 | ``` 98 | 99 | Note 1: Please note that for the users with both python 2 and python 3 installed, use `pip3` instead of `pip` in the commands 100 | 101 | Note 2: We use the packge `itkwidgets` for visualizaiotn within jupyter notebook. Currently, we find version `0.14.0` has slightly better performance in visualizing segmentation results. If you find this viwer keeps crashing in your browser, try `pip uninstall itkwidgets` and then `pip install itkwidgets==0.12.2`. For JupyterLab users, version >= `0.17.1` is needed. 102 | 103 | Note 3: For Jupyter Lab users, the itk viewer requires additionally run: 104 | 105 | ``` 106 | jupyter labextension install @jupyter-widgets/jupyterlab-manager itk-jupyter-widgets 107 | ``` 108 | 109 | Note 4: For advanced user to deploy segmenter on cluster, our package is also [available on PyPi](https://pypi.org/project/aicssegmentation/) 110 | 111 | #### Step 3.3: Test segmenter 112 | 113 | ``` bash 114 | cd C:\Projects\aics-segmentation\lookup_table_demo 115 | jupyter notebook, choose anaconda installer. 116 | ``` 117 | 118 | This will take you to your default browser (e.g., Chrome) and launch Jupyter Notebook App within your browser. Open "test_viewer.ipynb" and test if you can run the notebook from beginning to the end. See more details on [How to use Jupyter Notebook to running the workflow in the Look-up Table](../docs/jupyter_lookup_table.md) 119 | 120 | 121 | -------------------------------------------------------------------------------- /docs/object_identification.md: -------------------------------------------------------------------------------- 1 | # What is object identification? 2 | 3 | Suppose you have a multi-channel image with Golgi in one channel and plasma membrane in the another channel. One 2D z-slice of the 3D image is shown below. 4 | 5 | ![raw](./full.jpg) 6 | 7 | 8 | For simiplicity, to explain the concept of object identification, we use a small area (see the yellow box) for example. 9 | 10 | Suppose you have run the segmenter to get a binary image as the output as below. You can get some basic information, like how many pixels have been segmented as your target structure (i.e., Golgi) in this image or the physical size of structure in this whole image. 11 | 12 | ![s1](./step1.jpg) 13 | 14 | A simple way of **object identification** is to extract each [connected component](https://homepages.inf.ed.ac.uk/rbf/HIPR2/label.htm) and define each connected component as one object. 15 | 16 | ![s2](./step2.jpg) 17 | 18 | 19 | Furthermore, you can also convert the binary image into separated groups of analyzable objects according to **mask labels**. 20 | 21 | What is a mask label? Depending on the biological questions, the mask label may vary. It could be areas enclosed by each individual cell or each individual nucleus, or any other way you may want to partition the image into different analyzable regions. All the objects in one particular cell/nucleus/customized region within in the structure segmentation binary image would have the same group id. 22 | 23 | This is useful, for example, when a per-cell measurement is needed. In this case a cell segmentation is used as the mask label. 24 | 25 | 26 | *Note: In this demo, we are using a cell segmentation generated by a deep learning based segmentation algorithm developed at the Allen Institute for Cell Science. We are working on the release of our nuclear/cell segmentation workflows. Please stay tuned :) For your data, you may use your own nuclear/cell segmentation approach or you can do this via manual annotation in Fiji.* 27 | 28 | In this example, when we apply the cell segmentation as the mask label, we have: 29 | 30 | ![s3_1](./step3_p1.jpg) 31 | 32 | Then, we can get the object identification results as below. 33 | 34 | ![s3_2](./step3_p2.jpg) 35 | -------------------------------------------------------------------------------- /docs/rab5a_raw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/rab5a_raw.jpg -------------------------------------------------------------------------------- /docs/step1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/step1.jpg -------------------------------------------------------------------------------- /docs/step2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/step2.jpg -------------------------------------------------------------------------------- /docs/step3_p1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/step3_p1.jpg -------------------------------------------------------------------------------- /docs/step3_p2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/step3_p2.jpg -------------------------------------------------------------------------------- /docs/toolkit_paper_SI_vFinalForBioRxiv.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/toolkit_paper_SI_vFinalForBioRxiv.pdf -------------------------------------------------------------------------------- /docs/toolkit_paper_lookup_table_20181206.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/docs/toolkit_paper_lookup_table_20181206.pdf -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # This points to the location of the script plugins used to provide the build tasks. 2 | # This also provides the gradle version - run './gradlew wrapper' to set it. 3 | 4 | #### 5 | scriptPluginPrefix=https://aicsbitbucket.corp.alleninstitute.org/projects/sw/repos/gradle-script-plugins/raw/ 6 | scriptPluginSuffix=?at=refs/tags/ 7 | 8 | # This variable is separated in order to allow it to be overridden with an environment variable 9 | # See: https://docs.gradle.org/current/userguide/build_environment.html#sec:project_properties 10 | # This will be overridden by Jenkins with the version defined in the Jenkins configuration. 11 | # The variable can also be used locally: `ORG_GRADLE_PROJECT_scriptPluginTag=2.4.3 ./gradlew tasks` 12 | scriptPluginTag=2.4.2 13 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-rc-1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /lookup_table_demo/README.md: -------------------------------------------------------------------------------- 1 | List of "playgrounds" for the lookup table: 2 | 3 | 1. playground_st6gal.ipynb: workflow for Sialyltransferase 1 4 | 2. playground_spotty.ipynb: workflow for Fibrillarin, Beta catenin 5 | 3. playground_npm1.ipynb: workflow for Nucleophosmin 6 | 4. playground_curvi.ipynb: workflows for Sec61 beta, Tom 20, Lamin B1 (mitosis-specific) 7 | 5. playground_lamp1.ipynb: workflow for LAMP-1 8 | 6. playground_dots.ipynb: workflows for Centrin-2, Desmoplakin, and PMP34 9 | 7. playground_gja1.ipynb: workflow for Connexin-43 10 | 8. playground_filament3d.ipynb: workflows for Tight junction protein ZO1, Beta actin, Non-muscle myosin IIB, Alpha-actinin-1, Alpha tubulin, Troponin I, and Titin 11 | 9. playground_shell.ipynb: workflow for Lamin B1 (Interphase-specific) 12 | 13 | Find the sample in the lookup table with the closest morphology to your data and start the corresponding "playground" to test the workflow. -------------------------------------------------------------------------------- /lookup_table_demo/test_segmentation_TNNI1.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenInstitute/aics-segmentation/faa515ddb8e7deff0935e9bc999a74271473ef67/lookup_table_demo/test_segmentation_TNNI1.tiff -------------------------------------------------------------------------------- /lookup_table_demo/test_viewer.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 8, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from itkwidgets import view\n", 10 | "import numpy as np\n", 11 | "from aicssegmentation.core.pre_processing_utils import image_smoothing_gaussian_3d" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 5, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "im = np.ones((65,624,624),dtype=np.uint8)" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 6, 26 | "metadata": {}, 27 | "outputs": [ 28 | { 29 | "data": { 30 | "application/vnd.jupyter.widget-view+json": { 31 | "model_id": "06b697a8ce8d46b6bac6337b9fee386f", 32 | "version_major": 2, 33 | "version_minor": 0 34 | }, 35 | "text/plain": [ 36 | "Viewer(geometries=[], gradient_opacity=0.22, point_sets=[], rendered_image==1.15.1', 57 | 'scipy>=1.1.0', 58 | 'scikit-image==0.15.0', 59 | 'pandas>=0.23.4', 60 | 'aicsimageio>=3.0.0', 61 | 'aicsimageprocessing==0.7.1', 62 | 'numba>=0.40.0', 63 | 'itk' 64 | ], 65 | 66 | # For test setup. This will allow JUnit XML output for Jenkins 67 | setup_requires=['pytest-runner'], 68 | tests_require=test_deps, 69 | 70 | extras_require=extras, 71 | zip_safe=False 72 | ) 73 | --------------------------------------------------------------------------------