├── .gitignore ├── README.md ├── README.pdf ├── auxiliaryMethods ├── .gitignore ├── KLEEtoCNN │ ├── changeToLocalTracing.m │ ├── convertKleeTracingToLocalStack.m │ ├── findBBoxKLEE.m │ ├── generateCNNcontrol.m │ ├── generateCNNstacks.m │ ├── getClosedContour.m │ ├── removeSomaStacks.m │ ├── selectFiles.m │ ├── selectFilesHD.m │ ├── viewCNNstacks.m │ └── xyzMaskIntraExtra.m ├── addTree.m ├── bfs.m ├── convertKnossosNmlToHoc.m ├── copyCubeSubset.m ├── distinguishable_colors.m ├── exportSurfaceToAmira.m ├── genpathGit.m ├── license.txt ├── loadClassData.m ├── makeIsosurfaceView.m ├── makeMovie.m ├── makeSegMovie.m ├── makeSegmentList.m ├── mergeTrees.m ├── parseNml.c ├── parseNml_noInVP.c ├── plotIsosurfaces.m ├── plotOriginalData.m ├── readKnossosCube.m ├── readKnossosRoi.m ├── readNml.m ├── removeBbox.m ├── removeEmptySkeletons.m ├── removeGlia.m ├── startCPU.m ├── voxelBasedMetrics │ ├── Rand │ │ ├── fullRand.m │ │ ├── randContingencyTable.cpp │ │ ├── randErr.m │ │ ├── randErrMaskGreaterZero.m │ │ ├── randRMex.c │ │ ├── randRMexMaskGreaterZero.c │ │ └── useRand.m │ └── Warp │ │ ├── useWarp.m │ │ ├── voxelErr.m │ │ ├── warpErr.m │ │ ├── warpMexFull.c │ │ └── warpMexFull.cpp ├── writeKnossosConf.m ├── writeKnossosCube.m ├── writeKnossosRoi.m ├── writeNml.m └── writeNmlOld.m ├── cortex ├── CNN │ ├── .gitignore │ ├── @cnn │ │ ├── bwdPass3D.m │ │ ├── cnn.m │ │ ├── flipdims.m │ │ ├── forWeights.m │ │ ├── fwdPass3D.m │ │ ├── fwdPass3DonKhierachy.m │ │ ├── gradientPass.m │ │ ├── learn.m │ │ ├── loadLastCNN.m │ │ ├── loadResults.m │ │ ├── onlyFwdPass3D.m │ │ ├── plotNetActivities.m │ │ ├── plotNetActivitiesFull.m │ │ └── sgd.m │ ├── @train │ │ ├── expLearn.m │ │ ├── linearLearn.m │ │ └── train.m │ ├── cnnStart.m │ ├── evolution │ │ ├── cnnParameterSelection.m │ │ ├── continueParameterSearch.m │ │ ├── getResults.m │ │ ├── parameterSearch.m │ │ ├── plotError.m │ │ ├── plotErrorBinned.m │ │ ├── plotErrorResorted.m │ │ ├── plotResults.m │ │ ├── removeSomaStacks.m │ │ └── selectBestPerformers.m │ └── normalizeStack.m ├── metrics07x2 │ ├── convertTestSetFromKLEETracingToLabelmatrix.m │ ├── initalizationSchemeStatistics.m │ ├── metricsISBI.bsh │ ├── metricsISBIautomatedTest.bsh │ ├── metricsISBIautomatedTraining.bsh │ ├── testSetMetricsFor07x2.m │ ├── tifWriteForISBI.m │ └── watershedSegMarkersHmin2D.m ├── segmentation │ ├── correctSkeletonsToBBox_v2.m │ ├── equalizeSkeletons.m │ ├── evalParameterSegmentation.m │ ├── evaluateSeg.m │ ├── getParamCombinations.m │ ├── getPathLength.m │ ├── mainSeg.m │ ├── morphScanAndEval.m │ ├── parsave.m │ ├── seg20141017.m │ ├── skeletonPreparations.m │ ├── skeletonStatistics.m │ ├── switchToLocalCoords_v2.m │ ├── visualization │ │ ├── makeErrorMoviesP.m │ │ ├── makeSkeletonMovies.m │ │ ├── visSeg.m │ │ ├── visualizeMeSp.m │ │ ├── visualizeObjHistP.m │ │ ├── visualizeObjectChainsP_leftout.m │ │ ├── visualizeObjectChainsP_merger.m │ │ ├── visualizeObjectChainsP_show.m │ │ ├── visualizeOverview.m │ │ ├── visualizeOverviewComparison.m │ │ ├── visualizeOverviewNew.m │ │ ├── visualizeOverviewNodeSizeControl.m │ │ ├── visualizeOverviewWithThreeLinesAndZeroHits.m │ │ └── visualizeSingle.m │ ├── watershedSeg_v1_cortex.m │ └── watershedSeg_v2_cortex.m ├── setParameterSettings.m ├── setParameterSettingsBig.m ├── startup.m └── wholeDataset │ ├── bigFwdPass.m │ ├── miniSegmentation.m │ ├── minicubeFwdPass.m │ ├── onlyFwdPass3DonKnossosFolder.m │ └── wholeDatasetFwdPass.m ├── initalSettings.m ├── installer.fig ├── installer.m ├── license.txt ├── retina ├── CNN │ ├── @cnn │ │ ├── bwdPass3D.m │ │ ├── cnn.m │ │ ├── flipdims.m │ │ ├── forAll.m │ │ ├── fwdPass3D.m │ │ ├── fwdPass3Dfaster.m │ │ ├── gradientPass.m │ │ ├── learn.m │ │ ├── normalizeStack.m │ │ ├── probMask.m │ │ ├── trainGradient.m │ │ ├── xyMask.m │ │ ├── xyzMask.m │ │ └── xyzMaskIso.m │ ├── @train │ │ ├── train.m │ │ └── updateCasts.m │ ├── bigFwdPass.m │ ├── libJobHandling │ │ ├── getKleeStackList.m │ │ ├── killAllJobs.m │ │ ├── killJob.m │ │ ├── saveJobParamToXls.m │ │ └── submitJob.m │ ├── loadCNNResults.m │ ├── loadSingleCNN.m │ ├── main_legacy.m │ ├── minicubeFwdPass.m │ ├── normalizeStack.m │ └── visualization │ │ ├── plotError.m │ │ ├── plotErrorBinned.m │ │ ├── plotErrorResorted.m │ │ └── plotNetActivities.m ├── segmentation │ ├── correctSkeletonsToBBox.m │ ├── evalParameterSegmentation.m │ ├── evaluateSeg.m │ ├── getPathLength.m │ ├── mainSeg_legacy.m │ ├── morphR.m │ ├── parsave.m │ ├── scanParameterSegmentation.m │ ├── switchToLocalCoords.m │ ├── visualization │ │ ├── autoKLEE_colormap.mat │ │ ├── distinguishable_colors.m │ │ ├── makeErrorMovies.m │ │ ├── makeErrorMoviesP.m │ │ ├── makeErrorStacksP.m │ │ ├── makeOriginalDataMovie.m │ │ ├── makeSkeletonMovies.m │ │ ├── paper_plotRibbonsInGlobalBB.m │ │ ├── visSeg_legacy.m │ │ ├── visualizeMeSp.m │ │ ├── visualizeObjHist.m │ │ ├── visualizeObjHistP.m │ │ ├── visualizeObjectChains.m │ │ ├── visualizeObjectChainsP.m │ │ ├── visualizeObjectChainsP_leftout.m │ │ ├── visualizeObjectChainsP_merger.m │ │ ├── visualizeObjectChainsP_mergerNew.m │ │ ├── visualizeObjectChainsP_show.m │ │ ├── visualizeOverview.m │ │ ├── visualizeOverviewSamplingSeries.m │ │ ├── visualizeOverviewTestComparisonRetinaVsCortex.m │ │ ├── visualizeOverview_2.m │ │ ├── visualizeOverview_4.m │ │ └── visualizeSingle.m │ ├── watershedBasedSeg │ │ ├── binAff.m │ │ ├── sk_mbwshed_3d_2.m │ │ ├── watershedSeg_v1_paper.m │ │ ├── watershedSeg_v2_paper.m │ │ ├── watershed_3D.m │ │ ├── watershed_3D_PP.m │ │ ├── watershed_threeTimes3D.c │ │ └── watershed_threeTimes3D.cpp │ └── wholeDataset │ │ ├── ekSegmentationToJm.m │ │ └── segment_ek_0563ForPaper.m ├── startup.m └── wholeDatasetFwdPass.m └── volumeReconstruction ├── accumulateOverCubeBorders.m ├── contactDetectionCortex.m ├── contactDetectionCortexStart.m ├── contactDetectionRetina.m ├── contactDetectionRetinaStart.m ├── galleryCortex.m ├── galleryCortexStart.m ├── galleryRetina.m ├── galleryRetinaStart.m ├── skeletonsToContacts.m └── skeletonsToContacts_legacy.m /.gitignore: -------------------------------------------------------------------------------- 1 | *.m~ 2 | *.un~ 3 | *.as 4 | *.mex* 5 | *.md~ 6 | *.asv 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhlabCodingTeam/SegEM/a61ff23875ef36cf6c851ae3112cbdc640ece43f/README.md -------------------------------------------------------------------------------- /README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhlabCodingTeam/SegEM/a61ff23875ef36cf6c851ae3112cbdc640ece43f/README.pdf -------------------------------------------------------------------------------- /auxiliaryMethods/.gitignore: -------------------------------------------------------------------------------- 1 | *.asv 2 | *.m~ 3 | *.mexa64 4 | images/ 5 | *.db 6 | *.swp 7 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/changeToLocalTracing.m: -------------------------------------------------------------------------------- 1 | function KLEE_savedTracing = changeToLocalTracing( KLEE_savedTracing, offset ) 2 | 3 | for i=1:size(KLEE_savedTracing.contourList,1) 4 | KLEE_savedTracing.contourList(i,2) = KLEE_savedTracing.contourList(i,2) - offset(3) + 1; 5 | % Undo KLEE x/y mess in each contour 6 | temp = KLEE_savedTracing.contours{i}(:,2) - offset(2) + 1; 7 | KLEE_savedTracing.contours{i}(:,2) = KLEE_savedTracing.contours{i}(:,1) - offset(1) + 1; 8 | KLEE_savedTracing.contours{i}(:,1) = temp; 9 | KLEE_savedTracing.contours{i}(:,3) = KLEE_savedTracing.contours{i}(:,3) - offset(3) + 1; 10 | end 11 | 12 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/findBBoxKLEE.m: -------------------------------------------------------------------------------- 1 | function [KLEE_savedTracing, bbox] = findBBoxKLEE( KLEE_savedTracing ) 2 | % Extracts bbox from struct & checks for z-position inconsitency between contours & contourList 3 | 4 | bbox = KLEE_savedTracing.bbox; 5 | 6 | % Fix inconsistency between contourList & contours z-position 7 | toDel = zeros(size(KLEE_savedTracing.contourList,1),1); 8 | for i=1:size(KLEE_savedTracing.contourList,1) 9 | if isempty(KLEE_savedTracing.contours{i}) 10 | toDel(i) = 1; 11 | else 12 | if mean(KLEE_savedTracing.contours{i}(:,3)) ~= KLEE_savedTracing.contourList(i,2) 13 | warning('Something wrong with z-Postion'); 14 | % Fix it by trusting contourList over contours 15 | KLEE_savedTracing.contours{i}(:,3) = KLEE_savedTracing.contourList(i,2); 16 | end 17 | end 18 | end 19 | 20 | idx = find(toDel); 21 | KLEE_savedTracing.contours(idx) = []; 22 | KLEE_savedTracing.contourList(idx,:) = []; 23 | KLEE_savedTracing.contourComment(idx) = []; 24 | KLEE_savedTracing.contourTimeStamp(idx,:) = []; 25 | 26 | end 27 | 28 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/generateCNNcontrol.m: -------------------------------------------------------------------------------- 1 | function generateCNNcontrol(thres) 2 | % Thres defines cutoff in distance transform of labeled cells (thereby defining extracellular border in untraced regions) 3 | 4 | settings.rawDir = '/zdata/manuel/data/cortex/2012-09-28_ex145_07x2/mag1/'; 5 | settings.rawPrefix = '2012-09-28_ex145_07x2_mag1'; 6 | settings.sourceDir = '/zdata/manuel/data/cortex/Korrektur/'; 7 | dateStr = datestr(clock, 30); 8 | settings.stackDir = ['/zdata/manuel/data/cortex/' dateStr '/stackKLEE/']; 9 | settings.targetDir = ['/zdata/manuel/data/cortex/' dateStr '/targetKLEE/']; 10 | settings.metaFile = ['/zdata/manuel/data/cortex/' dateStr '/parameter.mat']; 11 | settings.border = [50; 50; 25]; 12 | 13 | % Make directories 14 | if ~exist(settings.stackDir) 15 | mkdir(settings.stackDir); 16 | end 17 | if ~exist(settings.targetDir) 18 | mkdir(settings.targetDir); 19 | end 20 | 21 | % Locate KLEE files from database & analyze 22 | files = dir([settings.sourceDir '*.mat']); 23 | stacks = selectFiles(files); 24 | 25 | for i=1:length(stacks) 26 | display(['Processing stack ' num2str(i) '/' num2str(length(stacks))]); 27 | load([settings.sourceDir stacks(i).filename]); 28 | [stack, bbox] = convertKleeTracingToLocalStack( KLEE_savedTracing ); 29 | target = xyzMaskIntraExtra(stack,thres); 30 | bbox = bbox([2 1 3],:); 31 | bboxRaw = bbox + [-settings.border settings.border]; 32 | rawBig = readKnossosRoi(settings.rawDir, settings.rawPrefix, bboxRaw); 33 | raw = readKnossosRoi(settings.rawDir, settings.rawPrefix, bbox); 34 | save([settings.stackDir num2str(stacks(i).taskID) '.mat'], 'raw', 'stack'); 35 | save([settings.targetDir num2str(stacks(i).taskID) '.mat'], 'rawBig', 'target'); 36 | stacks(i).stackFile = [settings.stackDir num2str(stacks(i).taskID) '.mat']; 37 | stacks(i).targetFile = [settings.targetDir num2str(stacks(i).taskID) '.mat']; 38 | stacks(i).bbox = bbox; 39 | stacks(i).bboxRaw = bboxRaw; 40 | end 41 | 42 | % Save all relevant meta information 43 | save(settings.metaFile, 'stacks', 'settings'); 44 | 45 | end 46 | 47 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/generateCNNstacks.m: -------------------------------------------------------------------------------- 1 | function generateCNNstacks() 2 | % Thres defines cutoff in distance transform of labeled cells (thereby defining extracellular border in untraced regions) 3 | 4 | settings.rawDir = '/zdata/manuel/data/cortex/2012-09-28_ex145_07x2_corrected/color/1/'; 5 | settings.rawPrefix = '2012-09-28_ex145_07x2_corrected_mag1'; 6 | settings.sourceDir = '/zdata/manuel/data/cortex/originalKLEE/'; 7 | dateStr = datestr(clock, 30); 8 | settings.stackDir = ['/zdata/manuel/data/cortex/' dateStr '/stackKLEE/']; 9 | settings.targetDir = ['/zdata/manuel/data/cortex/' dateStr '/targetKLEE/']; 10 | settings.metaFile = ['/zdata/manuel/data/cortex/' dateStr '/parameter.mat']; 11 | settings.border = [50; 50; 25]; 12 | 13 | % Make directories 14 | if ~exist(settings.stackDir) 15 | mkdir(settings.stackDir); 16 | end 17 | if ~exist(settings.targetDir) 18 | mkdir(settings.targetDir); 19 | end 20 | 21 | % Locate KLEE files from database & analyze 22 | files = dir([settings.sourceDir '3_15_*.mat']); 23 | stacksMR = selectFiles(files); 24 | files2 = dir([settings.sourceDir '*corrected.mat']); 25 | stacksHD = selectFilesHD(files2); 26 | stacks = [stacksMR stacksHD]; 27 | 28 | for i=1:length(stacks) 29 | display(['Processing stack ' num2str(i) '/' num2str(length(stacks))]); 30 | load([settings.sourceDir stacks(i).filename]); 31 | [stack, bbox] = convertKleeTracingToLocalStack( KLEE_savedTracing ); 32 | save([settings.stackDir num2str(stacks(i).taskID) '.mat'], 'stack'); 33 | stacks(i).stackFile = [settings.stackDir num2str(stacks(i).taskID) '.mat']; 34 | target = xyzMaskIntraExtra(stack, 10); 35 | bboxRaw = bbox([2 1 3],:) + [-settings.border settings.border]; 36 | raw = readKnossosRoi(settings.rawDir, settings.rawPrefix, bboxRaw); 37 | save([settings.targetDir num2str(stacks(i).taskID) '.mat'], 'raw', 'target'); 38 | stacks(i).targetFile = [settings.targetDir num2str(stacks(i).taskID) '.mat']; 39 | stacks(i).bbox = bbox; 40 | stacks(i).bboxRaw = bboxRaw; 41 | end 42 | 43 | % Save all relevant meta information 44 | save(settings.metaFile, 'stacks', 'settings'); 45 | 46 | end 47 | 48 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/getClosedContour.m: -------------------------------------------------------------------------------- 1 | function mgc_contCl = getClosedContour( mgc_cont ) 2 | 3 | % GETCLOSEDCONTOUR: Get a closed contour from any given KLEE contour 4 | % 5 | % The function has the following argument: 6 | % MGC_CONT: Give a two-dimensional array of a 2D KLEE contour, e.g. 7 | % one of the arrays in contours{} in a KLEE tracing. 8 | % 9 | % => getClosedContour( KLEE_savedTracing.contours{1} ) 10 | % 11 | 12 | % Initialize an array and sum up the three columns of mgc_cont into one 13 | mgc_contCl = []; 14 | mgc_sum = sum( mgc_cont, 2 ); 15 | 16 | % Only proceed if mgc_cont is not empty. Now the function determines, 17 | % which elements to copy from mgc_cont into mgc_contCl. 18 | if ~isempty( mgc_cont ) 19 | 20 | % If the first element is not a number (nan), then start with the 21 | % second element. 22 | if isnan( mgc_sum(1) ) 23 | mgc_indxR(1) = 2; 24 | else 25 | mgc_indxR(1) = 1; 26 | end 27 | 28 | % If the last element is not a number, then end with the second 29 | % last element. 30 | if isnan( mgc_sum( end ) ) 31 | mgc_indxR(2) = size( mgc_cont, 1 ) - 1; 32 | else 33 | mgc_indxR(2) = size( mgc_cont, 1 ); 34 | end 35 | 36 | % Now copy all the columns, from element mgc_indxR(1) till 37 | % mgc_indxR(2) and then again mgc_indxR(1) into mgc_contCl. The 38 | % element mgc_indxR(1) is copied twice to close the contour line. 39 | mgc_contCl = mgc_cont( [mgc_indxR(1) : mgc_indxR(2), mgc_indxR(1) ], : ); 40 | end 41 | end -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/removeSomaStacks.m: -------------------------------------------------------------------------------- 1 | function stacks = removeSomaStacks(stacks) 2 | 3 | load /zdata/manuel/data/cortex/originalKLEE/exclude.mat; 4 | for i=1:length(excludeTask) 5 | idx = [stacks.taskID] == excludeTask(i); 6 | stacks(idx) = []; 7 | end 8 | 9 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/selectFiles.m: -------------------------------------------------------------------------------- 1 | function out = selectFiles(files) 2 | % ALmost obsolete function, for full version see manuelCode repo (only 3 | % makes sense in combination with braintracing DB @braintracing.de) 4 | 5 | for i=1:length(files) 6 | param = regexp(files(i).name(1:end-4), '\_', 'split'); 7 | out(i).dataset = param{1}; 8 | out(i).taskID = str2double(param{2}); 9 | out(i).user = param{3}; 10 | out(i).filename = files(i).name; 11 | end 12 | 13 | end 14 | 15 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/selectFilesHD.m: -------------------------------------------------------------------------------- 1 | function out = selectFilesHD(files) 2 | 3 | for i=1:length(files) 4 | param = regexp(files(i).name(1:end-4), '\_', 'split'); 5 | out(i).taskID = str2num(param{2}); 6 | out(i).lastUpload = 1; 7 | out(i).tracer = str2num(param{3}); 8 | out(i).filename = files(i).name; 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/viewCNNstacks.m: -------------------------------------------------------------------------------- 1 | function viewCNNstacks(folder, number) 2 | 3 | load(['/zdata/manuel/data/cortex/' folder '/parameter.mat']); 4 | a = load(stacks(number).targetFile); 5 | raw = a.raw; 6 | target = a.target; 7 | load(stacks(number).stackFile); 8 | raw = raw(1+settings.border(1):end-settings.border(1),1+settings.border(2):end-settings.border(2),1+settings.border(3):end-settings.border(3)); 9 | param = stacks(number); 10 | save(['/zdata/manuel/sync/trainingData/' folder 'stack' num2str(number, '%.3i') '.mat'], 'raw', 'target', 'stack', 'param'); 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /auxiliaryMethods/KLEEtoCNN/xyzMaskIntraExtra.m: -------------------------------------------------------------------------------- 1 | function target = xyzMaskIntraExtra( stack, thres ) 2 | target = int8(stack > 0); 3 | distField = bwdist(stack); 4 | target(distField < thres & target == 0) = -1; 5 | end 6 | 7 | -------------------------------------------------------------------------------- /auxiliaryMethods/addTree.m: -------------------------------------------------------------------------------- 1 | function skel = addTree(skel, nodeCoord, name, border, pre, post) 2 | % Quick fix to be able to add single node trees to an skeleton 3 | 4 | nrNodes = size(nodeCoord,1); 5 | maxNodeID = max(skel{end}.nodesNumDataAll(:,1))+1; 6 | % subsample contact/merger visualizatiosn at factor 10 if more than 500 nodes 7 | if nrNodes > 500 && nrNodes <= 5000 8 | skel{end+1}.name = [name ' (10x subsampling) of size ' num2str(nrNodes)]; 9 | nodeCoord = nodeCoord(1:10:end,1:3); 10 | nrNodes = size(nodeCoord,1); 11 | elseif nrNodes > 5000 12 | skel{end+1}.name = [name ' (subsampling down to 5000 nodes) of size ' num2str(nrNodes)]; 13 | idx = randperm(nrNodes); 14 | idx = idx(1:5000); 15 | nodeCoord = nodeCoord(idx,1:3); 16 | nrNodes = size(nodeCoord,1); 17 | else 18 | skel{end+1}.name = [name ' (no subsampling) of size ' num2str(nrNodes)]; 19 | end 20 | % Create a basic tree to skeleton (has to be useable by writeNml later) 21 | skel{end}.thingID = length(skel); 22 | skel{end}.color = [0 0 1 1]; 23 | skel{end}.commentsString = ''; 24 | skel{end}.nodesNumDataAll = zeros(nrNodes, 8); 25 | skel{end}.nodesNumDataAll(:,3) = nodeCoord(:,1); 26 | skel{end}.nodesNumDataAll(:,4) = nodeCoord(:,2); 27 | skel{end}.nodesNumDataAll(:,5) = nodeCoord(:,3); 28 | skel{end}.nodesNumDataAll(:,1) = maxNodeID:maxNodeID+nrNodes-1; 29 | skel{end}.nodesNumDataAll(:,2) = 1.5*ones(nrNodes,1); 30 | % No comments for all the volume label nodes (see loop below for CoM nodes) 31 | for i=1:nrNodes 32 | skel{end}.nodesAsStruct{i}.id = maxNodeID+i-1; 33 | skel{end}.nodesAsStruct{i}.comment = ''; 34 | end 35 | % Connect all nodes to the one with the next ID (otherwise oxalis will split into different trees) 36 | for i=1:nrNodes-1; 37 | skel{end}.edges(i,:) = [i i+1]; 38 | end 39 | % Add CoM nodes to skeleton 40 | if nargin > 3 41 | % Add three commented nodes in center of mass of pre,post and border volumes 42 | borderCoM = mean(vertcat(border(:).centroid),1); 43 | skel{end}.nodesNumDataAll(end+1,:) = [maxNodeID+nrNodes 1.5 round(borderCoM) 0 0 0]; 44 | skel{end}.nodesAsStruct{1+nrNodes}.id = num2str(maxNodeID+nrNodes); 45 | skel{end}.nodesAsStruct{1+nrNodes}.comment = 'CoM border'; 46 | [preDistCoM, idx] = min([pre(:).distance]); 47 | skel{end}.nodesNumDataAll(end+1,:) = [maxNodeID+nrNodes+1 1.5 round(pre(idx).centroid) 0 0 0]; 48 | skel{end}.nodesAsStruct{1+nrNodes+1}.id = num2str(maxNodeID+nrNodes+1); 49 | skel{end}.nodesAsStruct{1+nrNodes+1}.comment = ['CoM presynaptic, distance: ' num2str(preDistCoM) 'nm']; 50 | [postDistCoM, idx] = min([post(:).distance]); 51 | skel{end}.nodesNumDataAll(end+1,:) = [maxNodeID+nrNodes+2 1.5 round(post(idx).centroid) 0 0 0]; 52 | skel{end}.nodesAsStruct{1+nrNodes+2}.id = num2str(maxNodeID+nrNodes+2); 53 | skel{end}.nodesAsStruct{1+nrNodes+2}.comment = ['CoM postsynaptic, distance: ' num2str(postDistCoM) 'nm']; 54 | % Trees need to be connected in order to not be splitted by oxalis 55 | skel{end}.edges(end+1,:) = [nrNodes nrNodes+1]; 56 | skel{end}.edges(end+1,:) = [nrNodes+1 nrNodes+2]; 57 | skel{end}.edges(end+1,:) = [nrNodes+1 nrNodes+3]; 58 | end 59 | 60 | end 61 | -------------------------------------------------------------------------------- /auxiliaryMethods/bfs.m: -------------------------------------------------------------------------------- 1 | function components = bfs(idx,adjacency_list) 2 | 3 | components ={}; 4 | k = 1; 5 | nonvisited = 1:length(idx); 6 | 7 | while ~isempty(nonvisited) 8 | components{k,1} = idx(nonvisited(1)); 9 | l1 = size(components{k,1},2); 10 | components{k,1}=horzcat(components{k,1},adjacency_list{nonvisited(1)}); 11 | l2 = size(components{k,1},2); 12 | nonvisited(1)=[]; 13 | while l1~=l2 14 | v=[]; 15 | for j=l1+1:l2 16 | index = find(idx==(components{k,1}(j))); 17 | v=[v,adjacency_list{index}]; 18 | nonvisited(nonvisited==index)=[]; 19 | end 20 | l1 = l2; 21 | v = intersect(v,idx(nonvisited)); 22 | components{k,1}=horzcat(components{k,1},v); 23 | l2 = size(components{k,1},2); 24 | end 25 | k = k+1; 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /auxiliaryMethods/convertKnossosNmlToHoc.m: -------------------------------------------------------------------------------- 1 | function y=convertKnossosNmlToHoc(a,filename,overWriteEdges,overWriteThickness,emphasizeNodes,useSplines,resolution) 2 | 3 | for i=1:size(a,2) 4 | if ~isempty(a{i}.nodes) 5 | a_sorted=sortrows([a{i}.nodes (1:size(a{i}.nodes,1))'],3); 6 | cast(a_sorted(end,:),'uint16') 7 | a{i}.nodes(a_sorted(end,5),4)=1000; 8 | listS=makeSegmentList(a{i},overWriteEdges,emphasizeNodes); 9 | fid=fopen([filename num2str(i, '%.4i') '.hoc'], 'w+'); 10 | fprintf(fid,'/* created with convertKnossosNmlToHoc.m */\n'); 11 | for ii=1:size(listS,1) 12 | y=listS{ii,1}(:,5); 13 | % if y(1)==1.5 14 | % y(1)=1; 15 | % end 16 | % if y(end)==1.5; 17 | % y(end)=1; 18 | % end 19 | x=1:size(y,1); 20 | xx=find(y-1.5); 21 | yy=y(y~=1.5); 22 | if size(xx,1)<1 23 | xx=[1 2]; 24 | yy=[27 27]; 25 | 26 | else if size(xx,1)<2 27 | if xx(1)==x(1) 28 | xx=[xx x(end)]; 29 | yy=[yy 27]; 30 | else 31 | xx=[x(1) xx]; 32 | yy=[27 yy]; 33 | end 34 | end 35 | end 36 | y=interp1(xx,yy,x); 37 | if useSplines 38 | listS{ii,1}(:,5)=y; 39 | end 40 | if overWriteThickness 41 | listS{ii,1}(:,5)=100; 42 | end 43 | 44 | fprintf(fid,'\n{create adhoc%i}\n',ii); 45 | fprintf(fid,'{access adhoc%i}\n',ii); 46 | for jj=1:ii-1 47 | if listS{jj,1}(1,1)==listS{ii,1}(1,1) 48 | fprintf(fid,'{connect adhoc%i(0), adhoc%i(0)}\n',ii,jj); 49 | break; 50 | end 51 | if listS{jj,1}(end,1)==listS{ii,1}(1,1) 52 | fprintf(fid,'{connect adhoc%i(1), adhoc%i(0)}\n',ii,jj); 53 | break; 54 | 55 | end 56 | 57 | end 58 | fprintf(fid,'{nseg = 1}\n'); 59 | fprintf(fid,'{strdef color color = "White"}\n'); 60 | fprintf(fid,'{pt3dclear()}\n'); 61 | for jj=listS{ii,1}' 62 | fprintf(fid,'{pt3dadd(%f,%f,%f,%f)}\n',jj(2)*resolution(1),jj(3)*resolution(2),jj(4)*resolution(3),jj(5)*mean(resolution)); 63 | end 64 | end 65 | fclose(fid); 66 | end 67 | end 68 | 69 | end 70 | 71 | -------------------------------------------------------------------------------- /auxiliaryMethods/copyCubeSubset.m: -------------------------------------------------------------------------------- 1 | function copyCubeSubset( kl_bbox_cubeIDs, kl_sourceDir, kl_targetDir ) 2 | 3 | % COPYCUBESUBSET: Copy subcubes of raw EM data from an existing directory to another. 4 | % 5 | % The function has the following arguments: 6 | % KL_BBOX_CUBEIDS: Give a 2x3-Matrix containing the xyz-coordinates 7 | % of the subcube, e.g. [ 0 1; 0 1; 0 1 ] 8 | % KL_SOURCEDIR: Give the root directory of the EM data as a string, 9 | % e.g. 'E:\e_k0563\k0563_mag1\' 10 | % KL_TARGETDIR: Give the target directory of the files as a 11 | % string, e.g. 'E:\e_k0563\k0563_mag1_subcube\' 12 | % 13 | % => copyCubeSubset( [ 0 1; 0 1; 0 1 ], 'E:\e_k0563\k0563_mag1\', 'E:\e_k0563\k0563_mag1_subcube\' ) 14 | % 15 | 16 | % Create the target directory 17 | if ~exist(kl_targetDir, 'dir') 18 | mkdir(kl_targetDir); 19 | end 20 | 21 | % Copy the file "knossos.conf" to the target directory 22 | copyfile(fullfile( kl_sourceDir, 'knossos.conf' ), kl_targetDir ); 23 | 24 | % Now successively create directories and copy the cubes 25 | for kl_x = kl_bbox_cubeIDs( 1, 1 ) : kl_bbox_cubeIDs( 1, 2 ) 26 | % Create all the "x"-directories 27 | if ~exist(fullfile( kl_targetDir, sprintf( 'x%04.0f', kl_x)), 'dir' ) 28 | mkdir(fullfile( kl_targetDir, sprintf( 'x%04.0f', kl_x))); 29 | end 30 | for kl_y = kl_bbox_cubeIDs( 2, 1 ) : kl_bbox_cubeIDs( 2, 2 ) 31 | % Create all the "y"-directories 32 | if ~exist(fullfile( kl_targetDir, sprintf( 'x%04.0f', kl_x ), sprintf( 'y%04.0f', kl_y )), 'dir'); 33 | mkdir(fullfile( kl_targetDir, sprintf( 'x%04.0f', kl_x ), sprintf( 'y%04.0f', kl_y ))); 34 | end 35 | for kl_z = kl_bbox_cubeIDs( 3, 1 ) : kl_bbox_cubeIDs( 3, 2 ) 36 | % Create all the "z"-directories 37 | if ~exist(fullfile( kl_targetDir, sprintf( 'x%04.0f', kl_x ), sprintf( 'y%04.0f', kl_y ), sprintf( 'z%04.0f', kl_z )), 'dir'); 38 | mkdir(fullfile( kl_targetDir, sprintf( 'x%04.0f', kl_x ), sprintf( 'y%04.0f', kl_y ), sprintf( 'z%04.0f', kl_z ))); 39 | end 40 | % Copy the .raw file into the target directory 41 | copyfile(fullfile( kl_sourceDir, sprintf( 'x%04.0f', kl_x ), ... 42 | sprintf( 'y%04.0f', kl_y ), sprintf( 'z%04.0f', kl_z ), '*.*' ), fullfile( kl_targetDir, ... 43 | sprintf( 'x%04.0f', kl_x ), sprintf( 'y%04.0f', kl_y ), sprintf( 'z%04.0f', kl_z ) ) ); 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /auxiliaryMethods/genpathGit.m: -------------------------------------------------------------------------------- 1 | function p = genpathGit(d) 2 | %GENPATH Generate recursive toolbox path. 3 | % P = GENPATH returns a new path string by adding all the subdirectories 4 | % of MATLABROOT/toolbox, including empty subdirectories. 5 | % 6 | % P = GENPATH(D) returns a path string starting in D, plus, recursively, 7 | % all the subdirectories of D, including empty subdirectories. 8 | % 9 | % NOTE 1: GENPATH will not exactly recreate the original MATLAB path. 10 | % 11 | % NOTE 2: GENPATH only includes subdirectories allowed on the MATLAB 12 | % path. 13 | % 14 | % See also PATH, ADDPATH, RMPATH, SAVEPATH. 15 | 16 | % Copyright 1984-2006 The MathWorks, Inc. 17 | % $Revision: 1.13.4.5 $ $Date: 2008/06/24 17:12:06 $ 18 | %------------------------------------------------------------------------------ 19 | 20 | if nargin==0, 21 | p = genpathGit(fullfile(matlabroot,'toolbox')); 22 | if length(p) > 1, p(end) = []; end % Remove trailing pathsep 23 | return 24 | end 25 | 26 | % initialise variables 27 | classsep = '@'; % qualifier for overloaded class directories 28 | packagesep = '+'; % qualifier for overloaded package directories 29 | p = ''; % path to be returned 30 | 31 | % Generate path based on given root directory 32 | files = dir(d); 33 | if isempty(files) 34 | return 35 | end 36 | 37 | % Add d to the path even if it is empty. 38 | p = [p d pathsep]; 39 | 40 | % set logical vector for subdirectory entries in d 41 | isdir = logical(cat(1,files.isdir)); 42 | % 43 | % Recursively descend through directories which are neither 44 | % private nor "class" directories. 45 | % 46 | dirs = files(isdir); % select only directory entries from the current listing 47 | 48 | for i=1:length(dirs) 49 | dirname = dirs(i).name; 50 | if ~strcmp( dirname, '.git') && ... 51 | ~strcmp( dirname, 'KLEE') && ... 52 | ~strcmp( dirname, 'CNNmpf') && ... 53 | ~strcmp( dirname,'.') && ... 54 | ~strcmp( dirname,'..') && ... 55 | ~strncmp( dirname,classsep,1) && ... 56 | ~strncmp( dirname,packagesep,1) && ... 57 | ~strcmp( dirname,'private') 58 | p = [p genpathGit(fullfile(d,dirname))]; % recursive calling of this function. 59 | end 60 | end 61 | 62 | %------------------------------------------------------------------------------ 63 | -------------------------------------------------------------------------------- /auxiliaryMethods/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2011, Tim Holy 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /auxiliaryMethods/loadClassData.m: -------------------------------------------------------------------------------- 1 | function class = loadClassData(root, prefix, bbox) 2 | % Wrapper for easier loading of Knossos-Hierachy classification 3 | class = readKnossosRoi(root, prefix, bbox, 'single', '', 'raw'); 4 | end -------------------------------------------------------------------------------- /auxiliaryMethods/makeIsosurfaceView.m: -------------------------------------------------------------------------------- 1 | function makeSegMovie( segmentation, raw, outputFile ) 2 | % make video of raw data + seg video 3 | 4 | % Relabel segmentation to continous IDs starting at 1 5 | sizeCube = size(segmentation); 6 | segmentation = segmentation(:); 7 | [localIds, ~, n] = unique(segmentation); 8 | nrUniqueIds = length(localIds) - 1; 9 | newIds = 0:1:nrUniqueIds; 10 | segmentation = newIds(n); 11 | segmentation = reshape(segmentation, sizeCube); 12 | 13 | % Create colormap (with bg set to white and black to avoid those) 14 | cm = distinguishable_colors(length(unique(segmentation(:)))-1, [0 0 0; 1 1 1]); 15 | % Add black for bg 16 | cm = [0 0 0; cm]; 17 | 18 | % Which raw data slices to show for each dimension 19 | slices = {[1] [1] [1]}; 20 | 21 | % Plot everything 22 | figure; 23 | hold on; 24 | plotIsosurfaces(segmentation, cm); 25 | plotOriginalData(raw, slices); 26 | xlim([1 size(raw,1)]); 27 | ylim([1 size(raw,2)]); 28 | zlim([1 size(raw,3)]); 29 | daspect([28 28 11.24]); 30 | axis off; 31 | view(110,25); 32 | camlight('headlight'); 33 | lighting phong; 34 | set(gcf, 'Color', 'w'); 35 | 36 | set(gcf,'PaperPositionMode', 'manual', 'PaperUnits','centimeters', ... 37 | 'Paperposition',[1 1 28 20], 'PaperSize', [29.2 21]) 38 | drawnow; 39 | print(gcf, '-dpdf', '-r300', outputFile); 40 | 41 | 42 | end 43 | 44 | -------------------------------------------------------------------------------- /auxiliaryMethods/makeMovie.m: -------------------------------------------------------------------------------- 1 | function makeMovie( raw, outputFile ) 2 | % make video of raw data + seg video 3 | 4 | if strcmp(computer('arch'), 'glnxa64') 5 | writerObj = VideoWriter(outputFile); 6 | elseif strcmp(computer('arch'), 'PCWIN64') || strcmp(computer('arch'), 'win64') 7 | writerObj = VideoWriter(outputFile); 8 | else 9 | error('Please set up video codex compatible with your architecture here!') 10 | end 11 | 12 | maxVal = 180; 13 | minVal = 60; 14 | raw(raw < minVal) = minVal; 15 | raw(raw > maxVal) = maxVal; 16 | raw = raw - minVal; 17 | raw = raw ./ (maxVal - minVal); 18 | 19 | writerObj.FrameRate = 8; 20 | open(writerObj); 21 | % Write each z-layer as one video frame 22 | for f=1:size(raw,3) 23 | writeVideo(writerObj,raw(:,:,f)); 24 | end 25 | close(writerObj); 26 | close all; 27 | 28 | end 29 | 30 | -------------------------------------------------------------------------------- /auxiliaryMethods/makeSegMovie.m: -------------------------------------------------------------------------------- 1 | function makeSegMovie( segmentation, raw, outputFile ) 2 | % make video of raw data + seg video 3 | 4 | % Relabel segmentation to continous IDs starting at 1 5 | sizeCube = size(segmentation); 6 | segmentation = segmentation(:); 7 | [localIds, ~, n] = unique(segmentation); 8 | nrUniqueIds = length(localIds) - 1; 9 | newIds = [0 1:nrUniqueIds]; 10 | segmentation = newIds(n); 11 | segmentation = reshape(segmentation, sizeCube); 12 | % Create colormap (with bg set to white and black to avoid those) 13 | cm = distinguishable_colors(length(unique(segmentation(:)))-1, [0 0 0; 1 1 1]); 14 | 15 | figure('Resize', 'off'); 16 | set(gcf,'NextPlot','replacechildren'); 17 | set(gcf,'Renderer','OpenGL'); 18 | if strcmp(computer('arch'), 'glnxa64') 19 | writerObj = VideoWriter(outputFile, 'Motion JPEG AVI'); 20 | elseif strcmp(computer('arch'), 'PCWIN64') || strcmp(computer('arch'), 'win64') 21 | writerObj = VideoWriter(outputFile, 'Uncompressed AVI'); 22 | else 23 | error('Please set up video codex compatible with your architecture here!') 24 | end 25 | 26 | writerObj.FrameRate = 4; 27 | open(writerObj); 28 | % Write each z-layer as one video frame 29 | for f=1:size(raw,3) 30 | hold off; 31 | imshow(raw(:,:,f), [0 255]); 32 | hold on; 33 | temp = label2rgb(segmentation(:,:,f), cm, 'k'); 34 | himage = imagesc(temp); 35 | caxis([-100 355]); 36 | set(himage, 'AlphaData', 0.1 ); 37 | frame = getframe; 38 | if f == 1 39 | sizeFrame = size(frame); 40 | end 41 | writeVideo(writerObj,frame(1:sizeFrame(1),1:sizeFrame(2))); 42 | end 43 | close(writerObj); 44 | close all; 45 | 46 | end 47 | 48 | -------------------------------------------------------------------------------- /auxiliaryMethods/makeSegmentList.m: -------------------------------------------------------------------------------- 1 | function listS=makeSegmentList(nml,overWriteEdges,emphasizeNodes) 2 | 3 | a=cell(1); 4 | a{1,1}=nml; 5 | if overWriteEdges 6 | a{1,1}.edges=zeros(size(a{1,1}.nodes,1)-1,2); 7 | for i=1:size(a{1,1}.edges,1) 8 | if emphasizeNodes 9 | a{1,1}.edges(i,:)=[1,i+1]; 10 | else 11 | a{1,1}.edges(i,:)=[i,i+1]; 12 | end 13 | end 14 | end 15 | 16 | conM=zeros(size(a{1,1}.nodes,1)); 17 | for ii=a{1,1}.edges' 18 | if ii(1)>0&&ii(2)>0 19 | conM(ii(1),ii(2))=1; 20 | end 21 | end 22 | conM=conM+conM'; 23 | sconM=sum(conM); 24 | sconM(sconM>1)=0; 25 | startP= find(sconM); 26 | directionP=find(conM(:,startP(1))); 27 | listS=n2hR(a{1,1},conM,startP(1),directionP); 28 | end 29 | 30 | function y=n2hR(aa,conM,oldNode,newNode) 31 | y=cell(1); 32 | y{1}=[oldNode,aa.nodes(oldNode,:)]; 33 | while(true) 34 | y{1}=[y{1};[newNode,aa.nodes(newNode,:)]]; 35 | switch sum(conM(:,newNode)) 36 | case 1 %terminate segment 37 | break; 38 | case 2 %continue segment 39 | listN=find(conM(:,newNode)); 40 | if listN(1)==oldNode 41 | oldNode=newNode; 42 | newNode=listN(2); 43 | else 44 | oldNode=newNode; 45 | newNode=listN(1); 46 | end 47 | otherwise %make child segments 48 | listN=find(conM(:,newNode))'; 49 | for nodeIt=listN 50 | if nodeIt~=oldNode 51 | y=[y; n2hR(aa,conM,newNode,nodeIt)]; 52 | end 53 | end 54 | break; 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /auxiliaryMethods/mergeTrees.m: -------------------------------------------------------------------------------- 1 | function newSkel = mergeTrees(skel1, skel2, name1, name2) 2 | % Joins two skeletons into two trees in one skeleton, makes some basic settings (color etc) 3 | 4 | newSkel(1) = skel1; 5 | newSkel{1}.parameters.activeNode.id = '1'; % some inconstinencies in auxiliaryMethods parse vs. writeNml? 6 | newSkel{1}.thingID = 1; % renumber things 7 | newSkel{1}.name = name1; 8 | newSkel{1}.color = [1 0 0 1]; 9 | newSkel{1}.commentsString = ''; 10 | % Have to renumber ids of nodes of second skeleton to keep ids globally unique (why? is this nml standard?) 11 | maxNodeID1 = max(skel1{1}.nodesNumDataAll(:,1)); 12 | maxNodeID2 = max(skel2{1}.nodesNumDataAll(:,1)); 13 | maxNodeID = max(maxNodeID1,maxNodeID2); 14 | oldIDs = skel2{1}.nodesNumDataAll(:,1); 15 | replace = find(oldIDs <= maxNodeID1); 16 | newIDs = maxNodeID+1:maxNodeID+length(replace); 17 | skel2{1}.nodesNumDataAll(replace,1) = newIDs; 18 | % Finished renumbering, add skeleton now 19 | newSkel(2) = skel2; 20 | newSkel{2}.thingID = 2; 21 | newSkel{2}.name = name2; 22 | newSkel{2}.color = [0 1 0 1]; 23 | newSkel{2}.commentsString = ''; 24 | 25 | end -------------------------------------------------------------------------------- /auxiliaryMethods/plotIsosurfaces.m: -------------------------------------------------------------------------------- 1 | function [k, issfs] = plotIsosurfaces( kl_stack, colors ) 2 | %UNTITLED2 Summary of this function goes here 3 | % Detailed explanation goes here 4 | cellLabel = unique(kl_stack); 5 | cellLabel(cellLabel == 0) = []; 6 | k = cell(size(cellLabel)); 7 | for i=1:length(cellLabel) 8 | singleCellStack = kl_stack == cellLabel(i); 9 | issfs{i} = isosurface(singleCellStack, .1); 10 | k{i} = patch(issfs{i}); 11 | set(k{i}, 'FaceColor', colors(mod(i-1,31)+1,:), 'EdgeColor', 'none'); 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /auxiliaryMethods/plotOriginalData.m: -------------------------------------------------------------------------------- 1 | function k = plotOriginalData( rawData, slicePos ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | k = slice(single(rawData), slicePos{1}, slicePos{2}, slicePos{3}); 5 | colormap(gray(256)); 6 | set(k, 'FaceColor', 'interp', 'EdgeColor', 'none'); 7 | end 8 | 9 | -------------------------------------------------------------------------------- /auxiliaryMethods/readKnossosCube.m: -------------------------------------------------------------------------------- 1 | function kl_cube = readKnossosCube( kl_parfolder, kl_fileprefix, kl_cubeCoord, classT, kl_filesuffix, ending,cubesize) 2 | 3 | % READKNOSSOSCUBE: Read raw data from EM into Matlab 4 | % 5 | % The function has the following arguments: 6 | % KL_PARFOLDER: Give the root directory of the data you want to read as a 7 | % string, e.g. 'E:\e_k0563\k0563_mag1\' 8 | % KL_FILEPREFIX: Give the name of the specific file you want to read without 9 | % the coordinates or the ending as a string, e.g. '100527_k0563_mag1' 10 | % KL_CUBECOORD: Give an array of 3 numbers of the xyz-coordinates as 11 | % given in the file name, no need for the full four digits: 0020 -> 12 | % 20. E.g. [21 30 150] 13 | % CLASST: Optional! Standard version is unsigned int with 8 bits. For the 14 | % precision of the values. 15 | % 16 | % => readKnossosCube( 'E:\e_k0563\k_0563_mag1', '100527_k0563_mag1', [21 30 150], 'uint8' ) 17 | % 18 | 19 | if( nargin < 4 ) 20 | classT = 'uint8=>uint8'; 21 | end 22 | if( nargin < 5 ) 23 | kl_filesuffix = ''; 24 | end 25 | if( nargin < 6 ) 26 | if( strcmp( classT, 'uint8=>uint8' ) ) 27 | ending = 'raw'; 28 | else 29 | ending = 'mat'; 30 | end 31 | end 32 | if (nargin<7) 33 | cubesize=[128 128 128]; 34 | end 35 | if numel(cubesize)==1 36 | cubesize=repmat(cubesize,1,3); 37 | end 38 | 39 | % Building the full filename 40 | kl_fullfile = fullfile( kl_parfolder, sprintf( 'x%04.0f', kl_cubeCoord(1) ),... 41 | sprintf( 'y%04.0f', kl_cubeCoord(2) ), sprintf( 'z%04.0f', kl_cubeCoord(3) ),... 42 | sprintf( ['%s_x%04.0f_y%04.0f_z%04.0f%s.' ending], kl_fileprefix, kl_cubeCoord, kl_filesuffix ) ); 43 | 44 | % If this file exists, load it into Matlab, else fill the matrix with zeros 45 | if( exist( kl_fullfile, 'file' ) ) 46 | if( strcmp( ending, 'raw' ) ) 47 | fid = fopen( kl_fullfile ); 48 | kl_cube = fread( fid, classT); 49 | kl_cube = reshape( kl_cube, cubesize); 50 | fclose( fid ); 51 | else 52 | load( kl_fullfile ); 53 | if ~exist( 'kl_cube', 'var' ) 54 | kl_cube = kl_stack; 55 | end 56 | end 57 | else 58 | classT2=bsxfun(@eq,classT,'>'); 59 | classT2=classT(find(classT2)+1:end); 60 | kl_cube = zeros( cubesize, classT2 ); 61 | end 62 | 63 | end -------------------------------------------------------------------------------- /auxiliaryMethods/removeBbox.m: -------------------------------------------------------------------------------- 1 | function skel = removeBbox(skel) 2 | % Removes all skeletons with name containing 'bbox' from skeleton collection 3 | % This should not be necessary anymore at some point, was just still necessary due to not yet implemented Oxalis BBox feature 4 | 5 | toDel = zeros(length(skel),1); 6 | for i=1:length(skel) 7 | if strfind(skel{i}.name,'bbox') 8 | toDel(i) = 1; 9 | end 10 | end 11 | display(['Removing ' num2str(sum(toDel)) ' bounding box trees from skeleton collection.']); 12 | skel(toDel > 0) = []; 13 | 14 | end -------------------------------------------------------------------------------- /auxiliaryMethods/removeEmptySkeletons.m: -------------------------------------------------------------------------------- 1 | function skel = removeEmptySkeletons( skel ) 2 | % Remove empty trees from skeleton 3 | 4 | toDel = zeros(length(skel),1); 5 | for i=1:length(skel) 6 | if isempty(skel{i}.nodes) || size(skel{i}.nodes,1) == 0 7 | toDel(i) = 1; 8 | end 9 | end 10 | if any(toDel) 11 | skel = skel(~toDel); 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /auxiliaryMethods/removeGlia.m: -------------------------------------------------------------------------------- 1 | function skel = removeGlia(skel) 2 | % Removes all skeletons with comment glia from skeleton collection 3 | 4 | toDel = zeros(length(skel),1); 5 | for i=1:length(skel) 6 | for j=1:length(skel{i}.nodesAsStruct) 7 | if ~isempty(strfind(skel{i}.nodesAsStruct{j}.comment,'glia')) || ~isempty(strfind(skel{i}.nodesAsStruct{j}.comment,'Glia')); 8 | toDel(i) = 1; 9 | end 10 | end 11 | end 12 | display(['Removing ' num2str(sum(toDel)) ' glia cells from skeleton collection.']); 13 | skel(toDel > 0) = []; 14 | 15 | end -------------------------------------------------------------------------------- /auxiliaryMethods/startCPU.m: -------------------------------------------------------------------------------- 1 | function job = startCPU( functionHandle, inputCell, jobName ) 2 | global jobManagerName; 3 | 4 | % Load cluster configuration 5 | jm = parcluster(jobManagerName); 6 | 7 | % Create job on cluster 8 | job = createJob(jm(1), 'Name', jobName); 9 | for i=1:length(functionHandle) 10 | createTask(job, functionHandle{i}, 0, inputCell{i}); 11 | end 12 | 13 | % Start job 14 | submit(job); 15 | 16 | end 17 | -------------------------------------------------------------------------------- /auxiliaryMethods/voxelBasedMetrics/Rand/fullRand.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhlabCodingTeam/SegEM/a61ff23875ef36cf6c851ae3112cbdc640ece43f/auxiliaryMethods/voxelBasedMetrics/Rand/fullRand.m -------------------------------------------------------------------------------- /auxiliaryMethods/voxelBasedMetrics/Rand/randContingencyTable.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhlabCodingTeam/SegEM/a61ff23875ef36cf6c851ae3112cbdc640ece43f/auxiliaryMethods/voxelBasedMetrics/Rand/randContingencyTable.cpp -------------------------------------------------------------------------------- /auxiliaryMethods/voxelBasedMetrics/Rand/useRand.m: -------------------------------------------------------------------------------- 1 | % Calculate the comparison plot between segm1, segm2 and segm3 2 | 3 | rMax = 2 : 0.5 : 12 ; 4 | n = max( size( rMax ) ); 5 | 6 | kMax = 4; 7 | 8 | err1 = zeros( n, kMax ); 9 | err2 = zeros( n, kMax ); 10 | err3 = zeros( n, kMax ); 11 | 12 | %parpool( kMax ); 13 | %delete( gcp ); 14 | 15 | % Calculate the rand error 16 | parfor k = 1 : kMax 17 | for i = 1 : n 18 | if mod( i - k , kMax ) == 0 19 | fprintf( 'Currently at: i = %d \n', i ); 20 | err1( i, k ) = randErr( gT, seg1, [ 0, rMax( i ) ], 1, 0 ); 21 | err2( i, k ) = randErr( gT, seg2, [ 0, rMax( i ) ], 1, 0 ); 22 | err3( i, k ) = randErr( gT, seg3, [ 0, rMax( i ) ], 1, 0 ); 23 | end 24 | end 25 | end 26 | 27 | % Save the data, don't save the data from loadData.m 28 | clear( 'classifier', 'em', 'gT', 'seg1', 'seg2', 'seg3', 'skel' ); 29 | 30 | folderName = '\Rand\'; 31 | fileName = 'data.mat'; 32 | 33 | if exist( [ pwd, folderName ], 'file' ) == 0 34 | mkdir( [ pwd, folderName ] ); 35 | if exist( [ pwd, folderName, fileName ], 'file' ) == 0 36 | save( [ pwd, folderName, fileName ] ); 37 | else 38 | fprintf( 'File already exists. Workspace has not been saved!\n' ); 39 | end 40 | else 41 | if exist( [ pwd, folderName, fileName ], 'file' ) == 0 42 | save( [ pwd, folderName, fileName ] ); 43 | else 44 | fprintf( 'File already exists. Workspace has not been saved!\n' ); 45 | end 46 | end 47 | 48 | err1 = sum( err1, 2 ); 49 | err2 = sum( err2, 2 ); 50 | err3 = sum( err3, 2 ); 51 | 52 | figure( 1 ); 53 | plot( rMax, err1, rMax, err2, rMax, err3 ); 54 | %xlim( [ 2, 12 ] ); 55 | ylim( [ 0, 1 ] ); 56 | grid on; 57 | title( 'Rand Error' ); 58 | xlabel( 'Distance rMax' ); 59 | ylabel( 'Rand error' ); 60 | legend( 'segm1', 'segm2', 'segm3', 'Location', 'NorthWest' ); 61 | 62 | -------------------------------------------------------------------------------- /auxiliaryMethods/voxelBasedMetrics/Warp/useWarp.m: -------------------------------------------------------------------------------- 1 | gT1 = gT; 2 | gT1( gT1 > 0 ) = 1; 3 | 4 | % threshold = 0.5; 5 | % thisBinary = ( classifier > threshold ); 6 | % thisBinary = double( thisBinary ); 7 | % err = warpErr( gT1, thisBinary, classifier, 1, 0 ); 8 | % 9 | % fprintf( 'Warp error with threshold %d is: %d\n', threshold, err ); 10 | 11 | % threshold = 0.1 : 0.1 : 0.9; 12 | % n = max( size( threshold ) ); 13 | % 14 | % err = zeros( 1, n ); 15 | % 16 | % for i = 1 : n 17 | % thisBinary = ( classifier > threshold( i ) ); 18 | % thisBinary = double( thisBinary ); 19 | % err( i ) = warpErr( gT1, thisBinary, classifier, 1, 0 ); 20 | % end 21 | % 22 | % figure( 1 ); 23 | % plot( threshold, err ); 24 | % grid on; 25 | % title( 'Warping Error' ); 26 | % xlabel( 'Threshold' ); 27 | % ylabel( 'Warping error' ); 28 | 29 | m = 6; 30 | p = 3; 31 | n = m * p; 32 | err = zeros( 1, n ); 33 | err1 = zeros( 1, p ); 34 | err2 = zeros( 1, p ); 35 | err3 = zeros( 1, p ); 36 | err4 = zeros( 1, p ); 37 | err5 = zeros( 1, p ); 38 | err6 = zeros( 1, p ); 39 | threshold = 0.05 : 0.05 : 0.90; 40 | 41 | parfor i = 1 : p 42 | thisBinary = double( classifier > threshold( i ) ); 43 | err1( i ) = warpErr( gT1, thisBinary, classifier, 1, 0 ); 44 | end 45 | fprintf( 'Done with #1\n' ); 46 | parfor i = 1 : p 47 | thisBinary = double( classifier > threshold( i + 1 * p ) ); 48 | err2( i ) = warpErr( gT1, thisBinary, classifier, 1, 0 ); 49 | end 50 | fprintf( 'Done with #2\n' ); 51 | parfor i = 1 : p 52 | thisBinary = double( classifier > threshold( i + 2 * p ) ); 53 | err3( i ) = warpErr( gT1, thisBinary, classifier, 1, 0 ); 54 | end 55 | fprintf( 'Done with #3\n' ); 56 | parfor i = 1 : p 57 | thisBinary = double( classifier > threshold( i + 3 * p ) ); 58 | err4( i ) = warpErr( gT1, thisBinary, classifier, 1, 0 ); 59 | end 60 | fprintf( 'Done with #4\n' ); 61 | parfor i = 1 : p 62 | thisBinary = double( classifier > threshold( i + 4 * p ) ); 63 | err5( i ) = warpErr( gT1, thisBinary, classifier, 1, 0 ); 64 | end 65 | fprintf( 'Done with #5\n' ); 66 | parfor i = 1 : p 67 | thisBinary = double( classifier > threshold( i + 5 * p ) ); 68 | err6( i ) = warpErr( gT1, thisBinary, classifier, 1, 0 ); 69 | end 70 | fprintf( 'Done with #6\n' ); 71 | 72 | for i = 1 : 6 73 | err( 1 : 3 ) = err1; 74 | err( 4 : 6 ) = err2; 75 | err( 7 : 9 ) = err3; 76 | err( 10 : 12 ) = err4; 77 | err( 13 : 15 ) = err5; 78 | err( 16 : 18 ) = err6; 79 | end 80 | 81 | figure( 1 ); 82 | plot( threshold, err ); 83 | grid on; 84 | ylim([0,1]); 85 | title( 'Warping Error' ); 86 | xlabel( 'Threshold' ); 87 | ylabel( 'Warping error' ); 88 | -------------------------------------------------------------------------------- /auxiliaryMethods/voxelBasedMetrics/Warp/voxelErr.m: -------------------------------------------------------------------------------- 1 | function err = voxelErr( gT, seg ) 2 | 3 | % VOXELERR Calculate the voxel error of a binary segmentation 4 | % 5 | % The function has the following arguments: 6 | % GT: The ground truth segmentation (3d matrix). 7 | % SEG: The binary segmentation of which you want to calculate the 8 | % metric (3d matrix). 9 | % 10 | 11 | if ~isfloat( gT ) 12 | gT = double( gT ); 13 | end 14 | if ~isfloat( seg ) 15 | seg = double( seg ); 16 | end 17 | if max( max( max( seg ) ) ) > 1 || min( min( min( seg ) ) ) < 0 18 | fprintf( 'The segmentation is not binary!\n' ); 19 | err = []; 20 | return; 21 | end 22 | if max( max( max( gT ) ) ) > 1 || min( min( min( gT ) ) ) < 0 23 | fprintf( 'The ground truth is not binary!\n' ); 24 | err = []; 25 | return; 26 | end 27 | 28 | [ n1, m1, k1 ] = size( gT ); 29 | [ n2, m2, k2 ] = size( seg ); 30 | 31 | if n1 ~= n2 || m1 ~= m2 || k1 ~= k2 32 | fprintf( 'The segmentation and the ground truth need to be the same size!\n' ); 33 | err = []; 34 | return; 35 | end 36 | 37 | % Count voxels, which have different values in gT and seg 38 | err = sum( sum( sum( abs( gT - seg ) ) ) ); 39 | 40 | % Normalize to a value between 0...1 41 | err = err / ( n1 * m1 * k1 ); 42 | end 43 | 44 | -------------------------------------------------------------------------------- /auxiliaryMethods/voxelBasedMetrics/Warp/warpErr.m: -------------------------------------------------------------------------------- 1 | function err = warpErr( gT, seg, analogue, useMex, useP ) 2 | 3 | % RANDERR Calculate the rand error of a (binary) segmentation 4 | % 5 | % The function has the following arguments: 6 | % GT: The binary ground truth segmentation (3d matrix). 7 | % SEG: The segmentation of which you want to calculate the metric 8 | % (3d matrix). 9 | % ANALOGUE: Original 3d image, on which the segmentation was 10 | % performed. This is used for warping. 11 | % USEMEX: Binary variable, whether to use the quicker mex function 12 | % (only 64bit). 13 | % USEP: Binary variable, whether to use parallel loops. 14 | % 15 | 16 | if nargin < 4 17 | useMex = 1; 18 | end 19 | 20 | if ~isfloat( gT ) 21 | gT = double( gT ); 22 | end 23 | if ~isfloat( seg ) 24 | seg = double( seg ); 25 | end 26 | if ~isfloat( analogue ) 27 | analogue = double( analogue ); 28 | end 29 | if max( max( max( seg ) ) ) > 1 || min( min( min( seg ) ) ) < 0 30 | fprintf( 'The segmentation is not binary!\n' ); 31 | err = []; 32 | return; 33 | end 34 | if max( max( max( gT ) ) ) > 1 || min( min( min( gT ) ) ) < 0 35 | fprintf( 'The ground truth is not binary!\n' ); 36 | err = []; 37 | return; 38 | end 39 | 40 | [ n1, m1, k1 ] = size( gT ); 41 | [ n2, m2, k2 ] = size( seg ); 42 | [ n3, m3, k3 ] = size( analogue ); 43 | 44 | if n1 ~= n2 || m1 ~= m2 || k1 ~= k2 45 | fprintf( 'The segmentation and the ground truth need to be the same size!\n' ); 46 | err = []; 47 | return; 48 | end 49 | if n2 ~= n3 || m2 ~= m3 || k2 ~= k3 50 | fprintf( 'The segmentation and the analogue image need to be the same size!\n' ); 51 | err = []; 52 | return; 53 | end 54 | 55 | % Main function 56 | if useMex == 1 57 | %warpSeg = warpMex( gT, analogue, useP ); 58 | warpSeg = warpMexFull2( gT, analogue ); 59 | %warpSeg = warpMexFullNoMask( gT, analogue ); 60 | else 61 | warpSeg = warp( gT, analogue ); 62 | end 63 | 64 | err = voxelErr( seg, warpSeg ); 65 | 66 | end 67 | 68 | -------------------------------------------------------------------------------- /auxiliaryMethods/writeKnossosConf.m: -------------------------------------------------------------------------------- 1 | function writeKnossosConf( savePath, expName, boundary, scale, magnification) 2 | %writeKnossosConf( savePath, expName, boundary, scale, magnification ) 3 | % Write KNOSSOS configuration file 4 | fid = fopen(fullfile(savePath, 'knossos.conf'), 'w'); 5 | if fid==-1 6 | warning(['Could not write ' fullfile(savePath, 'knossos.conf')]) 7 | else 8 | fprintf(fid, 'experiment name "%s";\n', expName); 9 | fprintf(fid, 'boundary x %i;\n', boundary(1)); 10 | fprintf(fid, 'boundary y %i;\n', boundary(2)); 11 | fprintf(fid, 'boundary z %i;\n', boundary(3)); 12 | fprintf(fid, 'scale x %4.2f;\n', scale(1)); 13 | fprintf(fid, 'scale y %4.2f;\n', scale(2)); 14 | fprintf(fid, 'scale z %4.2f;\n', scale(3)); 15 | fprintf(fid, 'magnification %i;\n', magnification); 16 | fclose(fid); 17 | end 18 | end -------------------------------------------------------------------------------- /cortex/CNN/.gitignore: -------------------------------------------------------------------------------- 1 | *.asv 2 | *.m~ 3 | *.mexa64 4 | *.swp 5 | 6 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/bwdPass3D.m: -------------------------------------------------------------------------------- 1 | function [sensitivity, lossSum] = bwdPass3D(cnet, activity, activityWithoutNL, target) 2 | % Backward pass of error through network 3 | 4 | % Initalize 5 | sensitivity = cell(cnet.numLayer,max(cnet.numFeature)); 6 | % Calculate error & loss mask in case area not annotated 7 | diff = (activity{cnet.numLayer,1}-target).*(target ~= 0); 8 | loss = cnet.lossFunction(diff); 9 | % Sum up for saving purposes 10 | lossSum = sum(loss(:)); 11 | % Do bwdPass wrt to loss Function 12 | sensitivity{cnet.numLayer,1} = cnet.nonLinearityD(activityWithoutNL{cnet.numLayer,1}).*cnet.lossFunctionD(diff); 13 | 14 | % Loop backwards 15 | for layer=cnet.numLayer:-1:3 16 | for prevFm=1:cnet.layer{layer-1}.numFeature 17 | sensitivity{layer-1,prevFm} = zeros(size(activity{layer-1,prevFm}), class(target)); 18 | for fm=1:cnet.layer{layer}.numFeature 19 | sensitivity{layer-1,prevFm} = sensitivity{layer-1,prevFm} + convn(sensitivity{layer,fm}, cnet.flipdims(cnet.layer{layer}.W{prevFm,fm})); 20 | end 21 | sensitivity{layer-1,prevFm} = sensitivity{layer-1,prevFm}.*cnet.nonLinearityD(activityWithoutNL{layer-1,prevFm}); 22 | end 23 | end 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/flipdims.m: -------------------------------------------------------------------------------- 1 | function Y = flipdims(~, X) 2 | %flips all dims of X 3 | Y=reshape(X(end:-1:1),size(X)); 4 | end 5 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/forWeights.m: -------------------------------------------------------------------------------- 1 | function [ cnet ] = forWeights( cnet,f ) 2 | % Apply a function to all free/learned parameters of the CNN 3 | 4 | % Weights 5 | for i=2:cnet.numLayer 6 | for j=1:cnet.layer{i-1}.numFeature 7 | for k=1:cnet.layer{i}.numFeature 8 | cnet.layer{i}.W{j,k} = f(cnet.layer{i}.W{j,k}); 9 | end 10 | end 11 | end 12 | 13 | % Biases 14 | for i=2:cnet.numLayer 15 | cnet.layer{i}.B = f(cnet.layer{i}.B); 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/fwdPass3D.m: -------------------------------------------------------------------------------- 1 | function [activity, activityWithoutNL] = fwdPass3D(cnet, input) 2 | % Forward Pass for network training 3 | 4 | % Initalize cell arrays & put input in first layer 5 | activity = cell(cnet.numLayer, max(cnet.numFeature)); 6 | activityWithoutNL = cell(cnet.numLayer, max(cnet.numFeature)); 7 | activity{1,1}= input; 8 | % Iterate over layers 9 | for layer=2:cnet.numLayer 10 | for fm=1:cnet.layer{layer}.numFeature 11 | % Initalize feature map with zeros 12 | activityWithoutNL{layer,fm} = zeros(size(input) - (layer - 1) * (cnet.filterSize - 1), class(input)); 13 | % Apply weights (all-to-all to previous layer) 14 | for prevFm=1:cnet.layer{layer-1}.numFeature 15 | activityWithoutNL{layer, fm} = activityWithoutNL{layer, fm} + convn(activity{layer-1, prevFm}, cnet.layer{layer}.W{prevFm,fm}, 'valid'); 16 | end 17 | % Apply biases 18 | activityWithoutNL{layer,fm} = activityWithoutNL{layer,fm} + cnet.layer{layer}.B(fm); 19 | % Apply nonlinearities 20 | activity{layer, fm} = cnet.nonLinearity(activityWithoutNL{layer, fm}); 21 | end 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/fwdPass3DonKhierachy.m: -------------------------------------------------------------------------------- 1 | function fwdPass3DonKhierachy(cnet, input, result, bbox) 2 | % Forward pass only directly on KNOSSOS Hierachy 3 | 4 | % Load data with right border for cnet to produce output at 'bbox' 5 | bboxWithBorder(:,1) = bbox(:,1) - ceil(cnet.randOfConvn'/2); 6 | bboxWithBorder(:,2) = bbox(:,2) + ceil(cnet.randOfConvn'/2); 7 | raw = readKnossosRoi(input.root, input.prefix, bboxWithBorder); 8 | % Normalize data 9 | if cnet.normalize 10 | raw = normalizeStack(single(raw)); 11 | else 12 | raw = single(raw); 13 | end 14 | % Memory efficent fwd pass 15 | class = onlyFwdPass3D(cnet, raw); 16 | % Save result to KNOSSOS folder 17 | writeKnossosRoi(result.root, result.prefix, bbox(:,1)', single(class), 'single'); 18 | 19 | end 20 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/gradientPass.m: -------------------------------------------------------------------------------- 1 | function gradient = gradientPass(cnet, activity, sensitivity) 2 | % Calculate gradient from result fwdPass and bwdPass 3 | 4 | for layer=2:cnet.numLayer 5 | for prevFm=1:cnet.layer{layer-1}.numFeature 6 | for fm=1:cnet.layer{layer}.numFeature 7 | gradient.layer{layer}.W{prevFm,fm} = cnet.run.saveClass(cnet.flipdims(convn(activity{layer-1,prevFm}, cnet.flipdims(sensitivity{layer,fm}), 'valid'))); 8 | end 9 | end 10 | gradient.layer{layer}.B = zeros(1,cnet.layer{layer}.numFeature); 11 | for fm=1:cnet.layer{layer}.numFeature 12 | gradient.layer{layer}.B(fm) = cnet.run.saveClass(sum(sensitivity{layer,fm}(:))); 13 | end 14 | end 15 | 16 | end 17 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/learn.m: -------------------------------------------------------------------------------- 1 | function learn( cnet, stacks ) 2 | % Learns weights of cnet according to stacks 3 | 4 | % This is abundant in this code, always use before/after using GPUs -> Jacket Bug? 5 | clear gpu_hook; 6 | 7 | % Set Matlab RNG to random state (random values will be saved with CNN) 8 | rng('shuffle'); 9 | 10 | w = getCurrentWorker(); 11 | if ~isempty(w) 12 | w = w.Name; 13 | gselect(str2double(w(16:17))); 14 | end 15 | 16 | % Check whether directory exsist and create otherwise 17 | if ~exist(fullfile(cnet.run.savingPath),'dir') 18 | mkdir(fullfile(cnet.run.savingPath)); 19 | end 20 | 21 | % Load all training cubes into array (assumes 100^3 stacks so far) 22 | % Keep in memory (RAM of CPU, takes ~14.5 GB) for decresed I/O 23 | sizeRaw = [100 100 100] + cnet.randOfConvn; 24 | borderRaw = ([100 100 50] - cnet.randOfConvn)/2; 25 | cubeRaw = zeros(sizeRaw(1), sizeRaw(2), sizeRaw(3), length(stacks)); 26 | cubeTarget = zeros(100, 100, 100, length(stacks)); 27 | for i=1:length(stacks) 28 | load(stacks(i).targetFile); 29 | if cnet.normalize 30 | cubeRaw(:,:,:,i) = normalizeStack(single(raw(1+borderRaw(1):end-borderRaw(1),1+borderRaw(2):end-borderRaw(2),1+borderRaw(3):end-borderRaw(3)))); 31 | else 32 | cubeRaw(:,:,:,i) = single(raw(1+borderRaw(1):end-borderRaw(1),1+borderRaw(2):end-borderRaw(2),1+borderRaw(3):end-borderRaw(3))); 33 | end 34 | cubeTarget(:,:,:,i) = single(target); 35 | end 36 | 37 | for iid=1:cnet.run.maxIter 38 | % Get random stack, permutation (of x,y only due to anisotropy) & 39 | random.idx = randi(length(stacks),1); 40 | random.permutation = randperm(2); 41 | random.flipdimensions = randi(2, 1, 3) - 1; 42 | % Cast stacks and CNN to GPU 43 | raw = cnet.run.actvtClass(cubeRaw(:,:,:,random.idx)); 44 | target = cnet.run.actvtClass(cubeTarget(:,:,:,random.idx)); 45 | cnetGPU = cnet.forWeights(cnet.run.actvtClass); 46 | % Randomly permute x & y dimension and randomly flip all dimensions 47 | raw = permute(raw, [random.permutation 3]); 48 | target = permute(target, [random.permutation 3]); 49 | for i=1:3 50 | if random.flipdimensions(i) 51 | raw = flipdim(raw, i); 52 | target = flipdim(target, i); 53 | end 54 | end 55 | % Pass raw data through CNN 56 | [activity, activityWithoutNL] = cnetGPU.fwdPass3D(raw); 57 | % Find sensitivity of output on weights 58 | [sensitivity, err] = cnetGPU.bwdPass3D(activity, activityWithoutNL, target); 59 | err = cnet.run.saveClass(err); 60 | % Compute gradient updates 61 | gradient = cnetGPU.gradientPass(activity, sensitivity); 62 | % Update paramaters (stochastic batch gradient descent) 63 | cnet = cnet.sgd(gradient); 64 | % Save data if debug flag is on, otherwise just cnet, error and random 65 | % values 66 | if cnet.run.debug 67 | save(fullfile(cnet.run.savingPath,[ 'debug' num2str(iid, '%010.0f') '.mat'])); 68 | system(['chmod 664 ' fullfile(cnet.run.savingPath,[ 'debug' num2str(iid, '%010.0f') '.mat'])]); 69 | display(num2str(err)); 70 | end 71 | save(fullfile(cnet.run.savingPath,[ 'saveNet' num2str(iid, '%010.0f') '.mat']), 'cnet', 'err', 'random'); 72 | system(['chmod 664 ' fullfile(cnet.run.savingPath,[ 'saveNet' num2str(iid, '%010.0f') '.mat'])]); 73 | clear cnetGPU raw target activity activityWithoutNL sensitivity; 74 | clear gpu_hook; 75 | end 76 | 77 | end 78 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/loadLastCNN.m: -------------------------------------------------------------------------------- 1 | function cnet = loadLastCNN( cnet ) 2 | % Load last saved CNN (useful if e.g. CNN got trained over jobmanager and 3 | % direct pointer to CNN is therfore not availible 4 | 5 | if exist(cnet.run.savingPath, 'dir') 6 | files = dir([cnet.run.savingPath '*.mat']); 7 | if isempty(files) 8 | warning(['No CNN found: ' cnet.run.savingPath]); 9 | else 10 | idx = length(files); 11 | while true 12 | try 13 | a = load([cnet.run.savingPath files(idx).name]); 14 | cnet = a.cnet; 15 | break; 16 | catch 17 | warning(['Corrupt file: ' cnet.run.savingPath files(idx).name]); 18 | idx = idx - 1; 19 | if idx == 0 20 | break; 21 | end 22 | end 23 | end 24 | end 25 | else 26 | warning(['Directory does not exist: ' cnet.run.savingPath]); 27 | end 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/loadResults.m: -------------------------------------------------------------------------------- 1 | function [results, nrIter] = loadResults(cnet) 2 | % Load all results (errors etc. from a CNN training) 3 | 4 | files = dir([cnet.run.savingPath 'saveNet*']); 5 | nrIter = length(files); 6 | if nrIter == 0 7 | results = struct(); 8 | warning('Empty results'); 9 | else 10 | for i=1:nrIter 11 | currentSave = load([cnet.run.savingPath files(i).name]); 12 | if any(strcmp(fieldnames(currentSave), 'error')); 13 | for j=1:length(currentSave.error) 14 | results.err(length(currentSave.error)*(i-1)+j) = currentSave.error{j}.all; 15 | end 16 | else 17 | results.err(i) = currentSave.err; 18 | results.idx(i) = currentSave.random.idx; 19 | results.flipdimensions(i,:) = currentSave.random.flipdimensions; 20 | results.permutation(i,:) = currentSave.random.permutation; 21 | end 22 | end 23 | end 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/onlyFwdPass3D.m: -------------------------------------------------------------------------------- 1 | function result = onlyFwdPass3D(cnet, input) 2 | % Fwd Pass only returining output, not intermediate activities in network 3 | 4 | % Load data with right border for cnet 5 | clear gpu_hook; 6 | cnet = cnet.forWeights(cnet.run.actvtClass); 7 | activity = cell(cnet.numLayer, max(cnet.numFeature)); 8 | activity{1,1} = cnet.run.actvtClass(input); 9 | % DO the THING (see fwdPass.m without keeping intermediates) 10 | layer = 2; 11 | while size(activity,1) > 1 12 | for fm=1:cnet.layer{layer}.numFeature 13 | activity{2,fm} = zeros(size(activity{1,1}) - cnet.filterSize + [1 1 1], class(activity{1,1})); 14 | for oldFm=1:cnet.layer{layer-1}.numFeature 15 | activity{2, fm} = activity{2, fm} + convn(activity{1, oldFm}, cnet.layer{layer}.W{oldFm,fm}, 'valid'); 16 | end 17 | activity{2, fm} = cnet.nonLinearity(activity{2, fm} + cnet.layer{layer}.B(fm)); 18 | end 19 | activity(1,:) = []; 20 | layer = layer + 1; 21 | end 22 | % Pass on result 23 | result = single(activity{1,1}); 24 | clear gpu_hook; 25 | 26 | end 27 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/plotNetActivities.m: -------------------------------------------------------------------------------- 1 | function plotNetActivities( cnet, stacks ) 2 | % Visualize transformation by net (e.g. input, output, target) 3 | 4 | % Set stack to classify 5 | stackNr = 1; 6 | % Load cubes into array 7 | load(stacks(stackNr).targetFile); 8 | borderRaw = ([100 100 50] - cnet.randOfConvn)/2; 9 | if cnet.normalize 10 | raw = normalizeStack(single(raw(1+borderRaw(1):end-borderRaw(1),1+borderRaw(2):end-borderRaw(2),1+borderRaw(3):end-borderRaw(3))));; 11 | else 12 | raw = single(raw); 13 | end 14 | target = single(target); 15 | 16 | % Run fwdPass 17 | activity = cnet.onlyFwdPass3D(raw); 18 | 19 | % Plot final + target*mask + raw 20 | figure('Visible', 'off'); 21 | colormap('gray'); 22 | a = size(raw); 23 | subplot(1,3,1); 24 | imagesc(raw(1+cnet.randOfConvn(1)/2:end-cnet.randOfConvn(1)/2,1+cnet.randOfConvn(2)/2:end-cnet.randOfConvn(2)/2,cnet.randOfConvn(3)/2+50)); 25 | axis equal; 26 | axis off; 27 | if cnet.normalize 28 | caxis([-3 3]); 29 | else 30 | caxis([40 210]); 31 | end 32 | title('Raw'); 33 | 34 | subplot(1,3,2); 35 | imagesc(activity(:,:,50)); 36 | axis equal; 37 | axis off; 38 | caxis([-1.7, 1.7]); 39 | title('Affinity'); 40 | 41 | subplot(1,3,3); 42 | imagesc(target(:,:,50)); 43 | axis equal; 44 | axis off; 45 | caxis([-1.7 1.7]); 46 | title('Target'); 47 | 48 | if ~exist(cnet.run.savingPath, 'dir'); 49 | mkdir(cnet.run.savingPath); 50 | system(['chmod -R 770 ' cnet.run.savingPath]); 51 | end 52 | 53 | saveas(gcf, [cnet.run.savingPath 'netActivity.fig']); 54 | saveas(gcf, [cnet.run.savingPath 'netActivity.pdf']); 55 | system(['chmod -R 770 ' cnet.run.savingPath]); 56 | close all; 57 | 58 | end 59 | 60 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/plotNetActivitiesFull.m: -------------------------------------------------------------------------------- 1 | function plotNetActivitiesFull( cnet, stacks ) 2 | % Plot activities in all layers 3 | 4 | % Set stack to classify 5 | stackNr = 1; 6 | % Load cubes into array 7 | load(stacks(stackNr).targetFile); 8 | borderRaw = ([100 100 50] - cnet.randOfConvn)/2; 9 | if cnet.normalize 10 | raw = normalizeStack(single(raw(1+borderRaw(1):end-borderRaw(1),1+borderRaw(2):end-borderRaw(2),1+borderRaw(3):end-borderRaw(3))));; 11 | else 12 | raw = single(raw); 13 | end 14 | 15 | % Run fwdPass 16 | activity = cnet.fwdPass3D(raw); 17 | 18 | % Plot final + target*mask + raw 19 | figure('Visible', 'off'); 20 | colormap('gray'); 21 | a = size(raw); 22 | for i=1:size(activity,1); 23 | for j=1:size(activity,2) 24 | if ~isempty(activity{i,j}); 25 | subplot(size(activity,2),size(activity,1),i+size(activity,1)*(j-1)); 26 | imagesc(activity{i,j}(1+(6-i)*(cnet.filterSize(1)-1)/2:end-(6-i)*(cnet.filterSize(1)-1)/2, ... % quick hack, replace 6 by size(sth) if different from 4 hidden layers 27 | 1+(6-i)*(cnet.filterSize(2)-1)/2:end-(6-i)*(cnet.filterSize(2)-1)/2,(6-i)*(cnet.filterSize(3)-1)/2+50)); 28 | axis equal; 29 | axis off; 30 | caxis([-1.7 1.7]); 31 | end 32 | end 33 | end 34 | 35 | if ~exist(cnet.run.savingPath, 'dir'); 36 | mkdir(cnet.run.savingPath); 37 | system(['chmod -R 770 ' cnet.run.savingPath]); 38 | end 39 | 40 | saveas(gcf, [cnet.run.savingPath 'netActivityFull.fig']); 41 | saveas(gcf, [cnet.run.savingPath 'netActivityFull.pdf']); 42 | system(['chmod -R 770 ' cnet.run.savingPath]); 43 | close all; 44 | 45 | end 46 | 47 | -------------------------------------------------------------------------------- /cortex/CNN/@cnn/sgd.m: -------------------------------------------------------------------------------- 1 | function cnet = sgd(cnet, gradient) 2 | % Update cnet according to gradient 3 | 4 | for layer=2:cnet.numLayer 5 | if cnet.run.linearRate 6 | [etaW, etaB] = cnet.run.linearLearn(layer-1); % -1 due to first layer having no parameters 7 | else 8 | [etaW, etaB] = cnet.run.expLearn(layer-1); 9 | end 10 | if cnet.normalizeLearningRates 11 | etaW = etaW ./ prod(cnet.run.outputSize); 12 | etaB = etaB ./ prod(cnet.run.outputSize); 13 | end 14 | for prevFm=1:cnet.layer{layer-1}.numFeature 15 | for fm=1:cnet.layer{layer}.numFeature 16 | cnet.layer{layer}.W{prevFm,fm} = cnet.layer{layer}.W{prevFm,fm} - etaW.*gradient.layer{layer}.W{prevFm,fm}; 17 | end 18 | end 19 | cnet.layer{layer}.B = cnet.layer{layer}.B - etaB.*gradient.layer{layer}.B; 20 | end 21 | 22 | -------------------------------------------------------------------------------- /cortex/CNN/@train/expLearn.m: -------------------------------------------------------------------------------- 1 | function [currentW, currentB] = expLearn(obj,layer) 2 | % factor 6.9 to have 1 promille of starting values at the end of training 3 | currentW = obj.wStart(layer)*exp(-6.9*obj.iterations/obj.maxIter); 4 | currentB = obj.bStart(layer)*exp(-6.9*obj.iterations/obj.maxIter); 5 | end 6 | 7 | -------------------------------------------------------------------------------- /cortex/CNN/@train/linearLearn.m: -------------------------------------------------------------------------------- 1 | function [currentW, currentB] = linearLearn(obj,layer) 2 | % Learning rate will decay to zero in linear fasion 3 | currentW = obj.wStart(layer)-obj.wStart(layer)*obj.iterations/obj.maxIter; 4 | currentB = obj.bStart(layer)-obj.bStart(layer)*obj.iterations/obj.maxIter; 5 | end 6 | -------------------------------------------------------------------------------- /cortex/CNN/@train/train.m: -------------------------------------------------------------------------------- 1 | classdef train 2 | %TRAIN class representing a training run for a CNN 3 | % Input to constructor 4 | % outputSize - size of output size after CNN application 5 | % savingPath - Folder for saving data generated during trainGradient 6 | % maxIter - max number of batch iterations 7 | % wStart - Inital value for learning rate weights (for each layer) 8 | % bStart - Inital value for learning rate biases (for each layer) 9 | 10 | properties 11 | % Parameter initalized in constructor 12 | outputSize 13 | savingPath 14 | maxIter 15 | wStart 16 | bStart 17 | % Parameter with default value 18 | iterations = 0; 19 | saveClass = @single; 20 | actvtClass = @gsingle; 21 | debug = false; 22 | linearRate = true; 23 | end 24 | methods 25 | % For additional methods (weight decay) see class folder (@train) 26 | function obj = train(varargin) 27 | if(nargin~=0) 28 | obj.outputSize = varargin{1}; 29 | obj.savingPath = varargin{2}; 30 | obj.maxIter = varargin{3}; 31 | obj.wStart = varargin{4}; 32 | obj.bStart = varargin{5}; 33 | end 34 | end 35 | end 36 | end 37 | 38 | -------------------------------------------------------------------------------- /cortex/CNN/cnnStart.m: -------------------------------------------------------------------------------- 1 | %% Example usage of CNN class 2 | % This file shows basic usage of a 3D-convolutional neural network 3 | 4 | %% Load raw and trace data 5 | stackFolder = [dataDirectory 'onlineMaterial' filesep 'extracted' filesep]; 6 | load([stackFolder filesep 'parameter.mat']); 7 | clear settings; 8 | 9 | %% Fix metadata of stacks for use with new data location 10 | for i=1:length(stacks) 11 | stacks(i).targetFile = strrep(stacks(i).targetFile, ... 12 | '/zdata/manuel/data/cortex/20130919T033350/', stackFolder); 13 | stacks(i).targetFile = strrep(stacks(i).targetFile, '/', filesep); 14 | stacks(i).stackFile = strrep(stacks(i).stackFile, ... 15 | '/zdata/manuel/data/cortex/20130919T033350/', stackFolder); 16 | stacks(i).stackFile = strrep(stacks(i).stackFile, '/', filesep); 17 | end 18 | clear stackFolder i; 19 | 20 | %% visualize some (arbitrary) stack 21 | stackNr = 1; 22 | load(stacks(stackNr).stackFile); 23 | load(stacks(stackNr).targetFile); 24 | makeSegMovie(stack, raw(51:150,51:150,26:125), [outputDirectory filesep 'stackVideo.avi']); 25 | makeIsosurfaceView(stack, raw(51:150,51:150,26:125), [outputDirectory filesep 'stackView.png']); 26 | 27 | %% Set up class objects 28 | runSetting = train([100 100 100], [outputDirectory filesep 'CNNdebug' filesep], ... 29 | 1e4, [1e-6 1e-6 1e-6 1e-6 1e-6], [1e-8 1e-8 1e-8 1e-8 1e-8]); 30 | % Produce more ouput 31 | runSetting.debug = true; 32 | % Run on GPU, set to runSetting.actvtClass = @single in case of errors; 33 | % (you can try setting this to gpuarray (MATLAB) or gsingle (Accelereyes JACKET)) 34 | % Requires Nvidia GPU and CUDA > 4.0 (?) 35 | if gpuDeviceCount > 1 36 | runSetting.actvtClass = @gpuArray; 37 | else 38 | runSetting.actvtClass = @single; 39 | end 40 | cnet = cnn(4,[10 10 10 10],[21 21 11], runSetting); 41 | cnet = cnet.init; 42 | clear runSetting; 43 | 44 | %% Train CNN 45 | cnet.learn(stacks); 46 | 47 | %% Plot CNN activity (if not trained for long/not at all activity should be gray with little variations in most layers) 48 | cnet.plotNetActivities(stacks); 49 | cnet.plotNetActivitiesFull(stacks); 50 | 51 | %% Load and visualize a trained CNN: 52 | load([dataDirectory filesep 'supplement' filesep 'extracted' filesep 'cortex - CNN20130516T204040_8_3.mat']); 53 | cnet.run.savingPath = strrep(cnet.run.savingPath, ... 54 | '/zdata/manuel/results/parameterSearch/20130516T204040/iter08/gpu03/', [outputDirectory filesep 'trainedCNN' filesep]); 55 | if gpuDeviceCount > 1 56 | cnet.run.actvtClass = @gpuArray; 57 | else 58 | cnet.run.actvtClass = @single; 59 | end 60 | cnet.plotNetActivities(stacks); 61 | cnet.plotNetActivitiesFull(stacks); 62 | -------------------------------------------------------------------------------- /cortex/CNN/evolution/cnnParameterSelection.m: -------------------------------------------------------------------------------- 1 | %% Example usage of CNN hyperparameter automated selection 2 | % This file shows basic usage of learning rate hyperparameter optimization 3 | % If parameter search is running it will print status each hour to the command line 4 | % and output visualization(s) to saveFolder every 24h 5 | stackFolder = [dataDirectory 'onlineMaterial' filesep 'extracted' filesep]; 6 | saveFolder = [outputDirectory filesep 'CNNparameterSearch']; 7 | 8 | %% Load stacks and remove soma stacks & stacks with errors 9 | load([stackFolder filesep 'parameter.mat']); 10 | load([stackFolder filesep 'exclude.mat']); 11 | stacks = removeSomaStacks(stacks, excludeTask); 12 | clear settings excludeTask; 13 | 14 | %% Fix metadata of stacks for use with new data location 15 | for i=1:length(stacks) 16 | stacks(i).targetFile = strrep(stacks(i).targetFile, ... 17 | '/zdata/manuel/data/cortex/20130919T033350/', stackFolder); 18 | stacks(i).targetFile = strrep(stacks(i).targetFile, '/', filesep); 19 | stacks(i).stackFile = strrep(stacks(i).stackFile, ... 20 | '/zdata/manuel/directory/data/cortex/20130919T033350/', stackFolder); 21 | stacks(i).stackFile = strrep(stacks(i).stackFile, '/', filesep); 22 | end 23 | clear stackFolder i; 24 | 25 | %% Settings for parameter search 26 | 27 | % General settings 28 | hyper.gpuToUse = 28; % GPUs used for each iteration; has to be multiple of nrNetsToKeep 29 | hyper.iterations = 28; % iterations of randomization & selection procedure 30 | hyper.timeEachIteration = 24; % in hours 31 | hyper.nrNetsToKeep = 14; % after each iteration 32 | 33 | % Save location 34 | hyper.start = datestr(clock, 30); 35 | hyper.saveDir = [saveFolder filesep hyper.start filesep]; 36 | if ~exist(hyper.saveDir, 'dir') 37 | mkdir(hyper.saveDir); 38 | end 39 | 40 | % Settings for metaparameter variation 41 | % 10^param(1) = Range for weight variation 42 | % 10^param(2) = Range for bias variation 43 | hyper.param(1).min = -10; 44 | hyper.param(1).max = -9; 45 | hyper.param(1).nr = 5; % individual learning rate for each layer 46 | hyper.param(2).min = -10; 47 | hyper.param(2).max = -9; 48 | hyper.param(2).nr = 5; 49 | 50 | %% Search hyperparameter (for CNN architecture see file) 51 | parameterSearch(hyper, stacks); 52 | 53 | %% In case something goes wrong, continue after a specific iteration 54 | continueParameterSearch(hyper, stacks, 3); 55 | -------------------------------------------------------------------------------- /cortex/CNN/evolution/getResults.m: -------------------------------------------------------------------------------- 1 | function results = getResults(cnets) 2 | 3 | for i=1:length(cnets) 4 | cnet = cnets(i).loadLastCNN; 5 | temp = cnet.loadResults; 6 | if ~isempty(fieldnames(temp)) 7 | results.data(i) = temp; 8 | end 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /cortex/CNN/evolution/plotError.m: -------------------------------------------------------------------------------- 1 | function plotError(data, savingDir, iter) 2 | 3 | if ~exist(savingDir, 'dir'); 4 | mkdir(savingDir); 5 | system(['chmod -R 770 ' savingDir]); 6 | end 7 | 8 | colors = {'k' 'g' 'r' 'b' 'y' 'c' 'm'}; 9 | figure('Visible', 'off'); 10 | for gpu=1:length(data) 11 | plot(data(gpu).err, ['x' colors{mod(gpu,7) + 1}], 'LineWidth', 2); 12 | hold on; 13 | legendString{gpu} = ['GPU: ' num2str(gpu, '%2i')]; 14 | end 15 | title(['Error during iteration' num2str(iter, '%.2i')]); 16 | legend(legendString); 17 | 18 | saveas(gcf,[savingDir 'errorRates' num2str(iter, '%.2i') '.fig']); 19 | saveas(gcf,[savingDir 'errorRates' num2str(iter, '%.2i') '.png']); 20 | system(['chmod -R 770 ' savingDir]); 21 | end 22 | -------------------------------------------------------------------------------- /cortex/CNN/evolution/plotErrorBinned.m: -------------------------------------------------------------------------------- 1 | function plotErrorBinned(data, savingDir, iter) 2 | 3 | if ~exist(savingDir, 'dir'); 4 | mkdir(savingDir); 5 | system(['chmod -R 770 ' savingDir]); 6 | end 7 | 8 | figure('Visible', 'off'); 9 | for gpu=1:length(data) 10 | if ~isempty(data(gpu).err) 11 | meanVal(gpu) = mean(data(gpu).err); 12 | minVal(gpu) = min(data(gpu).err); 13 | maxVal(gpu) = max(data(gpu).err); 14 | end 15 | end 16 | errorbar([1:length(meanVal)],meanVal,minVal,maxVal); 17 | title(['Error during iteration' num2str(iter, '%.2i') 'sorted by GPU']); 18 | 19 | saveas(gcf,[savingDir 'errorRatesGPU' num2str(iter, '%.2i') '.fig']); 20 | saveas(gcf,[savingDir 'errorRatesGPU' num2str(iter, '%.2i') '.png']); 21 | system(['chmod -R 770 ' savingDir]); 22 | end 23 | -------------------------------------------------------------------------------- /cortex/CNN/evolution/plotErrorResorted.m: -------------------------------------------------------------------------------- 1 | function plotErrorResorted(data, savingDir, iter) 2 | 3 | if ~exist(savingDir, 'dir'); 4 | mkdir(savingDir); 5 | end 6 | 7 | figure('Visible', 'off'); 8 | maxMinibatchId = max([data(:).idx]); 9 | collector = cell(length(data),maxMinibatchId); 10 | for gpu=1:length(data) 11 | [val, idx] = sort(data(gpu).idx); 12 | for i=1:length(val) 13 | collector{gpu, val(i)} = [collector{gpu, val(i)} mean(data(gpu).err(idx(i)))]; 14 | end 15 | end 16 | for i=1:maxMinibatchId 17 | a.mean(i) = mean([collector{:,i}]); 18 | a.lower(i) = min([collector{:,i}]); 19 | a.upper(i) = max([collector{:,i}]); 20 | end 21 | errorbar(1:maxMinibatchId, a.mean, a.lower, a.upper); 22 | title(['Error sorted according to minibatch for iteration ' num2str(iter, '%.2i')]); 23 | saveas(gcf,[savingDir 'errorRateMinibatches' num2str(iter, '%.2i') '.fig']); 24 | saveas(gcf,[savingDir 'errorRateMinibatches' num2str(iter, '%.2i') '.png']); 25 | 26 | end 27 | -------------------------------------------------------------------------------- /cortex/CNN/evolution/plotResults.m: -------------------------------------------------------------------------------- 1 | function plotResults(hyper, stacks, iter) 2 | 3 | % Save to sync for ease of transfer & visualization 4 | hyper.saveDir = strrep(hyper.saveDir, 'results', 'sync'); 5 | 6 | % Start plot of all net activities on CPU jobmanger 7 | for i=1:hyper.gpuToUse 8 | hyper.cnet(iter,i) = hyper.cnet(iter,i).loadLastCNN; 9 | hyper.cnet(iter,i).run.savingPath = strrep(hyper.cnet(iter,i).run.savingPath, 'results', 'sync'); 10 | startCPU(@plotNetActivities, {hyper.cnet(iter,i), stacks}); 11 | startCPU(@plotNetActivitiesFull, {hyper.cnet(iter,i), stacks}); 12 | end 13 | 14 | % Plot error plots 15 | startCPU(@plotError, {hyper.results{iter}.data, hyper.saveDir, iter}); 16 | startCPU(@plotErrorBinned, {hyper.results{iter}.data, hyper.saveDir iter}); 17 | startCPU(@plotErrorResorted, {hyper.results{iter}.data, hyper.saveDir, iter}); 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /cortex/CNN/evolution/removeSomaStacks.m: -------------------------------------------------------------------------------- 1 | function stacks = removeSomaStacks(stacks, excludeTask) 2 | 3 | for i=1:length(excludeTask) 4 | idx = [stacks.taskID] == excludeTask(i); 5 | stacks(idx) = []; 6 | end 7 | 8 | end 9 | -------------------------------------------------------------------------------- /cortex/CNN/evolution/selectBestPerformers.m: -------------------------------------------------------------------------------- 1 | function hyper = selectBestPerformers(hyper, iter) 2 | minibatchesEvaluated = 200; 3 | 4 | for gpu=1:length(hyper.results{iter}.data) 5 | nrEval = length(hyper.results{iter}.data(gpu).err); 6 | start = nrEval - minibatchesEvaluated + 1; 7 | if start >= 1 8 | score(gpu) = mean(hyper.results{iter}.data(gpu).err((end - minibatchesEvaluated + 1):end)); 9 | else 10 | score(gpu) = mean(hyper.results{iter}.data(gpu).err(1:end)); 11 | end 12 | end 13 | for winner=1:hyper.nrNetsToKeep 14 | [val, idx] = min(score); 15 | hyper.results{iter}.win(winner).val = val; 16 | hyper.results{iter}.win(winner).idx = idx; 17 | score(idx) = Inf; 18 | end 19 | 20 | end 21 | -------------------------------------------------------------------------------- /cortex/CNN/normalizeStack.m: -------------------------------------------------------------------------------- 1 | function out = normalizeStack( in ) 2 | %out = normalizeStack( in ) Subtract mean and devide by std 3 | out = in-122; 4 | out = out/22; 5 | end 6 | 7 | -------------------------------------------------------------------------------- /cortex/metrics07x2/convertTestSetFromKLEETracingToLabelmatrix.m: -------------------------------------------------------------------------------- 1 | function convertTestSetFromKLEETracingToLabelmatrix(settings) 2 | % For folder location see start of function, will probably need changes, 3 | % thres = cutoff in distance transform of labeled cells 4 | 5 | % Make directories 6 | if ~exist(settings.stackDir, 'dir') 7 | mkdir(settings.stackDir); 8 | end 9 | if ~exist(settings.targetDir, 'dir') 10 | mkdir(settings.targetDir); 11 | end 12 | 13 | % Locate KLEE files from database & analyze 14 | files = dir([settings.sourceDir '*.mat']); 15 | stacks = selectFiles(files); 16 | 17 | for i=1:length(stacks) 18 | display(['Processing stack ' num2str(i) '/' num2str(length(stacks))]); 19 | load([settings.sourceDir stacks(i).filename]); 20 | [stack, bbox] = convertKleeTracingToLocalStack( KLEE_savedTracing ); 21 | target = xyzMaskIntraExtra(stack,settings.cutoffDistance); 22 | bboxRaw = bbox + [-settings.border settings.border]; 23 | rawBig = readKnossosRoi(settings.rawDir, settings.rawPrefix, bboxRaw); 24 | raw = readKnossosRoi(settings.rawDir, settings.rawPrefix, bbox); 25 | save([settings.stackDir num2str(stacks(i).taskID) '.mat'], 'raw', 'stack'); 26 | save([settings.targetDir num2str(stacks(i).taskID) '.mat'], 'rawBig', 'target'); 27 | stacks(i).stackFile = [settings.stackDir num2str(stacks(i).taskID) '.mat']; 28 | stacks(i).targetFile = [settings.targetDir num2str(stacks(i).taskID) '.mat']; 29 | stacks(i).bbox = bbox; 30 | stacks(i).bboxRaw = bboxRaw; 31 | end 32 | 33 | % Save relevant meta information 34 | save(settings.metaFile, 'stacks', 'settings'); 35 | 36 | end 37 | 38 | -------------------------------------------------------------------------------- /cortex/metrics07x2/initalizationSchemeStatistics.m: -------------------------------------------------------------------------------- 1 | layers = [2 3 5 6]; 2 | titles = {'First CNN layer' 'Second CNN layer' 'Fifth CNN layer' 'Last CNN layer'}; 3 | xlabels = {'w_1_2', 'w_2_3', 'w_4_5', 'w_5_6'}; 4 | figure; 5 | for i = 1:4; 6 | layer = layers(i); 7 | subplot(4,1,i); 8 | % SegEM original 9 | cnet = cnn(4,[10 10 10 10], [10 10 10], train([10 10 10], '/home/mberning/', 1e6, 1e-2, 1e-2), 0, 0, 0, 1); 10 | cnet = cnet.init; 11 | weights = cat(4,cnet.layer{layer}.W{:}); 12 | allWeights(:,1) = weights(:); 13 | % SegEM fan-in 14 | cnet = cnn(4,[10 10 10 10], [10 10 10], train([10 10 10], '/home/mberning/', 1e6, 1e-2, 1e-2), 1, 0, 0, 1); 15 | cnet = cnet.init; 16 | weights = cat(4,cnet.layer{layer}.W{:}); 17 | allWeights(:,2) = weights(:); 18 | % SegEM fan-out 19 | cnet = cnn(4,[10 10 10 10], [10 10 10], train([10 10 10], '/home/mberning/', 1e6, 1e-2, 1e-2), 0, 1, 0, 1); 20 | cnet = cnet.init; 21 | weights = cat(4,cnet.layer{layer}.W{:}); 22 | allWeights(:,3) = weights(:); 23 | % SegEM He et al. 24 | cnet = cnn(4,[10 10 10 10], [10 10 10], train([10 10 10], '/home/mberning/', 1e6, 1e-2, 1e-2), 0, 0, 1, 1); 25 | cnet = cnet.init; 26 | weights = cat(4,cnet.layer{layer}.W{:}); 27 | allWeights(:,4) = weights(:); 28 | hist(allWeights, [-0.0395:0.001:0.0395]); 29 | legend('SegEM', 'fan-in', 'fan-out', 'He et al.'); 30 | title(titles{i}); 31 | xlabel(['value of ' xlabels{i}]); 32 | ylabel('# of weights'); 33 | clear allWeights; 34 | end -------------------------------------------------------------------------------- /cortex/metrics07x2/metricsISBIautomatedTraining.bsh: -------------------------------------------------------------------------------- 1 | import trainableSegmentation.metrics.*; 2 | import ij.IJ; 3 | import ij.measure.ResultsTable; 4 | import ij.plugin.filter.Analyzer; 5 | 6 | double[] params = new double[31]; 7 | double[] rErr = new double[31]; 8 | 9 | // should be some sort of linspace function in java? 10 | for ( int n = 0; n < params.length; n++) 11 | { 12 | params[n] = 0.55 + 0.01 * n; 13 | } 14 | 15 | originalLabels = IJ.openImage("Z:\\Data\\berningm\\20150205paper1submission\\onlineMaterial\\extracted\\testSet\\forFiji\\targetI1Up.tif"); 16 | originalLabels.show(); 17 | 18 | for ( int n = 0; n < params.length; n++ ) 19 | { 20 | filename = "Z:\\Data\\berningm\\20150205paper1submission\\onlineMaterial\\extracted\\testSet\\forFiji\\automated\\thres\\WS_th" + IJ.d2s(params[n], 2) + ".tif"; 21 | IJ.log(filename); 22 | 23 | proposedLabels = IJ.openImage( filename ); 24 | proposedLabels.show(); 25 | 26 | IJ.log("\nCalculating maximal F-score of the foreground-restricted Rand index..."); 27 | metric = new RandError( originalLabels, proposedLabels ); 28 | maxFScore = metric.getForegroundRestrictedRandIndexMaximalFScore( 0.0, 1.0, 0.1 ); 29 | IJ.log(" Minimum foreground-restricted Rand error: " + (1.0 - maxFScore) ); 30 | 31 | rErr[n] = 1.0 - maxFScore; 32 | 33 | proposedLabels.close(); 34 | } 35 | 36 | originalLabels.close(); 37 | 38 | // this for loop should not be necessaty either? how to log vector? 39 | for ( int n = 0; n < params.length; n++) 40 | { 41 | IJ.log(IJ.d2s(params[n],2) + "," + IJ.d2s(rErr[n],6)); 42 | } -------------------------------------------------------------------------------- /cortex/metrics07x2/tifWriteForISBI.m: -------------------------------------------------------------------------------- 1 | function tifWriteForISBI( imgdata, filename ) 2 | 3 | % Open file for writing 4 | tifFile = Tiff(filename, 'w'); 5 | 6 | % Settings for writing Tif (all necessary?) 7 | tagstruct.ImageLength = size(imgdata,1); 8 | tagstruct.ImageWidth = size(imgdata,2); 9 | tagstruct.Photometric = Tiff.Photometric.MinIsBlack; 10 | tagstruct.Compression = Tiff.Compression.None; 11 | tagstruct.BitsPerSample = 32; 12 | tagstruct.SamplesPerPixel = 1; 13 | tagstruct.SampleFormat = Tiff.SampleFormat.IEEEFP; 14 | tagstruct.RowsPerStrip = size(imgdata,1); 15 | tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky; 16 | 17 | for i=1:size(imgdata,3) 18 | tifFile.setTag(tagstruct); 19 | tifFile.write(imgdata(:,:,i)); 20 | tifFile.writeDirectory; 21 | end 22 | tifFile.close(); 23 | 24 | end 25 | 26 | -------------------------------------------------------------------------------- /cortex/metrics07x2/watershedSegMarkersHmin2D.m: -------------------------------------------------------------------------------- 1 | function markers = watershedSegMarkersHmin2D( aff, h, ao ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | affHmin= imhmin(aff, h, 4); 6 | bw1 = imregionalmin(affHmin, 4); 7 | markers = bwareaopen(bw1, ao, 4); 8 | 9 | end -------------------------------------------------------------------------------- /cortex/segmentation/correctSkeletonsToBBox_v2.m: -------------------------------------------------------------------------------- 1 | function skel = correctSkeletonsToBBox_v2( skel, sizeCube ) 2 | 3 | skelToDel = zeros(size(skel,2),1); 4 | allTooSmall = zeros(1,3); 5 | allTooBig = zeros(1,3); 6 | for l=1:size(skel,2) 7 | if isfield(skel{l}, 'nodesNumDataAll') && ~isempty(skel{l}.nodesNumDataAll) 8 | % Correct for skeletons running out of minicube, remove nodes 9 | tooSmall = skel{l}.nodesNumDataAll(:,3:5) < ones(size(skel{l}.nodesNumDataAll,1),3); 10 | tooBig = skel{l}.nodesNumDataAll(:,3:5) > repmat(sizeCube,size(skel{l}.nodesNumDataAll,1),1); 11 | toDel = any(tooSmall,2) | any(tooBig,2); 12 | if sum(tooSmall(:)) || sum(tooBig(:)) 13 | %display(['Nodes to be removed: ' num2str(sum(tooSmall,1)) ' too small, ' num2str(sum(tooBig,1)) ' too big.']); 14 | allTooSmall = allTooSmall + sum(tooSmall,1); 15 | allTooBig = allTooBig + sum(tooBig,1); 16 | end 17 | skel{l}.nodesNumDataAll(toDel,:) = []; 18 | skel{l}.nodes(toDel,:) = []; 19 | skel{l}.nodesAsStruct(toDel) = []; 20 | % ... remove edges accordingly 21 | if size(skel{l}.nodes,1) 22 | edgesToDel = find(toDel); 23 | edgeIdx = unique(skel{l}.edges(:)); 24 | for idx=1:length(edgesToDel) 25 | [row,~] = find(edgesToDel(idx) == skel{l}.edges); 26 | skel{l}.edges(row,:) = []; 27 | edgeIdx(edgeIdx == edgesToDel(idx)) = []; 28 | end 29 | edgeIdxNew = (1:length(edgeIdx))'; 30 | for idx=1:length(edgeIdxNew) 31 | renumber = skel{l}.edges == edgeIdx(idx); 32 | skel{l}.edges(renumber) = edgeIdxNew(idx); 33 | end 34 | else 35 | skelToDel(l) = 1; 36 | %display(['Skeleton ' num2str(l) ': empty after bbox cutoff']); 37 | end 38 | %if sum(toDel ~= 0) 39 | % display(['Skeleton ' num2str(l) ': ' num2str(sum(toDel)) ' nodes removed. ' num2str(size(skel{l}.nodes,1)) ' nodes remaining']); 40 | %end 41 | else 42 | skelToDel(l) = 1; 43 | end 44 | end 45 | 46 | display(['Nodes removed total for this tracing: ' num2str(allTooSmall) ' too small; ' num2str(allTooBig) ' too big.']); 47 | skel = skel(~skelToDel); 48 | 49 | end 50 | 51 | -------------------------------------------------------------------------------- /cortex/segmentation/equalizeSkeletons.m: -------------------------------------------------------------------------------- 1 | function skel = equalizeSkeletons(skel) 2 | 3 | % Determine skeleton with maximal inter-node distance 4 | interNodeDistance = calculateInterNodeDistance(skel); 5 | [maxVal, maxIdx] = max(interNodeDistance); 6 | toEqualize = setdiff(1:length(skel),maxIdx); 7 | 8 | % Actual equalization 9 | for i=1:length(toEqualize) 10 | % Downsample until other node distances are bigger 11 | while interNodeDistance(toEqualize(i)) < maxVal 12 | % Downsample 1% of nodes in each for loop 13 | for j=1:length(skel{toEqualize(i)}) 14 | r = rand(size(skel{toEqualize(i)}{j}.nodes,1),1); 15 | toDel = r < .01; 16 | if any(toDel) 17 | skel{toEqualize(i)}{j} = removeNodes(skel{toEqualize(i)}{j}, toDel); 18 | end 19 | end 20 | interNodeDistance(toEqualize(i)) = calculateInterNodeDistance(skel(toEqualize(i))); 21 | end 22 | end 23 | 24 | end 25 | 26 | function interNodeDistance = calculateInterNodeDistance(skel) 27 | % Calculates inter-node distance in (multiple) dense tracings with (multiple) trees each 28 | for i=1:length(skel) 29 | nrNodes = []; 30 | for j=1:length(skel{i}) 31 | nrNodes(j) = size(skel{i}{j}.nodes,1); 32 | end 33 | nodes(i) = sum(nrNodes); 34 | pathLength(i) = getPathLength(skel{i}); 35 | end 36 | interNodeDistance = pathLength./nodes; 37 | end 38 | 39 | function skel = removeNodes(skel, toDel) 40 | % Remove nodes from skeleton according to logical in 2nd Argument 41 | ids = 1:size(skel.nodes,1); 42 | skel.nodes(toDel,:) = []; 43 | skel.nodesNumDataAll(toDel,:) = []; 44 | skel.nodesAsStruct(toDel) = []; 45 | idsToDel = ids(toDel); 46 | idsToKeep = ids(~toDel); 47 | for ii=1:length(idsToDel) 48 | edgesToDel = skel.edges == idsToDel(ii); 49 | [row,col] = find(edgesToDel); 50 | col(col==2) = 0; 51 | col = col + 1; 52 | idsToJoin = skel.edges(row,col); 53 | idsToJoin = idsToJoin(:); 54 | idsToJoin(idsToJoin == idsToDel(ii)) = []; 55 | idsToJoin = unique(idsToJoin); 56 | skel.edges(row,:) = []; 57 | for j=2:length(idsToJoin) 58 | skel.edges(end+1,:) = [idsToJoin(1) idsToJoin(j)]; 59 | end 60 | end 61 | for ii=1:length(idsToKeep) 62 | skel.edges(skel.edges == idsToKeep(ii)) = ii; 63 | end 64 | end 65 | 66 | -------------------------------------------------------------------------------- /cortex/segmentation/evalParameterSegmentation.m: -------------------------------------------------------------------------------- 1 | function param = evalParameterSegmentation( param ) 2 | %UNTITLED4 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | for map=1:size(param.affMaps,1) 6 | display(['Evaluation: CNN # ' num2str(map) '/' num2str(size(param.affMaps,1))]); 7 | tic; 8 | for r=1:length(param.r) 9 | for algo=1:size(param.algo,2) 10 | if exist([param.dataFolder param.outputSubfolder filesep param.affMaps(map).name filesep 'seg' num2str(r) '-' num2str(algo) '.mat'], 'file'); 11 | a = load([param.dataFolder param.outputSubfolder param.affMaps(map).name filesep 'seg' num2str(r) '-' num2str(algo) '.mat']); 12 | eval = evaluateSeg(a.v, param.skel, param.nodeThres); 13 | parsave([param.dataFolder param.outputSubfolder filesep param.affMaps(map).name filesep 'evaluation' num2str(r) '-' num2str(algo) '.mat'], eval); 14 | end 15 | end 16 | end 17 | toc 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /cortex/segmentation/evaluateSeg.m: -------------------------------------------------------------------------------- 1 | function eval = evaluateSeg( segmentation, skeletons, nodeThres, nodeSize ) 2 | % Calculate skeleton based split-merger metric, pass a segmentation and 3 | % dense skeletons accordingly 4 | 5 | if nargin == 3 6 | nodeSize = 1; 7 | end 8 | 9 | general.maxNrObjects = single(length(unique(segmentation(:)))); 10 | general.equivMatrix = zeros(size(skeletons,2), single(max(segmentation(:)))); 11 | general.zeroHits = 0; 12 | general.nodesTotal = 0; 13 | for l=1:size(skeletons,2) 14 | if size(skeletons{l}.nodes,1) > 0 15 | nodes{l} = skeletons{l}.nodes(:,1:3); 16 | for m=1:size(nodes{l},1) 17 | centerNode = [nodes{l}(m,1) nodes{l}(m,2) nodes{l}(m,3)]; 18 | nodeIDs = segmentation(max((centerNode(1)-(nodeSize-1)/2),1):min((centerNode(1)+(nodeSize-1)/2),size(segmentation,1)), ... 19 | max((centerNode(2)-(nodeSize-1)/2),1):min((centerNode(2)+(nodeSize-1)/2),size(segmentation,2)), ... 20 | max((centerNode(3)-(nodeSize-1)/2),1):min((centerNode(3)+(nodeSize-1)/2),size(segmentation,3))); 21 | nodeIDs = unique(nodeIDs(:)); 22 | general.zeroHits = general.zeroHits + sum(nodeIDs == 0); 23 | general.nodesTotal = general.nodesTotal + 1; 24 | nodeIDs(nodeIDs == 0) = []; 25 | for i=1:length(nodeIDs) 26 | general.equivMatrix(l,nodeIDs(i)) = general.equivMatrix(l,nodeIDs(i)) + 1; 27 | end 28 | end 29 | end 30 | end 31 | general.equivMatrixBinary = general.equivMatrix >= nodeThres; 32 | % Calculate Splits 33 | split.vec = sum(general.equivMatrixBinary,2); 34 | split.idx = find(split.vec > 1); 35 | split.obj = cell(length(split.idx),1); 36 | for m=1:length(split.idx) 37 | split.obj{m} = find(general.equivMatrixBinary(split.idx(m),:)); 38 | end 39 | split.sum = sum(split.vec(split.idx)-1); 40 | % Calculate Merger 41 | merge.vec = sum(general.equivMatrixBinary,1); 42 | merge.idx = find(merge.vec > 1); 43 | merge.obj = cell(length(merge.idx),1); 44 | for m=1:length(merge.idx) 45 | merge.obj{m} = find(general.equivMatrixBinary(:,merge.idx(m))); 46 | end 47 | merge.sum = sum(merge.vec(merge.idx)-1); 48 | 49 | % Output all in case we need it again xD 50 | eval.general = general; 51 | eval.nodes = nodes; 52 | eval.split = split; 53 | eval.merge = merge; 54 | 55 | end 56 | 57 | -------------------------------------------------------------------------------- /cortex/segmentation/getParamCombinations.m: -------------------------------------------------------------------------------- 1 | function inputs = getParamCombinations( algo ) 2 | 3 | % Loop over each algorithm 4 | for i=1:length(algo) 5 | if ~isempty(algo(i).par{1}) 6 | numParam = length(algo(i).par); 7 | numParamVariations = cellfun(@length, algo(i).par); 8 | % Loop over each parameter 9 | for j=1:prod(numParamVariations) 10 | [subs{1:numParam}] = ind2sub(numParamVariations, j); 11 | inputs{i}{j} = {algo(i).fun cellfun(@(x,s)(x(s)), algo(i).par, subs, 'UniformOutput', false)}; 12 | end 13 | % % Quick hack, add values from paper segmentations cortex 14 | % inputs{i}{106} = {algo(i).fun {0.39 50}}; 15 | % inputs{i}{107} = {algo(i).fun {0.25 10}}; 16 | end 17 | end 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /cortex/segmentation/getPathLength.m: -------------------------------------------------------------------------------- 1 | function totalLength = getPathLength( skeleton ) 2 | 3 | if isempty(skeleton{1}.parameters) 4 | voxelsize= [1 1 1]; 5 | else 6 | voxelsize = [str2double(skeleton{1}.parameters.scale.x) ... 7 | str2double(skeleton{1}.parameters.scale.y) ... 8 | str2double(skeleton{1}.parameters.scale.z)]; 9 | end 10 | 11 | totalLength = 0; 12 | for sk=1:length(skeleton) 13 | if ~isempty(skeleton{sk}) 14 | if size(skeleton{sk}.edges,2) == 1 15 | % skeleton edges seem to switch dimensionality if only 16 | % one edge is present 17 | edgePos = skeleton{sk}.nodes(skeleton{sk}.edges(:,1)',1:3); 18 | totalLength = totalLength + norm((edgePos(1,:)-edgePos(2,:)).*voxelsize); 19 | else 20 | for ed=1:size(skeleton{sk}.edges,1) 21 | edgePos = skeleton{sk}.nodes(skeleton{sk}.edges(ed,:),1:3); 22 | totalLength = totalLength + norm((edgePos(1,:)-edgePos(2,:)).*voxelsize); 23 | end 24 | end 25 | end 26 | end 27 | 28 | end -------------------------------------------------------------------------------- /cortex/segmentation/morphScanAndEval.m: -------------------------------------------------------------------------------- 1 | function job = morphScanAndEval( param, nameAffMap, r, fullGrow) 2 | 3 | if nargin < 4 4 | % Classic SegEM behaviour 5 | fullGrow = false; 6 | end 7 | 8 | % Morphological Reconstruction 9 | a = load([param.dataFolder param.affSubfolder nameAffMap '.mat'], 'class'); 10 | r = param.r(r); 11 | if r ~= 0 12 | [x,y,z] = meshgrid(-r:r,-r:r,-r:r); 13 | se = (x/r).^2 + (y/r).^2 + (z/r).^2 <= 1; 14 | % Opening by reconstruction 15 | affEroded = imerode(a.class, se); 16 | affRecon = imreconstruct(affEroded, a.class); 17 | % Closing by reconstruction 18 | affReconDilated = imdilate(affRecon, se); 19 | affReconRecon = imreconstruct(imcomplement(affReconDilated), imcomplement(affRecon)); 20 | else 21 | affReconRecon = imcomplement(a.class); 22 | end 23 | if ~exist([param.dataFolder param.outputSubfolder nameAffMap filesep], 'dir') 24 | mkdir([param.dataFolder param.outputSubfolder nameAffMap filesep]); 25 | end 26 | save([param.dataFolder param.outputSubfolder nameAffMap filesep 'MorphRecon' num2str(r) '.mat'], 'affReconRecon'); 27 | 28 | % scan and eval 29 | paramCell = getParamCombinations(param.algo); 30 | for i=1:size(paramCell,2) 31 | parfor j=1:length(paramCell{i}) 32 | %scan 33 | display(j); 34 | fun = paramCell{i}{j}{1}; 35 | segmentation = fun(affReconRecon,paramCell{i}{j}{2}(:)); 36 | if fullGrow 37 | segTemp = imdilate(segmentation, ones(3,3,3)); 38 | borders = segmentation == 0; 39 | segmentation(borders) = segTemp(borders); 40 | end 41 | parsave([param.dataFolder param.outputSubfolder nameAffMap filesep 'seg' num2str(r) '-' num2str(i) '-' num2str(j) '.mat'], segmentation); 42 | %evaluate 43 | eval = evaluateSeg(segmentation, param.skel, param.nodeThres); 44 | parsave([param.dataFolder param.outputSubfolder nameAffMap filesep 'evaluation' num2str(r) '-' num2str(i) '-' num2str(j) '.mat'], eval); 45 | end 46 | end 47 | 48 | end 49 | -------------------------------------------------------------------------------- /cortex/segmentation/parsave.m: -------------------------------------------------------------------------------- 1 | function parsave( filepathname, v ) 2 | % Sometimes Matlab is just ridicuuulous 3 | 4 | save( filepathname, 'v', '-v7.3' ); 5 | 6 | end 7 | -------------------------------------------------------------------------------- /cortex/segmentation/seg20141017.m: -------------------------------------------------------------------------------- 1 | function seg20141017( root, prefix, bbox, saveFile ) 2 | 3 | % Load classification 4 | aff = loadClassData(root, prefix, bbox); 5 | 6 | % Replace this part with routines from segmentation submodule as soon as possible and add all parameter to active->setParameterSettings.m 7 | aff = imcomplement(aff); 8 | fgm1 = imextendedmin(aff, .25, 26); 9 | fgm1 = bwareaopen(fgm1, 10); 10 | map = imimposemin(aff, fgm1); 11 | seg = watershed(map, 26); 12 | seg = uint16(seg); 13 | 14 | % Save segmentation to MATLAB file in 'saveFolder' 15 | save(saveFile, 'seg'); 16 | 17 | end 18 | 19 | -------------------------------------------------------------------------------- /cortex/segmentation/skeletonPreparations.m: -------------------------------------------------------------------------------- 1 | % This script preprocesses (limits to bounding box, switch to local 2 | % coordinates of training region and removes glia cells and bounding box 3 | 4 | % Skeleton locations 5 | skelPath = [dataDirectory 'supplement' filesep 'extracted' filesep]; 6 | % Copy all skeletons to output directory 7 | copyfile([skelPath '*.nml'], [outputDirectory filesep]); 8 | % Load skeletons from output directory, only cortex will be preprocessed 9 | % here, for retina see legacy version 10 | skelFile{1} = [outputDirectory 'cortex_training.nml']; 11 | skelFile{2} = [outputDirectory 'cortex_test.nml']; 12 | skelFile{3} = [outputDirectory 'retina_training_local_subsampled.nml']; 13 | skelFile{4} = [outputDirectory 'retina_test_local_subsampled.nml']; 14 | % Skeleton bounding boxes (for cortex only, see legacy version for analog 15 | % retina processing which was still based on dense tracings aligned to 16 | % KNOSSOS cubes instead of arbitrary coordiantes (see 17 | % [SegEM]/retina/segmentation/mainSeg_legacy); 18 | bbox{1} = [4097 4737; 4481 5249; 2250 2451]; 19 | bbox{2} = [1417 1717; 4739 5039; 890 1190]; 20 | % Parse files to matlab structure 21 | skel = cell(length(skelFile),1); 22 | for i=1:length(skelFile) 23 | skel{i} = parseNml(skelFile{i}); 24 | end 25 | 26 | %% Create version of each skeleton in local coordinates of training region and clip to bounding box 27 | for i=1:2 28 | % Save parameter attachted to first tree in skeleton collection 29 | savePar = skel{i}{1}.parameters; 30 | % Remove annotations of glia cells 31 | skel{i} = removeGlia(skel{i}); 32 | % Remove annotation of bounding box (if present, outdated from old 33 | % oxalis version) 34 | skel{i} = removeBbox(skel{i}); 35 | % Remove all empty trees in struct 36 | skel{i} = removeEmptySkeletons(skel{i}); 37 | % Switch to coordinates of small subcube (offset has to be inital voxel of 38 | % bbox - [1 1 1] due to one index of matlab (another [1 1 1] if tracing was done in oxalis) 39 | skel{i} = switchToLocalCoords_v2(skel{i}, bbox{i}(:,1)' - [2 2 2]); 40 | % Remove all nodes outside small subcube 41 | skel{i} = correctSkeletonsToBBox_v2(skel{i}, bbox{i}(:,2)' - bbox{i}(:,1)'); 42 | % Remove again in case trees are empty 43 | skel{i} = removeEmptySkeletons(skel{i}); 44 | % Resore parameter in case first tree got gone 45 | skel{i}{1}.parameters = savePar; 46 | % Write local version of skeleton 47 | writeNml(strrep(skelFile{i}, '.', '_local.'), skel{i}); 48 | end 49 | 50 | %% Equalize inter-node distance for all skeletons 51 | skel = equalizeSkeletons(skel); 52 | 53 | %% Write equalized cortex skeletons to folder 54 | for i=1:2 55 | writeNml(strrep(skelFile{i}, '.', '_local_subsampled.'), skel{i}); 56 | end 57 | 58 | %% Calculate some statistics on all skeletons 59 | skeletonStatistics(outputDirectory); 60 | -------------------------------------------------------------------------------- /cortex/segmentation/skeletonStatistics.m: -------------------------------------------------------------------------------- 1 | function skeletonStatistics(directory) 2 | % Calculate some basic statistics of skeletons with a folder and save to file 3 | 4 | files = dir([directory '*.nml*']); 5 | fid = fopen([directory 'statistics.txt'], 'a'); 6 | fprintf( fid, ['Skeleton statistics from date: ' datestr(clock, 30) '\n']); 7 | fprintf( fid, '\n'); 8 | for i=1:length(files) 9 | skel = parseNml([directory files(i).name]); 10 | nodes = []; 11 | for tree=1:length(skel) 12 | nodes = [nodes; skel{tree}.nodes]; 13 | end 14 | scale = [str2num(skel{1}.parameters.scale.x) str2num(skel{1}.parameters.scale.y) str2num(skel{1}.parameters.scale.z)]; 15 | stat.nrNodes = size(nodes,1); 16 | stat.volumeBbox = prod((max(nodes(:,1:3)) - min(nodes(:,1:3)) + [1 1 1]) .* scale)/1e9; 17 | stat.pathLength = getPathLength(skel); 18 | stat.pathDensity = stat.pathLength./stat.nrNodes; 19 | stat.volumeDensity = stat.pathLength./stat.volumeBbox; 20 | fprintf( fid, [files(i).name ':\n' ]); 21 | fprintf( fid, ['Number nodes: ' num2str(stat.nrNodes) '\n']); 22 | fprintf( fid, ['Volume of axis-aligned bbox [microns^3]: ' num2str(stat.volumeBbox, '%.2i') '\n' ]); 23 | fprintf( fid, ['Path length of skeletons [mm]: ' num2str(stat.pathLength/1e6, '%.2i') '\n' ]); 24 | fprintf( fid, ['Average path length between nodes [nm]: ' num2str(stat.pathDensity, '%.2i') '\n' ]); 25 | fprintf( fid, ['Path length per volume [microns/microns^3]: ' num2str(stat.volumeDensity/1e3, '%.2i') '\n' ]); 26 | fprintf( fid, '\n'); 27 | end 28 | fprintf( fid, '\n'); 29 | fclose(fid); 30 | end 31 | 32 | -------------------------------------------------------------------------------- /cortex/segmentation/switchToLocalCoords_v2.m: -------------------------------------------------------------------------------- 1 | function skel = switchToLocalCoords_v2( skel, offset ) 2 | % Correct nodes, nodesNumDataAll and nodesAsStruct to bbox 3 | for l=1:size(skel,2) 4 | if isfield(skel{l}, 'nodesNumDataAll') && ~isempty(skel{l}.nodesNumDataAll); 5 | skel{l}.nodesNumDataAll(:,3:5) = skel{l}.nodesNumDataAll(:,3:5) - repmat(offset,size(skel{l}.nodesNumDataAll,1),1); 6 | end 7 | if isfield(skel{l}, 'nodes') && ~isempty(skel{l}.nodes); 8 | skel{l}.nodes(:,1:3) = skel{l}.nodes(:,1:3) - repmat(offset,size(skel{l}.nodes,1),1); 9 | end 10 | if isfield(skel{l}, 'nodesAsStruct') && ~isempty(skel{l}.nodesAsStruct); 11 | for i=1:length(skel{l}.nodesAsStruct) 12 | skel{l}.nodesAsStruct{i}.x = skel{l}.nodesAsStruct{i}.x - offset(1); 13 | skel{l}.nodesAsStruct{i}.y = skel{l}.nodesAsStruct{i}.y - offset(2); 14 | skel{l}.nodesAsStruct{i}.z = skel{l}.nodesAsStruct{i}.z - offset(3); 15 | end 16 | end 17 | end 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/makeErrorMoviesP.m: -------------------------------------------------------------------------------- 1 | function makeErrorMoviesP( param, eval, segmentation, raw) 2 | 3 | colors = {'or' 'og' 'ob' 'oy' 'oc' 'om'}; 4 | 5 | for errorIdx=1:length(eval.merge.obj) 6 | figure; 7 | writerObj = VideoWriter([param.outputFolder 'errorMovie' num2str(errorIdx, '%.3i')]); 8 | writerObj.FrameRate = 4; 9 | open(writerObj); 10 | for f=1:size(raw,3) 11 | hold off; 12 | imshow(raw(:,:,f), [60 180]); 13 | hold on; 14 | temp = single(segmentation(:,:,f)); 15 | temp(temp == eval.merge.idx(errorIdx)) = -1; 16 | temp(temp ~= -1) = 0; 17 | temp(temp == -1) = 255; 18 | temp = uint8(temp); 19 | temp = label2rgb(temp, 'jet'); 20 | str = []; 21 | for m=1:length(eval.merge.obj{errorIdx}) 22 | str = [str num2str(eval.merge.obj{errorIdx}(m)) ' ']; 23 | if sum(eval.nodes{eval.merge.obj{errorIdx}(m)}(:,3) == f) 24 | idNodes = find(eval.nodes{eval.merge.obj{errorIdx}(m)}(:,3) == f); 25 | plot(eval.nodes{eval.merge.obj{errorIdx}(m)}(idNodes,2), eval.nodes{eval.merge.obj{errorIdx}(m)}(idNodes,1), colors{rem(m,6)+1}, 'LineWidth', 3); 26 | end 27 | end 28 | himage = imshow(temp); 29 | set(himage, 'AlphaData', 0.15 ); 30 | if f == 1 31 | set(gcf,'NextPlot','replacechildren'); 32 | set(gcf,'Renderer','OpenGL'); 33 | end 34 | title(['Skeletons (KNOSSOS ID): ' str]); 35 | drawnow; 36 | writeVideo(writerObj,getframe(gca, [1 1 384 384])); 37 | end 38 | close(writerObj); 39 | close all; 40 | end 41 | 42 | end 43 | 44 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/makeSkeletonMovies.m: -------------------------------------------------------------------------------- 1 | function makeSkeletonMovies(param, raw) 2 | 3 | % Settings & Figure Setup 4 | colors = distinguishable_colors(length(param.skel)); 5 | figure; 6 | set(gcf,'NextPlot','replacechildren'); 7 | set(gcf,'Renderer','OpenGL'); 8 | writerObj = VideoWriter([param.dataFolder param.figureSubfolder '/skeletonMovie.avi']); 9 | writerObj.FrameRate = 4; 10 | open(writerObj); 11 | % Plot each frame raw data and skeletons & write to video 12 | for f=1:size(raw,3) 13 | hold off; 14 | imagesc(raw(:,:,f)); 15 | colormap('gray'); 16 | axis off; 17 | axis equal; 18 | caxis([-2 2]); 19 | hold on; 20 | for skel=1:length(param.skel) 21 | toPlot = param.skel{skel}.nodes(:,3) == f; 22 | if sum(toPlot) 23 | plot(param.skel{skel}.nodes(toPlot,2),param.skel{skel}.nodes(toPlot,1), 'x', 'Color', colors(skel,:), 'MarkerSize', 5, 'LineWidth', 2); 24 | end 25 | end 26 | drawnow; 27 | frame = getframe; 28 | %imwrite(frame.cdata, [param.dataFolder param.figureSubfolder '/skeletonFrame' num2str(f, '%.3i') '.tif']); 29 | writeVideo(writerObj,frame); 30 | end 31 | % Close everything 32 | close(writerObj); 33 | close all; 34 | end 35 | 36 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/visSeg.m: -------------------------------------------------------------------------------- 1 | %% Plot everything (including movies) for a specific segmentation 2 | 3 | %% Plot for which ROI index, see: param.affMaps(index) 4 | map = 1; 5 | param.affMaps(map) 6 | % which algorothm to use, see param.algo 7 | algo = 1; 8 | param.algo(algo).fun 9 | % which radius to use, index to param.r(r) 10 | r = 1; 11 | param.r(r) 12 | 13 | %% 14 | paramCell = getParamCombinations(param.algo); 15 | par = 10; 16 | paramCell{algo}{par}{2}; 17 | 18 | %% Might generate large amount of output data (e.g. one video for each merger) 19 | visualizeSingle(param, map, algo, r, par); 20 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/visualizeMeSp.m: -------------------------------------------------------------------------------- 1 | function visualizeMeSp( merge, split, length ) 2 | %UNTITLED4 Summary of this function goes here 3 | % Detailed explanation goes here 4 | markerSize = linspace(5,15,size(merge,3)); 5 | marker = {'o' 'x' '.' '*' '+' 's' 'd'}; 6 | colors = {'r' 'g' 'b' 'y' 'c' 'm' 'k'}; 7 | la = cell(numel(merge),1); 8 | figure('position', [1 41 1600 784]); 9 | for i=1:size(merge,1) 10 | for j=1:size(merge,2) 11 | for k=1:size(merge,3) 12 | plot(length/merge(i,j,k).sum, length/split(i,j,k).sum, [marker{i} colors{j}], 'MarkerSize', markerSize(k)); 13 | hold on; 14 | la{sub2ind(size(merge),i,j,k)} = [num2str(i, '%i') num2str(j, '%i') num2str(k, '%i')]; 15 | xlabel('# average microns between merger'); 16 | ylabel('# average microns between splits'); 17 | end 18 | end 19 | end 20 | legend(la, 'Location', 'BestOutside'); 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/visualizeObjHistP.m: -------------------------------------------------------------------------------- 1 | function visualizeObjHistP( param, general, segmentation, par1, par2) 2 | %UNTITLED4 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | figure('Visible', 'off'); 6 | sizeObj = hist(single(segmentation(:)),1:general.maxNrObjects); 7 | sizeObj(sizeObj > param.objSizeCutoff) = param.objSizeCutoff; 8 | hist(single(sizeObj), 250:500:(param.objSizeCutoff - 250)); 9 | xlabel('Object Size [voxel]'); 10 | ylabel('# Objects'); 11 | saveas(gcf, [param.outputFolder 'objHist.pdf']); 12 | close all; 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/visualizeObjectChainsP_leftout.m: -------------------------------------------------------------------------------- 1 | function visualizeObjectChainsP_leftout( param, eval, se, skel ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | % 100 unique colors, replicate a lot to make it work 6 | cm = distinguishable_colors(100, [1 1 1]); 7 | cm = repmat(cm, 100,1); 8 | views = {2, 3, [90,0]}; 9 | 10 | if ~exist([param.outputFolder 'objChains' filesep], 'dir') 11 | mkdir([param.outputFolder 'objChains' filesep]); 12 | end 13 | 14 | figure('Renderer', 'OpenGL'); 15 | test = sum(eval.general.equivMatrixBinary) < 1; 16 | k = cell(length(max(se(:))),1); 17 | for i=1:max(se(:)) 18 | if test(i) 19 | obj = se == i; 20 | issf = isosurface(obj, .1); 21 | k{i} = patch(issf); 22 | set(k{i}, 'FaceColor', cm(i,:), 'EdgeColor', 'none'); 23 | end 24 | end 25 | view(views{2}); 26 | daspect([25 25 12]); 27 | grid on; 28 | alpha(.4); 29 | xlim([1 size(se,1)]); 30 | ylim([1 size(se,2)]); 31 | zlim([1 size(se,3)]); 32 | camlight('headlight'); 33 | lighting phong; 34 | saveas(gcf, [param.outputFolder 'objChains' filesep 'leftout.fig']); 35 | saveas(gcf, [param.outputFolder 'objChains' filesep 'leftout.tif']); 36 | close all; 37 | 38 | end 39 | 40 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/visualizeObjectChainsP_merger.m: -------------------------------------------------------------------------------- 1 | function visualizeObjectChainsP_merger( param, eval, se, skel ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | % 100 unique colors, seems qnough for this application, maybe make it 6 | % dynamic? 7 | cm = distinguishable_colors(100, [1 1 1]); 8 | views = {2, 3, [90,0]}; 9 | 10 | if ~exist([param.outputFolder 'objChains' filesep], 'dir') 11 | mkdir([param.outputFolder 'objChains' filesep]); 12 | end 13 | 14 | for merger=1:length(eval.merge.obj) 15 | f = figure('Renderer', 'OpenGL'); 16 | for c=1:length(eval.merge.obj{merger}) 17 | chain = eval.merge.obj{merger}(c); 18 | sk = eval.nodes{chain}; 19 | ske = skel{chain}.edges; 20 | objects = unique(se(sub2ind(size(se),sk(:,1),sk(:,2),sk(:,3)))); 21 | objects(objects == 0) = []; 22 | subplot(1,length(eval.merge.obj{merger}),c); 23 | hold on; 24 | for i=1:size(ske,1) 25 | plot3(sk([ske(i,1) ske(i,2)],2), sk([ske(i,1) ske(i,2)],1), sk([ske(i,1) ske(i,2)],3), '-k', 'LineWidth', 3); 26 | end 27 | k = cell(length(objects),1); 28 | for i=1:length(objects) 29 | obj = se == objects(i); 30 | issf = isosurface(obj, .1); 31 | k{i} = patch(issf); 32 | if objects(i) == eval.merge.idx(merger) 33 | set(k{i}, 'FaceColor', 'r', 'EdgeColor', 'none'); 34 | else 35 | set(k{i}, 'FaceColor', cm(i,:), 'EdgeColor', 'none'); 36 | end 37 | end 38 | view(views{2}); 39 | daspect([25 25 12]); 40 | title(['Skelett (KNOSSOS ID): ' num2str(skel{chain}.thingID)]); 41 | grid on; 42 | alpha(.4); 43 | xlim([1 size(se,1)]); 44 | ylim([1 size(se,2)]); 45 | zlim([1 size(se,3)]); 46 | camlight('headlight'); 47 | lighting phong; 48 | end 49 | set(f, 'Renderer', 'OpenGL'); 50 | saveas(f, [param.outputFolder 'objChains' filesep 'merger' num2str(merger, '%3.3i') '.tif']); 51 | saveas(f, [param.outputFolder 'objChains' filesep 'merger' num2str(merger, '%3.3i') '.fig']); 52 | close all; 53 | end 54 | 55 | end 56 | 57 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/visualizeObjectChainsP_show.m: -------------------------------------------------------------------------------- 1 | function visualizeObjectChainsP_show( param, eval, se, skel ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | % 100 unique colors, seems qnough for this application, maybe make it 6 | % dynamic? 7 | cm = distinguishable_colors(100, [1 1 1]); 8 | views = {2, 3, [90,0]}; 9 | 10 | if ~exist([param.outputFolder 'objChains' filesep], 'dir') 11 | mkdir([param.outputFolder 'objChains' filesep]); 12 | end 13 | 14 | for chain=1:length(skel) 15 | sk = eval.nodes{chain}; 16 | ske = skel{chain}.edges; 17 | if size(ske,2) > 1 && size(ske,1) > 0 18 | objects = unique(se(sub2ind(size(se),sk(:,1),sk(:,2),sk(:,3)))); 19 | objects(objects == 0) = []; 20 | f = figure('Renderer', 'OpenGL'); 21 | hold on; 22 | k = cell(length(objects),1); 23 | for i=1:length(objects) 24 | obj = se == objects(i); 25 | issf = isosurface(obj, .1); 26 | k{i} = patch(issf); 27 | set(k{i}, 'FaceColor', cm(i,:), 'EdgeColor', 'none'); 28 | end 29 | for i=1:size(ske,1) 30 | plot3(sk([ske(i,1) ske(i,2)],2), sk([ske(i,1) ske(i,2)],1), sk([ske(i,1) ske(i,2)],3), '-k', 'LineWidth', 3); 31 | end 32 | view(views{2}); 33 | daspect([25 25 12]); 34 | %title(['Skelett (KNOSSOS ID): ' num2str(skel{chain}.thingID)], 'FontSize', 18); 35 | grid on; 36 | alpha(.4); 37 | xlim([1 size(se,1)]); 38 | ylim([1 size(se,2)]); 39 | zlim([1 size(se,3)]); 40 | camlight('headlight'); 41 | lighting phong; 42 | set(gca, 'XTickLabel', ''); 43 | set(gca, 'YTickLabel', ''); 44 | set(gca, 'ZTickLabel', ''); 45 | saveas(gcf, [param.outputFolder 'objChains' filesep 'chain' num2str(chain, '%3.3i') '.png']); 46 | close all; 47 | end 48 | end 49 | 50 | end 51 | 52 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/visualizeOverviewComparison.m: -------------------------------------------------------------------------------- 1 | function visualizeOverviewComparison( param,paramTest,nodeSize ) 2 | %UNTITLED2 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | if nargin == 2 6 | nodeSize = 1; 7 | end 8 | 9 | if ~exist([param.dataFolder param.figureSubfolder '/'], 'dir') 10 | mkdir([param.dataFolder param.figureSubfolder '/']); 11 | end 12 | display('Overview Training vs. Test Comparison'); 13 | figure('position', [1 1 1600 785]); 14 | hold on; 15 | [a, b, c] = plotParam(param, [0 0 0]); 16 | [d, e, f] = plotParam(paramTest, [0.05 0.5 0.25]); 17 | xlabel('average distance between merger [nm]'); 18 | ylabel('average distance between splits [nm]'); 19 | zlabel('# objects'); 20 | set(gca, 'XScale', 'log'); 21 | set(gca, 'YScale', 'log'); 22 | grid off; 23 | legend([a b c d e f], 'training node threshold 1', 'training node threshold 2', 'training node threshold 3' ... 24 | , 'test node threshold 1', 'test node threshold 2', 'test node threshold 3'); 25 | saveas(gcf, [param.dataFolder param.figureSubfolder filesep 'overviewComparisonNew.fig']); 26 | 27 | function [u, v, w] = plotParam(param, color) 28 | marker = {'+' 'o' 'x'}; 29 | paramCell = getParamCombinations(param.algo); 30 | for i=1:size(paramCell,2) 31 | for j=1:length(paramCell{i}) 32 | display([num2str(j, '%.3i') ' of ' num2str(length(paramCell{i}), '%.3i')]); 33 | load([param.dataFolder param.outputSubfolder param.affMaps(1).name filesep 'seg' num2str(0) '-' num2str(i) '-' num2str(j) '.mat'], 'v'); 34 | eval1 = evaluateSeg(v, param.skel, 1, nodeSize); 35 | eval2 = evaluateSeg(v, param.skel, 2, nodeSize); 36 | eval3 = evaluateSeg(v, param.skel, 3, nodeSize); 37 | u = plot3(param.totalPathLength./max(eval1.merge.sum,1), param.totalPathLength./max(eval1.split.sum,1), eval1.general.maxNrObjects,... 38 | marker{1}, 'MarkerEdgeColor', color, 'MarkerSize', 5); 39 | v = plot3(param.totalPathLength./max(eval2.merge.sum,1), param.totalPathLength./max(eval2.split.sum,1), eval2.general.maxNrObjects,... 40 | marker{2}, 'MarkerEdgeColor', color, 'MarkerSize', 5); 41 | w = plot3(param.totalPathLength./max(eval3.merge.sum,1), param.totalPathLength./max(eval3.split.sum,1), eval3.general.maxNrObjects,... 42 | marker{3}, 'MarkerEdgeColor', color, 'MarkerSize', 5); 43 | end 44 | end 45 | end 46 | 47 | end 48 | 49 | -------------------------------------------------------------------------------- /cortex/segmentation/visualization/visualizeSingle.m: -------------------------------------------------------------------------------- 1 | function visualizeSingle( param, map, algo, r, par ) 2 | 3 | display('Visualization Single:'); 4 | tic; 5 | 6 | % Load relevant data (aka. segmentation, classification, raw data & skeleton-based 7 | % split-merger evaluation) 8 | a = load([param.dataFolder param.outputSubfolder param.affMaps(map).name filesep 'evaluation' num2str(param.r(r)) '-' num2str(algo) '-' num2str(par) '.mat']); 9 | b = load([param.dataFolder param.outputSubfolder param.affMaps(map).name filesep 'seg' num2str(param.r(r)) '-' num2str(algo) '-' num2str(par) '.mat']); 10 | load([param.dataFolder param.affSubfolder param.affMaps(map).name '.mat']); 11 | 12 | % Big contender for longest ever concatenation of strings to just get 13 | % output subfolder (not sure what I thought back then, not important, must 14 | % be unique so visualizeSingle can be used for multiple segmentations in 15 | % parallel 16 | param.outputFolder = [param.dataFolder param.figureSubfolder param.affMaps(map).name '-' num2str(param.r(r)) '-' num2str(algo) '-' num2str(par, '%.3i') filesep]; 17 | if ~exist(param.outputFolder, 'dir'); 18 | mkdir(param.outputFolder); 19 | end 20 | 21 | if param.makeSegMovies 22 | makeSegMovie( b.v, raw, [param.outputFolder 'segVideo.avi'] ); 23 | end 24 | 25 | if param.makeErrorMovies 26 | makeErrorMoviesP( param, a.v, b.v, raw); 27 | end 28 | 29 | if param.plotObjSizeHist 30 | visualizeObjHistP( param, a.v.general, b.v); 31 | end 32 | 33 | if param.plotObjChains 34 | visualizeObjectChainsP_merger(param, a.v, b.v, param.skel); 35 | visualizeObjectChainsP_show(param, a.v, b.v, param.skel); 36 | visualizeObjectChainsP_leftout(param, a.v, b.v, param.skel); 37 | end 38 | 39 | toc 40 | 41 | end 42 | 43 | -------------------------------------------------------------------------------- /cortex/segmentation/watershedSeg_v1_cortex.m: -------------------------------------------------------------------------------- 1 | function segmentation = watershedSeg_v1_cortex( aff, cell ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | hRange = cell{1}; 6 | vRange = cell{2}; 7 | 8 | affHmin= imhmin(aff, hRange, 26); 9 | bw1 = imregionalmin(affHmin, 26); 10 | clear affHmin; 11 | bw1 = bwareaopen(bw1, vRange, 26); 12 | affImposed = imimposemin(aff, bw1); 13 | segmentation = watershed(affImposed, 26); 14 | 15 | end -------------------------------------------------------------------------------- /cortex/segmentation/watershedSeg_v2_cortex.m: -------------------------------------------------------------------------------- 1 | function segmentation = watershedSeg_v2_cortex( aff, cell) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | tRange = cell{1}; 6 | vRange = cell{2}; 7 | 8 | fgm1 = aff < tRange; 9 | fgm1 = bwareaopen(fgm1, vRange, 26); 10 | affImposed = imimposemin(aff, fgm1); 11 | segmentation= watershed(affImposed, 26); 12 | 13 | end 14 | -------------------------------------------------------------------------------- /cortex/startup.m: -------------------------------------------------------------------------------- 1 | % set Matlab path for cortex 2 | addpath(genpath([codeDirectory filesep 'cortex'])); 3 | addpath(genpath([codeDirectory filesep 'auxiliaryMethods'])); 4 | addpath(genpath([codeDirectory filesep 'volumeReconstruction'])); 5 | 6 | % open relevant scripts for cortex 7 | cortexSubfolder = [codeDirectory filesep 'cortex' filesep]; 8 | open([cortexSubfolder 'CNN' filesep 'cnnStart.m']); 9 | open([cortexSubfolder 'CNN' filesep 'evolution' filesep 'cnnParameterSelection.m']); 10 | open([cortexSubfolder 'segmentation' filesep 'mainSeg.m']); 11 | open([cortexSubfolder 'segmentation' filesep 'visualization' filesep 'visSeg.m']); 12 | open([cortexSubfolder 'wholeDataset' filesep 'wholeDatasetFwdPass.m']); 13 | open([codeDirectory filesep 'volumeReconstruction' filesep 'skeletonsToContacts.m']); 14 | clear cortexSubfolder; 15 | 16 | % create parameter settings for cortex for easier access to data/storage 17 | % locations etc.: 18 | [p, pT] = setParameterSettings(dataDirectory, outputDirectory); -------------------------------------------------------------------------------- /cortex/wholeDataset/bigFwdPass.m: -------------------------------------------------------------------------------- 1 | function job = bigFwdPass( parameter, bboxOutput ) 2 | % do the whole classifcation for structure 3 | 4 | load(parameter.cnn.first, 'cnet'); 5 | 6 | % If only one argument is supplied use bbox from parameter file and add tile border to be able to do segmentation with big field of view for games 7 | if nargin == 1 8 | bbox = parameter.bbox + parameter.tileBorder; 9 | else 10 | bbox = bboxOutput; 11 | end 12 | 13 | cubeSize = [256 256 128]; % This is not of any importance due to CNN translation invariance, can be choosen for computational efficency, currenlty optimized for running on GPU with 6GB, should be multiples of 128 14 | X = bbox(1,1):cubeSize(1):bbox(1,2)+1; 15 | Y = bbox(2,1):cubeSize(2):bbox(2,2)+1; 16 | Z = bbox(3,1):cubeSize(3):bbox(3,2)+1; 17 | for i=1:length(X)-1 18 | for j=1:length(Y)-1 19 | for k=1:length(Z)-1 20 | idx = sub2ind([length(X)-1 length(Y)-1 length(Z)-1], i, j, k); 21 | functionH{idx} = @onlyFwdPass3DonKnossosFolder; 22 | inputCell{idx} = {cnet, parameter.cnn.GPU, parameter.raw, parameter.class, [X(i) X(i+1)-1; Y(j) Y(j+1)-1; Z(k) Z(k+1)-1]}; 23 | end 24 | end 25 | end 26 | 27 | if parameter.cnn.GPU 28 | job = startGPU(functionH, inputCell, 'classification'); 29 | else 30 | job = startCPU(functionH, inputCell, 'classification'); 31 | end 32 | 33 | end 34 | 35 | -------------------------------------------------------------------------------- /cortex/wholeDataset/miniSegmentation.m: -------------------------------------------------------------------------------- 1 | function jobs = miniSegmentation(parameter) 2 | 3 | for i=1:size(parameter.local,1) 4 | for j=1:size(parameter.local,2) 5 | for k=1:size(parameter.local,3) 6 | if ~exist(parameter.local(i,j,k).saveFolder, 'dir') 7 | mkdir(parameter.local(i,j,k).saveFolder); 8 | end 9 | idx = sub2ind(size(parameter.local), i, j, k); 10 | functionH{idx} = parameter.seg.func; 11 | if isfield(parameter.local(i,j,k), 'class') 12 | inputCell{idx} = {parameter.local(i,j,k).class.root parameter.local(i,j,k).class.prefix, parameter.local(i,j,k).bboxSmall, parameter.local(i,j,k).segFile}; 13 | else 14 | inputCell{idx} = {parameter.class.root parameter.class.prefix, parameter.local(i,j,k).bboxBig, parameter.local(i,j,k).segFile}; 15 | end 16 | end 17 | end 18 | end 19 | 20 | jobs = startCPU(functionH, inputCell, 'segmentation'); 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /cortex/wholeDataset/minicubeFwdPass.m: -------------------------------------------------------------------------------- 1 | function job = minicubeFwdPass( parameter ) 2 | % classification of subregions within the data set (for segmentation optimization and GP training) 3 | 4 | load(parameter.cnn.first, 'cnet'); 5 | 6 | for tr=1:length(parameter.local) 7 | bbox = parameter.local(tr).bboxSmall; 8 | functionH{tr} = @onlyFwdPass3DonKnossosFolder; 9 | inputCell{tr} = {cnet, parameter.cnn.GPU, parameter.raw, parameter.local(tr).class, bbox}; 10 | end 11 | 12 | if parameter.cnn.GPU 13 | job = startGPU(functionH, inputCell, 'classification'); 14 | else 15 | job = startCPU(functionH, inputCell, 'classification'); 16 | end 17 | 18 | end 19 | 20 | -------------------------------------------------------------------------------- /cortex/wholeDataset/onlyFwdPass3DonKnossosFolder.m: -------------------------------------------------------------------------------- 1 | function onlyFwdPass3DonKnossosFolder(cnet, gpuSwitch, input, result, bbox) 2 | 3 | % Choose the right GPU if switch is set 4 | if gpuSwitch 5 | w = getCurrentWorker(); 6 | w = w.Name; 7 | gselect(str2double(w(end-1:end))); 8 | end 9 | 10 | % Set activity class of CNN 11 | if gpuSwitch 12 | cnet.run.actvtClass = @gpuarray; 13 | else 14 | cnet.run.actvtClass = @single; 15 | end 16 | 17 | % Load data with right border for cnet 18 | bboxWithBorder(:,1) = bbox(:,1) - ceil(cnet.randOfConvn'/2); 19 | bboxWithBorder(:,2) = bbox(:,2) + ceil(cnet.randOfConvn'/2); 20 | raw = readKnossosRoi(input.root, input.prefix, bboxWithBorder); 21 | 22 | % Normalize data 23 | if cnet.normalize 24 | raw = normalizeStack(single(raw)); 25 | else 26 | raw = single(raw); 27 | end 28 | 29 | % Memory efficent fwd pass 30 | classification = onlyFwdPass3D(cnet, raw); 31 | % Save result to KNOSSOS folder 32 | writeKnossosRoi(result.root, result.prefix, bbox(:,1)', classification, 'single'); 33 | 34 | end 35 | -------------------------------------------------------------------------------- /initalSettings.m: -------------------------------------------------------------------------------- 1 | % Use jobMangerName as global variable, will be set in installer 2 | global jobManagerName; 3 | 4 | % A GUI to set releveant directories, Matlab jobmanager and chose a dataset 5 | iHandle = installer; 6 | waitfor(iHandle); 7 | clear iHandle; 8 | 9 | % NO MODIFICATIONS NECESSARY UNDER THIS LINE USUALLY 10 | 11 | % Compile functions needed later using Matlab mex compiler 12 | display('If you get warning or errors here, please try to run mex -setup and choose a compiler supported by Matlab'); 13 | % Compile mex watershed and nml parser 14 | if strcmp(computer('arch'), 'glnxa64') 15 | % Linux mex 16 | mex CFLAGS="\$CFLAGS -U FORTIFY_SOURCE -std=c99" -largeArrayDims -outdir retina/segmentation/watershedBasedSeg retina/segmentation/watershedBasedSeg/watershed_threeTimes3D.c; 17 | mex -outdir auxiliaryMethods auxiliaryMethods/parseNml.c; 18 | mex -outdir auxiliaryMethods auxiliaryMethods/parseNml_noInVP.c; 19 | elseif strcmp(computer('arch'), 'PCWIN64') || strcmp(computer('arch'), 'win64') % Matlab docu inconsitent 20 | % Windows mex (was not able to get watershed compile using Windows SDK 21 | % 7.1 C-compiler (does not support C99 standard?). Works using c++ 22 | % compiler, weird behaviour 23 | mex -largeArrayDims -outdir retina\segmentation\watershedBasedSeg retina\segmentation\watershedBasedSeg\watershed_threeTimes3D.cpp; 24 | mex -outdir auxiliaryMethods auxiliaryMethods\parseNml.c; 25 | mex -outdir auxiliaryMethods auxiliaryMethods\parseNml_noInVP.c; 26 | else 27 | display('Please set up mex to run with your architecture!') 28 | end 29 | 30 | % This requires that matlab is started from the baseDirectory of the github 31 | % repo, better alternative? 32 | codeDirectory = pwd; 33 | 34 | % Open relevant scripts for dataset/code version 35 | if strcmp(chosenCodebase, 'Legacy version (for retina dataset e_k0563)') 36 | run(['retina' filesep 'startup.m']); 37 | end 38 | if strcmp(chosenCodebase, 'SegEM') 39 | run(['cortex' filesep 'startup.m']); 40 | end 41 | -------------------------------------------------------------------------------- /installer.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhlabCodingTeam/SegEM/a61ff23875ef36cf6c851ae3112cbdc640ece43f/installer.fig -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Manuel Berning and Moritz Helmstaedter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /retina/CNN/@cnn/bwdPass3D.m: -------------------------------------------------------------------------------- 1 | function sensitivity = bwdPass3D(cnet, activity, activityWithoutNL, target, mask) 2 | sensitivity = cell(cnet.numLayer,cnet.numFeature); 3 | for label=1:cnet.numLabels 4 | sensitivity{cnet.numLayer,label} = cnet.lossFunctionD( activity{cnet.numLayer,label},cnet.run.actvtTyp(target{label})) ... 5 | .*cnet.run.actvtTyp(mask{label}).*cnet.nonLinearityD(activityWithoutNL{cnet.numLayer,label}); 6 | end 7 | for layer=cnet.numLayer:-1:3 % iteration over layers, starting with the last 8 | for prevFm=1:cnet.layer{layer-1}.numFeature % iteration over featuremaps of the previous layer 9 | sensitivity{layer-1,prevFm} = zeros(size(activityWithoutNL{layer-1,prevFm}), class(cnet.run.actvtTyp(1))); 10 | for fm=1:cnet.layer{layer}.numFeature % iteration over featuremaps of this layer 11 | sensitivity{layer-1,prevFm} = sensitivity{layer-1,prevFm} + ... 12 | convn(sensitivity{layer,fm}, cnet.run.actvtTyp(cnet.flipdims(cnet.layer{layer}.W{prevFm,fm})));% was W{fm} 13 | end 14 | sensitivity{layer-1,prevFm} = sensitivity{layer-1,prevFm}.*cnet.nonLinearityD(activityWithoutNL{layer-1,prevFm}); 15 | end 16 | end -------------------------------------------------------------------------------- /retina/CNN/@cnn/cnn.m: -------------------------------------------------------------------------------- 1 | %CNN convolutional neural network class 2 | % Input: 3 | % numHiddenLayer - total number of hidden layers 4 | % numFeature - feature maps per layer 5 | % filterSize - size of filter used by convn 6 | % numLabels - number of maps in output layer 7 | classdef cnn 8 | properties 9 | % Parameters 10 | numHiddenLayer 11 | numFeature 12 | numLabels 13 | numLayer 14 | filterSize 15 | run 16 | % Dependent parameters (calculated when calling initNet) 17 | randOfConvn 18 | layer 19 | % Parameter with default value 20 | normalize = true; 21 | noRandomBias = true; 22 | masking=@(x)~isnan(x); 23 | isoBorder = 1; 24 | outputSize = [5 5 5]; 25 | % Anonymus functions and derivatives (loss func & nonlinearity) 26 | nonLinearity = @(x) 1.7159*tanh(0.66*x); 27 | nonLinearityD =@(x) 1.1325./(cosh(0.66*x).^2); 28 | lossFunction = @(x,y) 0.5*(x-y).^2; 29 | lossFunctionD = @(x,y) (x-y); 30 | end 31 | methods 32 | function cnet = cnn(varargin) 33 | if(nargin~=0) 34 | cnet.numHiddenLayer = varargin{1}; 35 | cnet.numFeature = varargin{2}; 36 | cnet.filterSize = varargin{3}; 37 | cnet.numLabels = varargin{4}; 38 | end 39 | end 40 | % After calling initNet changing parameters passed into constructor 41 | % becomes obsolete! 42 | function cnet = init(cnet) 43 | cnet.numLayer=cnet.numHiddenLayer+2; 44 | cnet.randOfConvn = (cnet.numHiddenLayer + 1) * (cnet.filterSize - 1); 45 | % One map in input and three maps in output layer 46 | cnet.layer{1}.numFeature = 1; 47 | for l=1:cnet.numHiddenLayer 48 | cnet.layer{l+1}.numFeature = cnet.numFeature; 49 | end 50 | cnet.layer{cnet.numHiddenLayer+2}.numFeature = cnet.numLabels; 51 | % Initalize Weights and Biases randomly 52 | for l=2:length(cnet.layer) 53 | cnet.layer{l}.W = cell(cnet.layer{l}.numFeature, 1); 54 | for prevFm=1:cnet.layer{l-1}.numFeature 55 | for fm=1:cnet.layer{l}.numFeature 56 | cnet.layer{l}.W{prevFm,fm} = randn(cnet.filterSize) ... 57 | /(2*sqrt(prod(cnet.filterSize))); 58 | end 59 | end 60 | if cnet.noRandomBias 61 | cnet.layer{l}.B = zeros(1,cnet.layer{l}.numFeature); 62 | else 63 | cnet.layer{l}.B = randn(1,cnet.layer{l}.numFeature); 64 | end 65 | end 66 | end 67 | end 68 | methods(Static) 69 | [target, mask] = probMask( currentTrace ); 70 | end 71 | end -------------------------------------------------------------------------------- /retina/CNN/@cnn/flipdims.m: -------------------------------------------------------------------------------- 1 | function Y = flipdims(~, X) 2 | %flips all dims of X 3 | Y=reshape(X(end:-1:1),size(X));%1.1x(1000x1000 array)-20x(5x5x5x5x5x5 array) speedup (6x at common use) 4 | end 5 | -------------------------------------------------------------------------------- /retina/CNN/@cnn/forAll.m: -------------------------------------------------------------------------------- 1 | function [ cnet ] = forAll( cnet,f ) 2 | %FORALL Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | for i=2:cnet.numLayer 6 | for j=1:cnet.layer{i-1}.numFeature 7 | for k=1:cnet.layer{i}.numFeature 8 | cnet.layer{i}.W{j,k} =f(cnet.layer{i}.W{j,k}); 9 | end 10 | end 11 | cnet.layer{i}.B = f(cnet.layer{i}.B); 12 | end 13 | end 14 | 15 | -------------------------------------------------------------------------------- /retina/CNN/@cnn/fwdPass3D.m: -------------------------------------------------------------------------------- 1 | function [activity, activityWithoutNL] = fwdPass3D(cnet, input) 2 | activity = cell(cnet.numLayer, cnet.numFeature); 3 | activityWithoutNL = cell(cnet.numLayer, cnet.numFeature); 4 | % Cast input to right type in output array & start computation 5 | activity{1,1} = cnet.run.actvtTyp(input); 6 | for layer=2:cnet.numLayer 7 | for fm=1:cnet.layer{layer}.numFeature 8 | activity{layer,fm} = zeros(size(input) - (layer - 1) * (cnet.filterSize - 1), class(cnet.run.actvtTyp(1))); 9 | for oldFm=1:cnet.layer{layer-1}.numFeature 10 | activity{layer, fm} = activity{layer, fm} + convn(activity{layer-1, oldFm}, ... 11 | cnet.run.actvtTyp(cnet.layer{layer}.W{oldFm,fm}), 'valid'); 12 | end 13 | activityWithoutNL{layer, fm} = activity{layer, fm} + cnet.layer{layer}.B(fm); 14 | activity{layer, fm} = cnet.nonLinearity(activityWithoutNL{layer, fm}); 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /retina/CNN/@cnn/fwdPass3Dfaster.m: -------------------------------------------------------------------------------- 1 | function fwdPass3Dfaster(cnet, input, result) 2 | % Load & normalize data and make sure single is used 3 | activity = cell(cnet.numLayer, cnet.numFeature); 4 | bbox(:,1) = input.cube(:,1)*128 + 1 - ceil(cnet.randOfConvn'/2) + 1; 5 | bbox(:,2) = (input.cube(:,1) + 1)*128 + ceil(cnet.randOfConvn'/2); 6 | activity{1,1} = readKnossosRoi(input.root, input.prefix, bbox); 7 | clear gpu_hook; 8 | if cnet.normalize 9 | activity{1,1} = cnet.normalizeStack(cnet.run.actvtTyp(activity{1,1})); 10 | end 11 | % Do the THING 12 | layer = 2; 13 | while size(activity,1) > 1 14 | for fm=1:cnet.layer{layer}.numFeature 15 | activity{2,fm} = zeros(size(activity{1,1}) - (cnet.filterSize - 1), class(cnet.run.actvtTyp(1))); 16 | for oldFm=1:cnet.layer{layer-1}.numFeature 17 | activity{2, fm} = activity{2, fm} + convn(activity{1, oldFm}, ... 18 | cnet.run.actvtTyp(cnet.layer{layer}.W{oldFm,fm}), 'valid'); 19 | end 20 | activity{2, fm} = cnet.nonLinearity(activity{2, fm} + cnet.layer{layer}.B(fm)); 21 | end 22 | activity(1,:) = []; 23 | layer = layer + 1; 24 | end 25 | % Save result to 3 KNOSSOS folders 26 | activity(cellfun(@isempty,activity)) = []; 27 | for i=1:size(activity,2) 28 | writeKnossosCube([result.root result.folders{i} '/'], result.prefix, input.cube, single(activity{1,i}), 'single', ''); 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /retina/CNN/@cnn/gradientPass.m: -------------------------------------------------------------------------------- 1 | function cnet = gradientPass(cnet, activity, sensitivity) 2 | 3 | for layer=2:cnet.numLayer 4 | for prevFm=1:cnet.layer{layer-1}.numFeature 5 | for fm=1:cnet.layer{layer}.numFeature 6 | dW = cnet.flipdims(convn(activity{layer-1,prevFm}, cnet.flipdims(sensitivity{layer,fm}), 'valid')); 7 | if cnet.run.constant_stepsize 8 | dW = dW ./ sum(abs(dW(:))); 9 | end 10 | cnet.layer{layer}.W{prevFm,fm} = cnet.run.wghtTyp(cnet.layer{layer}.W{prevFm,fm} - cnet.run.etaW(cnet.run.iterations) * dW); 11 | end 12 | end 13 | for fm=1:cnet.layer{layer}.numFeature 14 | dB = sum(sensitivity{layer,fm}(:))/numel(sensitivity{layer,fm}); 15 | cnet.layer{layer}.B(fm) = cnet.run.wghtTyp(cnet.layer{layer}.B(fm) - cnet.run.etaB(cnet.run.iterations) * dB); 16 | end 17 | end 18 | end -------------------------------------------------------------------------------- /retina/CNN/@cnn/normalizeStack.m: -------------------------------------------------------------------------------- 1 | function out = normalizeStack(~, in ) 2 | %out = normalizeStack( in ) Subtract mean and devide by std 3 | out = in-mean(in(:)); 4 | out = out/(2*std(out(:))); 5 | end 6 | 7 | -------------------------------------------------------------------------------- /retina/CNN/@cnn/probMask.m: -------------------------------------------------------------------------------- 1 | function [target, mask] = probMask( currentTrace) 2 | %PROBMASK Summary of this function goes here 3 | % Detailed explanation goes here 4 | target0=1==currentTrace;%-min(min(min(currentTrace))); 5 | %target=target/max(max(max(target))); 6 | mask0=ones(size(currentTrace)); 7 | nPos=sum(sum(sum(target0==1))); 8 | nNeg=sum(sum(sum(target0==0))); 9 | mask0(target0==1)=(nNeg/nPos+1)/2; 10 | mask0(target0==0)=(nPos/nNeg+1)/2; 11 | target{1}=target0; 12 | mask{1}=mask0; 13 | end 14 | 15 | -------------------------------------------------------------------------------- /retina/CNN/@cnn/trainGradient.m: -------------------------------------------------------------------------------- 1 | function cnet = trainGradient(cnet, rawData, tracedData, run) 2 | 3 | w = getCurrentWorker(); 4 | if ~isempty(w) 5 | w = w.Name; 6 | gselect(str2double(w(16:17))); 7 | end 8 | % Transfer run to cnet.run (which will be used in this function; cnet.run 9 | % can also be defined before hand) 10 | if(nargin==4) 11 | cnet.run=run; 12 | end 13 | 14 | % Check whether direactory exsist and create otherwise 15 | if(~exist(fullfile(cnet.run.savingPath),'dir')) 16 | mkdir(fullfile(cnet.run.savingPath)); 17 | end 18 | 19 | for iid1 = 1:cnet.run.maxIter 20 | % Set up counter and cell array for erros within GPU task of current minicube 21 | nrFails = 0; 22 | failReport = {}; 23 | % Choose minicube randomly 24 | currentIndex = ceil(length(rawData)*rand); 25 | % For debuging pourpes learn with only one minicube 26 | if cnet.run.debug 27 | currentIndex=2; 28 | end 29 | % Loads variable kl_roi 30 | load(rawData{currentIndex}); 31 | % Loads variable kl_stack (or KLEE_savedStack) 32 | load(tracedData{currentIndex}); 33 | if(exist('KLEE_savedStack','var') && ~exist('kl_stack','var')) 34 | kl_stack=KLEE_savedStack; 35 | clear('KLEE_savedStack'); 36 | end 37 | % Create Task on jobmanager if running on cluster, otherwise just call 38 | % learn 39 | [cnet, error, randEdges, rngState] = cnet.learn( kl_roi, kl_stack); 40 | % Save some data 41 | currentStack = rawData{currentIndex}; 42 | cnet = cnet.forAll(cnet.run.saveTyp); 43 | save(fullfile(cnet.run.savingPath,[ 'saveNet' num2str(iid1, '%010.0f') '.mat']), 'cnet', 'failReport', 'currentStack', 'rngState', 'error', 'randEdges'); 44 | if(~cnet.run.local) 45 | system(['chmod 664 ' fullfile(cnet.run.savingPath,[ 'saveNet' num2str(iid1, '%010.0f') '.mat'])]); 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /retina/CNN/@cnn/xyMask.m: -------------------------------------------------------------------------------- 1 | function [target, mask] = xyMask( ~, currentTrace ) 2 | %mask = cnet.xyzMask(currentTrace) Calculate Masks for three affinity maps in 3 | %output layer and return in cell array 4 | target = cell(2,1); 5 | mask = cell(2,1); 6 | 7 | target{1} = zeros(size(currentTrace)-[0 1]); 8 | for i=1:size(currentTrace,2)-1 9 | target{1}(:,i) = ((currentTrace(:,i) == currentTrace(:,i+1) & currentTrace(:,i) ~= 0) - 0.5) * 2; 10 | end 11 | target{1}(1,:) = []; 12 | 13 | mask{1} = currentTrace(2:end,2:end) ~= 0; 14 | mask{1} = mask{1} | cat(2, zeros(size(mask{1},1),1), mask{1}(:,1:end-1)); 15 | 16 | target{2} = zeros(size(currentTrace)-[1 0]); 17 | for i=1:size(currentTrace,1)-1 18 | target{2}(i,:) = ((currentTrace(i,:) == currentTrace(i+1,:) & currentTrace(i,:) ~= 0) - 0.5) * 2; 19 | end 20 | target{2}(:,1) = []; 21 | 22 | mask{2} = currentTrace(2:end,2:end) ~= 0; 23 | mask{2} = mask{2} | cat(1, zeros(1, size(mask{2},2)), mask{2}(1:end-1,:)); 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /retina/CNN/@cnn/xyzMask.m: -------------------------------------------------------------------------------- 1 | function [target, mask] = xyzMask( cnet, currentTrace ) 2 | %mask = cnet.xyzMask(currentTrace) Calculate Masks for three affinity maps in 3 | %output layer and return in cell array 4 | target = cell(3,1); 5 | mask = cell(3,1); 6 | 7 | target{1} = zeros(size(currentTrace)-[0 1 0]); 8 | for i=1:size(currentTrace,2)-1 9 | target{1}(:,i,:) = ((currentTrace(:,i,:) == currentTrace(:,i+1,:) & currentTrace(:,i,:) ~= 0) - 0.5) * 2; 10 | end 11 | target{1}(1,:,:) = []; 12 | target{1}(:,:,1) = []; 13 | 14 | mask{1} = currentTrace(2:end,2:end,2:end) ~= 0; 15 | mask{1} = mask{1} | cat(2, zeros(size(mask{1},1),1,size(mask{1},3)), mask{1}(:,1:end-1,:)); 16 | 17 | target{2} = zeros(size(currentTrace)-[1 0 0]); 18 | 19 | for i=1:size(currentTrace,1)-1 20 | target{2}(i,:,:) = ((currentTrace(i,:,:) == currentTrace(i+1,:,:) & currentTrace(i,:,:) ~= 0) - 0.5) * 2; 21 | end 22 | target{2}(:,1,:) = []; 23 | target{2}(:,:,1) = []; 24 | 25 | mask{2} = currentTrace(2:end,2:end,2:end) ~= 0; 26 | mask{2} = mask{2} | cat(1, zeros(1, size(mask{2},2), size(mask{2},3)), mask{2}(1:end-1,:,:)); 27 | 28 | target{3} = zeros(size(currentTrace)-[0 0 1]); 29 | for i=1:size(currentTrace,3)-1 30 | target{3}(:,:,i) = ((currentTrace(:,:,i) == currentTrace(:,:,i+1) & currentTrace(:,:,i) ~= 0) - 0.5) * 2; 31 | end 32 | target{3}(1,:,:) = []; 33 | target{3}(:,1,:) = []; 34 | 35 | mask{3} = currentTrace(2:end,2:end,2:end) ~= 0; 36 | mask{3} = mask{3} | cat(3, zeros(size(mask{3},1),size(mask{3},2), 1), mask{3}(:,:,1:end-1)); 37 | 38 | end 39 | 40 | -------------------------------------------------------------------------------- /retina/CNN/@train/train.m: -------------------------------------------------------------------------------- 1 | %TRAIN class representing a trainging run for a cnn 2 | % inputSize - input cube size 3 | % eta - Learning rate 4 | % savingPath - Folder for saving data generated during trainGradient 5 | % maxIter - max number of iterations over samples 6 | % maxIterMini - max number of iterations within a sample 7 | 8 | classdef train 9 | %TRAIN Summary of this class goes here 10 | % Detailed explanation goes here 11 | 12 | properties 13 | % Parameter 14 | inputSize 15 | savingPath 16 | maxIter 17 | maxIterMini 18 | wStart 19 | bStart 20 | % Parameter with default value 21 | etaW=@(X)0.001; 22 | etaB=@(X)0.001; 23 | maxIterRandom = 100; 24 | GPU = true; 25 | local = false; 26 | iterations = 0; 27 | wghtTyp = @single; 28 | actvtTyp = @gsingle; 29 | saveTyp = @single; 30 | debug = false; 31 | debugLearn = false; 32 | percentageReqElem = 0.3; 33 | percentageReqEach = 0.3; 34 | constant_stepsize = false; 35 | costFunctionCutoff = true; 36 | end 37 | methods 38 | function obj = train(varargin) 39 | if(nargin~=0) 40 | obj.inputSize = varargin{1}; 41 | obj.etaW =@(it)varargin{2}; 42 | obj.savingPath = varargin{3}; 43 | obj.maxIter = varargin{4}; 44 | obj.maxIterMini = varargin{5}; 45 | end 46 | end 47 | function obj = setEtaWLinear(obj,etaStart,etaEnd) 48 | obj.etaW=@(i)etaStart+(etaEnd-etaStart)/(obj.maxIter*obj.maxIterMini)*i; 49 | obj.wStart = etaStart; 50 | end 51 | function obj = setEtaWExp(obj,etaStart,etaEnd) 52 | obj.etaW=@(i)etaStart*exp(i*log(etaEnd/etaStart)/(obj.maxIter*obj.maxIterMini)); 53 | obj.wStart = etaStart; 54 | end 55 | function obj = setEtaBLinear(obj,etaStart,etaEnd) 56 | obj.etaB=@(i)etaStart+(etaEnd-etaStart)/(obj.maxIter*obj.maxIterMini)*i; 57 | obj.bStart = etaStart; 58 | end 59 | function obj = setEtaBExp(obj,etaStart,etaEnd) 60 | obj.etaB=@(i)etaStart*exp(i*log(etaEnd/etaStart)/(obj.maxIter*obj.maxIterMini)); 61 | obj.bStart = etaStart; 62 | end 63 | end 64 | end 65 | 66 | -------------------------------------------------------------------------------- /retina/CNN/@train/updateCasts.m: -------------------------------------------------------------------------------- 1 | function run=updateCasts( run ) 2 | %classT = getVarTypeOfCNN( run ) Get variable type to use for a CNN obj 3 | %during GPU operation (classT1) and during CPU operation (classT2) 4 | if run.double 5 | if run.GPU 6 | run.wghtTyp = @gdouble; 7 | else 8 | run.wghtTyp = @double; 9 | end 10 | if run.GPU 11 | run.actvtTyp = @gdouble; 12 | else 13 | run.actvtTyp = @double; 14 | end 15 | run.saveTyp=@double; 16 | else 17 | if run.GPU 18 | run.wghtTyp = @gsingle; 19 | else 20 | run.wghtTyp = @single; 21 | end 22 | if run.GPU 23 | run.atvtTyp = @gsingle; 24 | else 25 | run.atvtTyp= @single; 26 | end 27 | run.saveTyp=@single; 28 | end 29 | 30 | end 31 | 32 | -------------------------------------------------------------------------------- /retina/CNN/bigFwdPass.m: -------------------------------------------------------------------------------- 1 | function bigFwdPass( cnet, input, result, datasetSize) 2 | jm = findResource('scheduler', 'type', 'jobmanager', 'LookupURL', 'fermat01'); 3 | jm = jm(1); 4 | pathToAdd = {'/path/to/some/directory/code/CNN/', '/path/to/some/directory/code/aux/', '/usr/local/jacket/', '/usr/local/jacket/engine/'}; 5 | nrIter = ceil(datasetSize / 128); 6 | for i=1:nrIter(3) 7 | job = createJob(jm); 8 | set(job, 'PathDependencies', pathToAdd); 9 | set(job, 'RestartWorker', 1); 10 | % Set username on cluster here 11 | set(job, 'UserName', 'someUser'); 12 | for j=1:nrIter(2) 13 | for k=1:nrIter(1) 14 | % Account for cubeIDs starting at 0 instead of 1 15 | input.cube = [k-1; j-1; i-1]; 16 | inputargs = {cnet, input, result}; 17 | task = createTask(job, @fwdPass3Dfaster, 0, inputargs); 18 | set(task, 'MaximumNumberOfRetries', 5); 19 | end 20 | end 21 | submit(job); 22 | end 23 | 24 | end 25 | 26 | -------------------------------------------------------------------------------- /retina/CNN/libJobHandling/getKleeStackList.m: -------------------------------------------------------------------------------- 1 | function [ dataRaw, dataTrace ] = getKleeStackList(pathRaw, pathTracing) 2 | %[ dataRaw, dataTrace ] = getKleeStackList() 3 | % Creates two cell arrays with raw and traing data 4 | 5 | % Parameters for file name generation 6 | rawPre = 'e_k0563_ribbon_'; 7 | rawSuf = '_raw.mat'; 8 | startIndex = 16; 9 | 10 | files = dir([pathTracing '*.mat']); 11 | dataRaw = cell(length(files),1); 12 | dataTrace = cell(length(files),1); 13 | for i=1:length(files) 14 | dataRaw{i} = fullfile(pathRaw, [rawPre files(i).name(startIndex:startIndex+3) rawSuf]); 15 | dataTrace{i} = fullfile(pathTracing, files(i).name); 16 | end 17 | 18 | end 19 | 20 | -------------------------------------------------------------------------------- /retina/CNN/libJobHandling/killAllJobs.m: -------------------------------------------------------------------------------- 1 | function killAllJobs(which, finished) 2 | %killJob( jobIDsToKill ) 3 | % Kills jobs on "which" jobmanager (if finsished = 1, only finshed jobs) 4 | 5 | jm = findResource('scheduler', 'type', 'jobmanager', 'LookupURL', 'fermat01'); 6 | if any(which == 1) 7 | if finished 8 | jobs = findJob(jm(1), 'Username', 'someUser', 'state', 'finished'); 9 | else 10 | jobs = findJob(jm(1), 'Username', 'someUser'); 11 | end 12 | if ~isempty(jobs) 13 | destroy(jobs); 14 | end 15 | end 16 | if any(which == 2) 17 | if finished 18 | jobs = findJob(jm(2), 'Username', 'someUser', 'state', 'finished'); 19 | else 20 | jobs = findJob(jm(2), 'Username', 'someUser'); 21 | end 22 | if ~isempty(jobs) 23 | destroy(jobs); 24 | end 25 | end 26 | delete('/path/to/some/directory/fermatResults/activeJobs.mat'); 27 | 28 | end 29 | 30 | -------------------------------------------------------------------------------- /retina/CNN/libJobHandling/killJob.m: -------------------------------------------------------------------------------- 1 | function killJob( numbers ) 2 | %killJob( jobIDsToKill ) 3 | % Kills jobs with same parameters as cnet 4 | load /path/to/some/directory/fermatResults/activeJobs.mat; 5 | 6 | nets = fieldnames(jobs); 7 | jobIDs = cell(length(numbers),1); 8 | randNumber = cell(length(numbers),1); 9 | for nr =1:length(numbers) 10 | for i=1:length(nets) 11 | if sum(jobs.(nets{i}).rand == numbers{nr}); 12 | jobIDs{nr} = jobs.(nets{i}).id; 13 | randNumber{nr} = jobs.(nets{i}).rand; 14 | end 15 | end 16 | end 17 | jobIDs(cellfun('isempty',jobIDs)) = []; 18 | randNumber(cellfun('isempty',randNumber)) = []; 19 | jm = findResource('scheduler', 'type', 'jobmanager', 'configuration', 'FermatGPU'); 20 | for i = 1:length(jobIDs) 21 | job = findJob(jm, 'Username', 'someUser', 'ID', jobIDs{i}); 22 | destroy(job); 23 | jobs = rmfield(jobs, ['net' num2str(randNumber{i}, '%6.6u')]); 24 | end 25 | 26 | save('/path/to/some/directory/fermatResults/activeJobs.mat', 'jobs'); 27 | 28 | end 29 | 30 | -------------------------------------------------------------------------------- /retina/CNN/libJobHandling/saveJobParamToXls.m: -------------------------------------------------------------------------------- 1 | function saveJobParamToXls( cnet, folder ) 2 | %function saveJobParamToXls( cnet, folder ) 3 | % Save CNN parametrs to Excel File 4 | if ~exist(folder,'dir') 5 | mkdir(folder); 6 | end 7 | fid = fopen([folder 'parameter.xls'], 'a'); 8 | par = fieldnames(cnet); 9 | for i=1:length(par) 10 | if ~strcmp(par{i},'run') && ~strcmp(par{i}, 'layer') 11 | if strcmp(class(cnet.(par{i})), 'function_handle') 12 | fprintf(fid, '%s\t', func2str(cnet.(par{i}))); 13 | elseif isnumeric(cnet.(par{i})) 14 | fprintf(fid, '%s\t', num2str(cnet.(par{i}))); 15 | else 16 | fprintf(fid, '%s\t', cnet.(par{i})); 17 | end 18 | end 19 | end 20 | parRun = fieldnames(cnet.run); 21 | for i=1:length(parRun) 22 | if strcmp(class(cnet.run.(parRun{i})), 'function_handle') 23 | fprintf(fid, '%s\t', func2str(cnet.run.(parRun{i}))); 24 | elseif isnumeric(cnet.run.(parRun{i})) 25 | fprintf(fid, '%s\t', num2str(cnet.run.(parRun{i}))); 26 | else 27 | fprintf(fid, '%s\t', cnet.run.(parRun{i})); 28 | end 29 | end 30 | fprintf(fid, '\n'); 31 | fclose(fid); 32 | 33 | end 34 | 35 | -------------------------------------------------------------------------------- /retina/CNN/libJobHandling/submitJob.m: -------------------------------------------------------------------------------- 1 | function submitJob( cnet, dataRaw, dataTrace, outputDir ) 2 | %createJob( cnet ) 3 | % Create Job training CNN on cluster 4 | 5 | % Load parcluster configuration 6 | global jobManagerName; 7 | jm = parcluster(jobManagerName); 8 | 9 | % Create random string for identification of network 10 | rng('shuffle'); % Set RNG to 'random' state based on time 11 | randNumber = floor(rand*1000000); 12 | randString = [date filesep 'net' num2str(randNumber, '%6.6u')]; 13 | resultDir = [outputDir randString filesep]; 14 | 15 | % Create Directories for saving results & start learning 16 | if(exist(resultDir,'dir')) 17 | error(['Folder already exsits: ' resultDir ' Please retry.']); 18 | else 19 | mkdir(resultDir); 20 | cnet.run.savingPath = resultDir; 21 | % Create job on cluster 22 | job = createJob(jm); 23 | inputargs = {cnet, dataRaw, dataTrace}; 24 | createTask(job, @trainGradient, 1, inputargs); 25 | % Save CNN Parameter values to Excel File 26 | saveJobParamToXls(cnet, [resultDir filesep date filesep]); 27 | % Start job and save job in "DB" 28 | if exist([resultDir filesep 'activeJobs.mat'], 'file') 29 | load([resultDir filesep 'activeJobs.mat']); 30 | end 31 | jobs.(['net' num2str(randNumber, '%6.6u')]).rand = randNumber; 32 | jobs.(['net' num2str(randNumber, '%6.6u')]).date = date; 33 | jobs.(['net' num2str(randNumber, '%6.6u')]).id = job.ID; 34 | save([resultDir filesep 'activeJobs.mat'], 'jobs'); 35 | submit(job); 36 | end 37 | 38 | end 39 | 40 | -------------------------------------------------------------------------------- /retina/CNN/loadCNNResults.m: -------------------------------------------------------------------------------- 1 | function [results, nrIter] = loadCNNResults( path, var ) 2 | %[results, nrIter] = loadCNNResults( path ) 3 | % var = {'cnet', 'failReport', 'currentStack', 'rngState', 'error', 'randEdges'}; 4 | % Switch warnings off because jobs and workers can not be recieved an will 5 | % produce error each 6 | warning off; 7 | nrIter = length(dir([path 'saveNet' '*'])); 8 | if nrIter == 0 9 | results = struct(); 10 | end 11 | for i=1:nrIter 12 | load([path 'saveNet' num2str(i, '%010.0f') '.mat']); 13 | for v=1:length(var) 14 | results.(var{v}){i} = eval(var{v}); 15 | end 16 | end 17 | warning on; 18 | end 19 | 20 | -------------------------------------------------------------------------------- /retina/CNN/loadSingleCNN.m: -------------------------------------------------------------------------------- 1 | function [result, nrIter] = loadSingleCNN( path, iter ) 2 | %[results, nrIter] = loadCNNResults( path ) 3 | 4 | nrIter = length(dir([path 'saveNet' '*'])); 5 | if nrIter == 0 6 | result = struct(); 7 | else 8 | if nargin == 1 9 | iter = nrIter; 10 | end 11 | load([path 'saveNet' num2str(iter, '%010.0f') '.mat']); 12 | result = eval('cnet'); 13 | end 14 | 15 | 16 | 17 | end 18 | 19 | -------------------------------------------------------------------------------- /retina/CNN/minicubeFwdPass.m: -------------------------------------------------------------------------------- 1 | function job = minicubeFwdPass( parameter ) 2 | % classification of subregions within the data set (for segmentation optimization and GP training) 3 | 4 | load(parameter.cnn.first, 'cnet'); 5 | 6 | for tr=1:length(parameter.local) 7 | bbox = parameter.local(tr).bboxSmall; 8 | functionH{tr} = @onlyFwdPass3DonKnossosFolder; 9 | inputCell{tr} = {cnet, parameter.cnn.GPU, parameter.raw, parameter.local(tr).class, bbox}; 10 | end 11 | 12 | if parameter.cnn.GPU 13 | job = startGPU(functionH, inputCell, 'classification'); 14 | else 15 | job = startCPU(functionH, inputCell, 'classification'); 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /retina/CNN/normalizeStack.m: -------------------------------------------------------------------------------- 1 | function out = normalizeStack( in ) 2 | %out = normalizeStack( in ) Subtract mean and devide by std 3 | out = in-mean(in(:)); 4 | out = out/std(out(:)); 5 | end 6 | 7 | -------------------------------------------------------------------------------- /retina/CNN/visualization/plotError.m: -------------------------------------------------------------------------------- 1 | function plotError( struct, sizeMovAvg ) 2 | %plotError( struct, sizeMovAvg ) 3 | % Plot errors and save to file 4 | 5 | a = 1; 6 | b = 1/sizeMovAvg*ones(sizeMovAvg,1); 7 | colors = {'r' 'g' 'b' 'y' 'k' 'c' ':r' ':g' ':b' ':y' ':k' ':c' '--r' '--g' '--b' '--y' '--k' '--c' 'r' 'g' 'b' 'y' 'k' 'c' ':r' ':g' ':b' ':y' ':k' ':c' '--r' '--g' '--b' '--y' '--k' '--c'}; 8 | figure('Visible', 'off'); 9 | hold on; 10 | 11 | fields = fieldnames(struct); 12 | nrIter = zeros(length(fields),1); 13 | for i=1:length(fields) 14 | [result, nrIter(i)] = loadCNNResults(['/path/to/some/directory/fermatResults/' struct.(fields{i}).date '/net' num2str(struct.(fields{i}).rand, '%6.6u') '/'], {'error'}); 15 | [cnet, ~] = loadSingleCNN(['/path/to/some/directory/fermatResults/' struct.(fields{i}).date '/net' num2str(struct.(fields{i}).rand, '%6.6u') '/']); 16 | maxIterMini = cnet.run.maxIterMini; 17 | error = zeros(length(result.error)*maxIterMini,1); 18 | errorC = zeros(length(result.error)*maxIterMini,1); 19 | for j=1:length(result.error) 20 | for k=1:length(result.error{j}) 21 | errorC(k+(j-1)*maxIterMini) = result.error{j}{k}.cutoff; 22 | error(k+(j-1)*maxIterMini) = result.error{j}{k}.all; 23 | end 24 | end 25 | error(isnan(error)) = 0; 26 | errorC(isnan(errorC)) = 0; 27 | subplot(2,1,1); 28 | plot(filter(b,a,error), colors{i}); 29 | hold on; 30 | title('Pixel-Error in all Affinity Maps'); 31 | subplot(2,1,2); 32 | plot(filter(b,a,errorC), colors{i}); 33 | hold on; 34 | title('Pixel-Error in all Affinity Maps with Cutoff'); 35 | end 36 | n = max(nrIter)*maxIterMini; 37 | subplot(2,1,1); 38 | xlim([sizeMovAvg+1 n-sizeMovAvg]); 39 | ylim([-10e-2 10e-2]); 40 | subplot(2,1,2); 41 | xlim([sizeMovAvg+1 n-sizeMovAvg]); 42 | ylim([-10e-2 10e-2]); 43 | legend(fields, 'Location', 'BestOutside'); 44 | 45 | % Save to PDF file in sync folder 46 | set(gcf, 'PaperPosition', [0 0 15 10]); 47 | set(gcf, 'PaperSize', [15 10]); 48 | print('-dpdf', ['/path/to/some/directory/sync/toP1-377/PDF/' struct.(fields{i}).date '/error.pdf']); 49 | close all; 50 | 51 | end 52 | 53 | -------------------------------------------------------------------------------- /retina/CNN/visualization/plotErrorBinned.m: -------------------------------------------------------------------------------- 1 | function plotErrorBinned( struct ) 2 | %plotError( struct, sizeMovAvg ) 3 | % Plot errors and save to file 4 | 5 | colors = {'sr' 'sg' 'sb' 'sy' 'sk' 'sc' 'dr' 'dg' 'db' 'dy' 'dk' 'dc' 'or' 'og' 'ob' 'oy' 'ok' 'oc'}; 6 | figure('Visible', 'off'); 7 | hold on; 8 | 9 | fields = fieldnames(struct); 10 | nrIter = zeros(length(fields),1); 11 | for i=1:length(fields) 12 | [result, nrIter(i)] = loadCNNResults(['/path/to/some/directory/fermatResults/' struct.(fields{i}).date '/net' num2str(struct.(fields{i}).rand, '%6.6u') '/'], {'error'}); 13 | [cnet, ~] = loadSingleCNN(['/path/to/some/directory/fermatResults/' struct.(fields{i}).date '/net' num2str(struct.(fields{i}).rand, '%6.6u') '/']); 14 | maxIterMini = cnet.run.maxIterMini; 15 | errorMean = zeros(length(result.error),1); 16 | errorMeanC = zeros(length(result.error),1); 17 | errorStd = zeros(length(result.error),1); 18 | errorStdC = zeros(length(result.error),1); 19 | temp = zeros(maxIterMini, 1); 20 | tempC = zeros(maxIterMini, 1); 21 | for j=1:length(result.error) 22 | for k=1:length(result.error{j}) 23 | temp(k) = result.error{j}{k}.all; 24 | tempC(k) = result.error{j}{k}.cutoff; 25 | end 26 | errorMean(j) = mean(temp); 27 | errorMeanC(j) = mean(tempC); 28 | errorStd(j) = std(temp); 29 | errorStdC(j) = std(tempC); 30 | end 31 | errorMean(isnan(errorMean)) = 0; 32 | errorMeanC(isnan(errorMeanC)) = 0; 33 | subplot(2,1,1); 34 | errorbar(errorMean, errorStd, colors{i}); 35 | hold on; 36 | title('Pixel-Error in all Affinity Maps'); 37 | subplot(2,1,2); 38 | errorbar(errorMeanC, errorStdC, colors{i}); 39 | hold on; 40 | title('Pixel-Error in all Affinity Maps with Cutoff'); 41 | end 42 | legend(fields, 'Location', 'BestOutside'); 43 | 44 | % Save to PDF file in sync folder 45 | set(gcf, 'PaperPosition', [0 0 15 10]); 46 | set(gcf, 'PaperSize', [15 10]); 47 | print('-dpdf', ['/path/to/some/directory/sync/toP1-377/PDF/' struct.(fields{i}).date '/errorB.pdf']); 48 | close all; 49 | 50 | end 51 | 52 | -------------------------------------------------------------------------------- /retina/CNN/visualization/plotErrorResorted.m: -------------------------------------------------------------------------------- 1 | function plotErrorResorted( struct ) 2 | %plotError( struct, sizeMovAvg ) 3 | % Plot errors and save to file 4 | 5 | colors = {'sr' 'sg' 'sb' 'sy' 'sk' 'sc' 'dr' 'dg' 'db' 'dy' 'dk' 'dc' 'or' 'og' 'ob' 'oy' 'ok' 'oc'}; 6 | figure('Visible', 'off'); 7 | hold on; 8 | 9 | fields = fieldnames(struct); 10 | nrIter = zeros(length(fields),1); 11 | for i=1:length(fields) 12 | [result, nrIter(i)] = loadCNNResults(['/path/to/some/directory/fermatResults/' struct.(fields{i}).date '/net' num2str(struct.(fields{i}).rand, '%6.6u') '/'], {'error' 'currentStack'}); 13 | [cnet, ~] = loadSingleCNN(['/path/to/some/directory/fermatResults/' struct.(fields{i}).date '/net' num2str(struct.(fields{i}).rand, '%6.6u') '/']); 14 | maxIterMini = cnet.run.maxIterMini; 15 | errorMean = zeros(length(result.error),1); 16 | errorMeanC = zeros(length(result.error),1); 17 | errorStd = zeros(length(result.error),1); 18 | errorStdC = zeros(length(result.error),1); 19 | currentStack = zeros(length(result.currentStack),1); 20 | temp = zeros(maxIterMini, 1); 21 | tempC = zeros(maxIterMini, 1); 22 | for j=1:length(result.error) 23 | for k=1:length(result.error{j}) 24 | temp(k) = result.error{j}{k}.all; 25 | tempC(k) = result.error{j}{k}.cutoff; 26 | end 27 | temp(isnan(temp)) = []; 28 | tempC(isnan(tempC)) = []; 29 | errorMeanC(isnan(errorMeanC)) = 0; 30 | currentStack(j) = str2double(result.currentStack{j}(48:51)); 31 | errorMean(j) = mean(temp); 32 | errorMeanC(j) = mean(tempC); 33 | errorStd(j) = std(temp); 34 | errorStdC(j) = std(tempC); 35 | end 36 | [currentStack, ind] = sort(currentStack); 37 | current = 0; 38 | for j=1:length(currentStack) 39 | if current ~= currentStack(j) 40 | current = currentStack(j); 41 | counter = 0; 42 | else 43 | counter = counter + 1; 44 | end 45 | currentStack(j) = current + counter * 0.1; 46 | end 47 | errorMean = errorMean(ind); 48 | errorMeanC = errorMeanC(ind); 49 | errorStd = errorStd(ind); 50 | errorStdC = errorStdC(ind); 51 | subplot(2,1,1); 52 | errorbar(currentStack, errorMean, errorStd, colors{i}); 53 | xlim([0 236]); 54 | grid on; grid minor; 55 | hold on; 56 | title('Pixel-Error resorted by cube identity'); 57 | subplot(2,1,2); 58 | errorbar(currentStack, errorMeanC, errorStdC, colors{i}); 59 | xlim([0 236]); 60 | grid on; grid minor; 61 | hold on; 62 | title('Pixel-Error resorted by cube identity with Cutoff'); 63 | end 64 | legend(fields, 'Location', 'BestOutside'); 65 | 66 | % Save to PDF file in sync folder 67 | set(gcf, 'PaperPosition', [0 0 15 10]); 68 | set(gcf, 'PaperSize', [15 10]); 69 | print('-dpdf', ['/path/to/some/directory/sync/toP1-377/PDF/' struct.(fields{i}).date '/errorR.pdf']); 70 | close all; 71 | 72 | end 73 | 74 | -------------------------------------------------------------------------------- /retina/segmentation/correctSkeletonsToBBox.m: -------------------------------------------------------------------------------- 1 | function skel = correctSkeletonsToBBox( skel, sizeCube ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | if nargin == 1 5 | sizeCube = [384 384 384]; 6 | end 7 | allToBig = [0 0 0]; 8 | allToSmall = [0 0 0]; 9 | allToDel = 0; 10 | 11 | for l=1:size(skel,2) 12 | if isfield(skel{l}, 'nodesNumDataAll') 13 | % Correct for skeletons running out of minicube 14 | tooSmall = skel{l}.nodesNumDataAll(:,3:5) < ones(size(skel{l}.nodesNumDataAll,1),3); 15 | tooBig = skel{l}.nodesNumDataAll(:,3:5) > repmat(sizeCube,size(skel{l}.nodesNumDataAll,1),1); 16 | toDel = any(tooSmall,2) | any(tooBig,2); 17 | if any(toDel) 18 | display(['Skeleton ' num2str(l) ': Nodes to be removed: ' num2str(sum(tooSmall,1)) ' too small, ' num2str(sum(tooBig,1)) ' too big.']); 19 | allToBig = allToBig + sum(tooBig,1); 20 | allToSmall = allToSmall + sum(tooSmall,1); 21 | allToDel = allToDel + sum(toDel); 22 | end 23 | skel{l}.nodesNumDataAll(toDel,:) = []; 24 | edgesToDel = find(toDel); 25 | edgeIdx = unique(skel{l}.edges(:)); 26 | for idx=1:length(edgesToDel) 27 | [row,~] = find(edgesToDel(idx) == skel{l}.edges); 28 | skel{l}.edges(row,:) = []; 29 | edgeIdx(edgeIdx == edgesToDel(idx)) = []; 30 | end 31 | edgeIdxNew = (1:length(edgeIdx))'; 32 | for idx=1:length(edgeIdxNew) 33 | renumber = skel{l}.edges == edgeIdx(idx); 34 | skel{l}.edges(renumber) = edgeIdxNew(idx); 35 | end 36 | if sum(toDel ~= 0) 37 | display(['Skeleton ' num2str(l) ': ' num2str(sum(toDel)) ' nodes removed.']); 38 | end 39 | end 40 | end 41 | display('TOTAL:'); 42 | display(['Nodes removed: ' num2str(allToSmall) ' too small, ' num2str(allToBig) ' too big.']); 43 | display(['Total number: ' num2str(allToDel) ' nodes removed.']); 44 | end 45 | -------------------------------------------------------------------------------- /retina/segmentation/evalParameterSegmentation.m: -------------------------------------------------------------------------------- 1 | function param = evalParameterSegmentation( param ) 2 | %UNTITLED4 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | for map=1:size(param.affMaps,1) 6 | display(['Evaluation: CNN # ' num2str(map) '/' num2str(size(param.affMaps,1))]); 7 | tic; 8 | for r=1:length(param.r) 9 | for algo=1:size(param.algo,2) 10 | if exist([param.dataFolder param.outputSubfolder filesep param.affMaps(map).name filesep 'seg' num2str(r) '-' num2str(algo) '.mat'], 'file'); 11 | a = load([param.dataFolder param.outputSubfolder param.affMaps(map).name filesep 'seg' num2str(r) '-' num2str(algo) '.mat']); 12 | eval = evaluateSeg(a.v, param.skel, param.nodeThres); 13 | parsave([param.dataFolder param.outputSubfolder filesep param.affMaps(map).name filesep 'evaluation' num2str(r) '-' num2str(algo) '.mat'], eval); 14 | end 15 | end 16 | end 17 | toc 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /retina/segmentation/evaluateSeg.m: -------------------------------------------------------------------------------- 1 | function eval = evaluateSeg( segmentation, skeletons, nodeThres ) 2 | %UNTITLED3 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | general = struct('equivMatrix', {}, 'maxNrObjects', {}); 6 | nodes = cell(length(size(skeletons,2)),1); 7 | split = struct('vec', {}, 'idx', {}, 'obj', {}, 'sum', {}); 8 | merge = struct('vec', {}, 'idx', {}, 'obj', {}, 'sum', {}); 9 | for i=1:size(segmentation,1) 10 | for j=1:size(segmentation,2) 11 | for k=1:size(segmentation,3) 12 | display(num2str([i j k])); 13 | general(i,j,k).maxNrObjects = single(length(unique(segmentation{i,j,k}(:)))); 14 | general(i,j,k).equivMatrix = zeros(size(skeletons,2), single(max(segmentation{i,j,k}(:)))); 15 | for l=1:size(skeletons,2) 16 | if size(skeletons{l}.nodes,1) > 1 17 | nodes{l} = skeletons{l}.nodes(:,1:3); 18 | for m=1:size(nodes{l},1) 19 | if segmentation{i,j,k}(nodes{l}(m,1), nodes{l}(m,2), nodes{l}(m,3)) 20 | general(i,j,k).equivMatrix(l,segmentation{i,j,k}(nodes{l}(m,1), nodes{l}(m,2), nodes{l}(m,3))) = ... 21 | general(i,j,k).equivMatrix(l,segmentation{i,j,k}(nodes{l}(m,1), nodes{l}(m,2), nodes{l}(m,3))) + 1; 22 | end 23 | end 24 | end 25 | end 26 | general(i,j,k).equivMatrixBinary = general(i,j,k).equivMatrix >= nodeThres; 27 | % Calculate Splits 28 | split(i,j,k).vec = sum(general(i,j,k).equivMatrixBinary,2); 29 | split(i,j,k).idx = find(split(i,j,k).vec > 1); 30 | split(i,j,k).obj = cell(length(split(i,j,k).idx),1); 31 | for m=1:length(split(i,j,k).idx) 32 | split(i,j,k).obj{m} = find(general(i,j,k).equivMatrixBinary(split(i,j,k).idx(m),:)); 33 | end 34 | split(i,j,k).sum = sum(split(i,j,k).vec(split(i,j,k).idx)-1); 35 | % Calculate Merger 36 | merge(i,j,k).vec = sum(general(i,j,k).equivMatrixBinary,1); 37 | merge(i,j,k).idx = find(merge(i,j,k).vec > 1); 38 | merge(i,j,k).obj = cell(length(merge(i,j,k).idx),1); 39 | for m=1:length(merge(i,j,k).idx) 40 | merge(i,j,k).obj{m} = find(general(i,j,k).equivMatrixBinary(:,merge(i,j,k).idx(m))); 41 | end 42 | merge(i,j,k).sum = sum(merge(i,j,k).vec(merge(i,j,k).idx)-1); 43 | end 44 | end 45 | end 46 | 47 | eval.general = general; 48 | eval.nodes = nodes; 49 | eval.split = split; 50 | eval.merge = merge; 51 | 52 | end 53 | 54 | -------------------------------------------------------------------------------- /retina/segmentation/getPathLength.m: -------------------------------------------------------------------------------- 1 | function totalLength = getPathLength( skeleton ) 2 | 3 | if isempty(skeleton{1}.parameters) 4 | voxelsize= [1 1 1]; 5 | else 6 | voxelsize = [str2double(skeleton{1}.parameters.scale.x) ... 7 | str2double(skeleton{1}.parameters.scale.y) ... 8 | str2double(skeleton{1}.parameters.scale.z)]; 9 | end 10 | 11 | totalLength = 0; 12 | for sk=1:length(skeleton) 13 | if ~isempty(skeleton{sk}) 14 | if size(skeleton{sk}.edges,2) == 1 15 | % skeleton edges seem to switch dimensionality if only 16 | % one edge is present 17 | edgePos = skeleton{sk}.nodes(skeleton{sk}.edges(:,1)',1:3); 18 | totalLength = totalLength + norm((edgePos(1,:)-edgePos(2,:)).*voxelsize); 19 | else 20 | for ed=1:size(skeleton{sk}.edges,1) 21 | edgePos = skeleton{sk}.nodes(skeleton{sk}.edges(ed,:),1:3); 22 | totalLength = totalLength + norm((edgePos(1,:)-edgePos(2,:)).*voxelsize); 23 | end 24 | end 25 | end 26 | end 27 | 28 | end -------------------------------------------------------------------------------- /retina/segmentation/morphR.m: -------------------------------------------------------------------------------- 1 | function morphR( param ) 2 | 3 | parfor map=1:size(param.affMaps,1) 4 | display(['Morphological Reconstruction: CNN # ' num2str(map) '/' num2str(size(param.affMaps,1))]); 5 | tic; 6 | a = load([param.dataFolder param.affSubfolder param.affMaps(map).name '.mat'], 'affX', 'affY', 'affZ'); 7 | aff = {a.affX a.affY a.affZ}; 8 | affReconRecon = cell(length(aff),1); 9 | for r=1:length(param.r) 10 | rT = param.r(r); 11 | for dir=1:length(aff) 12 | if rT ~= 0 13 | [x,y,z] = meshgrid(-rT:rT,-rT:rT,-rT:rT); 14 | se = (x/rT).^2 + (y/rT).^2 + (z/rT).^2 <= 1; 15 | % Opening by reconstruction 16 | affEroded = imerode(aff{dir}, se); 17 | affRecon = imreconstruct(affEroded, aff{dir}); 18 | % Closing by reconstruction 19 | affReconDilated = imdilate(affRecon, se); 20 | affReconRecon{dir} = imreconstruct(imcomplement(affReconDilated), imcomplement(affRecon)); 21 | % affReconRecon{dir} = imcomplement(affReconRecon{dir}); 22 | else 23 | affReconRecon{dir} = imcomplement(aff{dir}); 24 | end 25 | end 26 | if ~exist([param.dataFolder param.outputSubfolder param.affMaps(map).name '/'], 'dir') 27 | mkdir([param.dataFolder param.outputSubfolder param.affMaps(map).name '/']); 28 | end 29 | parsave([param.dataFolder param.outputSubfolder param.affMaps(map).name filesep 'MorphRecon' num2str(r) '.mat'], affReconRecon); 30 | end 31 | toc 32 | end 33 | 34 | 35 | end 36 | 37 | -------------------------------------------------------------------------------- /retina/segmentation/parsave.m: -------------------------------------------------------------------------------- 1 | function parsave( filepathname, v ) 2 | 3 | save( filepathname, 'v', '-v7.3' ); 4 | 5 | end 6 | -------------------------------------------------------------------------------- /retina/segmentation/scanParameterSegmentation.m: -------------------------------------------------------------------------------- 1 | function scanParameterSegmentation( param ) 2 | %UNTITLED4 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | for map=1:size(param.affMaps,1) 6 | display(['Segmentation: CNN # ' num2str(map) '/' num2str(size(param.affMaps,1))]); 7 | tic; 8 | for r=1:length(param.r) 9 | a = load([param.dataFolder param.outputSubfolder param.affMaps(map).name filesep 'MorphRecon' num2str(r) '.mat']); 10 | for algo=1:size(param.algo,2) 11 | if strcmp(param.algo{algo}, 'v1') 12 | segmentation = watershedSeg_v1_paper(a.v, param.pR{map,algo}{1}, param.pR{map,algo}{2}); 13 | end 14 | if strcmp(param.algo{algo}, 'v2') 15 | segmentation = watershedSeg_v2_paper(a.v, param.pR{map,algo}{1}, param.pR{map,algo}{2}); 16 | end 17 | if strcmp(param.algo{algo}, 'v3') 18 | segmentation = watershedSeg_v3_paper(a.v, param.pR{map,algo}{1}, param.pR{map,algo}{2}); 19 | end 20 | parsave([param.dataFolder param.outputSubfolder param.affMaps(map).name filesep 'seg' num2str(r) '-' num2str(algo) '.mat'], segmentation); 21 | end 22 | end 23 | toc 24 | end 25 | 26 | end 27 | 28 | -------------------------------------------------------------------------------- /retina/segmentation/switchToLocalCoords.m: -------------------------------------------------------------------------------- 1 | function skel = switchToLocalCoords( skel, cubeIDs, cubeSwitch ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | if nargin == 2 || cubeSwitch == 1 5 | for l=1:size(skel,2) 6 | if isfield(skel{l}, 'nodesNumDataAll') 7 | skel{l}.nodesNumDataAll(:,3:5) = skel{l}.nodesNumDataAll(:,3:5) - repmat(( cubeIDs * 128) + [0 0 0],size(skel{l}.nodesNumDataAll,1),1); 8 | end 9 | end 10 | else 11 | for l=1:size(skel,2) 12 | if isfield(skel{l}, 'nodesNumDataAll') 13 | skel{l}.nodesNumDataAll(:,3:5) = skel{l}.nodesNumDataAll(:,3:5) - repmat(cubeIDs,size(skel{l}.nodesNumDataAll,1),1); 14 | end 15 | end 16 | end 17 | 18 | end 19 | 20 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/autoKLEE_colormap.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhlabCodingTeam/SegEM/a61ff23875ef36cf6c851ae3112cbdc640ece43f/retina/segmentation/visualization/autoKLEE_colormap.mat -------------------------------------------------------------------------------- /retina/segmentation/visualization/makeErrorMovies.m: -------------------------------------------------------------------------------- 1 | function makeErrorMovies( raw, segmentation, nodes, split, merge, iRange, jRange, kRange, viewErrors, viewSplits, colormap, outputDir ) 2 | %UNTITLED2 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | colors = {'or' 'og' 'ob' 'oy' 'oc' 'om'}; 6 | 7 | for i=iRange 8 | for j=jRange 9 | for k=kRange 10 | % for errorIdx=1:length(merge(i,j,k).obj) 11 | % writerObj = VideoWriter([outputDir 'error' num2str(errorIdx, '%3.3i') '.avi']); 12 | % writerObj.FrameRate = 4; 13 | % open(writerObj); 14 | for f=1:384 15 | hold off; 16 | imshow(raw(:,:,f)); 17 | hold on; 18 | if ~viewErrors 19 | temp = label2rgb(segmentation{i,j,k}(:,:,f), repmat(colormap,100,1)); 20 | else 21 | if viewSplits 22 | % implementation of split viewing to be done 23 | else 24 | temp = single(segmentation{i,j,k}(:,:,f)); 25 | temp(temp == merge(i,j,k).idx(errorIdx)) = -1; 26 | temp(temp ~= -1) = 0; 27 | temp(temp == -1) = 255; 28 | temp = uint8(temp); 29 | temp = label2rgb(temp, 'jet'); 30 | for m=1:length(merge(i,j,k).obj{errorIdx}) 31 | if sum(nodes{merge(i,j,k).obj{errorIdx}(m)}(:,3) == f) 32 | idNodes = find(nodes{merge(i,j,k).obj{errorIdx}(m)}(:,3) == f); 33 | plot(nodes{merge(i,j,k).obj{errorIdx}(m)}(idNodes,2), nodes{merge(i,j,k).obj{errorIdx}(m)}(idNodes,1), colors{rem(m,6)+1}, 'LineWidth', 3); 34 | end 35 | end 36 | end 37 | end 38 | % himage = imshow(temp); 39 | % set(himage, 'AlphaData', 0.2 ); 40 | % title([num2str(i) num2str(j) num2str(k) ': ' num2str(errorIdx, '%3.3i')]); 41 | if f == 1 42 | set(gcf,'NextPlot','replacechildren'); 43 | set(gcf,'Renderer','OpenGL'); 44 | end 45 | drawnow; 46 | % writeVideo(writerObj,getframe(gca, [0 0 384 384])); 47 | % pause(.2); 48 | saveas(gcf, [outputDir num2str(f, '%3.0i') '.pdf']); 49 | end 50 | % close(writerObj); 51 | % end 52 | end 53 | end 54 | end 55 | 56 | end 57 | 58 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/makeErrorMoviesP.m: -------------------------------------------------------------------------------- 1 | function makeErrorMoviesP( param, eval, segmentation, raw, par1, par2) 2 | %UNTITLED2 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | colors = {'or' 'og' 'ob' 'oy' 'oc' 'om'}; 6 | 7 | for errorIdx=1:length(eval.merge(par1,par2).obj) 8 | figure; 9 | writerObj = VideoWriter([param.dataFolder param.figureSubfolder param.subfolder '/errorMovie' num2str(errorIdx, '%2.2i')]); 10 | writerObj.FrameRate = 4; 11 | open(writerObj); 12 | for f=1:size(raw,3) 13 | hold off; 14 | imshow(raw(:,:,f), [60 180]); 15 | hold on; 16 | temp = single(segmentation{par1,par2}(:,:,f)); 17 | temp(temp == eval.merge(par1,par2).idx(errorIdx)) = -1; 18 | temp(temp ~= -1) = 0; 19 | temp(temp == -1) = 255; 20 | temp = uint8(temp); 21 | temp = label2rgb(temp, 'jet'); 22 | str = []; 23 | for m=1:length(eval.merge(par1,par2).obj{errorIdx}) 24 | str = [str num2str(eval.merge(par1,par2).obj{errorIdx}(m)) ' ']; 25 | if sum(eval.nodes{eval.merge(par1,par2).obj{errorIdx}(m)}(:,3) == f) 26 | idNodes = find(eval.nodes{eval.merge(par1,par2).obj{errorIdx}(m)}(:,3) == f); 27 | plot(eval.nodes{eval.merge(par1,par2).obj{errorIdx}(m)}(idNodes,2), eval.nodes{eval.merge(par1,par2).obj{errorIdx}(m)}(idNodes,1), colors{rem(m,6)+1}, 'LineWidth', 3); 28 | end 29 | end 30 | himage = imshow(temp); 31 | set(himage, 'AlphaData', 0.15 ); 32 | if f == 1 33 | set(gcf,'NextPlot','replacechildren'); 34 | set(gcf,'Renderer','OpenGL'); 35 | end 36 | title(['Skeletons (KNOSSOS ID): ' str]); 37 | drawnow; 38 | writeVideo(writerObj,getframe(gca, [1 1 384 384])); 39 | end 40 | close(writerObj); 41 | close all; 42 | end 43 | 44 | end 45 | 46 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/makeErrorStacksP.m: -------------------------------------------------------------------------------- 1 | function makeErrorStacksP( param, eval, segmentation, raw, par1, par2) 2 | %UNTITLED2 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | % colors = {'or' 'og' 'ob' 'oy' 'oc' 'om'}; 6 | 7 | for errorIdx=1:length(eval.merge(par1,par2).obj) 8 | temp = single(segmentation{par1,par2}); 9 | temp(temp == eval.merge(par1,par2).idx(errorIdx)) = -1; 10 | temp(temp ~= -1) = 0; 11 | temp(temp == -1) = 255; 12 | obj = uint8(temp); 13 | skel = zeros(size(raw)); 14 | for m=1:length(eval.merge(par1,par2).obj{errorIdx}) 15 | idNodes = eval.nodes{eval.merge(par1,par2).obj{errorIdx}(m)}; 16 | skel(sub2ind(size(skel), idNodes(:,1), idNodes(:,2), idNodes(:,3))) = m; 17 | end 18 | save([param.dataFolder param.figureSubfolder param.subfolder '/errorStacks' num2str(errorIdx, '%2.2i') '.mat'], 'raw', 'obj', 'skel'); 19 | display(num2str(errorIdx)); 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/makeOriginalDataMovie.m: -------------------------------------------------------------------------------- 1 | function makeOriginalDataMovie( rawData ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | close all; 5 | figure('Position', [100 100, 640 400], 'Renderer', 'OpenGL'); 6 | nrMovieFrames = 60; 7 | 8 | % Create 3D Point Cloud Plot of data 9 | [X,Y,Z] = meshgrid(linspace(1,257,257),linspace(1,257,257),linspace(1,257,257)); 10 | scatter3(X(:),Y(:),Z(:),115,rawData(:), 's', 'filled'); 11 | set(gca,'NextPlot','replacechildren'); 12 | xlim([1 size(rawData,1)]); 13 | ylim([1 size(rawData,1)]); 14 | zlim([1 size(rawData,1)]); 15 | set(gcf, 'Color', 'w'); 16 | daspect([25 25 25]); 17 | axis off; 18 | colormap(gray(256)); 19 | set(gca, 'CameraViewAngle', 4); 20 | campos([-50 128 128]); 21 | camtarget([374 128 128]); 22 | 23 | % for i=1:nrMovieFrames 24 | % print(gcf, '-djpeg', '-r50', ['soonToBeMovie' num2str(i, '%04.0f') '.jpg']); 25 | % campan(1,0); 26 | % end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/makeSkeletonMovies.m: -------------------------------------------------------------------------------- 1 | function makeSkeletonMovies(param, raw) 2 | 3 | % Settings & Figure Setup 4 | colors = distinguishable_colors(length(param.skel)); 5 | figure; 6 | set(gcf,'NextPlot','replacechildren'); 7 | set(gcf,'Renderer','OpenGL'); 8 | if ~exist([param.dataFolder param.figureSubfolder], 'dir') 9 | mkdir([param.dataFolder param.figureSubfolder]); 10 | end 11 | writerObj = VideoWriter([param.dataFolder param.figureSubfolder '/skeletonMovie.avi']); 12 | writerObj.FrameRate = 4; 13 | open(writerObj); 14 | % Plot each frame raw data and skeletons & write to video 15 | for f=1:size(raw,3) 16 | hold off; 17 | imagesc(raw(:,:,f)); 18 | colormap('gray'); 19 | axis off; 20 | axis equal; 21 | caxis([100 200]); 22 | hold on; 23 | for skel=1:length(param.skel) 24 | toPlot = param.skel{skel}.nodes(:,3) == f; 25 | if sum(toPlot) 26 | plot(param.skel{skel}.nodes(toPlot,2),param.skel{skel}.nodes(toPlot,1), 'x', 'Color', colors(skel,:), 'MarkerSize', 10, 'LineWidth', 3); 27 | end 28 | end 29 | drawnow; 30 | frame = getframe; 31 | imwrite(frame.cdata, [param.dataFolder param.figureSubfolder '/skeletonFrame' num2str(f, '%.3i') '.tif']); 32 | writeVideo(writerObj,frame); 33 | end 34 | % Close everything 35 | close(writerObj); 36 | close all; 37 | end 38 | 39 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/paper_plotRibbonsInGlobalBB.m: -------------------------------------------------------------------------------- 1 | %% Information about gloabal position of training data 2 | 3 | data = xlsread('/p/Ribbon0001-0232_Knossoscoords.xls'); 4 | 5 | %% Load stacks to check whether they were used 6 | ribbonDir = '/data/e_k0563/local/stacksTrace/'; 7 | files = dir([ribbonDir '*.mat']); 8 | ribbonsWithErrors = [6 26 64 106 130 131 132 159 163 183 186]; 9 | 10 | %% Compare which ribbons are in all three sets (file exists & global position is known & did not have an error) 11 | globalPosition = ~isnan(mean(data,2)); 12 | fileExist = zeros(length(globalPosition),1); 13 | for i=1:length(files) 14 | fileExist(str2double(files(i).name(16:19))) = 1; 15 | end 16 | noError = ones(length(globalPosition),1); 17 | noError(ribbonsWithErrors) = 0; 18 | 19 | % Flächen der Würfel, siehe Hilfe zu patch und Multifaceted Patches 20 | faces = [1 2 6 5;2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8]; 21 | % PLot the boundingBoxes 22 | maxID = min([length(fileExist) length(noError) length(globalPosition)]); 23 | figure; 24 | a = 0; 25 | for i=1:maxID 26 | if fileExist(i) > 0 && noError(i) > 0 && globalPosition(i) 27 | a = a + 1; 28 | load([ribbonDir 'e_k0563_ribbon_' num2str(i, '%.4i') '_fused.mat']); 29 | this_EdgeLength = size(kl_stack); 30 | d = (this_EdgeLength-1)/2; 31 | x = data(i,2); 32 | y = data(i,3); 33 | z = data(i,4); 34 | vertices(:,1,:)=[x-d;x+d;x+d;x-d;x-d;x+d;x+d;x-d]; 35 | vertices(:,2,:)=[y-d;y-d;y+d;y+d;y-d;y-d;y+d;y+d]; 36 | vertices(:,3,:)=[z-d;z-d;z-d;z-d;z+d;z+d;z+d;z+d]; 37 | 38 | % Zeichnen der Würfel 39 | patch('Vertices',vertices(:,:,k),'Faces',faces,'FaceAlpha',0.5,... 40 | 'FaceColor','flat','FaceVertexCData',hsv(6)); 41 | 42 | end 43 | end 44 | daspect([25 25 12]); 45 | grid on; 46 | view(3); 47 | xlabel('x'); 48 | ylabel('y'); 49 | zlabel('z'); 50 | display(num2str(a)) 51 | 52 | % for j=1:36 53 | % camorbit(10,0); pause(.5); 54 | % end 55 | % close all; 56 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visSeg_legacy.m: -------------------------------------------------------------------------------- 1 | %% Plot everything (including movies) for a specific segmentation 2 | map = 1; 3 | algo = 2; 4 | r = 2; 5 | par1 = 11; 6 | par2 = 6; 7 | visualizeSingle(paramTest, map, algo, r, par1, par2); 8 | 9 | %% KLEE: Show segmentation 10 | map = 1; 11 | algo = 1; 12 | r = 1; 13 | par1 = 3; 14 | par2 = 2; 15 | load([param.dataFolder param.affSubfolder param.affMaps(map).name '.mat'], 'raw'); 16 | load([param.dataFolder param.outputSubfolder param.affMaps(map).name '/seg' num2str(r) '-' num2str(algo) '.mat']); 17 | addpath('KLEE'); 18 | KLEE_v4('stack', raw, 'stack_2', v{par1,par2}); 19 | 20 | %% KLEE: Show morhological opening: 21 | map = 1; 22 | r = 2; 23 | load([param.dataFolder param.affSubfolder param.affMaps(map).name '.mat']); 24 | load([param.dataFolder param.outputSubfolder param.affMaps(map).name '/MorphRecon' num2str(r) '.mat']); 25 | %% add path to KLEE repo from github 26 | addpath('/home/someUser/code/KLEE'); 27 | KLEE_v4('stack', aff, 'stack_2', v, 'stack_3', raw); 28 | 29 | %% KLEE: Show errors of a segmentation (see makeErrorStacks.m) 30 | map = 4; 31 | algo = 2; 32 | r = 1; 33 | par1 = 1; 34 | par2 = 1; 35 | error = 1; 36 | param.subfolder = [param.affMaps(map).name '_' num2str(algo) '_' num2str(param.r(r)) '_' num2str(param.pR{map,algo}{1}(par1), '%4.4f') '_' num2str(param.pR{map,algo}{2}(par2), '%4.4f') '/']; 37 | load([param.dataFolder param.figureSubfolder param.subfolder 'errorStacks' num2str(error, '%2.2i') '.mat']); 38 | %% add path to KLEE repo from github 39 | addpath('/home/someUser/code/KLEE'); 40 | KLEE_v4('stack', raw, 'stack_2', obj, 'stack_3', skel); 41 | 42 | a = skel == 2 & obj ~=0; 43 | coord = ind2sub(size(a), find(a)); 44 | 45 | %% Remove KLEE path (as it shadows certain MATLAB functions used above when in path) 46 | rmpath('/home/someUser/code/KLEE'); -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeMeSp.m: -------------------------------------------------------------------------------- 1 | function visualizeMeSp( merge, split, length ) 2 | %UNTITLED4 Summary of this function goes here 3 | % Detailed explanation goes here 4 | markerSize = linspace(5,15,size(merge,3)); 5 | marker = {'o' 'x' '.' '*' '+' 's' 'd'}; 6 | colors = {'r' 'g' 'b' 'y' 'c' 'm' 'k'}; 7 | la = cell(numel(merge),1); 8 | figure('position', [1 41 1600 784]); 9 | for i=1:size(merge,1) 10 | for j=1:size(merge,2) 11 | for k=1:size(merge,3) 12 | plot(length/merge(i,j,k).sum, length/split(i,j,k).sum, [marker{i} colors{j}], 'MarkerSize', markerSize(k)); 13 | hold on; 14 | la{sub2ind(size(merge),i,j,k)} = [num2str(i, '%i') num2str(j, '%i') num2str(k, '%i')]; 15 | xlabel('# average microns between merger'); 16 | ylabel('# average microns between splits'); 17 | end 18 | end 19 | end 20 | legend(la, 'Location', 'BestOutside'); 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeObjHist.m: -------------------------------------------------------------------------------- 1 | function visualizeObjHist( general, segmentation, cutoff, iRange, jRange, kRange ) 2 | %UNTITLED4 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | for i=iRange 6 | for j=jRange 7 | for k=kRange 8 | figure('position', [1 41 1600 784]); 9 | sizeObj = hist(single(segmentation{i,j,k}(:)),1:general(i,j,k).maxNrObjects); 10 | sizeObj(sizeObj > cutoff) = cutoff; 11 | hist(single(sizeObj), 250:500:(cutoff - 250)); 12 | xlabel('Object Size [voxel]'); 13 | ylabel('# Objects'); 14 | title([num2str(i, '%i') num2str(j, '%i') num2str(k, '%i')]); 15 | display([num2str(i) num2str(j) num2str(k)]); 16 | pause(.2); 17 | end 18 | end 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeObjHistP.m: -------------------------------------------------------------------------------- 1 | function visualizeObjHistP( param, general, segmentation, par1, par2) 2 | %UNTITLED4 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | figure('Visible', 'off'); 6 | sizeObj = hist(single(segmentation{par1, par2}(:)),1:general(par1,par2).maxNrObjects); 7 | sizeObj(sizeObj > param.objSizeCutoff) = param.objSizeCutoff; 8 | hist(single(sizeObj), 250:500:(param.objSizeCutoff - 250)); 9 | xlabel('Object Size [voxel]'); 10 | ylabel('# Objects'); 11 | saveas(gcf, [param.dataFolder param.figureSubfolder param.subfolder '/objHist.pdf']); 12 | close all; 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeObjectChains.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = visualizeObjectChainsP( input_args ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | for chain=1:100 5 | 6 | % Randomizer 7 | while true 8 | randSkel = ceil(length(nodes)*rand(1)); 9 | if ~isempty(nodes{randSkel}) 10 | if size(skel{randSkel}.edges,1) > 2 11 | whichSkel = randSkel; 12 | display(['Skelett: ' num2str(whichSkel)]); 13 | break; 14 | end 15 | end 16 | end 17 | se = seg{1,3,1}; 18 | load segColormap.mat; 19 | sk = nodes{whichSkel}; 20 | ske = skel{whichSkel}.edges; 21 | slices = {[] [] 10:40:250}; 22 | 23 | objects = unique(se(sub2ind(size(se),sk(:,1),sk(:,2),sk(:,3)))); 24 | objects(objects == 0) = []; 25 | labelAt = [100 200 300]; 26 | close all; 27 | f = figure('Position', [1601 133 1024 692], 'Renderer', 'OpenGL', 'Visible', 'off' ); 28 | views = {2, 3, [90,0]}; 29 | for subp=1:3 30 | subplot(1,3,subp); 31 | hold on; 32 | for i=1:length(objects) 33 | obj = se == objects(i); 34 | display(num2str(i)); 35 | issf = isosurface(obj, .1); 36 | k{i} = patch(issf); 37 | set(k{i}, 'FaceColor', c(mod(i-1,31)+1,:), 'EdgeColor', 'none'); 38 | end 39 | 40 | for i=1:size(ske,1) 41 | plot3(sk([ske(i,1) ske(i,2)],2), sk([ske(i,1) ske(i,2)],1), sk([ske(i,1) ske(i,2)],3), '-r', 'LineWidth', 3); 42 | end 43 | % plot3([1 384],[384 384],[384 384], 'k'); 44 | % plot3([384 384], [1 384],[384 384], 'k'); 45 | % plot3([384 384], [384 384], [1 384], 'k'); 46 | % r = plotOriginalData(double(raw), slices); 47 | view(views{subp}); 48 | daspect([25 25 12]); 49 | title(['Skelett: ' num2str(whichSkel)]); 50 | % axis off; 51 | grid on; 52 | %axis vis3d; 53 | alpha(.7); 54 | xlim([1 384]); 55 | ylim([1 384]); 56 | zlim([1 384]); 57 | %zoom(1.5); 58 | light = camlight('headlight'); 59 | lighting phong; 60 | end 61 | % % Fly around 62 | % for i=1:36 63 | % camorbit(10,0,'data') 64 | % camlight(light, 'headlight') 65 | % % switchVisibility(k, 1) 66 | % drawnow 67 | % end 68 | % set(f,'PaperPositionMode','auto') 69 | 70 | 71 | 72 | set(f,'PaperPositionMode', 'manual', 'PaperUnits','centimeters', ... 73 | 'Paperposition',[1 1 28 20], 'PaperSize', [29.2 21]) 74 | drawnow; pause(.3); 75 | %orient landscape; 76 | % saveas(gcf, ['object_chains/chain' num2str(chain, '%4.4i') '.pdf']) 77 | print(f, '-dpdf', '-r300', ['/some/output/directory/object_chains/chain' num2str(chain, '%4.4i')]); 78 | %pause; 79 | 80 | end 81 | 82 | end 83 | 84 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeObjectChainsP.m: -------------------------------------------------------------------------------- 1 | function visualizeObjectChainsP( param, nodes, se, skel ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | load(param.cmSource); 6 | autoKLEE_colormap = repmat(autoKLEE_colormap, 100, 1); 7 | views = {2, 3, [90,0]}; 8 | 9 | if ~exist([param.dataFolder param.figureSubfolder param.subfolder 'objChains/'], 'dir') 10 | mkdir([param.dataFolder param.figureSubfolder param.subfolder 'objChains/']); 11 | end 12 | 13 | for chain=1:length(skel) 14 | sk = nodes{chain}; 15 | ske = skel{chain}.edges; 16 | if size(ske,2) > 1 17 | objects = unique(se(sub2ind(size(se),sk(:,1),sk(:,2),sk(:,3)))); 18 | objects(objects == 0) = []; 19 | f = figure('Renderer', 'OpenGL', 'Visible', 'off' ); 20 | 21 | for subp=1:3 22 | subplot(1,3,subp); 23 | hold on; 24 | k = cell(length(objects),1); 25 | for i=1:length(objects) 26 | obj = se == objects(i); 27 | issf = isosurface(obj, .1); 28 | k{i} = patch(issf); 29 | set(k{i}, 'FaceColor', autoKLEE_colormap(i,:), 'EdgeColor', 'none'); 30 | end 31 | for i=1:size(ske,1) 32 | plot3(sk([ske(i,1) ske(i,2)],2), sk([ske(i,1) ske(i,2)],1), sk([ske(i,1) ske(i,2)],3), '-r', 'LineWidth', 3); 33 | end 34 | view(views{subp}); 35 | daspect([25 25 12]); 36 | title(['Skelett (KNOSSOS ID): ' num2str(skel{chain}.thingID)]); 37 | grid on; 38 | alpha(.7); 39 | xlim([1 384]); 40 | ylim([1 384]); 41 | zlim([1 384]); 42 | camlight('headlight'); 43 | lighting phong; 44 | end 45 | 46 | set(f,'PaperPositionMode', 'manual', 'PaperUnits','centimeters', ... 47 | 'Paperposition',[1 1 28 20], 'PaperSize', [29.2 21]) 48 | drawnow; 49 | 50 | 51 | print(f, '-dpdf', '-r300', [param.dataFolder param.figureSubfolder param.subfolder 'objChains/chain' num2str(chain, '%3.3i')]); 52 | end 53 | 54 | end 55 | 56 | end 57 | 58 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeObjectChainsP_leftout.m: -------------------------------------------------------------------------------- 1 | function visualizeObjectChainsP_leftout( param, eval, se, skel, par1, par2 ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | load(param.cmSource); 6 | autoKLEE_colormap = repmat(autoKLEE_colormap, 100, 1); 7 | views = {2, 3, [90,0]}; 8 | 9 | if ~exist([param.dataFolder param.figureSubfolder param.subfolder 'objChains/'], 'dir') 10 | mkdir([param.dataFolder param.figureSubfolder param.subfolder 'objChains/']); 11 | end 12 | 13 | figure('Renderer', 'OpenGL', 'Visible', 'off' ); 14 | test = sum(eval.general(par1,par2).equivMatrixBinary) < 1; 15 | k = cell(length(max(se(:))),1); 16 | for i=1:max(se(:)) 17 | if test(i) 18 | obj = se == i; 19 | issf = isosurface(obj, .1); 20 | k{i} = patch(issf); 21 | set(k{i}, 'FaceColor', autoKLEE_colormap(i,:), 'EdgeColor', 'none'); 22 | end 23 | view(views{2}); 24 | daspect([25 25 12]); 25 | grid on; 26 | alpha(.9); 27 | xlim([1 384]); 28 | ylim([1 384]); 29 | zlim([1 384]); 30 | camlight('headlight'); 31 | lighting phong; 32 | end 33 | saveas(gcf, [param.dataFolder param.figureSubfolder param.subfolder 'objChains/leftout.fig']); 34 | saveas(gcf, [param.dataFolder param.figureSubfolder param.subfolder 'objChains/leftout.tif']); 35 | close all; 36 | 37 | end 38 | 39 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeObjectChainsP_merger.m: -------------------------------------------------------------------------------- 1 | function visualizeObjectChainsP_merger( param, eval, se, skel, par1, par2 ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | load(param.cmSource); 6 | autoKLEE_colormap = repmat(autoKLEE_colormap, 10, 1); 7 | views = {2, 3, [90,0]}; 8 | 9 | if ~exist([param.dataFolder param.figureSubfolder param.subfolder 'objChains/'], 'dir') 10 | mkdir([param.dataFolder param.figureSubfolder param.subfolder 'objChains/']); 11 | end 12 | 13 | for merger=1:length(eval.merge(par1,par2).obj) 14 | f = figure('Renderer', 'OpenGL'); 15 | for c=1:length(eval.merge(par1,par2).obj{merger}) 16 | chain = eval.merge(par1,par2).obj{merger}(c); 17 | sk = eval.nodes{chain}; 18 | ske = skel{chain}.edges; 19 | % objects = unique(se(sub2ind(size(se),sk(:,1),sk(:,2),sk(:,3)))); 20 | % objects(objects == 0) = []; 21 | objects = eval.merge(par1,par2).idx(merger); 22 | hold on; 23 | for i=1:size(ske,1) 24 | plot3(sk([ske(i,1) ske(i,2)],2), sk([ske(i,1) ske(i,2)],1), sk([ske(i,1) ske(i,2)],3), '-', 'Color', autoKLEE_colormap(c,:), 'LineWidth', 3); 25 | end 26 | k = cell(length(objects),1); 27 | for i=1:length(objects) 28 | obj = smooth3(se == objects(i), 'gaussian', 9, 2); 29 | issf = isosurface(obj, .1); 30 | k{i} = patch(issf); 31 | if objects(i) == eval.merge(par1,par2).idx(merger) 32 | set(k{i}, 'FaceColor', 'r', 'EdgeColor', 'none'); 33 | if c ~= 1 34 | set(k{i}, 'Visible', 'off'); 35 | end 36 | else 37 | set(k{i}, 'FaceColor', 'g', 'EdgeColor', 'none'); 38 | end 39 | end 40 | view(views{2}); 41 | daspect([25 25 12]); 42 | grid on; 43 | xlim([1 384]); 44 | ylim([1 384]); 45 | zlim([1 384]); 46 | alpha(.4); 47 | camlight('headlight'); 48 | lighting phong; 49 | end 50 | saveas(f, [param.dataFolder param.figureSubfolder param.subfolder 'objChains/merger' num2str(merger, '%3.3i') '.tif']); 51 | saveas(f, [param.dataFolder param.figureSubfolder param.subfolder 'objChains/merger' num2str(merger, '%3.3i') '.fig']); 52 | close all; 53 | end 54 | 55 | end 56 | 57 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeObjectChainsP_mergerNew.m: -------------------------------------------------------------------------------- 1 | function visualizeObjectChainsP_mergerNew( param, eval, se, skel, par1, par2 ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | load(param.cmSource); 6 | myCMap = [0 1 0; 0 0 1; 0 1 1]; 7 | views = {2, 3, [90,0]}; 8 | 9 | if ~exist([param.dataFolder param.figureSubfolder param.subfolder 'objChains/'], 'dir') 10 | mkdir([param.dataFolder param.figureSubfolder param.subfolder 'objChains/']); 11 | end 12 | 13 | for merger=1:length(eval.merge(par1,par2).obj) 14 | tic; 15 | f = figure('Renderer', 'OpenGL'); 16 | for c=1:length(eval.merge(par1,par2).obj{merger}) 17 | chain = eval.merge(par1,par2).obj{merger}(c); 18 | sk = eval.nodes{chain}; 19 | ske = skel{chain}.edges; 20 | objects = eval.merge(par1,par2).idx(merger); 21 | hold on; 22 | for i=1:size(ske,1) 23 | plot3(sk([ske(i,1) ske(i,2)],2), sk([ske(i,1) ske(i,2)],1), sk([ske(i,1) ske(i,2)],3), '-', 'Color', myCMap(c,:), 'LineWidth', 3); 24 | end 25 | k = cell(length(objects),1); 26 | for i=1:length(objects) 27 | obj = smooth3(se == objects(i), 'gaussian', 9, 2); 28 | issf = isosurface(obj, .1); 29 | k{i} = patch(issf); 30 | set(k{i}, 'FaceColor', 'r', 'EdgeColor', 'none'); 31 | end 32 | view(views{2}); 33 | daspect([25 25 12]); 34 | grid on; 35 | xlim([1 384]); 36 | ylim([1 384]); 37 | zlim([1 384]); 38 | alpha(.4); 39 | camlight('headlight'); 40 | lighting phong; 41 | end 42 | saveas(f, [param.dataFolder param.figureSubfolder param.subfolder 'objChains/merger' num2str(merger, '%3.3i') '.tif']); 43 | saveas(f, [param.dataFolder param.figureSubfolder param.subfolder 'objChains/merger' num2str(merger, '%3.3i') '.fig']); 44 | close all; 45 | toc; 46 | end 47 | 48 | end 49 | 50 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeObjectChainsP_show.m: -------------------------------------------------------------------------------- 1 | function visualizeObjectChainsP_show( param, eval, se, skel ) 2 | %UNTITLED6 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | load(param.cmSource); 6 | autoKLEE_colormap = repmat(autoKLEE_colormap, 100, 1); 7 | views = {2, 3, [90,0]}; 8 | 9 | if ~exist([param.dataFolder param.figureSubfolder param.subfolder 'objChains/'], 'dir') 10 | mkdir([param.dataFolder param.figureSubfolder param.subfolder 'objChains/']); 11 | end 12 | 13 | for chain=1:length(skel) 14 | sk = eval.nodes{chain}; 15 | ske = skel{chain}.edges; 16 | if size(ske,2) > 1 && size(ske,1) > 0 17 | objects = unique(se(sub2ind(size(se),sk(:,1),sk(:,2),sk(:,3)))); 18 | objects(objects == 0) = []; 19 | f = figure('Renderer', 'OpenGL', 'Visible', 'off' ); 20 | hold on; 21 | k = cell(length(objects),1); 22 | for i=1:length(objects) 23 | obj = smooth3(se == objects(i), 'gaussian', 9, 2); 24 | issf = isosurface(obj, .1); 25 | k{i} = patch(issf); 26 | set(k{i}, 'FaceColor', autoKLEE_colormap(i,:), 'EdgeColor', 'none'); 27 | end 28 | for i=1:size(ske,1) 29 | plot3(sk([ske(i,1) ske(i,2)],2), sk([ske(i,1) ske(i,2)],1), sk([ske(i,1) ske(i,2)],3), '-r', 'LineWidth', 3); 30 | end 31 | view(views{2}); 32 | daspect([25 25 12]); 33 | %title(['Skelett (KNOSSOS ID): ' num2str(skel{chain}.thingID)], 'FontSize', 18); 34 | grid on; 35 | alpha(.4); 36 | xlim([1 384]); 37 | ylim([1 384]); 38 | zlim([1 384]); 39 | camlight('headlight'); 40 | lighting phong; 41 | set(gca, 'XTickLabel', ''); 42 | set(gca, 'YTickLabel', ''); 43 | set(gca, 'ZTickLabel', ''); 44 | saveas(gcf, [param.dataFolder param.figureSubfolder param.subfolder 'objChains/chain' num2str(chain, '%3.3i') '.fig']); 45 | saveas(gcf, [param.dataFolder param.figureSubfolder param.subfolder 'objChains/chain' num2str(chain, '%3.3i') '.png']); 46 | % set(f,'PaperPositionMode', 'manual', 'PaperUnits','centimeters', ... 47 | % 'Paperposition',[1 1 28 20], 'PaperSize', [29.2 21]) 48 | % drawnow; 49 | % 50 | % 51 | % print(f, '-dpdf', '-r300', [param.dataFolder param.figureSubfolder param.subfolder 'objChains/chain' num2str(chain, '%3.3i')]); 52 | % close all; 53 | end 54 | 55 | end 56 | 57 | end 58 | 59 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeOverview_2.m: -------------------------------------------------------------------------------- 1 | function visualizeOverview_2( param ) 2 | %UNTITLED2 Summary of this function goes here 3 | % Detailed explanation goes here 4 | markerSize = linspace(5,15,length(param.r)); 5 | colors = distinguishable_colors(30, [1 1 1]); 6 | marker = {'+' 'o' '*' '.' 'x' 's' 'd' '^' 'v' '>' '<' 'p' 'h'}; 7 | 8 | if ~exist([param.dataFolder param.figureSubfolder '/']) 9 | mkdir([param.dataFolder param.figureSubfolder '/']); 10 | end 11 | 12 | for map=1:size(param.affMaps,1) 13 | display(['Overview Detail: CNN # ' num2str(map) '/' num2str(length(param.affMaps))]); 14 | tic; 15 | for algo=1:size(param.algo,2) 16 | figure('position', [1 1 1600 785], 'Renderer', 'painters'); 17 | la = cell(length(param.r)*size(param.pR{map,algo},1)*size(param.pR{map,algo},2),1); 18 | for r=1:length(param.r) 19 | a = load([param.dataFolder param.outputSubfolder param.affMaps(map).name '/evaluation' num2str(r) '-' num2str(algo) '.mat']); 20 | for i=1:size(a.v.merge,1) 21 | for j=1:size(a.v.merge,2) 22 | plot3(param.totalPathLength/a.v.merge(i,j).sum, param.totalPathLength/a.v.split(i,j).sum, a.v.general(i,j).maxNrObjects, marker{mod(i,13) + 1}, 'MarkerEdgeColor', colors(j,:), 'MarkerSize', markerSize(r)); 23 | hold on; 24 | la{sub2ind([size(a.v.merge,2) size(a.v.merge,1) length(param.r)],j,i,r)} = [num2str(param.r(r), '%i') '-' num2str(param.pR{map,algo}{1}(i), '%4.3f') '-' num2str(param.pR{map, algo}{2}(j), '%4.3f')]; 25 | end 26 | end 27 | end 28 | xlabel('average distance between merger [nm]'); 29 | ylabel('average distance between splits [nm]'); 30 | zlabel('# objects'); 31 | la(cellfun(@isempty,la)) = []; 32 | legend(la, 'Location', 'BestOutside'); 33 | grid on; 34 | saveas(gcf, [param.dataFolder param.figureSubfolder '/overview' param.affMaps(map).name '-' num2str(algo) '.fig']); 35 | close all; 36 | figure('position', [1 1 1600 785]); 37 | for r=1:length(param.r) 38 | if ~isempty(a.v.nodes{1}) 39 | % b = load([param.dataFolder param.outputSubfolder param.affMaps(map).name '/seg' num2str(r) '-' num2str(algo) '.mat']); 40 | for i=1:size(a.v.merge,1) 41 | for j=1:size(a.v.merge,2) 42 | plot3(param.r(r), param.pR{map,algo}{1}(i), param.pR{map,algo}{2}(j), marker{mod(i,13) + 1}, 'MarkerEdgeColor', colors(j,:), 'MarkerSize', markerSize(r)); 43 | hold on; 44 | end 45 | end 46 | end 47 | end 48 | xlabel('radius of structuring element (rse)'); 49 | ylabel('threshold for marker generation (tmg)'); 50 | zlabel('minimum marker size (mms)'); 51 | la(cellfun(@isempty,la)) = []; 52 | legend(la, 'Location', 'BestOutside'); 53 | grid on; 54 | saveas(gcf, [param.dataFolder param.figureSubfolder '/overview' param.affMaps(map).name '-' num2str(algo) 'legend.fig']); 55 | close all; 56 | end 57 | toc 58 | end 59 | 60 | end 61 | 62 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeOverview_4.m: -------------------------------------------------------------------------------- 1 | function visualizeOverview_4( param,paramTest ) 2 | %UNTITLED2 Summary of this function goes here 3 | % Detailed explanation goes here 4 | load(param.cmSource); 5 | if ~exist([param.dataFolder param.figureSubfolder '/'], 'dir') 6 | mkdir([param.dataFolder param.figureSubfolder '/']); 7 | end 8 | display('Overview Training vs. Test Comparison'); 9 | figure('position', [1 1 1600 785]); 10 | hold on; 11 | [a,b,c] = plotParam(param, autoKLEE_colormap(1,:)); 12 | [d,e,f] = plotParam(paramTest, autoKLEE_colormap(2,:)); 13 | xlabel('average distance between merger [nm]'); 14 | ylabel('average distance between splits [nm]'); 15 | zlabel('# objects'); 16 | grid on; 17 | legend([a b c d e f], 'training node threshold 1', 'training node threshold 2', 'training node threshold 3' ... 18 | , 'test node threshold 1', 'test node threshold 2', 'test node threshold 3'); 19 | set(gca, 'XScale', 'log'); 20 | set(gca, 'YScale', 'log'); 21 | saveas(gcf, [param.dataFolder param.figureSubfolder '/overviewComparison.fig']); 22 | 23 | function [u,v,w] = plotParam(param, color) 24 | marker = {'+' 'o' 'x'}; 25 | for r=1:2 26 | for algo=2 27 | aa = load([param.dataFolder param.outputSubfolder param.affMaps(1).name filesep 'seg' num2str(r) '-' num2str(algo) '.mat'], 'v'); 28 | eval1 = evaluateSeg(aa.v, param.skel, 1); 29 | eval2 = evaluateSeg(aa.v, param.skel, 2); 30 | eval3 = evaluateSeg(aa.v, param.skel, 3); 31 | for i=1:size(aa.v,1) 32 | for j=1:size(aa.v,2) 33 | u = plot3(param.totalPathLength./max([eval1.merge(i,j,1).sum],1), param.totalPathLength./[eval1.split(i,j,1).sum], [eval1.general(i,j,1).maxNrObjects],... 34 | marker{1}, 'MarkerEdgeColor', color, 'MarkerSize', 5); 35 | v = plot3(param.totalPathLength./max([eval2.merge(i,j,1).sum],1), param.totalPathLength./[eval2.split(i,j,1).sum], [eval2.general(i,j,1).maxNrObjects],... 36 | marker{2}, 'MarkerEdgeColor', color, 'MarkerSize', 5); 37 | w = plot3(param.totalPathLength./max([eval3.merge(i,j,1).sum],1), param.totalPathLength./[eval3.split(i,j,1).sum], [eval3.general(i,j,1).maxNrObjects],... 38 | marker{3}, 'MarkerEdgeColor', color, 'MarkerSize', 5); 39 | end 40 | end 41 | end 42 | end 43 | end 44 | 45 | end 46 | 47 | -------------------------------------------------------------------------------- /retina/segmentation/visualization/visualizeSingle.m: -------------------------------------------------------------------------------- 1 | function visualizeSingle( param, map, algo, r, par1, par2 ) 2 | %UNTITLED3 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | display('Visualization Single:'); 6 | param.subfolder = [param.affMaps(map).name '_' num2str(algo) '_' num2str(param.r(r)) '_' num2str(param.pR{map,algo}{1}(par1), '%4.4f') '_' num2str(param.pR{map,algo}{2}(par2), '%4.4f') '/']; 7 | tic; 8 | 9 | a = load([param.dataFolder param.outputSubfolder param.affMaps(map).name '/evaluation' num2str(r) '-' num2str(algo) '.mat']); 10 | b = load([param.dataFolder param.outputSubfolder param.affMaps(map).name '/seg' num2str(r) '-' num2str(algo) '.mat']); 11 | load([param.dataFolder param.affSubfolder param.affMaps(map).name '.mat']); 12 | 13 | if ~exist([param.dataFolder param.figureSubfolder param.subfolder], 'dir'); 14 | mkdir([param.dataFolder param.figureSubfolder param.subfolder]); 15 | end 16 | 17 | % if param.makeSegMovies 18 | % makeSegMoviesP( param, b.v{par1,par2}, raw ); 19 | % end 20 | % if param.makeErrorMovies 21 | % makeErrorMoviesP( param, a.v, b.v, raw, par1, par2); 22 | % end 23 | if param.plotObjSizeHist 24 | % visualizeObjHistP( param, a.v.general, b.v, par1, par2); 25 | end 26 | if param.plotObjChains 27 | visualizeObjectChainsP_mergerNew(param, a.v, b.v{par1,par2}, param.skel, par1, par2); 28 | visualizeObjectChainsP_show(param, a.v, b.v{par1,par2}, param.skel); 29 | % visualizeObjectChainsP_leftout(param, a.v, b.v{par1,par2}, param.skel, par1, par2); 30 | end 31 | % if param.makeErrorStacks 32 | % makeErrorStacksP( param, a.v, b.v, raw, par1, par2 ); 33 | % end 34 | %toc 35 | 36 | 37 | end 38 | 39 | -------------------------------------------------------------------------------- /retina/segmentation/watershedBasedSeg/binAff.m: -------------------------------------------------------------------------------- 1 | function affBinned = binAff( aff, N_LEVELS ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | mini = min(aff(:)); 5 | maxi = max(aff(:)); 6 | affBinned = uint16(round((N_LEVELS-1) * (aff-mini)/(maxi-mini))); 7 | end 8 | -------------------------------------------------------------------------------- /retina/segmentation/watershedBasedSeg/watershedSeg_v1_paper.m: -------------------------------------------------------------------------------- 1 | function segmentation = watershedSeg_v1_paper( aff, hRange, vRange ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | segmentation = cell([length(hRange) length(vRange)]); 6 | affHmin = cell(size(aff)); 7 | for h=1:length(hRange) 8 | for dir=1:length(aff) 9 | affHmin{dir} = imhmin(aff{dir}, hRange(h), 26); 10 | end 11 | affHminAll = (affHmin{1} + affHmin{2} + affHmin{3}) / 3; 12 | bw1 = imregionalmin(affHminAll, 26); 13 | for v=1:length(vRange) 14 | bw1 = bwareaopen(bw1, vRange(v), 26); 15 | segmentation{h,v} = watershed_3D(affHmin{1}, affHmin{2}, affHmin{3}, bw1); 16 | end 17 | end 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /retina/segmentation/watershedBasedSeg/watershedSeg_v2_paper.m: -------------------------------------------------------------------------------- 1 | function segmentation = watershedSeg_v2_paper( aff, tRange, vRange) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | segmentation = cell([length(tRange) length(vRange)]); 6 | affAll = (aff{1} + aff{2} + aff{3}) / 3; 7 | for t=1:length(tRange) 8 | display(num2str(t)); 9 | fgm1 = affAll < tRange(t); 10 | for v=1:length(vRange) 11 | fgm1 = bwareaopen(fgm1, vRange(v), 26); 12 | segmentation{t,v} = watershed_3D(aff{1}, aff{2}, aff{3}, fgm1); 13 | % Temporary fix: Grow out!!! 14 | % while any(segmentation{t,v}(:) == 0) 15 | % segTemp = imdilate(segmentation{t,v}, ones(5,5,5)); 16 | % borders = segmentation{t,v} == 0; 17 | % segmentation{t,v}(borders) = segTemp(borders); 18 | % end 19 | end 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /retina/segmentation/watershedBasedSeg/watershed_3D.m: -------------------------------------------------------------------------------- 1 | function seg = watershed_3D( affX, affY, affZ, bw) 2 | %UNTITLED5 Summary of this function goes here 3 | % Detailed explanation goes here 4 | mex = true; % an binAff + 1 denken 5 | N_LEVELS = 20000; 6 | N_LEVELS_BOUNDARY = 1; 7 | 8 | affX = binAff(affX, N_LEVELS); 9 | affY = binAff(affY, N_LEVELS); 10 | affZ = binAff(affZ, N_LEVELS); 11 | marker = uint16(labelmatrix(bwconncomp(bw))); 12 | if mex 13 | if sum(marker(:) ~= 0) == 0 14 | seg = zeros(384,384,384); 15 | else 16 | seg = watershed_threeTimes3D(affX, affY, affZ, marker, N_LEVELS, N_LEVELS - N_LEVELS_BOUNDARY); 17 | end 18 | else 19 | seg = sk_mbwshed_3d_2(affX, affY, affZ, marker, N_LEVELS); 20 | end 21 | 22 | end 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /retina/segmentation/watershedBasedSeg/watershed_3D_PP.m: -------------------------------------------------------------------------------- 1 | function seg = watershed_3D_PP( affX, affY, affZ, marker) 2 | %UNTITLED5 Summary of this function goes here 3 | % Detailed explanation goes here 4 | mex = true; % an binAff + 1 denken 5 | N_LEVELS = 20000; 6 | N_LEVELS_BOUNDARY = 1; 7 | 8 | affX = binAff(affX, N_LEVELS); 9 | affY = binAff(affY, N_LEVELS); 10 | affZ = binAff(affZ, N_LEVELS); 11 | if mex 12 | if sum(marker(:) ~= 0) == 0 13 | seg = zeros(384,384,384); 14 | else 15 | seg = watershed_threeTimes3D(affX, affY, affZ, marker, N_LEVELS, N_LEVELS - N_LEVELS_BOUNDARY); 16 | end 17 | else 18 | seg = sk_mbwshed_3d_2(affX, affY, affZ, marker, N_LEVELS); 19 | end 20 | 21 | end 22 | 23 | -------------------------------------------------------------------------------- /retina/segmentation/wholeDataset/ekSegmentationToJm.m: -------------------------------------------------------------------------------- 1 | function ekSegmentationToJm() 2 | 3 | dir = '/path/to/some/directory/results/CNNfwdPass/14-Feb-2013618765/'; 4 | jm = findResource('scheduler', 'configuration', 'local_1'); 5 | job = createJob(jm, 'configuration', 'local_1'); 6 | for i=1:2%36 7 | for j=1:2%43 8 | for k=1:2%45 9 | inputargs = {dir, i-1,j-1,k-1}; 10 | task = createTask(job, @segment_ek_0563ForPaper, 0, inputargs, 'configuration', 'local_1'); 11 | end 12 | end 13 | end 14 | submit(job); 15 | 16 | end 17 | 18 | -------------------------------------------------------------------------------- /retina/segmentation/wholeDataset/segment_ek_0563ForPaper.m: -------------------------------------------------------------------------------- 1 | function segment_ek_0563ForPaper( dir, xCP, yCP, zCP ) 2 | % Uses affinity map 5 algo 2 radius 2 pR 2,2 from nov2 parmater scan 3 | 4 | overlap = [-64 64; -64 64; -64 64]; 5 | % Morphological opening 6 | rT = 1; 7 | folders = {'x/' 'y/' 'z/'}; 8 | affReconRecon = cell(3,1); 9 | [x,y,z] = meshgrid(-rT:rT,-rT:rT,-rT:rT); 10 | se = (x/rT).^2 + (y/rT).^2 + (z/rT).^2 <= 1; 11 | for dir=1:length(folders) 12 | % Decide with region to read in, notice overlap 13 | bbox = [[xCP;yCP;zCP],[xCP;yCP;zCP] + 1] * 128; 14 | bbox(:,1) = bbox(:,1) + 1; 15 | aff = readKnossosRoi([dir folders{dir}], '100527_k0563_seg', bbox + overlap, 'single', '', 'raw'); 16 | % Opening by reconstruction 17 | affEroded = imerode(aff, se); 18 | affRecon = imreconstruct(affEroded, aff); 19 | % Closing by reconstruction 20 | affReconDilated = imdilate(affRecon, se); 21 | affReconRecon{dir} = imreconstruct(imcomplement(affReconDilated), imcomplement(affRecon)); 22 | end 23 | 24 | % Marker generation 25 | fgm1 = (affReconRecon{1} + affReconRecon{2} + affReconRecon{3}) / 3; 26 | fgm1 = fgm1 < .31; 27 | fgm1 = bwareaopen(fgm1, 20, 26); 28 | 29 | % Segmentation using Ramin's mex watershed 30 | N_LEVELS = 20000; 31 | N_LEVELS_BOUNDARY = 1; 32 | for dir=1:length(folders) 33 | mini = min(affReconRecon{dir}(:)); 34 | maxi = max(affReconRecon{dir}(:)); 35 | affReconRecon{dir} = uint16(round((N_LEVELS-1) .* (affReconRecon{dir}-mini)./(maxi-mini))); 36 | end 37 | marker = uint16(labelmatrix(bwconncomp(fgm1))); 38 | seg = watershed_threeTimes3D(affReconRecon{1}, affReconRecon{2}, affReconRecon{3}, marker, N_LEVELS, N_LEVELS - N_LEVELS_BOUNDARY); 39 | writeKnossosCube([dir 'seg/'], '100527_k0563_seg', [xCP,yCP,zCP], seg, 'uint16'); 40 | 41 | end 42 | 43 | -------------------------------------------------------------------------------- /retina/startup.m: -------------------------------------------------------------------------------- 1 | % set Matlab path for cortex 2 | addpath(genpath([codeDirectory filesep 'retina'])); 3 | addpath(genpath([codeDirectory filesep 'auxiliaryMethods'])); 4 | addpath(genpath([codeDirectory filesep 'volumeReconstruction'])); 5 | 6 | % open relevant scripts 7 | open('CNN/main_legacy.m'); 8 | open('segmentation/mainSeg_legacy.m'); 9 | open('segmentation/visualization/visSeg_legacy.m'); 10 | open('../volumeReconstruction/skeletonsToContacts_legacy.m'); -------------------------------------------------------------------------------- /retina/wholeDatasetFwdPass.m: -------------------------------------------------------------------------------- 1 | %% This was not yet set up in retina case 2 | 3 | % See bigFwdPass and minicubeFwdPass, not very well generalized at this 4 | % stage 5 | -------------------------------------------------------------------------------- /volumeReconstruction/accumulateOverCubeBorders.m: -------------------------------------------------------------------------------- 1 | function [skel, accStruct] = accumulateOverCubeBorders(skel, aStruct, nameForTree) 2 | % Pass structure with field voxel (in global coordinates) positions, will be merged if overlapping, name for tree to add to skel 3 | 4 | nrElements = length(aStruct); 5 | adjList = cell(nrElements,1); 6 | % Create symetric adjaceny list of elements 7 | for i=1:nrElements-1 8 | for j=i+1:nrElements 9 | a = aStruct(i).voxel; 10 | b = aStruct(j).voxel; 11 | if ~isempty(intersect(a, b, 'rows')) 12 | adjList{i}(end+1) = j; 13 | adjList{j}(end+1) = i; 14 | end 15 | end 16 | end 17 | % Find CC 18 | components = bfs(1:nrElements, adjList); 19 | % Write all volumes as nodes to the skeleton according to CC 20 | for i=1:length(components) 21 | accStruct(i).voxel = unique(vertcat(aStruct(components{i}).voxel), 'rows'); 22 | if isfield(aStruct, 'border'); 23 | % Group CoM data according to CC 24 | border = vertcat(aStruct(components{i}).border); 25 | pre = vertcat(aStruct(components{i}).pre); 26 | post = vertcat(aStruct(components{i}).post); 27 | skel = addTree(skel, accStruct(i).voxel, [nameForTree num2str(i, '%.2i')], border, pre, post); 28 | else 29 | skel = addTree(skel, accStruct(i).voxel, [nameForTree num2str(i, '%.2i')]); 30 | end 31 | end 32 | 33 | end 34 | 35 | -------------------------------------------------------------------------------- /volumeReconstruction/contactDetectionCortexStart.m: -------------------------------------------------------------------------------- 1 | function contactDetectionCortexStart(p, dataFolder, saveFolder) 2 | 3 | pathPre = [dataFolder filesep 'supplement' filesep 'extracted' filesep 'axonsForPaper' filesep]; 4 | pathPost = [dataFolder filesep 'supplement' filesep 'extracted' filesep 'spinyStellateForPaper' filesep]; 5 | filesPre = dir([pathPre '*.nml']); 6 | filesPost = dir([pathPost '*.nml']); 7 | 8 | for i=1:length(filesPre) 9 | for j=1:length(filesPost) 10 | idx = sub2ind([length(filesPre) length(filesPost)], i, j); 11 | functionH{idx} = @contactDetectionCortex; 12 | inputCell{idx} = {p [pathPre filesPre(i).name] [pathPost filesPost(j).name] [saveFolder filesPre(i).name(1:end-4) 'TO' filesPost(j).name(1:end-4) '.nml']}; 13 | end 14 | end 15 | 16 | startCPU(functionH, inputCell, 'cortex gallery full'); 17 | 18 | end 19 | -------------------------------------------------------------------------------- /volumeReconstruction/contactDetectionRetinaStart.m: -------------------------------------------------------------------------------- 1 | function contactDetectionRetinaStart(inputFolder, outputDir, seg) 2 | 3 | pathBP = [inputFolder filesep 'supplement' filesep 'extracted' filesep 'bpc' filesep]; 4 | pathGC = [inputFolder filesep 'supplement' filesep 'extracted' filesep 'gcl' filesep]; 5 | filesBP = dir([pathBP '*.nml']); 6 | filesGC = dir([pathGC '*.nml']); 7 | 8 | for i=1:length(filesBP) 9 | for j=1:length(filesGC) 10 | idx = sub2ind([length(filesBP) length(filesGC)], i, j); 11 | functionH{idx} = @contactDetectionRetina; 12 | inputCell{idx} = {[pathBP filesBP(i).name] [pathGC filesGC(j).name] [outputDir filesBP(i).name(1:end-4) 'TO' filesGC(j).name(1:end-4) '.nml'] seg}; 13 | end 14 | end 15 | 16 | startCPU(functionH, inputCell, 'retina contact detection full'); 17 | 18 | end 19 | 20 | -------------------------------------------------------------------------------- /volumeReconstruction/galleryCortexStart.m: -------------------------------------------------------------------------------- 1 | function galleryCortexStart(p, dataFolder, saveFolder) 2 | 3 | skelPath = [dataFolder filesep 'supplement' filesep 'extracted' filesep 'spinyStellateForPaper' filesep]; 4 | 5 | files = dir([skelPath '*.nml']); 6 | 7 | for i=1:length(files) 8 | functionH{i} = @galleryCortex; 9 | inputCell{i} = {p, skelPath, files(i).name, saveFolder}; 10 | end 11 | 12 | startCPU(functionH, inputCell, 'whole cell cortex'); 13 | 14 | clear files functionH inputCell; 15 | 16 | skelPath = [dataFolder filesep 'supplement' filesep 'extracted' filesep 'axonsForPaper' filesep]; 17 | 18 | files = dir([skelPath '*.nml']); 19 | 20 | for i=1:length(files) 21 | functionH{i} = @galleryCortex; 22 | inputCell{i} = {p, skelPath, files(i).name, saveFolder}; 23 | end 24 | 25 | startCPU(functionH, inputCell, 'whole cell cortex'); 26 | 27 | end 28 | 29 | -------------------------------------------------------------------------------- /volumeReconstruction/galleryRetinaStart.m: -------------------------------------------------------------------------------- 1 | function galleryRetinaStart(inputFolder,outputFolder, seg) 2 | 3 | preFolder = [inputFolder filesep 'supplement' filesep 'extracted' filesep 'bpc' filesep]; 4 | 5 | files = dir([preFolder '*.nml']); 6 | 7 | functionH = cell(length(files),1); 8 | inputCell = cell(length(files),1); 9 | for i=1:length(files) 10 | functionH{i} = @galleryRetina; 11 | inputCell{i} = {preFolder, files(i).name, outputFolder, seg}; 12 | end 13 | 14 | startCPU(functionH, inputCell, 'gallery retina'); 15 | 16 | clear functionH inputCell files; 17 | 18 | postFolder = [inputFolder filesep 'supplement' filesep 'extracted' filesep 'gcl' filesep]; 19 | 20 | files = dir([postFolder '*.nml']); 21 | 22 | functionH = cell(length(files),1); 23 | inputCell = cell(length(files),1); 24 | for i=1:length(files) 25 | functionH{i} = @galleryRetina; 26 | inputCell{i} = {postFolder, files(i).name, outputFolder, seg}; 27 | end 28 | 29 | startCPU(functionH, inputCell, 'gallery retina'); 30 | 31 | end 32 | 33 | -------------------------------------------------------------------------------- /volumeReconstruction/skeletonsToContacts.m: -------------------------------------------------------------------------------- 1 | %% Skeleton based volume reconstruction 2 | % This file shows how to use segmentation of whole dataset 3 | % for volume reconstruction and contact detection 4 | 5 | %% 6 | % Set output directory in setParameterSettings to datasets subfolder for 7 | % using segmentation supplied segmentation (for testing without having to 8 | % rerun classification and segmentation 9 | providedSegmentationFolder = [dataDirectory filesep 'datasets' filesep '2012-09-28_ex145_07x2_corrected' filesep]; 10 | [pBig, ~] = setParameterSettingsBig(dataDirectory, providedSegmentationFolder, '20141007T094904'); 11 | % Start isosurface visualization of volume reconstruction 12 | galleryCortexStart(pBig, dataDirectory, outputDirectory) 13 | 14 | %% 15 | contactDetectionCortexStart(pBig, dataDirectory, outputDirectory) 16 | -------------------------------------------------------------------------------- /volumeReconstruction/skeletonsToContacts_legacy.m: -------------------------------------------------------------------------------- 1 | %% Skeleton based volume reconstruction 2 | % This file shows how to use segmentation of whole dataset 3 | % for volume reconstruction and contact detection based on skeletons 4 | 5 | %% 6 | % Set output directory in setParameterSettings to datasets subfolder for 7 | % using segmentation supplied segmentation (for testing without having to 8 | % rerun classification and segmentation 9 | seg.root = [dataDirectory filesep 'datasets' filesep 'ek0563' filesep 'seg' filesep]; 10 | seg.prefix = '100527_k0563_seg'; 11 | % Start isosurface visualization of volume reconstruction 12 | galleryRetinaStart(dataDirectory, outputDirectory, seg); 13 | 14 | %% 15 | contactDetectionRetinaStart(dataDirectory, outputDirectory, seg); 16 | --------------------------------------------------------------------------------