├── .gitignore ├── README.md ├── celltype_annotations.zip ├── scripts ├── BackCorr_after_Analyze_ALL_channels.m ├── Callbarcodes_ALL_channels.m ├── alltforms.m ├── back_correct_multi_pos.m ├── bkcorrintron.m ├── colocalizeBarcodeV2_markedup_NO_INTENSITY.m ├── correctbackground.m ├── filterseeds_marked_up.m ├── findDotsBarcodeV2.m ├── findGaussianDots_return_all.m ├── findtformV3.m ├── gene_calling.m ├── grab_ims.m ├── grab_ims_Blanks.m ├── handle_ambiguous_barcodes.m ├── loadTiffStacks.m ├── logMask.m ├── numseeds.m ├── pointLocations.m ├── removeBeads.m ├── removezeros.m ├── removezeros2.m ├── saveastiff.m └── selfseg.m └── sourcedata.zip /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all .mat .tif .png .txt .zip .fig .asv ~ File endings 2 | *.mat 3 | *.tif 4 | *.png 5 | *.txt 6 | *.csv 7 | *.zip 8 | *.fig 9 | *.asv 10 | *~ 11 | 12 | # Ignore the folder 'testdata' 13 | testdata/ 14 | testscripts/ 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # seqFISH+ 2 | This repostory contains the scripts used in processing the images and barcode calling of seqFISH+ experiment and the source data which consists of the processed data. The cell type annotations zip file contains the annotations for each single cells with their Louvain clusters number. The gene ID for each transcript location in the mouse brain data or NIH/3T3 cell data corresponds to the codebook. Additional source data such as the mRNA point locations in NIH/3T3 cells are available on Zenodo at http://doi.org/10.5281/zenodo.2669683. 3 | 4 | ## Getting Started 5 | * Download all the contents of the folder and add it to your Matlab path. 6 | 7 | ### Prerequisites 8 | * MATLAB 9 | 10 | ### Dependencies 11 | * radialcenter.m by Dr. Parthasarathy, which can be downloaded [here](https://media.nature.com/original/nature-assets/nmeth/journal/v9/n7/extref/nmeth.2071-S2.zip). 12 | 13 | ## Running the Code 14 | *Overview of the steps for the seqFISH+ pipeline* 15 | ### Prerequisites 16 | * points spread function of a bead 17 | * Region of interests (ROI) holds polygon cell segmentations created from ImageJ software 18 | * thresholding values after Preprocessing Step 19 | 20 | ### Preprocessing 21 | * BackCorr_After_Analyze_ALL_channels.m 22 | * a. grab_ims.m - grabs all the hybridization images in the 3 channels 23 | * b. grab_ims.m - grab the dapi channel in channel 4 24 | * c. imregcorr.m - calculate the dapi transformation to the first reference dapi image 25 | * d. deconvlucy.m - deconvolve the image with the point spread function 26 | * e. grab_ims_Blanks.m - grab the blank images 27 | * f. back_correct_multi_pos.m - get the background corrections 28 | * g. findDotsBarcodeV2.m - find the dots using a laplacian of gaussians and a regional maxima 29 | * h. radialcenter.m - super resolve dots with radial center 30 | * i. transformPointsForward.m - apply transformation to dots 31 | ### Postprocessing 32 | * Callbarcodes_ALL_channels.m 33 | * a. gene_calling.m - colocalize all the points and recieve all the found barcodes 34 | * b. handle_ambiguous_barcodes.m - match points to genes and remove ambiguous barcodes 35 | * c. pointLocations.m – create the point locations and lists for each gene 36 | * d. numseeds.m – calculate the number of seeds for each point 37 | * e. filterseeds_marked_up.m – filter the points that have seeds 3 or 4 (not in function) 38 | 39 | ## License 40 | Free for non-commercial and academic research. The software is bound by the licensing rules of California Institute of Technology (Caltech) 41 | 42 | ## Acknowledgments 43 | * Michael Lawson - Writing and implementing code for the project 44 | * Sheel Shah - Developing the algorithm to find the barcodes, finding dots, and much more 45 | * Nico Pierson - Cleaning and updating code 46 | 47 | ## Contact 48 | * Contact the corresponding author: Long Cai (lcai@caltech.edu) for any inquiry. 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /celltype_annotations.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CaiGroup/seqFISH-PLUS/ee6c416006fe09262526eb364c6f66edd35adc88/celltype_annotations.zip -------------------------------------------------------------------------------- /scripts/BackCorr_after_Analyze_ALL_channels.m: -------------------------------------------------------------------------------- 1 | function [] = BackCorr_after_Analyze_ALL_channels(posI, TFperNom, myChannel,zSlices,zfocus,psfI) 2 | 3 | 4 | %% Declare Variables 5 | % setup path for blank images 6 | blankPath = []; 7 | 8 | loc_path = pwd; 9 | all_nm = [647 561 488]; 10 | numRnds = 81; 11 | channel = myChannel + 1; 12 | channel_nm = all_nm(channel); 13 | my_pos = posI-1; 14 | 15 | 16 | %% Grab FISH images 17 | [Image_647] = ... 18 | grab_ims(loc_path, my_pos, numRnds, myChannel, zSlices); 19 | 20 | 21 | %% Grab DAPI images 22 | DAPI_Channel = 3; 23 | [Image_DAPI] = ... 24 | grab_ims(loc_path, my_pos, numRnds, DAPI_Channel, zSlices); 25 | 26 | 27 | %% use DAPI to find approximate tform between images... 28 | fprintf('DAPI aligning all hybs and Z-slices... \r') 29 | bead_im =Image_DAPI{1}(:,:,zfocus); 30 | trans = zeros(numRnds,2); 31 | tic 32 | for i = 1:numRnds 33 | my_im = Image_DAPI{i}(:,:,zfocus); 34 | TFORM_final(i) = imregcorr(my_im,bead_im,'translation'); 35 | trans(i,:) = TFORM_final(i).T(3,1:2); 36 | end 37 | toc 38 | clear Image_DAPI 39 | 40 | 41 | %% check bead bleaching, Z-focus values, and tform estimates 42 | figure 43 | plot(trans(:,1),'ro') 44 | hold on 45 | plot(trans(:,2),'mo') 46 | legend('x est','y est','Location','best') 47 | savefig([loc_path sprintf('\\Analysis_Details_NO_FISH_RCE\\Bead_Alignment\\Pos%.0f_%.0fnm.fig',my_pos, channel_nm)]) 48 | close all 49 | 50 | 51 | %% clean up images 52 | fprintf('Cleaning up images through Miji...\n') 53 | parfor hyb = 1:81 54 | tic 55 | hyb 56 | locIm = Image_647{hyb}; 57 | myIm = locIm(:,:,zfocus); 58 | [Image_647_clean{hyb}] = deconvlucy(myIm,psfI); 59 | end 60 | save([ loc_path '\Analysis_Details_NO_FISH_RCE\Back_Subtract_Z_focused\' sprintf('Deconvolved_Pos%.0f_%.0fnm.mat',my_pos, channel_nm)],'Image_647_clean') 61 | 62 | 63 | %% Correct for laser 64 | % load blank image 65 | fprintf('Correcting for laser...\n') 66 | myChannel = channel-1; 67 | [Blank_Image_647] = ... 68 | grab_ims_Blanks(blankPath, 0:6, myChannel, zSlices); 69 | 70 | corrections = back_correct_multi_pos(Blank_Image_647); 71 | tic 72 | parfor hyb = 1:81 73 | hyb 74 | locIm = Image_647_clean{hyb}; 75 | focusBeadImage{hyb} = locIm; 76 | BC_im{hyb} = double(locIm)./corrections; 77 | end 78 | toc 79 | tic 80 | for hyb = 1:80:81 81 | fprintf(sprintf('Save backcorrected %.0f ...\n',hyb)) 82 | myIm = BC_im{hyb}; 83 | save([loc_path filesep 'Analysis_Details' filesep 'Back_Subtract_Z_focused' filesep... 84 | sprintf('Back_Corrected_Pos%.0f_hyb%.0f_%.0fnm.mat',my_pos, hyb, channel_nm)], 'myIm') 85 | end 86 | toc 87 | Image_647_clean = BC_im; 88 | 89 | 90 | %% find FISH dots in all rounds, using rolling ball from miji 91 | fprintf('Finding FISH dots in all hyb rounds...\n') 92 | load(sprintf('threshold_factor_%.0f.mat',channel_nm)) 93 | 94 | threshold_factor = threshold_factor * TFperNom; 95 | HCRorFISH = 1; %FISH 96 | debug = 0; 97 | FISHdots = cell(81,1); 98 | Pixels = 3; 99 | tic 100 | 101 | for hyb = 1:81 102 | myIm = Image_647_clean{hyb}; 103 | threshold = threshold_factor(hyb); 104 | [dotInt{hyb},FISHdots{hyb}] = findDotsBarcodeV2({myIm}, threshold, HCRorFISH,debug); 105 | srDots{hyb} = FISHdots{hyb}.channels; 106 | end 107 | toc 108 | 109 | 110 | %% keep only dots in segmented cells 111 | fprintf('Removing dots outside segmented cells ...\n') 112 | PathName = [loc_path filesep '..' filesep]; 113 | fullpath = [PathName filesep 'RoiSet_Pos' num2str(my_pos) ]; 114 | vertex = selfseg(fullpath); 115 | for hyb = 1:81 116 | loc_dots = FISHdots{hyb}.channels(:,1:2); 117 | keep_I = zeros(length(loc_dots),1); 118 | for i = 1:length(vertex) 119 | keep_I = keep_I + ... 120 | inpolygon(loc_dots(:,1),loc_dots(:,2),vertex(i).x,vertex(i).y); 121 | end 122 | keep_I = find(keep_I); 123 | FISHdots{hyb}.channels = FISHdots{hyb}.channels(keep_I,:); 124 | srDots{hyb} = FISHdots{hyb}.channels; 125 | end 126 | 127 | 128 | %% super resolve with radial center applied to raw image all dots 129 | fprintf('SR all dots with RCE ...\n') 130 | Pixels = 3; 131 | tic 132 | for hyb = 1:81 133 | locDots = FISHdots{hyb}.channels; 134 | locIm = Image_647_clean{hyb}; 135 | xc = []; 136 | yc = []; 137 | for dotID = 1:length(locDots) 138 | I = double((locIm((-Pixels:Pixels)+locDots(dotID,2),(-Pixels:Pixels)+locDots(dotID,1)))); 139 | [xc(dotID),yc(dotID)] = radialcenter(I); 140 | end 141 | xyc = locDots(:,1:2) + [xc; yc]' - [Pixels, Pixels]-1; 142 | numdots(hyb) = length(xyc); 143 | srDots{hyb} = xyc; 144 | end 145 | 146 | 147 | %% build hyb labelled dot lists 148 | tic 149 | fprintf('Build hyb labelled dot lists...\n') 150 | dotsWid = {}; % dots with ID of actual hyb (i.e. image index -1) 151 | for bcI = 1:4 152 | myDots = []; 153 | for hybI = 1:20 154 | gHybI = (bcI-1)*20+hybI; 155 | hDots = srDots{gHybI}; 156 | locDots = transformPointsForward( TFORM_final(gHybI),hDots(:,1:2)); 157 | myDots = [myDots; locDots ones(size(locDots,1),1)*(hybI)]; 158 | end 159 | dotsWid(bcI) = {myDots}; 160 | end 161 | FISH_only = dotsWid; 162 | 163 | 164 | %% Save FISH dots 165 | FISH_only 166 | fprintf('saving results...\n') 167 | save([loc_path filesep sprintf('%.0f_Analysis',channel_nm) filesep sprintf('Analysis_Details_NO_FISH_RCE_%.1f',TFperNom) filesep 'extractedData' filesep... 168 | sprintf('FISH_only_Pos%.0f_%.0fnm_results.mat',my_pos,channel_nm)],'FISH_only') 169 | 170 | fprintf('results saved...\n') 171 | % end 172 | -------------------------------------------------------------------------------- /scripts/Callbarcodes_ALL_channels.m: -------------------------------------------------------------------------------- 1 | function [] = Callbarcodes_ALL_channels(posI, TFperNom, radius, myChannel) 2 | 3 | % load barcode codebook 4 | barcodePath = []; 5 | 6 | %% Delcare Variables 7 | load(barcodePath) 8 | loc_pat = pwd; 9 | all_nm = [647 561 488]; 10 | channel = myChannel + 1; 11 | channel_nm = all_nm(channel); 12 | FISH_TF = 1; 13 | bead_TF = 100; 14 | Path = pwd; 15 | numRnds = 81; 16 | zSlices = 5; 17 | 18 | % %%%%%%%%%%%%%%%%% adapt output for Sheel's code %%%%%%%%%%%%%%%%%%%%%%%%%%% 19 | my_pos = posI-1 20 | tic 21 | % load points 22 | load([loc_pat filesep sprintf('%.0f_Analysis',channel_nm) filesep sprintf('Analysis_Details_NO_FISH_RCE_%.1f',TFperNom) filesep 'extractedData' filesep sprintf('FISH_only_Pos%.0f_%.0fnm_results.mat',my_pos, channel_nm)]) 23 | 24 | toc 25 | 26 | hyb = 4; %bcR 27 | channum = 20; %hybs 28 | alloweddiff = 1; 29 | conthresh = 1; 30 | 31 | close all 32 | fprintf('Converting dot organization...\n') 33 | my_pos 34 | tic 35 | for bcR = 1:4 36 | locDots = FISH_only{bcR}; 37 | for channel = 1:20 38 | IDs = find(locDots(:,3) == channel); 39 | points(bcR).dots(channel).channels = [locDots(IDs,1:2) ones(length(locDots(IDs,1)),1)]; 40 | end 41 | end 42 | toc 43 | 44 | 45 | 46 | %% divide into cells, then run analysis as normal 47 | ROI_path = [loc_pat filesep '..']; 48 | roi_prefix = 'RoiSet_Pos'; 49 | fullpath = [ROI_path filesep roi_prefix num2str(my_pos) ]; 50 | vertex = selfseg(fullpath); 51 | 52 | 53 | 54 | for cell_I = 1:size(vertex,2) 55 | 56 | %% keep only dots in THIS segmented cells 57 | fprintf('Selecting dots in this cell ...\n') 58 | for bcrI = 1:hyb 59 | for channel = 1:channum 60 | loc_dots = points(bcrI).dots(channel).channels(:,1:2); 61 | keep_I = []; 62 | keep_I = inpolygon(loc_dots(:,1),loc_dots(:,2),vertex(cell_I).x,vertex(cell_I).y); 63 | thisCellPoints(bcrI).dots(channel).channels = points(bcrI).dots(channel).channels(keep_I,:); 64 | end 65 | end 66 | 67 | fprintf('Finding barcodes...\n') 68 | [cell_I my_pos] 69 | tic 70 | [foundbarcodes] = gene_calling(thisCellPoints,radius); 71 | toc 72 | 73 | fprintf('Handle ambiguous codes...\n') 74 | [cell_I my_pos] 75 | tic 76 | [foundbarcodes, totdropped, copynumfinal, rawfound] = ... 77 | handle_ambiguous_barcodes(foundbarcodes, thisCellPoints, hyb, channum, ... 78 | barcodekey, alloweddiff,conthresh, ROI_path, [0 0],my_pos,roi_prefix) 79 | toc 80 | 81 | 82 | 83 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 84 | fprintf('Find gene location ...\n') 85 | [cell_I my_pos] 86 | tic 87 | [dotlocations,copynumfinalrevised,PosList] = ... 88 | pointLocations(ROI_path,my_pos,hyb, channum, thisCellPoints, foundbarcodes,barcodekey,copynumfinal,radius) 89 | toc 90 | 91 | 92 | 93 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 94 | fprintf('Counting seeds per gene ...\n') 95 | [cell_I my_pos] 96 | tic 97 | 98 | [seeds, int, ints] = numseeds(PosList,dotlocations); 99 | toc 100 | 101 | 102 | save([loc_pat filesep sprintf('%.0f_Analysis',channel_nm) filesep sprintf('Analysis_Details_NO_FISH_RCE_%.1f',TFperNom) filesep 'postProcData' filesep sprintf('Radius_%.1f_loc',radius) filesep ... 103 | sprintf('Pos%.0f_Cell_%.0f_%.0fnm_results.mat',my_pos,cell_I,channel_nm)],'foundbarcodes','totdropped','copynumfinal',... 104 | 'dotlocations','copynumfinalrevised','PosList',... 105 | 'seeds','rawfound') 106 | clear foundbarcodes rawfound 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /scripts/alltforms.m: -------------------------------------------------------------------------------- 1 | function [tforms] = alltforms(PathName,colors,channels,reference) 2 | % colors = # of channels in stack minus DAPI 3 | % channels = channels numbers that need to be aligned 4 | % reference = number of reference channel 5 | 6 | fld = pwd; 7 | Miji; 8 | cd(fld); 9 | 10 | if isempty(PathName) 11 | [FileName,PathName,FilterIndex] = uigetfile('.tif'); 12 | path_to_fish = ['path=[' PathName FileName ']']; 13 | else 14 | path_to_fish = ['path=[' PathName ']']; 15 | C = strsplit(PathName,'\'); 16 | FileName = C{end}; 17 | k = strfind(PathName,'\'); 18 | PathName = PathName(1:k(end)-1); 19 | end 20 | 21 | MIJ.run('Open...', path_to_fish); 22 | %range = inputdlg('Where Should I Start In Z'); 23 | MIJ.run('Z Project...', 'projection=[Max Intensity]'); 24 | %MIJ.run('Subtract Background...', 'rolling=10 stack'); 25 | MIJ.run('Split Channels'); 26 | mkdir([PathName 'channelsWBG']); 27 | for i = 1:colors 28 | name = ['C' num2str(i) '-MAX_' FileName]; 29 | Images = uint16(MIJ.getImage(name)); 30 | saveastiff(Images, [PathName 'channelsWBG\channel' num2str(i) '.tif']) 31 | end 32 | 33 | MIJ.run('Close All'); 34 | MIJ.exit; 35 | for i = 1:colors 36 | tforms{i} = []; 37 | end 38 | for i = 1:length(channels) 39 | [tforms{channels(i)}] = findtformV3([PathName 'channelsWBG\channel' num2str(channels(i)) '.tif'],[PathName 'channelsWBG\channel' num2str(reference) '.tif']); 40 | pause('on'); 41 | pause; 42 | close all; 43 | end 44 | 45 | tforms(cellfun(@isempty,tforms)) = tforms(reference); 46 | 47 | 48 | -------------------------------------------------------------------------------- /scripts/back_correct_multi_pos.m: -------------------------------------------------------------------------------- 1 | function corrections = back_correct_multi_pos(blankIm) 2 | %% Use the blank slide image to do corrections 3 | cy5back = []; 4 | bic = 0; 5 | for posI = 1:length(blankIm) 6 | posI 7 | for i = 1:size(blankIm{posI},3) 8 | % blur blank ims 9 | bic = bic+1 10 | cy5back(:,:,bic) = imopen(blankIm{posI}(:,:,i),strel('disk',100)); 11 | end 12 | end 13 | % find median over all blank im for each pixel 14 | cy5med = median(cy5back,3); 15 | % normalize to max 16 | corrections = double(cy5med)/double(max(max(cy5med))); 17 | 18 | 19 | -------------------------------------------------------------------------------- /scripts/bkcorrintron.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | PathName = uigetdir; 4 | 5 | listing = dir([PathName '/*.tif']); 6 | fld = pwd; 7 | Miji; 8 | cd(fld); 9 | cy7back = []; 10 | cy5back = []; 11 | a594back = []; 12 | cy3back = []; 13 | a488back = []; 14 | 15 | for i = 1:length(listing) 16 | path_to_fish = ['path=[' PathName '\' listing(i).name ']']; 17 | MIJ.run('Open...', path_to_fish); 18 | MIJ.run('Split Channels'); 19 | for loop = 1:3 20 | name = ['C' num2str(loop) '-' listing(i).name]; 21 | im = uint16(MIJ.getImage(name)); 22 | hybnum.color{loop} = im; 23 | end 24 | MIJ.run('Close All'); 25 | %imcortex = loadtiff(['/Volumes/New Volume/10132015Brain/Final Images to Use/Organized/pos' num2str(num(i)) '/Nissel.tif']); 26 | %S = load([PathName '/pos' num2str(num(i)) '/hybnum' num2str(num(i)) '.mat']); 27 | cy7 = max(hybnum.color{1},[],3); 28 | cy5 = max(hybnum.color{2},[],3); 29 | a594 = max(hybnum.color{3},[],3); 30 | % cy3 = max(hybnum.color{4},[],3); 31 | % a488 = max(hybnum.color{5},[],3); 32 | cy7back(:,:,i) = imopen(cy7,strel('disk',100)); 33 | cy5back(:,:,i) = imopen(cy5,strel('disk',100)); 34 | a594back(:,:,i) = imopen(a594,strel('disk',100)); 35 | % cy3back(:,:,i) = imopen(cy3,strel('disk',100)); 36 | % a488back(:,:,i) = imopen(a488,strel('disk',100)); 37 | end 38 | 39 | cy7med = median(cy7back,3); 40 | cy5med = median(cy5back,3); 41 | a594med = median(a594back,3); 42 | % cy3med = median(cy3back,3); 43 | % a488med = median(a488back,3); 44 | 45 | cy7med = double(cy7med)/double(max(max(cy7med))); 46 | cy5med = double(cy5med)/double(max(max(cy5med))); 47 | a594med = double(a594med)/double(max(max(a594med))); 48 | % cy3med = double(cy3med)/double(max(max(cy3med))); 49 | % a488med = double(a488med)/double(max(max(a488med))); 50 | 51 | corrections(1).corrections{1} = cy7med; 52 | corrections(1).corrections{2} = cy5med; 53 | corrections(1).corrections{3} = a594med; 54 | % corrections(1).corrections{4} = cy3med; 55 | % corrections(1).corrections{5} = a488med; 56 | 57 | figure; 58 | surf(double(cy7med(1:8:end,1:8:end))),zlim([0 1]); 59 | ax = gca; 60 | ax.YDir = 'reverse'; 61 | 62 | figure; 63 | surf(double(cy5med(1:8:end,1:8:end))),zlim([0 1]); 64 | ax = gca; 65 | ax.YDir = 'reverse'; 66 | 67 | figure; 68 | surf(double(a594med(1:8:end,1:8:end))),zlim([0 1]); 69 | ax = gca; 70 | ax.YDir = 'reverse'; 71 | 72 | % figure; 73 | % surf(double(cy3med(1:8:end,1:8:end))),zlim([0 1]); 74 | % ax = gca; 75 | % ax.YDir = 'reverse'; 76 | % 77 | % figure; 78 | % surf(double(a488med(1:8:end,1:8:end))),zlim([0 1]); 79 | % ax = gca; 80 | % ax.YDir = 'reverse'; 81 | 82 | 83 | MIJ.exit 84 | -------------------------------------------------------------------------------- /scripts/colocalizeBarcodeV2_markedup_NO_INTENSITY.m: -------------------------------------------------------------------------------- 1 | function [ pts1, pts2, called1, called2, pair ] = colocalizeBarcodeV2_markedup_NO_INTENSITY(points, hybnum,hybnum2, channels,radius,debug ) 2 | %COLOCALIZE Summary of this function goes here 3 | % Detailed explanation goes here 4 | %if length(dots(channels(1)).channels)>length(dots(channels(2)).channels) 5 | %conc1 = dots(channels(2)).channels; 6 | %conc2 = dots(channels(1)).channels; 7 | %else 8 | conc1 = points(hybnum).dots(channels(1)).channels; 9 | conc2 = points(hybnum2).dots(channels(2)).channels; 10 | %end 11 | 12 | [idx,D]= rangesearch(conc1,conc2,sqrt(radius)+.00001); 13 | [idx2,D2] = rangesearch(conc2,conc1,sqrt(radius)+.00001); 14 | pair = []; 15 | % if both sets have colocalization 16 | if ~isempty(idx) & ~isempty(idx2) 17 | %Match Unique Points symmetrically 18 | idx2temp = idx2; 19 | D2temp = D2; 20 | for i = 1:length(idx) 21 | % if this idx only has 1 close enough 22 | if length(idx{i}) == 1 23 | % if f0r this idx there is only one idx2 close enough, and that 24 | % idx2 only has one idx close enough close enough, then yay! 25 | if length(idx2{idx{i}}) == 1; 26 | idxtemp{i,1} = idx{i}; 27 | Dtemp{i,1} = D{i}; 28 | % if fpr this idx there is only one idx2 close enough, BUT that 29 | % idx2 only has multiple idx close enough close enough... 30 | else 31 | % grab who all those idx2 that are close enough to idx 32 | dummy = idx2{idx{i}}; 33 | dummyD = D2{idx{i}}; 34 | % check how many of thosed idx2's idx that are close enough 35 | % have only one close enough 36 | matches = cellfun(@length,idx(dummy))'; 37 | % if any indx2's idx has only one close enough 38 | keepers = matches == 1; 39 | % keep all idx in idxtemp 40 | idxtemp{i,1} = idx{i}; 41 | Dtemp{i,1} = D{i}; 42 | % but only keep idx2 that have an idx close enough that 43 | % only has one close enough 44 | idx2temp{idx{i}} = dummy(keepers); 45 | D2temp{idx{i}} = dummyD(keepers); 46 | end 47 | % if there are multiple close enough do nothing 48 | else 49 | idxtemp{i,1} = idx{i}; 50 | Dtemp{i,1} = D{i}; 51 | end 52 | end 53 | 54 | idxunique = idxtemp; 55 | Dunique = Dtemp; 56 | for i = 1:length(idx2temp) 57 | % if idx2temp has only 1 idx closenough 58 | if length(idx2temp{i}) == 1 59 | % and that idx has only one idx2 close enough, then it's a 60 | % unique pair 61 | if length(idxtemp{idx2temp{i}}) == 1; 62 | idx2unique{i,1} = idx2temp{i}; 63 | D2unique{i,1} = D2temp{i}; 64 | else 65 | dummy = idxtemp{idx2temp{i}}; 66 | dummyD = Dtemp{idx2temp{i}}; 67 | matches = cellfun(@length,idx2temp(dummy))'; 68 | keepers = matches == 1; 69 | idx2unique{i,1} = idx2temp{i}; 70 | D2unique{i,1} = D2temp{i}; 71 | idxunique{idx2temp{i}} = dummy(keepers); 72 | Dunique{idx2temp{i}} = dummyD(keepers); 73 | end 74 | else 75 | idx2unique{i,1} = idx2temp{i}; 76 | D2unique{i,1} = D2temp{i}; 77 | end 78 | end 79 | 80 | % Place unique matches in curated points list 81 | % Remove points from not uniquely matched list 82 | [idxcurated{1:length(idx), 1}] = deal(zeros(1,1)); 83 | [idx2curated{1:length(idx2), 1}] = deal(zeros(1,1)); 84 | counter = 1; 85 | if length(idx2unique)>length(idxunique) 86 | for i = 1:length(idx2unique) 87 | if length(idx2unique{i})==1 && logical(sum(idxunique{idx2unique{i}} == i)) && length(idxunique{idx2unique{i}}) == 1 88 | idx2curated{i} = idx2unique{i}; 89 | idxcurated{idx2unique{i}} = idxunique{idx2unique{i}}; 90 | D2unique{i} = []; 91 | Dunique{idx2unique{i}} = []; 92 | idxunique{idx2unique{i}} = []; 93 | idx2unique{i} = []; 94 | pair(counter,2) = idx2curated{i}; 95 | pair(counter,1) = i; 96 | counter = counter +1; 97 | end 98 | end 99 | else 100 | for i = 1:length(idxunique) 101 | if length(idxunique{i})==1 && logical(sum(idx2unique{idxunique{i}} == i)) && length(idx2unique{idxunique{i}}) == 1 102 | idxcurated{i} = idxunique{i}; 103 | idx2curated{idxunique{i}} = idx2unique{idxunique{i}}; 104 | Dunique{i} = []; 105 | D2unique{idxunique{i}} = []; 106 | idx2unique{idxunique{i}} = []; 107 | idxunique{i} = []; 108 | pair(counter,1) = idxcurated{i}; %conc1 109 | pair(counter,2) = i; %conc2 110 | counter = counter + 1; 111 | end 112 | end 113 | end 114 | 115 | % pts1 = conc1(pair(:,1),:); 116 | % pts2 = conc2(pair(:,2),:); 117 | % figure; showMatchedFeatures(max(m{1},[],3), max(m{2},[],3), pts1(:,1:2), pts2(:,1:2)); 118 | 119 | %Distance Minimization 120 | 121 | idxmin = idxunique; 122 | Dmin = Dunique; 123 | for i = 1:length(idxunique); 124 | if length(Dunique{i}) > 1; 125 | smallest = Dunique{i} == min(Dunique{i}); 126 | if sum(smallest) == 1 127 | idxmin{i,1} = idxunique{i}(smallest); 128 | Dmin{i,1} = Dunique{i}(smallest); 129 | end 130 | end 131 | end 132 | 133 | idx2min = idx2unique; 134 | D2min = D2unique; 135 | for i = 1:length(idx2unique); 136 | if length(D2unique{i}) > 1; 137 | smallest = D2unique{i} == min(D2unique{i}); 138 | if sum(smallest) == 1 139 | idx2min{i,1} = idx2unique{i}(smallest); 140 | D2min{i,1} = D2unique{i}(smallest); 141 | end 142 | end 143 | end 144 | 145 | 146 | % counter = 1; 147 | % clear pair; 148 | % clear pts1; 149 | % clear pts2; 150 | if length(idx2min)>length(idxmin) 151 | for i = 1:length(idx2min) 152 | if length(idx2min{i})==1 && length(idxmin{idx2min{i}}) == 1 153 | if idxmin{idx2min{i}} == i 154 | idx2curated{i} = idx2min{i}; 155 | idxcurated{idx2min{i}} = idxmin{idx2min{i}}; 156 | D2min{i} = []; 157 | Dmin{idx2min{i}} = []; 158 | idxmin{idx2min{i}} = []; 159 | idx2min{i} = []; 160 | pair(counter,2) = idx2curated{i}; 161 | pair(counter,1) = i; 162 | counter = counter +1; 163 | else 164 | idx2min{i} = []; 165 | D2min{i} = []; 166 | end 167 | elseif length(idx2min{i})==1 && isempty(idxmin{idx2min{i}}) 168 | idxmin{i} = []; 169 | Dmin{i} = []; 170 | end 171 | end 172 | else 173 | for i = 1:length(idxmin) 174 | if length(idxmin{i})==1 && length(idx2min{idxmin{i}}) == 1 175 | if idx2min{idxmin{i}} == i 176 | idxcurated{i} = idxmin{i}; 177 | idx2curated{idxmin{i}} = idx2min{idxmin{i}}; 178 | Dmin{i} = []; 179 | D2min{idxmin{i}} = []; 180 | idx2min{idxmin{i}} = []; 181 | idxmin{i} = []; 182 | pair(counter,2) = i; 183 | pair(counter,1) = idxcurated{i}; 184 | counter = counter +1; 185 | else 186 | idxmin{i} = []; 187 | Dmin{i} = []; 188 | end 189 | elseif length(idxmin{i})==1 && isempty(idx2min{idxmin{i}}) 190 | idxmin{i} = []; 191 | Dmin = []; 192 | end 193 | end 194 | end 195 | 196 | % pts1 = conc1(pair(:,1),:); 197 | % pts2 = conc2(pair(:,2),:); 198 | % figure; showMatchedFeatures(max(m{1},[],3), max(m{2},[],3), pts1(:,1:2), pts2(:,1:2)); 199 | 200 | % same z check based on distance 201 | %idxmin = idxunique; 202 | idxz = idxmin; 203 | %Dz = Dfinal; 204 | for i = 1:length(idxz) 205 | if length(idxz{i}) > 1 206 | zref = conc2(i,3); 207 | zdots = conc1(idxmin{i}, 3); 208 | keepers = zdots == zref; 209 | dummy = idxz{i}; 210 | %dummyD = Dfinal{i}; 211 | idxz{i} = dummy(keepers); 212 | %Dz{i} = dummyD(keepers); 213 | end 214 | end 215 | 216 | %idx2min = idx2unique; 217 | idx2z = idx2min; 218 | %Dz = Dfinal; 219 | for i = 1:length(idx2z) 220 | if length(idx2z{i}) > 1 221 | zref = conc1(i,3); 222 | zdots = conc2(idx2min{i}, 3); 223 | keepers = zdots == zref; 224 | dummy = idx2min{i}; 225 | %dummyD = Dfinal{i}; 226 | idx2z{i} = dummy(keepers); 227 | %Dz{i} = dummyD(keepers); 228 | end 229 | end 230 | 231 | % counter = 1; 232 | % clear pair; 233 | % clear pts1; 234 | % clear pts2; 235 | if length(idx2z)>length(idxz) 236 | for i = 1:length(idx2z) 237 | if length(idx2z{i})==1 && length(idxz{idx2z{i}}) == 1 238 | if idxz{idx2z{i}} == i 239 | idx2curated{i} = idx2z{i}; 240 | idxcurated{idx2z{i}} = idxz{idx2z{i}}; 241 | idxz{idx2z{i}} = []; 242 | idx2z{i} = []; 243 | pair(counter,2) = idx2curated{i}; 244 | pair(counter,1) = i; 245 | counter = counter +1; 246 | else 247 | idx2z{i} = []; 248 | end 249 | elseif length(idx2z{i})==1 && isempty(idxz{idx2z{i}}) 250 | idx2z{i} = []; 251 | elseif length(idx2z{i})>1 252 | len = cellfun(@length,idxz(idx2z{i})); 253 | if sum(len) == 1 254 | keepers = len' == 1; 255 | vals = idx2z{i}(keepers); 256 | idx2curated{i} = vals; 257 | idxcurated{vals} = idxz{vals}; 258 | idx2z{i} = []; 259 | idxz{vals} = []; 260 | pair(counter,2) = idx2curated{i}; 261 | pair(counter,1) = i; 262 | counter = counter +1; 263 | end 264 | end 265 | end 266 | else 267 | for i = 1:length(idxz) 268 | if length(idxz{i})==1 && length(idx2z{idxz{i}}) == 1 269 | if idx2z{idxz{i}} == i 270 | idxcurated{i} = idxz{i}; 271 | idx2curated{idxz{i}} = idx2z{idxz{i}}; 272 | idx2z{idxz{i}} = []; 273 | idxz{i} = []; 274 | pair(counter,2) = i; 275 | pair(counter,1) = idxcurated{i}; 276 | counter = counter +1; 277 | else 278 | idxz{i} = []; 279 | end 280 | elseif length(idxz{i})==1 && isempty(idx2z{idxz{i}}) 281 | idxz{i} = []; 282 | elseif length(idxz{i})>1 283 | len = cellfun(@length,idx2z(idxz{i})); 284 | if sum(len) == 1 285 | keepers = len' == 1; 286 | vals = idxz{i}(keepers); 287 | idxcurated{i} = vals; 288 | idx2curated{vals} = idx2z{vals}; 289 | idxz{i} = []; 290 | idx2z{vals} = []; 291 | pair(counter,2) = i; 292 | pair(counter,1) = idxcurated{i}; 293 | counter = counter +1; 294 | end 295 | end 296 | end 297 | end 298 | 299 | %%%% added to remove multiple matching 300 | for i = 1:length(idxz) 301 | if length(idxz{i})>1 302 | a = idx2z(idxz{i}); 303 | for j = length(a):-1:1 304 | if length(a{j}) == 1 & a{j} ~= i 305 | idxz{i}(j) = []; 306 | elseif isempty(a{j}) 307 | idxz{i}(j) = []; 308 | end 309 | end 310 | end 311 | end 312 | 313 | for i = 1:length(idx2z) 314 | if length(idx2z{i})>1 315 | a = idxz(idx2z{i}); 316 | for j = length(a):-1:1 317 | if length(a{j}) == 1 & a{j} ~= i 318 | idx2z{i}(j) = []; 319 | elseif isempty(a{j}) 320 | idx2z{i}(j) = []; 321 | end 322 | end 323 | end 324 | end 325 | %%%%% 326 | 327 | if length(idxz)>length(idx2z) 328 | for i = 1:length(idxz) 329 | if ~isempty(idxz{i}) & length(idx2z(idxz{i})) == 1 & length(idxz{i}) ==1 & idx2z{idxz{i}} == i 330 | pair(counter,2) = i; 331 | pair(counter,1) = idxz{i}; 332 | idx2z{idxz{i}} = []; 333 | idxz{i} = []; 334 | counter = counter + 1; 335 | end 336 | end 337 | else 338 | for i = 1:length(idx2z) 339 | if ~isempty(idx2z{i}) & length(idxz(idx2z{i})) == 1 & length(idx2z{i}) ==1 & idxz{idx2z{i}} == i 340 | pair(counter,2) = idx2z{i}; 341 | pair(counter,1) = i; 342 | idxz{idx2z{i}} = []; 343 | idx2z{i} = []; 344 | counter = counter + 1; 345 | end 346 | end 347 | end 348 | 349 | % for i = 1:length(idxz) 350 | % if length(idxz{i}) > 1 351 | % bart = points(hybnum).dots(channels(1)).intensity(idxz{i}) == max(points(hybnum).dots(channels(1)).intensity(idxz{i})); 352 | % if sum(bart) > 1 353 | % bart = false(1,length(bart)); 354 | % bart(1) = 1; 355 | % end 356 | % pair(counter,2) = i; 357 | % pair(counter,1) = idxz{i}(bart'); 358 | % idxz{i} = []; 359 | % counter = counter + 1; 360 | % end 361 | % end 362 | % 363 | % for i = 1:length(idx2z) 364 | % if length(idx2z{i})==1 && isempty(idxz{idx2z{i}}) 365 | % idx2z{i} = []; 366 | % elseif length(idx2z{i}) > 1 367 | % bart = points(hybnum2).dots(channels(2)).intensity(idx2z{i}) == max(points(hybnum2).dots(channels(2)).intensity(idx2z{i})); 368 | % if sum(bart) > 1 369 | % bart = false(1,length(bart)); 370 | % bart(1) = 1; 371 | % end 372 | % pair(counter,2) = idx2z{i}(bart'); 373 | % pair(counter,1) = i; 374 | % idx2z{i} = []; 375 | % counter = counter + 1; 376 | % end 377 | % end 378 | 379 | %remove this for barcoding 380 | 381 | if ~isempty(pair) 382 | 383 | called1 = zeros(size(conc1,1),1); 384 | called1(pair(:,1)) = 1; 385 | called1 = logical(called1); 386 | called2 = zeros(size(conc2,1),1); 387 | called2(pair(:,2)) = 1; 388 | called2 = logical(called2); 389 | 390 | %2D gaussian mixture model scaled by intensity 391 | 392 | 393 | %Fit a known barcode 394 | pts1 = conc1(pair(:,1),:); 395 | pts2 = conc2(pair(:,2),:); 396 | end 397 | else 398 | called1 = zeros(size(conc1,1),1); 399 | called2 = zeros(size(conc2,1),1); 400 | pair = []; 401 | pts1 = []; 402 | pts2 = []; 403 | end 404 | 405 | if isempty(pair) 406 | called1 = zeros(size(conc1,1),1); 407 | called2 = zeros(size(conc2,1),1); 408 | pair = []; 409 | pts1 = []; 410 | pts2 = []; 411 | end 412 | %image ouput of colocalization 413 | % if debug == 1 414 | % figure; 415 | % g(1:length(pts1), 1) = 1; 416 | % g(length(pts1)+1:2*length(pts1), 1) = 2; 417 | % vec = pts2 - pts1; 418 | % allpts = [pts1;pts2]; 419 | % z = allpts(:,3); 420 | % % call GSCATTER and capture output argument (handles to lines) 421 | % h = gscatter(allpts(:,1), allpts(:,2), g,[],'ox+*sdv^<>ph.',5); 422 | % % for each unique group in 'g', set the ZData property appropriately 423 | % gu = unique(g); 424 | % for k = 1:numel(gu) 425 | % set(h(k), 'ZData', z( g == gu(k) )); 426 | % end 427 | % view(3) 428 | % hold on; quiver3(pts1(:,1),pts1(:,2),pts1(:,3),vec(:,1),vec(:,2),vec(:,3),0,'MaxHeadSize',0.5) 429 | % figure; ax = axes; showMatchedFeatures(max(color1,[],3), max(color2,[],3), pts1(:,1:2), pts2(:,1:2)); 430 | % legend(ax,'dots 1','dots 2'); 431 | % hold on 432 | % for i = 1:length(pts1) 433 | % text(pts1(i,1),pts1(i,2),num2str(i)); 434 | % end 435 | % 436 | % for i = 1:length(pts2) 437 | % text(pts2(i,1)+.2,pts2(i,2)+.2,num2str(i)); 438 | % end 439 | % 440 | % end 441 | 442 | -------------------------------------------------------------------------------- /scripts/correctbackground.m: -------------------------------------------------------------------------------- 1 | function hybnumcor = correctbackground(hybnum, corrections,channels) 2 | 3 | for j = 1:length(channels) 4 | B = repmat(corrections.corrections{j},1,1,size(hybnum.color{j},3)); 5 | hybnumcor.color{j} = uint16(double(hybnum.color{j})./B); 6 | end 7 | -------------------------------------------------------------------------------- /scripts/filterseeds_marked_up.m: -------------------------------------------------------------------------------- 1 | function [numtotal final_PosList] = filterseeds_marked_up(numseeds,seedlist,orig_PosList) 2 | b = cellfun(@(x) x >= numseeds,seedlist(:,2:end),'UniformOutput',0); 3 | num = cellfun(@sum,b); 4 | final_PosList = orig_PosList; 5 | for i = 1:length(b) 6 | if ~isempty(b{i}) 7 | dIdx = find(~b{i}); 8 | final_PosList{i,2}(dIdx,:) = []; 9 | end 10 | end 11 | final_PosList = final_PosList(:,2); 12 | numtotal = sum(num,2); 13 | -------------------------------------------------------------------------------- /scripts/findDotsBarcodeV2.m: -------------------------------------------------------------------------------- 1 | function [m,dots] = findDotsBarcodeV2(images, multiplier, HCRorFISH,debug)%BWfull)%,tform3,tform4) 2 | 3 | 4 | % for i = 1:length(channels) 5 | % figure; histogram(double(color{dum})); 6 | % end 7 | 8 | %z = size(images{1},3); 9 | % if isempty(BWfull) == 1 10 | % figure; imshow(max(images{1},[],3),[0 mean(mean(max(images{1},[],3)))+2000]) 11 | % answer = inputdlg('How Many ROIs Will You Choose'); 12 | % for i = 1:str2num(answer{1}) 13 | % BW(:,:,i) = roipoly; 14 | % end 15 | % BWfull = repmat(max(BW,[],3),1,1,z); 16 | % else 17 | % BWfull = repmat(BWfull(:,:,1),1,1,z); 18 | % end 19 | 20 | for dee = 1:length(HCRorFISH) 21 | 22 | fish = images{dee}; 23 | %fish = fish.*uint16(BWfull); 24 | 25 | if HCRorFISH(dee) == 1 %fish 26 | logFish=[]; 27 | fish=double(fish); 28 | %fish = double(max(fish,[],3)); 29 | for i=1:size(fish,3) 30 | logFish(:,:,i)=logMask(fish(:,:,i)); 31 | end 32 | cands=imregionalmax(logFish); 33 | % sortedValues = unique(logFish(cands)); 34 | % p10 = round(length(sortedValues)*.1); 35 | % maxValues = sortedValues(end-p10:end); 36 | % maxIndex = ismember(logFish,maxValues); 37 | % logFish2 = logFish; 38 | % logFish2(maxIndex) = mean(mean(mean(logFish))); 39 | %thresh=multithresh(mat2gray(logFish2(cands)),2)*max(logFish2(cands))*multiplier(dee); 40 | m{dee}= cands & logFish > multiplier(dee); 41 | bord = ones(size(m{dee})); 42 | bord(1:5,:,:) = 0; 43 | bord(end-5:end,:,:) = 0; 44 | bord(:,end-5:end,:) = 0; 45 | bord(:,1:5,:) = 0; 46 | m{dee} = m{dee}.*logical(bord); 47 | elseif HCRorFISH(dee) == 2 48 | logFish = fish; 49 | %logFish = double(max(fish,[],3)); 50 | baba = sort(logFish(:)); 51 | thresh = multithresh(baba(1:(length(baba)-100)),2)*multiplier(dee); 52 | %# s = 3D array 53 | msk = true(3,3,3); 54 | msk(2,2,2) = false; 55 | %c%# assign, to every voxel, the maximum of its neighbors 56 | apply = logFish < thresh(2); 57 | logFish(apply) = 0; 58 | s_dil = imdilate(logFish,msk); 59 | m{dee} = logFish > s_dil; %# M is 1 wherever a voxel's value is greater than its neighbors 60 | dtf = sum(sum(sum(m{dee}))); 61 | iter = 0; 62 | while dtf <8000 || dtf > 12000 63 | if dtf< 8000%28000 64 | thresh(2) = thresh(2) - 30; 65 | elseif dtf > 12000 %33000 66 | thresh(2) = thresh(2) + 53; 67 | end 68 | logFish = fish; 69 | apply = logFish < thresh(2); 70 | logFish(apply) = 0; 71 | s_dil = imdilate(logFish,msk); 72 | m{dee} = logFish > s_dil; 73 | dtf = sum(sum(sum(m{dee}))); 74 | iter = iter + 1; 75 | if iter == 250 76 | iter = 0; 77 | thresh = multithresh(baba(1:(length(baba)-100)),2)*multiplier(dee)*rand; 78 | end 79 | end 80 | elseif HCRorFISH(dee) == 3 81 | logFish=[]; 82 | fish=double(fish); 83 | %fish = double(max(fish,[],3)); 84 | for i=1:size(fish,3) 85 | logFish(:,:,i)=logMask(fish(:,:,i)); 86 | end 87 | cands=imregionalmax(logFish); 88 | sortedValues = unique(logFish(cands)); 89 | p10 = round(length(sortedValues)*.1); 90 | maxValues = sortedValues(end-p10:end); 91 | maxIndex = ismember(logFish,maxValues); 92 | logFish2 = logFish; 93 | logFish2(maxIndex) = mean(mean(mean(logFish))); 94 | thresh=multithresh(mat2gray(logFish2(cands)),2)*max(logFish2(cands))*multiplier(dee); 95 | m{dee}= cands & logFish > thresh(1); 96 | bord = ones(size(m{dee})); 97 | bord(1:5,:,:) = 0; 98 | bord(end-5:end,:,:) = 0; 99 | bord(:,end-5:end,:) = 0; 100 | bord(:,1:5,:) = 0; 101 | m{dee} = m{dee}.*logical(bord); 102 | else 103 | logFish = fish; 104 | %logFish = double(max(fish,[],3)); 105 | %# s = 3D array 106 | msk = true(3,3,3); 107 | msk(2,2,2) = false; 108 | %# assign, to every voxel, the maximum of its neighbors 109 | logFish2 = logFish; 110 | %thresh = thresh(th); 111 | apply = logFish < multiplier(dee); 112 | logFish2(apply) = 0; 113 | s_dil = imdilate(logFish2,msk); 114 | m{dee} = logFish2 > s_dil; %# M is 1 wherever a voxel's value is greater than its neighbors 115 | 116 | end 117 | 118 | 119 | if debug == 1 120 | figure 121 | imshow(max(images{dee},[],3),[min(min(max(images{dee},[],3))) mean(mean(max(images{dee},[],3)))+5000]); 122 | hold on; 123 | [v2,v1]=find(max(m{dee},[],3)==1); 124 | scatter(v1(:),v2(:),75); 125 | hold off; 126 | %txt_h = labelpoints(v1+.05, v2+.05, ind2sub(size(v1),v1), 'NE',.01 ,'Color','y'); 127 | end 128 | 129 | [y,x,z] = ind2sub(size(m{dee}),find(m{dee} == 1)); 130 | 131 | dots(dee).channels = [x y z]; 132 | im = max(images{dee},[],3); 133 | for i = 1:length(y) 134 | dots(dee).intensity(i,1) = im(y(i),x(i)); 135 | % dots(dee).integratedintensity(i,1) = sum(sum(im(y(i)-1:y(i)+1,x(i)-1:x(i)+1))); 136 | end 137 | %thresholds(dee) = thresh; 138 | end 139 | -------------------------------------------------------------------------------- /scripts/findGaussianDots_return_all.m: -------------------------------------------------------------------------------- 1 | function [gXf] = findGaussianDots_return_all(locDots,locIm,Pixels) 2 | 3 | options = optimset('Display','off'); 4 | Xf = []; 5 | sigma = []; 6 | 7 | for dotID = 1:size(locDots,1) 8 | data = double(locIm([-Pixels:Pixels]+locDots(dotID,2),[-Pixels:Pixels]+locDots(dotID,1))); 9 | x0 = [min(min(data)) max(max(data))-min(min(data)) Pixels+1 Pixels+1 1 1 45]; 10 | sup = size(data); 11 | f = @(x)D2gauss_wRot(x,sup,data); 12 | [xf, fva] = fminsearch(f,x0,options); 13 | Xf = [Xf; xf]; 14 | 15 | end 16 | gXf = Xf; 17 | gXf(:,3:4) = locDots(:,1:2) + Xf(:,[4 3]) - [Pixels, Pixels]-1; 18 | end 19 | -------------------------------------------------------------------------------- /scripts/findtformV3.m: -------------------------------------------------------------------------------- 1 | function [tform, controlimage] = findtformV3(filename1,filename2) 2 | 3 | %first use imageJ to do a 10 pixel background subtraction 4 | %save individual channels 5 | %Filename2 is reference image 6 | 7 | img = loadtiff(filename1); 8 | img2 = loadtiff(filename2); 9 | 10 | tform = imregcorr(img,img2,'similarity'); 11 | controlimage = imwarp(img,tform,'OutputView',imref2d(size(img2))); 12 | 13 | falsecolorOverlay1 = imfuse(img2,controlimage); 14 | falsecolorOverlay2 = imfuse(img2,img); 15 | figure; 16 | imshow(falsecolorOverlay1,'InitialMagnification','fit'); 17 | figure; 18 | imshow(falsecolorOverlay2,'InitialMagnification','fit'); 19 | 20 | LinkFigures(1:2) 21 | -------------------------------------------------------------------------------- /scripts/gene_calling.m: -------------------------------------------------------------------------------- 1 | function [foundbarcodes] = gene_calling(points, radius) 2 | 3 | hyb = 4; 4 | channum = 20; 5 | channels = channum; 6 | debug = 0; 7 | 8 | disp('Initializing....') 9 | %initialize barcode matrix 10 | for i = 1:hyb 11 | for j = 1:channum 12 | c = size(points(i).dots(j).channels,1); 13 | filler = zeros(c,1); 14 | filler(:) = j; 15 | idxfill = zeros(c,1); 16 | idxfill(:) = 1:c; 17 | foundbarcodes(i).found(j).channel(:,i) = num2cell(filler); 18 | foundbarcodes(i).found(j).idx(:,i) = num2cell(idxfill); 19 | end 20 | end 21 | for i = 1:hyb 22 | for k = 1:hyb 23 | if k ~= i 24 | [i, k] 25 | for j = 1:channum 26 | calledall = []; 27 | calledidx = []; 28 | for l = 1:channum 29 | [~, ~, called1, ~, pair ] = colocalizeBarcodeV2_markedup_NO_INTENSITY(points, i,k, [j l],radius,debug ); 30 | calledall = [calledall, l*double(called1)]; 31 | brat = zeros(length(called1),1); 32 | if ~isempty(pair) 33 | brat(pair(:,1)) = pair(:,2); 34 | end 35 | calledidx = [calledidx, brat]; 36 | end 37 | calledall = mat2cell(calledall, ones(length(called1),1),channum); 38 | x = cellfun(@removezeros,calledall,'UniformOutput',0); 39 | foundbarcodes(i).found(j).channel(:,k) = x; 40 | calledidx = mat2cell(calledidx, ones(length(called1),1),channum); 41 | foundbarcodes(i).found(j).idx(:,k) = calledidx; 42 | end 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /scripts/grab_ims.m: -------------------------------------------------------------------------------- 1 | function [My_Image] = grab_ims(Path, posList, numRnds, myChannel, zSlices) 2 | 3 | warning ('off','all'); 4 | % load raw images 5 | for posI = 1:length(posList) 6 | myPos = posList(posI); 7 | position = sprintf('Pos%.0f',myPos); 8 | % grab all rounds, bead only is first 9 | for i = 1:numRnds 10 | myPath = [Path filesep '..' filesep sprintf('HybCycle_%.0f',i-1)]; 11 | My_Image(i) = {loadTiffStacks(myPath,position,(1:zSlices)+myChannel*zSlices)}; 12 | end 13 | end 14 | 15 | -------------------------------------------------------------------------------- /scripts/grab_ims_Blanks.m: -------------------------------------------------------------------------------- 1 | function [My_Image] = grab_ims_Blanks(Path, posList, myChannel, zSlices) 2 | warning ('off','all'); 3 | % load raw images 4 | for posI = 1:length(posList) 5 | myPos = posList(posI) 6 | position = sprintf('Pos%.0f',myPos); 7 | 8 | My_Image(posI) = {loadTiffStacks(Path,position,(1:zSlices)+myChannel*zSlices)}; 9 | end 10 | warning ('on','all'); 11 | -------------------------------------------------------------------------------- /scripts/handle_ambiguous_barcodes.m: -------------------------------------------------------------------------------- 1 | function [foundbarcodes, totdropped, copynumfinal, rawfound] = ... 2 | handle_ambiguous_barcodes(foundbarcodes, points, hyb, channum, barcodekey, alloweddiff,conthresh, PathName, regvec, posnum, roi_prefix) 3 | 4 | channels = 1:channum; 5 | 6 | % adapted for Sheel's BarcodeNoMiji_v5.m 7 | rawfound = foundbarcodes; 8 | disp('Determining Barcodes....') 9 | 10 | %call Barcodes 11 | totdropped = 0; 12 | % 1: per dot, due to not enough dots close enough in at least 2 other 13 | % rounds. 14 | % 2: per dot, dropped because multi and not sufficiently close to the code 15 | % book 16 | for k = 1:hyb 17 | for j = 1:channum 18 | drop = []; 19 | bobo = []; 20 | bratat = {}; 21 | br = []; 22 | len = []; 23 | multi = []; 24 | rows = []; 25 | 26 | %lentemp: number of barcodes with this hyb and color as seed 27 | lentemp = size(foundbarcodes(k).found(j).channel,1); 28 | for i = 1:lentemp 29 | bobo = cell2mat(foundbarcodes(k).found(j).channel(i,:)); 30 | % bratat contains all hyb possible channels concatinated to 1 31 | % array 32 | bratat{i,1} = bobo; 33 | end 34 | % br: number of hybs with zero for one dot 35 | br = cellfun(@(x) sum(x == 0),bratat,'UniformOutput',0); 36 | %initialize called barcodes as the size of the dots 37 | called = zeros(lentemp,1); 38 | % more than 1 non called hyb... 39 | drop=cellfun(@(x) x>1,br); 40 | % set whole thing to zero, presumably to drop later 41 | foundbarcodes(k).found(j).channel(drop,:) ={0}; 42 | foundbarcodes(k).found(j).idx(drop,:) ={0}; 43 | bratat(drop) = {[0 0 0 0]}; 44 | br2 = cellfun(@removezeros2,bratat,'UniformOutput',0); 45 | % br2 is bratat without zeros 46 | % len is the non-zero length of each baratat entry 47 | len = cellfun(@length,br2); 48 | multi = len+cell2mat(br)>hyb; 49 | [rows] = find(multi ==1); 50 | % deal with mulitple hit codes 51 | for l = 1:length(rows) 52 | possbarcodes = []; 53 | Dposs = []; 54 | A = []; 55 | posscell = []; 56 | code = []; 57 | gene = []; 58 | possreal = []; 59 | vernoi = []; 60 | vernoiz = []; 61 | ind = []; 62 | set = []; 63 | vari = []; 64 | variz = []; 65 | % find all equally minimum hamming distance to the code book 66 | % combinations of this dot 67 | possbarcodes = combvec(foundbarcodes(k).found(j).channel{rows(l),:})'; 68 | Dposs = pdist2(possbarcodes,barcodekey.barcode,'hamming'); 69 | A = Dposs == min(min(Dposs)); 70 | % code is the idea of the posscodes that are closest 71 | [code, ~] = find(A == 1); 72 | % if there is only one possible code and it is close enough 73 | % call that the correct one 74 | if length(code) == 1 && Dposs(A)*hyb < alloweddiff 75 | posscell = num2cell(possbarcodes); 76 | % set found barcode to the closest barcode 77 | foundbarcodes(k).found(j).channel(rows(l),:) = posscell(code,:); 78 | bratat{rows(l)} = cell2mat(posscell(code,:)); 79 | elseif Dposs(A)*hyb < alloweddiff & length(code) > 1 80 | % grab all the equally closest ones 81 | possreal = possbarcodes(code,:); 82 | % idx contains the index for each channel in each hyb that 83 | % showed up for the dot seeded from channel j in hyb k 84 | ind = foundbarcodes(k).found(j).idx(rows(l),:); 85 | caca = zeros(1,length(channels)); 86 | caca(1,j) = ind{k}; 87 | ind{k} = caca; 88 | for p = 1:size(possreal,1) 89 | for h = 1:hyb 90 | % for the non-zero values in a given possible real 91 | % code 92 | if possreal(p,h) > 0 93 | % for each possible code, build a location list 94 | % of the dots associated with it 95 | set(p).set(h,:) = points(h).dots(possreal(p,h)).channels(ind{h}(possreal(p,h)),:); 96 | else 97 | set(p).set(h,:) = zeros(1,3); 98 | end 99 | end 100 | % all the dots should have the same location 101 | % so find the sum of the variance in position 102 | vari(p) = sum(var(set(p).set)); 103 | variz(p) = var(set(p).set(:,3)); 104 | end 105 | % binary map of the minimum variance codes 106 | vernoi = vari == min(vari); 107 | vernoiz = variz == min(variz); 108 | if sum(vernoi) == 1 109 | foundbarcodes(k).found(j).channel(rows(l),:) = num2cell(possreal(vernoi',:)); 110 | bratat{rows(l)} = possreal(vernoi',:); 111 | end 112 | else 113 | foundbarcodes(k).found(j).channel(rows(l),:) ={0}; % remove ambiguous dots 114 | foundbarcodes(k).found(j).idx(rows(l),:) ={0}; 115 | bratat(rows) = {[0 0 0 0]}; 116 | end 117 | end 118 | 119 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 120 | % Fill in dropped cells 121 | % br2 is bratat (cell array containg barcode arrays (as opposed 122 | % cellarry barcodes)) with zeros removed from the barcode arrays 123 | br2 = cellfun(@removezeros2,bratat,'UniformOutput',0); 124 | len = cellfun(@length,br2); 125 | % find the codes tha are one hyb value less than the full number 126 | missing = len == hyb-1; 127 | % rows contains their IDs 128 | [rows] = find(missing ==1); 129 | for l = 1:length(rows) 130 | possbarcodes = []; 131 | Dposs = []; 132 | A = []; 133 | posscell = []; 134 | code = []; 135 | gene = []; 136 | possreal = []; 137 | vernoi = []; 138 | vernoiz = []; 139 | ind = []; 140 | set = []; 141 | vari = []; 142 | variz = []; 143 | % essentially a repeat of above, but this time fill in the 144 | % missing value to make a four round code 145 | possbarcodes = combvec(foundbarcodes(k).found(j).channel{rows(l),:})'; 146 | Dposs = pdist2(possbarcodes,barcodekey.barcode,'hamming'); 147 | A = Dposs == min(min(Dposs)); 148 | [code, gene] = find(A == 1); 149 | if length(gene) == 1 && Dposs(A)*hyb < alloweddiff 150 | foundbarcodes(k).found(j).channel(rows(l),:) = num2cell(barcodekey.barcode(gene,:)); 151 | bratat{rows(l)} = barcodekey.barcode(gene,:); 152 | % if there is more than one that are equally close and close 153 | % enough 154 | elseif Dposs(A)*hyb < alloweddiff & length(code) > 1 155 | possreal = possbarcodes(code,:); 156 | ind = foundbarcodes(k).found(j).idx(rows(l),:); 157 | caca = zeros(1,5); 158 | caca(1,j) = ind{k}; 159 | ind{k} = caca; 160 | for p = 1:size(possreal,1) 161 | for h = 1:hyb 162 | if possreal(p,h) > 0 163 | set(p).set(h,:) = points(h).dots(possreal(p,h)).channels(ind{h}(possreal(p,h)),:); 164 | else 165 | set(p).set(h,:) = zeros(1,3); 166 | end 167 | end 168 | vari(p) = sum(var(set(p).set)); 169 | variz(p) = var(set(p).set(:,3)); 170 | end 171 | vernoi = vari == min(vari); 172 | vernoiz = variz == min(variz); 173 | % grab the one with smallest spatial variance in dots 174 | % called 175 | if sum(vernoi) == 1 176 | foundbarcodes(k).found(j).channel(rows(l),:) = num2cell(possreal(vernoi',:)); 177 | bratat{rows(l)} = possreal(vernoi',:); 178 | else 179 | totdropped = totdropped + 1; 180 | foundbarcodes(k).found(j).channel(rows(l),:) ={0}; % remove ambiguous dots 181 | foundbarcodes(k).found(j).idx(rows(l),:) ={0}; 182 | bratat(rows) = {[0 0 0 0]}; 183 | end 184 | else 185 | foundbarcodes(k).found(j).channel(rows(l),:) ={0}; % remove ambiguous dots 186 | foundbarcodes(k).found(j).idx(rows(l),:) ={0}; 187 | bratat(rows(l)) = {[0 0 0 0]}; 188 | end 189 | end 190 | 191 | 192 | % call barcodes 193 | if ~isempty(foundbarcodes(k).found(j).channel) 194 | cell2 = []; 195 | minmat = []; 196 | tester = []; 197 | logicalstuff = []; 198 | posscell = {}; 199 | % initiallizes posscell to add barcodes seeded from this 200 | % hyb (bcR, k) and channel (hyb, j) 201 | [posscell{1:size(foundbarcodes(k).found(j).channel,1),1:hyb}] = deal(0); 202 | % finds distance from each identified code to each code 203 | D = pdist2(cell2mat(foundbarcodes(k).found(j).channel),barcodekey.barcode,'hamming'); 204 | [r,c] = size(D); 205 | minmat = cellfun(@(x) x == min(x,[],2) & x<=((alloweddiff-1)/hyb),mat2cell(D,ones(1,r),c),'UniformOutput',0); 206 | % finds the ones from the previous step, i.e. barcodes to call 207 | [re, co] = cellfun(@(x) find(x),minmat,'UniformOutput',0); 208 | dasdf = cellfun(@isempty,re,'UniformOutput',0); 209 | re(logical(cell2mat(dasdf))) = {0}; 210 | mm = cellfun(@length,re); 211 | mmdrop = mm > 1; 212 | re(mmdrop) = {0}; 213 | % finds the cells with a code (i.e. re == 1) 214 | rows = find(cell2mat(re)); 215 | % populates posscell with found code book codes 216 | posscell(rows,:) = num2cell(barcodekey.barcode(cell2mat(co(rows)),:)); 217 | co(logical(cell2mat(dasdf))) = {0}; 218 | co(mmdrop) = {0}; 219 | foundbarcodes(k).found(j).called = cell2mat(co); 220 | awe = foundbarcodes(k).found(j).called > 0; 221 | rawfound(k).found(j).called = foundbarcodes(k).found(j).called; 222 | for m = 1:size(foundbarcodes(k).found(j).channel,1) 223 | % for each hyb (barcode number) 224 | for n = 1:hyb 225 | mu = zeros(1,channum); 226 | if foundbarcodes(k).found(j).channel{m,n} > 0 227 | mu(1,foundbarcodes(k).found(j).channel{m,n}) = 1; 228 | end 229 | cell2{m,n} = mu; 230 | end 231 | end 232 | foundbarcodes(k).found(j).idx = cellfun(@(x,y) x.*y,foundbarcodes(k).found(j).idx,cell2,'UniformOutput',0); 233 | else 234 | foundbarcodes(k).found(j).idx = []; 235 | end 236 | end 237 | end 238 | 239 | 240 | disp('Forming Point Consensus....') 241 | %consensus point calling 242 | for i = 1:hyb 243 | for j = 1:length(channels) 244 | % initialize compiled with zeros the size of the number of seeded 245 | foundbarcodes(i).found(j).compiled = zeros(size(foundbarcodes(i).found(j).called,1),hyb); 246 | end 247 | end 248 | % create a compiled list for every dot 249 | disp('Compiling List....') 250 | % compiled will contain an with the code called using that dot based on 251 | % seeding from each hyb, which will be used to form consensus of where each 252 | % dot belongs 253 | for i = 1:hyb 254 | for j = 1:length(channels) 255 | calledrows = find(foundbarcodes(i).found(j).called>0); 256 | if ~isempty(calledrows) 257 | % r contains cells array, seeded x hybs, with ones for kepth 258 | % codes 259 | % c contains the a cell array with the channel for each hyb for 260 | % each kept code 261 | % v contains the a cell array with the point id associated with 262 | % each value in c 263 | [r,c,v]=cellfun(@(x) find(x),foundbarcodes(i).found(j).idx,'UniformOutput',0); 264 | for k = 1:length(calledrows) 265 | for l = 1:hyb 266 | if ~isempty(c{calledrows(k),l}) 267 | foundbarcodes(l).found(c{calledrows(k),l}).compiled(v{calledrows(k),l},i) = foundbarcodes(i).found(j).called(calledrows(k)); 268 | end 269 | end 270 | end 271 | end 272 | end 273 | end 274 | 275 | 276 | disp('Dropping Ambiguous Matches....') 277 | for i = 1:hyb 278 | for j = 1:length(channels) 279 | % Drop Ambigous Matches 280 | % conver to compiled to cell array 281 | cellver = mat2cell(foundbarcodes(i).found(j).compiled,ones(size(foundbarcodes(i).found(j).compiled,1),1),hyb); 282 | % remove zeros, so they can not be the mode 283 | cellver = cellfun(@removezeros, cellver,'UniformOutput',0); 284 | % resolve ambiquous by grabbing the most frequently called code 285 | [M,F,C] = cellfun(@mode,cellver,'UniformOutput',0); 286 | % if there are multiple mode values M only contains the smalles, 287 | % whereas C contains all of them ... 288 | eq = cellfun(@(x) length(x{1}),C); 289 | M = cell2mat(M); 290 | % if there's more than one mode, then toss it 291 | M(eq>1)=0; 292 | % F says how often that code was called, so this makes sure it was 293 | % called seeding from a sufficient number of hybs (i.e. >conthresh) 294 | M(cell2mat(F)0); 13 | else 14 | bw=lapFrame; 15 | end 16 | 17 | -------------------------------------------------------------------------------- /scripts/numseeds.m: -------------------------------------------------------------------------------- 1 | function [seeds, int, ints] = numseeds(PosList,dotlocations) 2 | 3 | %load([PathName '\Pos' num2str(Posnum) '\pos' num2str(Posnum) 'Barcodes11092016.mat']); 4 | 5 | 6 | seeds = PosList; 7 | int = PosList; 8 | ints = PosList; 9 | % for each cell i 10 | for i = 1:size(dotlocations,2) 11 | % for each gene j that appears in dotlocations (only genes that are 12 | % called) 13 | for j = 1:size(dotlocations(i).cell,1) 14 | % find the conversion from dotlocation id to global geneID (ind) 15 | ind = find(strcmpi(dotlocations(i).cell{j,1},PosList)); 16 | % check if there's only one such gene called (i+1 because PosList 17 | % has gene names in the first column 18 | if size(PosList{ind,i+1},1) == 1 19 | % if this is the only time this gene is called, then all 20 | % seedings are associated with this one call and the number of 21 | % seeds for this RNA call = the number of seedings called for 22 | % this gene 23 | seeds{ind,i+1} = size(dotlocations(i).cell{j,4},1); 24 | % int{ind,i+1} = dotlocations(i).cell{j,7}; 25 | % ints{ind,i+1} = dotlocations(i).cell{j,6}; 26 | else 27 | % if a gene is called multiple times (has multiple centroids), 28 | % then for each FISH dot [dotlocations(i).cell{j,2}] it finds 29 | % the closest RNA centroid [PosList{ind,i+1}] 30 | idx = dsearchn(PosList{ind,i+1},dotlocations(i).cell{j,2}); 31 | % holdint = zeros(size(PosList{ind,i+1},1),hybs); 32 | % holdints = zeros(size(PosList{ind,i+1},1),hybs); 33 | % for k = 1:size(PosList{ind,i+1},1) 34 | % kee = idx ==k; 35 | % hybnums = cell2mat(dotlocations(i).cell(j,4)); 36 | % hybnums = hybnums(kee); 37 | % % inttemps = cell2mat(dotlocations(i).cell(j,6)); 38 | % % inttemp = cell2mat(dotlocations(i).cell(j,7)); 39 | % % inttemps = inttemps(kee); 40 | % % inttemp = inttemp(kee); 41 | % % holdint(k,hybnums) = inttemp; 42 | % % holdints(k,hybnums) = inttemps; 43 | % end 44 | % uses hist to bin the centroid ids associated with each FISH 45 | % dot, so the result is the number of FISH dots associated with 46 | % each centroid 47 | seeds{ind,i+1} = hist(idx,size(PosList{ind,i+1},1)); 48 | % int{ind,i+1} = holdint; 49 | % ints{ind,i+1} = holdints; 50 | end 51 | end 52 | end 53 | %save([PathName '\Pos' num2str(Posnum) '\pos' num2str(Posnum) 'Barcodes11092016.mat'],'seeds','-append'); 54 | -------------------------------------------------------------------------------- /scripts/pointLocations.m: -------------------------------------------------------------------------------- 1 | function [dotlocations,copynumfinalrevised,PosList] = pointLocations(PathName,posnum,hyb, channum, points, foundbarcodes,barcodekey,copynumfinal,radius) 2 | 3 | copynumfinalrevised = copynumfinal; 4 | fullpath = [PathName filesep 'RoiSet_Pos' num2str(posnum) ]; 5 | vertex = selfseg(fullpath); 6 | PosList = cell(size(barcodekey.names,1),length(vertex)+1); 7 | PosList(:,1) = copynumfinal(:,1); 8 | 9 | for i = 1:length(vertex) 10 | g = {}; 11 | allcodes = []; 12 | allpoints = []; 13 | ptchannel = []; 14 | hybnum = []; 15 | ptint = []; 16 | ptintabs = []; 17 | for j = 1:hyb 18 | for k = 1:channum 19 | if ~isempty(foundbarcodes(j).found(k).consensus) 20 | include = inpolygon(points(j).dots(k).channels(:,1),points(j).dots(k).channels(:,2),vertex(i).x,vertex(i).y); 21 | foundint = foundbarcodes(j).found(k).consensus > 0; 22 | keepdgf = include & foundint; 23 | allcodes = [allcodes; foundbarcodes(j).found(k).consensus(keepdgf)]; 24 | allpoints = [allpoints; points(j).dots(k).channels(keepdgf,:)]; 25 | ptchannel = [ptchannel; k*ones(size(foundbarcodes(j).found(k).consensus(keepdgf),1),1)]; 26 | ptint = [ptint;ones(size(foundbarcodes(j).found(k).consensus(keepdgf)))]; 27 | ptintabs = [ptintabs;ones(size(foundbarcodes(j).found(k).consensus(keepdgf)))]; 28 | hybnum = [hybnum; j*ones(size(foundbarcodes(j).found(k).consensus(keepdgf),1),1)]; 29 | end 30 | end 31 | end 32 | fun = unique(allcodes); 33 | for l = 1:length(fun); 34 | g{l,2} = allpoints(allcodes==fun(l),:); 35 | g{l,1} = barcodekey.names{fun(l)}; 36 | g{l,3} = ptchannel(allcodes==fun(l),:); 37 | g{l,4} = hybnum(allcodes==fun(l),:); 38 | g{l,6} = ptint(allcodes==fun(l),:); 39 | g{l,7} = ptintabs(allcodes==fun(l),:); 40 | clusnum = copynumfinal{fun(l),i+1}; 41 | if size(g{l,2},1) < clusnum 42 | clusnum = size(g{l,2},1); 43 | end 44 | bobobo = 1; 45 | keepgoing = 1; 46 | while keepgoing == 1 47 | if clusnum <2 48 | C = mean(g{l,2},1); 49 | idx = ones(size(g{l,2},1),1); 50 | else 51 | [idx,C] = kmeans(g{l,2},clusnum); 52 | end 53 | for m = 1:size(C,1); 54 | D{m,:} = pdist2(C(m,:),g{l,2}(idx == m,:)); 55 | end 56 | s = sum(cell2mat(cellfun(@(x) sum(x > sqrt(radius))>0, D, 'UniformOutput',0))); 57 | clear D; 58 | if s > 0 59 | clusnum = clusnum + 1; 60 | copynumfinalrevised{fun(l),i+1} = clusnum; 61 | elseif pdist(C) 4GB 24 | % 25 | % Defalut value of 'options' is 26 | % options.color = false; 27 | % options.comp = 'no'; 28 | % options.message = false; 29 | % options.ask = false; 30 | % options.append = false; 31 | % options.big = false; 32 | % 33 | % Copyright (c) 2012, YoonOh Tak 34 | % All rights reserved. 35 | % 36 | % Redistribution and use in source and binary forms, with or without 37 | % modification, are permitted provided that the following conditions are 38 | % met: 39 | % 40 | % * Redistributions of source code must retain the above copyright 41 | % notice, this list of conditions and the following disclaimer. 42 | % * Redistributions in binary form must reproduce the above copyright 43 | % notice, this list of conditions and the following disclaimer in 44 | % the documentation and/or other materials provided with the distribution 45 | % * Neither the name of the Gwangju Institute of Science and Technology (GIST), Republic of Korea nor the names 46 | % of its contributors may be used to endorse or promote products derived 47 | % from this software without specific prior written permission. 48 | % 49 | % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 50 | % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 | % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 | % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 53 | % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 54 | % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 55 | % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 56 | % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 57 | % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 58 | % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 59 | % POSSIBILITY OF SUCH DAMAGE. 60 | 61 | errcode = -1; 62 | try 63 | if isreal(data) == false 64 | errcode = 8; assert(false); 65 | end 66 | if nargin < 3 67 | options.color = false; 68 | options.comp = 'no'; 69 | options.message = false; 70 | options.ask = false; 71 | options.append = false; 72 | end 73 | if isfield(options, 'message') == 0 74 | options.message = false; 75 | end 76 | if isfield(options, 'ask') == 0 77 | options.ask = false; 78 | end 79 | if isfield(options, 'append') == 0 80 | options.append = false; 81 | end 82 | if isfield(options, 'comp') == 0 83 | options.comp = 'no'; 84 | end 85 | if isfield(options, 'color') == 0 86 | options.color = false; 87 | end 88 | if (options.color == false && ndims(data) > 3) ... 89 | || (options.color == true && ndims(data) > 4) 90 | errcode = 10; assert(false); 91 | end 92 | if isfield(options, 'big') == 0 93 | options.big = false; 94 | end 95 | 96 | [pathstr, fname, fext] = fileparts(which(path)); 97 | if ~isempty(pathstr) 98 | if strcmpi(pathstr, pwd) 99 | if options.append 100 | tappend = Tiff(path, 'r+'); 101 | else 102 | if options.ask 103 | reply = input('File already exist, do you wish to overwrite? Y/n: ', 's'); 104 | if isempty(reply), reply = 'Y'; end 105 | if any(upper(reply) ~= 'Y') 106 | errcode = 1; assert(false); 107 | end 108 | end 109 | end 110 | else 111 | if options.append 112 | if options.ask 113 | display(['File path: ' pathstr '\' fname fext]); 114 | reply = input('File already exist but not in the current folder, do you wish to append? Y/n: ', 's'); 115 | if isempty(reply), reply = 'Y'; end 116 | if any(upper(reply) == 'Y') 117 | errcode = 1; assert(false); 118 | end 119 | tappend = Tiff(path, 'r+'); 120 | end 121 | else 122 | if options.ask 123 | display(['File path: ' pathstr '\' fname fext]); 124 | reply = input('File already exist but not in the current folder, do you wish to overwrite? Y/n: ', 's'); 125 | if isempty(reply), reply = 'Y'; end 126 | if any(upper(reply) ~= 'Y') 127 | errcode = 1; assert(false); 128 | end 129 | end 130 | end 131 | end 132 | else 133 | if exist(path, 'dir') && isempty(fname) 134 | errcode = 0; assert(false); 135 | end 136 | options.append = false; 137 | end 138 | 139 | if isempty(data) 140 | errcode = 2; assert(false); 141 | end 142 | 143 | if ~options.color 144 | if ndims(data) >= 4, errcode = 3; assert(false); end; 145 | [height, width, depth] = size(data); 146 | tagstruct.Photometric = Tiff.Photometric.MinIsBlack; 147 | else 148 | if ndims(data) >= 5, errcode = 3; assert(false); end; 149 | [height, width, rgb, depth] = size(data); 150 | if rgb ~= 3, errcode = 4; assert(false); end; 151 | if isa(data, 'uint8'), data = uint8(data); end; 152 | tagstruct.Photometric = Tiff.Photometric.RGB; 153 | end 154 | 155 | tagstruct.ImageLength = height; 156 | tagstruct.ImageWidth = width; 157 | tagstruct.SamplesPerPixel = (options.color+1)*(options.color+2)/2; 158 | tagstruct.RowsPerStrip = height; 159 | tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky; 160 | 161 | % Compresstion type : http://en.wikipedia.org/wiki/Tagged_Image_File_Format 162 | switch lower(options.comp) 163 | case 'no' 164 | tagstruct.Compression = Tiff.Compression.None; 165 | case 'lzw' 166 | tagstruct.Compression = Tiff.Compression.LZW; 167 | case 'jpeg' 168 | tagstruct.Compression = Tiff.Compression.JPEG; 169 | case 'adobe' 170 | tagstruct.Compression = Tiff.Compression.AdobeDeflate; 171 | otherwise 172 | if options.ask 173 | reply = input('Unsupported compression type : Data will not be compressed.\nDo you wish to continue? Y/n: ', 's'); 174 | if isempty(reply), reply = 'Y'; end 175 | if any(upper(reply) ~= 'Y') 176 | tagstruct.Compression = Tiff.Compression.None; 177 | else 178 | errcode = 0; assert(false); 179 | end 180 | else 181 | tagstruct.Compression = Tiff.Compression.None; 182 | end 183 | end 184 | 185 | switch class(data) 186 | case {'uint8', 'uint16', 'uint32'} 187 | tagstruct.SampleFormat = Tiff.SampleFormat.UInt; 188 | case {'int8', 'int16', 'int32'} 189 | tagstruct.SampleFormat = Tiff.SampleFormat.Int; 190 | if options.color == 3 191 | errcode = 8; assert(false); 192 | end 193 | case {'single', 'double'} 194 | tagstruct.SampleFormat = Tiff.SampleFormat.IEEEFP; 195 | otherwise 196 | errcode = 9; assert(false); 197 | end 198 | 199 | switch class(data) 200 | case {'uint8', 'int8'} 201 | tagstruct.BitsPerSample = 8; 202 | case {'uint16', 'int16'} 203 | tagstruct.BitsPerSample = 16; 204 | case {'uint32', 'int32'} 205 | tagstruct.BitsPerSample = 32; 206 | case {'single'} 207 | tagstruct.BitsPerSample = 32; 208 | case {'double'} 209 | tagstruct.BitsPerSample = 64; 210 | otherwise 211 | errcode = 9; assert(false); 212 | end 213 | 214 | tStart = tic; 215 | if ~options.append 216 | if ispc 217 | tempfile = '~$temporal.tif'; 218 | else 219 | tempfile = '._temporal.tif'; 220 | end 221 | s=whos('data'); 222 | if s.bytes > 2^32-1 || options.big 223 | t = Tiff(tempfile, 'w8'); 224 | else 225 | t = Tiff(tempfile, 'w'); 226 | end 227 | if ispc 228 | fileattrib(tempfile, '+h +w', '', 's'); 229 | end 230 | for d = 1:depth 231 | t.setTag(tagstruct); 232 | if ~options.color 233 | t.write(data(:, :, d)); 234 | else 235 | t.write(data(:, :, :, d)); 236 | end 237 | if d ~= depth 238 | t.writeDirectory(); 239 | end 240 | end 241 | 242 | t.close(); 243 | if ispc 244 | fileattrib(tempfile, '-h +w'); 245 | end 246 | if isempty(pathstr) 247 | movefile(tempfile, path, 'f'); 248 | else 249 | movefile(tempfile, [pathstr '\' fname fext], 'f'); 250 | end 251 | else 252 | while ~tappend.lastDirectory(); 253 | tappend.nextDirectory(); 254 | end 255 | 256 | try 257 | tappend.writeDirectory(); 258 | for d = 1:depth 259 | tappend.setTag(tagstruct); 260 | if ~options.color 261 | tappend.write(data(:, :, d)); 262 | else 263 | tappend.write(data(:, :, :, d)); 264 | end 265 | if d ~= depth 266 | tappend.writeDirectory(); 267 | end 268 | end 269 | catch 270 | errcode = 11; assert(false); 271 | end 272 | tappend.close(); 273 | end 274 | 275 | tElapsed = toc(tStart); 276 | if options.message 277 | display(sprintf('File saved successfully. Elapsed time : %.3f s.', tElapsed)); 278 | end 279 | 280 | catch exception 281 | if exist('t', 'var') 282 | t.close(); 283 | if exist('tappend', 'var'), tappend.close(); end 284 | delete(tempfile); 285 | end 286 | 287 | if options.message 288 | switch errcode 289 | case 0 290 | error 'Invalide path.'; 291 | case 1 292 | case 2 293 | error '''data'' is empty.'; 294 | case 3 295 | error 'Data dimension is too large.'; 296 | case 4 297 | error 'Third dimesion (color depth) should be 3.'; 298 | case 6 299 | error 'RGB color image can not have int8, int16 or int32 format.'; 300 | case 8 301 | error 'It does not support complex numbers.'; 302 | case 9 303 | error 'Unsupported data type.'; 304 | case 10 305 | error 'Dimension of source data is too large.'; 306 | case 11 307 | error 'If file size exceeded, create a new big tiff file using ''options.big = true''' 308 | otherwise 309 | rethrow(exception); 310 | end 311 | end 312 | end 313 | end 314 | -------------------------------------------------------------------------------- /scripts/selfseg.m: -------------------------------------------------------------------------------- 1 | function vertex = selfseg(PathName) 2 | 3 | files = dir([PathName filesep '*.roi']); 4 | [sROI] = ReadImageJROI(strcat(PathName, filesep, {files.name})); 5 | 6 | 7 | for i = 1:length(sROI) 8 | if strcmp(sROI{1,i}.strType, 'Oval') 9 | y0 = mean(sROI{1,i}.vnRectBounds(logical([1 0 1 0]))); 10 | x0 = mean(sROI{1,i}.vnRectBounds(logical([0 1 0 1]))); 11 | rx = abs(sROI{1,i}.vnRectBounds(logical([0 0 1 0])) - sROI{1,i}.vnRectBounds(logical([1 0 0 0])))/2; 12 | ry = abs(sROI{1,i}.vnRectBounds(logical([0 1 0 0])) - sROI{1,i}.vnRectBounds(logical([0 0 0 1])))/2; 13 | t = linspace(0, 2*pi, 360)'; 14 | vertex(i).x = x0 + ry * cos(t); 15 | vertex(i).y = y0 + rx * sin(t); 16 | elseif strcmp(sROI{1,i}.strType, 'Rectangle') 17 | vertex(i).y = [sROI{1,i}.vnRectBounds(1) sROI{1,i}.vnRectBounds(3) sROI{1,i}.vnRectBounds(3) sROI{1,i}.vnRectBounds(1)]; 18 | vertex(i).x = [sROI{1,i}.vnRectBounds(2) sROI{1,i}.vnRectBounds(2) sROI{1,i}.vnRectBounds(4) sROI{1,i}.vnRectBounds(4)]; 19 | else 20 | vertex(i).x = sROI{1,i}.mnCoordinates(:,1); 21 | vertex(i).y = sROI{1,i}.mnCoordinates(:,2); 22 | end 23 | end 24 | 25 | 26 | -------------------------------------------------------------------------------- /sourcedata.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CaiGroup/seqFISH-PLUS/ee6c416006fe09262526eb364c6f66edd35adc88/sourcedata.zip --------------------------------------------------------------------------------