├── .gitignore ├── AutomatedAnalysis.m ├── LICENSE.md ├── README.md ├── SpectralPipeline.m ├── chronic ├── ChronicFindNonMatches.m ├── ChronicMatching.m ├── ChronicMatchingUpdate.m ├── ImageRegistrationApp │ ├── ImageReg2P.prj │ ├── README.md │ ├── config │ │ ├── createConfig.m │ │ ├── default_config.mat │ │ └── resetConfig.m │ ├── dep │ │ ├── CreateRGB2.m │ │ ├── PyramidRegisterPair.m │ │ ├── basicQueue.m │ │ ├── cmapL.m │ │ ├── fetchData.m │ │ ├── fetchDir.m │ │ ├── fetchFile.m │ │ ├── getLargestImgRef.m │ │ ├── mergeStructs.m │ │ └── registerImgs.m │ ├── finished_app │ │ └── ImageReg2P.mlappinstall │ ├── imgRegMain.mlapp │ ├── res │ │ ├── next-button.png │ │ ├── save.png │ │ └── upload.png │ ├── tester.m │ └── util │ │ ├── getDate.m │ │ ├── getIDName.m │ │ ├── getImg.m │ │ └── getMask.m ├── MoveLikeChronic.m ├── MoveLikeChronicFun.m └── dep │ ├── BImgOverlapScore.m │ ├── ChronicViewer.m │ ├── CutEmptyEdges.m │ ├── CutEmptyEdgesImg.m │ └── OverlapScore.m ├── docs ├── Figure_Analysis_Pipeline.png ├── Figure_spectral-Delier_20190916_002-1-Declutter.png ├── RoiManagerGUI_Manual_V4.pdf └── Spectral-Segmentation_Manual.pdf ├── getSig ├── DeconvolveSignals.m ├── SbxSigPatches.m ├── SealSignals.m ├── autoRetrieveDecon.m ├── dep │ ├── MLPest20210313.mat │ ├── MLpest20180927.mat │ ├── basecorrect.m │ └── retrievesignals_parWB.m └── retrievesignals.m ├── sbxConversions ├── Hdf52Sbx.m ├── Sbx2TiffStack.m ├── SbxCropTime.m ├── TiffImages2Sbx.m ├── TiffStack2OneSbx.m ├── TiffStack2Sbx.m ├── WriteSbx.m └── mp4vid2Sbx.m ├── spectral ├── DecimateTrans.m ├── RoiManagerGUI.fig ├── RoiManagerGUI.m ├── SpectralColorImg.m ├── StackTranspose.m ├── dep │ ├── PixelCor.m │ ├── SpectParArm.fig │ ├── SpectParArm.m │ ├── Spectroiparm.m │ ├── SummaryGetRois.m │ ├── XYgetZ.m │ ├── ZgetXY.m │ ├── Zgetinfo.m │ ├── Zorder.cpp │ ├── Zorder.mexa64 │ ├── Zorder.mexmaci64 │ ├── Zorder.mexw64 │ ├── getCon.m │ ├── getcontourlines.m │ ├── getcorpow.m │ ├── getcsdf.m │ ├── getcsdfnd.m │ ├── localmax.m │ ├── perimarea.m │ ├── roisfromlocalmax.m │ ├── setminlevel.m │ ├── smoothG.m │ └── transmemap.m ├── getSpectrois.m ├── spectral.m └── spectralOld.m ├── startup.m └── util ├── BackgroundSubtractSbx.m ├── BackgroundSubtractSbxExampleFrame.m ├── EyeData2Avi.m ├── FluorescenceImgSbx.m ├── Mask3D_Flatten.m ├── PPModernize.m ├── PPfromMask.m ├── PPfromMaskFile.m ├── PrintBImg.m ├── PrintBImgs.m ├── RunPrintBImgs.m ├── SbxCropTimeTest.m ├── SbxZStack.m ├── ShiftLinesCheck.m ├── ShiftLinesSbx.m ├── Showsbx.m ├── SpatialCorrCalcRun.m ├── SpecProfileCalcRun.m ├── dep ├── AskDate.m ├── BufferMask.m ├── Colorbar2D.m ├── CorrRoiCorners.m ├── CreateRGB.m ├── CreateRGB2.m ├── CreateRGB2_mat.m ├── ETA.m ├── FindNNumInStr.m ├── GetCenteredFigPos.m ├── GetRoiCoM.m ├── GetRoiCorners.m ├── MidtoneBalance.m ├── PlotCon.m ├── PlotManyImgs.m ├── Register2Imgs.m ├── Register2ImgsNew.m ├── RemoveROIs.m ├── RotatePPCoordinates.m ├── SaveImg.m ├── SetLimits.m ├── ShiftLinesImg.m ├── Showsbx.html ├── SortROIsMask.m ├── SortROIsPP.m ├── SpatialCorrCalcFun.m ├── SpecProfileCalcFun.m ├── ViewVolumeRGB1.m ├── a.png ├── cmapL.m ├── cmapLimsAround0.m ├── figtitle.m ├── findjobj.m ├── getSystemMem.m ├── iconvideo.png ├── largestmemblock.m ├── license_xcorr2_ftt.txt ├── prctfilt.m ├── sbxread.m ├── sbxsigout.m ├── sbxsplit.m ├── subtightplot.m ├── sum.png ├── toolbar.PNG └── xcorr2_fft.m ├── normcorreSpecSeg.m ├── sbx2ij.m └── simonalign3.m /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.asv 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 2.0 Generic License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. 2 | -------------------------------------------------------------------------------- /SpectralPipeline.m: -------------------------------------------------------------------------------- 1 | %% Pipeline for spectral segmentation analysis 2 | % 3 | % Via this script all major steps of the spectral segmentation pipeline 4 | % for ROI selection and matching can be executed. 5 | % All of the functions can be called without input, the functions will 6 | % ask which file to analyse. 7 | % Be aware that your image sequence needs to be aligned in advance! 8 | 9 | % sbx data is required. TIFF can be converted to sbx 10 | %% Convert (multiple) tiff files that have multiple frames (full movie) to as many sbxfiles 11 | TiffStack2Sbx 12 | 13 | %% Convert multiple tiff files that have multiple frames to one sbx file 14 | TiffStack2OneSbx 15 | 16 | %% Convert a folder full of tiff files, each tif file consisting of 1 frame 17 | TiffImages2Sbx 18 | 19 | %% Convert H5 files to sbx 20 | Hdf52Sbx 21 | 22 | 23 | %% For 1 photon/ miniscope data background subtraction is necessary 24 | BackgroundSubtractSbx 25 | 26 | 27 | %% Correct for bidirectional scanning misalignment? uneven vs even lines shifted? 28 | % Also decreases really high values (>65500) to something low in the data!! 29 | trans = false; % false: Correct for horizontal lines. True: correct for vertical lines 30 | % Check for shift. 31 | ShiftLinesSbx([], trans, 1) 32 | 33 | 34 | %% Motion correct sbx data 35 | Showsbx 36 | % Press the A button for the Alignment/motion correction 37 | % Rightclick on main image to adjust color scale etc 38 | 39 | %% Transpose the motion corrected sbx file to improve reading speed 40 | % Creates _Trans.dat file 41 | StackTranspose 42 | 43 | %% Decimate the Trans.dat file to ~1 Hz, and convert data to double class 44 | % Creates _DecTrans.dat file 45 | DecimateTrans 46 | 47 | %% Calculate the cross spectral power for each pixel with 8 surrounding 48 | % pixels. Requires DecTrans.dat file to function 49 | % Creates _SPSIG.mat file 50 | spectral 51 | 52 | %% Create calcium fluorescence images (maximum and average projection) 53 | % Projections get saved into SPSIG file (and outputted into the workspace) 54 | FluorescenceImgSbx; 55 | 56 | %% Print pngs of fluorescence images & colored spectral (optional) 57 | % Uses images in the SPSIG file created by FLuorescenceImgSbx 58 | PrintBImgs 59 | 60 | %% ROI segmentation (neurons, or boutons) 61 | % ROIs, ROI properties and used spectral images get saved into SPSIG file 62 | getSpectrois 63 | 64 | %% Remove or add ROIS manually, display and compare roi sets 65 | % If save button is pressed, edits are made in the SPSIG file 66 | RoiManagerGUI 67 | 68 | %% Retrieve the signals associated with these rois from the aligned data 69 | % Signals get added to the _SPSIG file 70 | retrievesignals 71 | 72 | %% Create a fast Simple Estimate of Activity by Leander (SEAL) 73 | % Seal signal gets added to the _SPSIG file 74 | SealSignals 75 | 76 | %% deconvolve signals 77 | % MLspike spike estimation signals get added to the _SPSIG file 78 | DeconvolveSignals 79 | 80 | %% Match ROIs of multiple recordings together 81 | % Run this script step by step. 82 | ChronicMatching 83 | 84 | -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/ImageReg2P.prj: -------------------------------------------------------------------------------- 1 | 2 | 3 | ImageReg2P 4 | Augustijn Vrolijk 5 | a.vrolijk@nin.knaw.nl 6 | Nederlandse Herseninstituut 7 | 8 | 9 | GUI enabling automatic image registration for two-photon microscopy recordings 10 | 11 | 12 | 1.0 13 | 14 | Image Processing Toolbox 15 | 16 | 17 | 17 18 | 19 | 20 | 24.2 21 | 22 | 23 | ${PROJECT_ROOT}\finished_app 24 | 7febb115-2cee-4f77-8d72-9c52b2b2eae6 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ${PROJECT_ROOT}\imgRegMain.mlapp 35 | 36 | 37 | C:\Users\augus\NIN_Stuff\SpectralSegmentation\util\dep\cmapL.m 38 | C:\Users\augus\NIN_Stuff\SpectralSegmentation\util\dep\CreateRGB2.m 39 | 40 | 41 | ${PROJECT_ROOT}\config 42 | ${PROJECT_ROOT}\dep 43 | ${PROJECT_ROOT}\res 44 | ${PROJECT_ROOT}\util 45 | 46 | 47 | 48 | C:\Users\augus\NIN_Stuff\SpectralSegmentation\chronic\ImageRegistrationApp\finished_app 49 | 50 | 51 | 52 | C:\Program Files\MATLAB\R2024b 53 | 54 | 55 | 56 | 57 | 58 | 59 | true 60 | 61 | 62 | 63 | 64 | true 65 | 66 | 67 | 68 | 69 | false 70 | false 71 | true 72 | false 73 | false 74 | false 75 | false 76 | false 77 | 10.0 78 | false 79 | true 80 | win64 81 | true 82 | 83 | 84 | -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/README.md: -------------------------------------------------------------------------------- 1 | # MATLAB Image registration and GUI 2 | 3 | ## Method: 4 |
5 | Image registration is performed pairwise, i.e. at each iteration one image is selected as a fixed image, and another is chosen as the moving image, which is shifted (Transformed) to match up onto the fixed image as best as possible. 6 | The current method for registration is built around affine transformations (Translation, Rotation, Scaling, Shearing) and takes part in three steps. 7 | 8 | - Creating a "Pyramid level" representation of the images:
reducing their quality and initally registering the "easier" (and smaller) images before iteratively using the best found solution on the next larger image 9 | - Solving an initial cross correlation on the lowest Pyramid level:
Initially selecting the best found solution by cross-correlating the two smallest images together. This is usually done with only translation, It is possible to change the configuration to include rotation and scaling 10 | - Iterative solving:
After the initial cross correlation, we optimise based on your chosen metric by translating, rotating, scaling or shearing the images around. This is iteratively done, with the best found solution being passed down the pyramid back to the original images 11 | 12 | ## Features: 13 | 14 | As a user you have full control over the optimisation algorithm and metric. A configuration file is added to save your preferences as well as provide standard settings, but there is a choice between different metrics and optimsation algorithms, as well as their parameters.
15 | 16 | When selecting more than two images, two options are possible: 17 | 18 | - With Pivot:
One image is selected to remain the fixed image, iterate through the list of images, solving between the fixed image and the nth image. The best found solution is passed onto the next image down the list 19 | - Without pivot:
The list of images is descended iteratively, choosing the current and next image as the fixed and moving image respectively 20 | 21 | I.e. for a list of 5 images to be registered: 22 | 23 | | With Pivot | Without Pivot | 24 | | --- | --- | 25 | |
FixedMoving
Image 1Image 2
Image 1Image 3
Image 1Image 4
Image 1Image 5
|
FixedMoving
Image 1Image 2
Image 2Image 3
Image 3Image 4
Image 4Image 5
| 26 | 27 | ## Outputs: 28 | 29 | The scripts to run the optimisation are also provided as standalone scripts called by the app, and so can be used without needing to run the app. These scrips return affinetform2d objects, which describe an affine transformation. Functions to apply these transforms to your images are also provided and the app 30 | natively does this as seen on the "Image" tab. 31 | 32 | Options to either save the transform object, or the transformed images are possible. 33 | 34 | ## GUI: 35 | 36 | The scripts can either be run independently, or via the provided GUI. The GUI enables easy integration of the configuration settings, with customisability to allow for different image formats, optimisation settings and more. 37 | An integrated image tab allows you to verify the optimisation as well as selectively refine unsatisfactory registrations. 38 | 39 | ## Coming Soon: 40 | 41 | - Automatic integrated ROI selection to enable tracking of neuron activity between recordings. 42 | - Automatic analysis on tracked ROIs including correlation of activity between recordings 43 | -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/config/createConfig.m: -------------------------------------------------------------------------------- 1 | function config = createConfig(name) 2 | arguments (Input) 3 | name string = "NOTVALIDNAME" 4 | end 5 | if strcmp(name, "NOTVALIDNAME") 6 | error("no name given for the configuration, either add one manually or call createConfig with a name") 7 | end 8 | 9 | config = struct; 10 | config.register = struct; 11 | config.data = struct; 12 | 13 | 14 | %ALL IMAGE REGISTRATION INFO CAN BE FOUND AT: 15 | %https://nl.mathworks.com/help/images/image-registration.html 16 | 17 | 18 | [optimiser, metric] = imregconfig('monomodal'); 19 | %for default configurations check out: https://www.mathworks.com/help/images/ref/imregconfig.html 20 | 21 | config.register.metric = metric; 22 | %options include: 23 | %https://nl.mathworks.com/help/images/ref/registration.metric.mattesmutualinformation.html 24 | %https://nl.mathworks.com/help/images/ref/registration.metric.meansquares.html 25 | 26 | config.register.optimiser = optimiser; 27 | %options include: 28 | %https://nl.mathworks.com/help/images/ref/registration.optimizer.oneplusoneevolutionary.html 29 | %https://nl.mathworks.com/help/images/ref/registration.optimizer.regularstepgradientdescent.html 30 | 31 | config.register.levels = 4; 32 | config.register.transform = "affine"; 33 | %options include: "translation", "rigid", "similarity", "affine" 34 | config.register.crossCTransform = "translation"; 35 | %options include: "translation", "rigid", "similarity" 36 | 37 | config.data.ExtraColumns = {"IDName = getIDName(Name, Date)", "Date = getDate(Name)"}; 38 | config.data.FetchDataCols = {"Image = getImg(Name, Path)", "Mask = getMask(Name, Path)"}; 39 | 40 | if ispref('imageReg2P', name) 41 | rmpref('imageReg2P', name) 42 | end 43 | addpref('imageReg2P', name, config) 44 | 45 | if ispref('imageReg2P', 'config_name') 46 | rmpref('imageReg2P', 'config_name') 47 | end 48 | addpref('imageReg2P', 'config_name', name) 49 | 50 | clc 51 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/config/default_config.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/chronic/ImageRegistrationApp/config/default_config.mat -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/config/resetConfig.m: -------------------------------------------------------------------------------- 1 | function config = resetConfig() 2 | 3 | config = struct; 4 | [optimiser, metric] = imregconfig('monomodal'); 5 | 6 | config.register = struct; 7 | config.register.metric = metric; 8 | config.register.optimiser = optimiser; 9 | config.register.levels = 4; 10 | config.register.transform = "affine"; 11 | config.register.crossCTransform = "translation"; 12 | 13 | 14 | config.data = struct; 15 | config.data.ExtraColumns = {"IDName = getIDName(Name, Date)", "Date = getDate(Name)"}; 16 | config.data.FetchDataCols = {"Image = getImg(Name, Path)", "Mask = getMask(Name, Path)"}; 17 | 18 | if ispref('imageReg2P', 'default_config') 19 | rmpref('imageReg2P', 'default_config') 20 | end 21 | addpref('imageReg2P', 'default_config', config) 22 | 23 | name = "default_config"; 24 | if ispref('imageReg2P', 'config_name') 25 | rmpref('imageReg2P', 'config_name') 26 | end 27 | addpref('imageReg2P', 'config_name', name) 28 | 29 | clc 30 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/dep/CreateRGB2.m: -------------------------------------------------------------------------------- 1 | function [RGB] = CreateRGB2(data, colors, varargin) 2 | % Create a colorfull image by overlaying 2D images from a cell array using 3 | % a requested specific colormap 4 | % 5 | % RGB = CreateRGB2(data, colors, normalization, whitebalance, selected) 6 | % 7 | % input: 8 | % - data: ([n x 1] cell array), with 2D or 3D doubles. 9 | % - colors ([n x 3] double): color values to give to corresponding data. 10 | % Optional input: can be left empty [] or disregarded completely 11 | % - normalize: true or false. Normalizes each data slice 12 | % - wbalance : true or false. White balances final RGB image. Can make 13 | % the images not correspond to their intended colors. 14 | % - selected ([n x 1] double): In case each cell contains a 3D matrix 15 | % select which image of the 3rd dimension to use. 16 | % 17 | % 18 | % output: 19 | % - RGB: 3D double [height x width x 3] of largest 2D double in data 20 | % 21 | % 22 | % See also CreateRGB, CreateRGB2_mat 23 | % 24 | % Leander de Kraker 25 | % 2019-3-1 26 | % 27 | 28 | % normalize? 29 | if (nargin > 3) && ~isempty(varargin{1}) 30 | norma = varargin{1}; 31 | else 32 | norma = false; 33 | end 34 | if (nargin >= 4) && ~isempty(varargin{2}) 35 | wbalance = varargin{2}; 36 | else 37 | wbalance = false; 38 | end 39 | if (nargin == 5) 40 | selected = varargin{3}; 41 | else 42 | selected = 1; 43 | end 44 | 45 | nslices = length(data); 46 | dims = (cellfun(@size, data,'UniformOutput',false)); 47 | dims = cat(1,dims{:}); 48 | if size(dims, 2)==3 49 | for i = 1:nslices 50 | data{i} = data{i}(:,:,selected); 51 | end 52 | end 53 | 54 | maxdim(1) = max(dims(:,1)); 55 | maxdim(2) = max(dims(:,2)); 56 | RGB = zeros(maxdim(1), maxdim(2), 3); 57 | 58 | 59 | for i = 1:nslices 60 | 61 | if norma % normalize intensities of the channel 62 | data{i} = (data{i}-min(data{i}(:)))./ range(data{i}(:)); 63 | else % Set the data to minimum 0 64 | data{i} = data{i}-min(data{i}(:)); 65 | end 66 | 67 | for c = 1:3 68 | if colors(i,c)>0 69 | % RGB update = old colorchannel values + imgage i * colormap value 70 | RGB(1:dims(i,1),1:dims(i,2),c) = RGB(1:dims(i,1),1:dims(i,2),c) + ... 71 | data{i} .* colors(i,c); 72 | end 73 | end 74 | end 75 | 76 | 77 | % Normalize colors 78 | minvals = min(RGB(:)); 79 | maxvals = max(RGB(:)); 80 | % Delete -infs and infs if found 81 | if minvals == -inf 82 | vals = unique(RGB); 83 | minvals = vals(2); % second smallest value (not -inf) 84 | idx = RGB < minvals; % indexes of -inf values in this colorchannel 85 | RGB(idx) = minvals; 86 | end 87 | if maxvals == inf 88 | vals = unique(RGB); 89 | maxvals(i) = vals(end-1); 90 | idx = RGB > maxvals; % indexes of -inf values in this colorchannel 91 | RGB(idx) = maxvals; 92 | end 93 | 94 | % normalize 95 | RGB = (RGB-minvals) ./ range([minvals, maxvals]); 96 | 97 | if wbalance 98 | % Normalize colors (per color channel)(results in unrequested colors... 99 | % ...but it's "white balanced") 100 | maxvals = squeeze(max(squeeze(max(RGB)))); 101 | minvals = squeeze(min(squeeze(min(RGB)))); 102 | for i = 1:3 103 | % Normalize 104 | if range([minvals(i), maxvals(i)])>0 105 | RGB(:,:,i) = (RGB(:,:,i)-minvals(i)) ./ range([minvals(i), maxvals(i)]); 106 | end 107 | end 108 | end 109 | 110 | end 111 | 112 | 113 | -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/dep/PyramidRegisterPair.m: -------------------------------------------------------------------------------- 1 | function finalTForm = PyramidRegisterPair(fixed, moving, metric, optimizer, progress, options) 2 | arguments (Input) 3 | fixed (:, :) double 4 | moving (:, :) double 5 | metric = [] 6 | optimizer = [] 7 | progress = struct(); 8 | options.levels double = 4 9 | options.transform string = "affine" 10 | options.crossCTransform string = "translation" 11 | end 12 | arguments (Output) 13 | finalTForm affinetform2d 14 | end 15 | defaultProg = struct('iter',1,'total',1,'progressBar',0); 16 | progress = mergeStructs(defaultProg, progress); 17 | %LOOK into a default check function, for all the optimise funcs, which 18 | %does the optimizer/metric/levels/transform checking 19 | 20 | [defaultOptimizer, defaultMetric] = imregconfig("monomodal"); 21 | if isempty(optimizer) 22 | optimizer = defaultOptimizer; 23 | end 24 | if isempty(metric) 25 | metric = defaultMetric; 26 | end 27 | if options.levels < 1 28 | error("Must select a level strength greater than or equal to 1") 29 | end 30 | 31 | pyramidImgTable = table('Size', [options.levels, 2], 'VariableTypes',{'cell', 'cell'}, 'VariableNames',{'fixed', 'moving'}); 32 | [pyramidImgTable.fixed{1}, pyramidImgTable.moving{1}] = trimToSize(fixed, moving); 33 | 34 | for i=2:options.levels 35 | pyramidImgTable.fixed{i} = impyramid(pyramidImgTable.fixed{i-1}, "reduce"); 36 | pyramidImgTable.moving{i} = impyramid(pyramidImgTable.moving{i-1}, "reduce"); 37 | end 38 | %can change the transform type for cross corr, but has a risk of 39 | %unpredictable behaviour 40 | if ~isequal(progress.progressBar, 0) 41 | level = 1; 42 | updateWaitbar(level); 43 | end 44 | curTForm = imregcorr(pyramidImgTable.moving{options.levels},pyramidImgTable.fixed{options.levels},options.crossCTransform); 45 | 46 | for i = options.levels-1:-1:1 47 | if ~isequal(progress.progressBar, 0) 48 | level = options.levels+1 - i; 49 | updateWaitbar(level); 50 | end 51 | nextTForm = pyramidUpTform(curTForm); %scale up transform for the next pyramid layer 52 | curTForm = imregtform(pyramidImgTable.moving{i}, pyramidImgTable.fixed{i}, options.transform, optimizer, metric, PyramidLevels=1, InitialTransformation=nextTForm); 53 | end 54 | 55 | finalTForm = curTForm; 56 | 57 | 58 | function tformUp = pyramidUpTform(inputTForm) 59 | %{ 60 | I BELIEVE EVERYTHING SCALES OTHER THAN THE TRANSLATION, if its a 3x3 61 | matrix, the one in position, 1,3 and 2,3 are the translation vectors, 62 | therefore just need to double the .A (affine transform) in positions 63 | 1,3 and 2,3 to get the upscaled transform 64 | %} 65 | transformMatrix = inputTForm.A; 66 | transformMatrix([1,2], 3) = 2*transformMatrix([1,2], 3); 67 | tformUp = affinetform2d(transformMatrix); 68 | end 69 | 70 | function [fixedTrimmed, movingTrimmed] = trimToSize(fixed, moving) 71 | 72 | fixedSize = size(fixed); 73 | movingSize = size(moving); 74 | minrow = min(fixedSize(1), movingSize(1)); 75 | mincol = min(fixedSize(2), movingSize(2)); 76 | 77 | fixedTrimmed = fixed(1:minrow, 1:mincol); 78 | movingTrimmed = moving(1:minrow, 1:mincol); 79 | 80 | end 81 | 82 | function updateWaitbar(tLevel) 83 | progressPercent = ((progress.iter - 1) * options.levels + tLevel) / (progress.total * options.levels); 84 | message = sprintf('Registering image pair: %d/%d on pyramid level: %d/%d', ... 85 | progress.iter, progress.total, tLevel, options.levels); 86 | waitbar(progressPercent, progress.progressBar, message); 87 | end 88 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/dep/fetchData.m: -------------------------------------------------------------------------------- 1 | function outputTable = fetchData(filenames, filepaths, vars) 2 | arguments (Input) 3 | filenames (:,1) string 4 | filepaths (:,1) string 5 | vars (1, :) cell 6 | end 7 | arguments (Output) 8 | outputTable (:, :) table 9 | end 10 | 11 | nFiles = length(filenames); 12 | for i = 1:nFiles 13 | filename = fullfile(filepaths(i), filenames(i)); 14 | loadedStruct(i) = load(filename, vars{:}); 15 | end 16 | fields = fieldnames(loadedStruct); 17 | 18 | if length(fields) == 1 && nFiles == 1 19 | loadedStruct.(fields{1}) = {loadedStruct.(fields{1})}; 20 | end 21 | 22 | outputTable = struct2table(loadedStruct); 23 | end 24 | -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/dep/fetchDir.m: -------------------------------------------------------------------------------- 1 | function [filenames, filepaths] = fetchDir() 2 | arguments (Output) 3 | filenames (:, 1) string 4 | filepaths (:, 1) string 5 | end 6 | 7 | [rawNames, rawPaths] = selectFolder(); 8 | nFiles = length(rawNames); 9 | filenames = strings(nFiles, 1); 10 | filepaths = strings(nFiles, 1); 11 | 12 | for i=1:nFiles 13 | filenames(i) = rawNames{i}; 14 | filepaths(i) = rawPaths{i}; 15 | end 16 | 17 | function [rawNames, rawPaths] = selectFolder() 18 | folderPath = uigetdir(); 19 | if isequal(folderPath, 0) 20 | rawNames = {}; 21 | rawPaths = {}; 22 | 23 | else 24 | tempFolder = dir(folderPath); 25 | tempFolder([tempFolder.isdir]) = []; 26 | 27 | rawNames = {tempFolder.name}'; 28 | rawPaths = {tempFolder.folder}'; 29 | end 30 | end 31 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/dep/fetchFile.m: -------------------------------------------------------------------------------- 1 | function [filenames, filepaths] = fetchFile() 2 | arguments (Output) 3 | filenames (:, 1) string 4 | filepaths (:, 1) string 5 | end 6 | 7 | [rawNames, rawPaths] = uigetfile("MultiSelect","on"); 8 | 9 | if ischar(rawNames) 10 | nFiles = 1; 11 | elseif iscell(rawNames) 12 | nFiles = length(rawNames); 13 | elseif rawNames == 0 14 | nFiles = 0; 15 | else 16 | error("error fetching file, returned filename is not 0, a cell or a char") 17 | 18 | end 19 | 20 | if ~ischar(rawPaths) && rawPaths ~= 0 21 | error("error fetching file, returned filepath is not a char as expected") 22 | end 23 | 24 | filenames = strings(nFiles, 1); 25 | filepaths = strings(nFiles, 1); 26 | 27 | for i=1:nFiles 28 | if ischar(rawNames) 29 | filenames(i) = rawNames; 30 | else 31 | filenames(i) = rawNames{i}; 32 | end 33 | filepaths(i) = rawPaths; 34 | end 35 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/dep/getLargestImgRef.m: -------------------------------------------------------------------------------- 1 | function finalImgRef = getLargestImgRef(ImgRefs) 2 | arguments (Input) 3 | ImgRefs (:, 1) imref2d 4 | end 5 | arguments (Output) 6 | finalImgRef imref2d 7 | end 8 | %first retrieve the world limit property into a 2*n matirx, then 9 | %reshape to an array of 1*2n. 10 | XWorldLimitsArray = reshape(vertcat(ImgRefs.XWorldLimits), 1, []); 11 | YWorldLimitsArray = reshape(vertcat(ImgRefs.YWorldLimits), 1, []); 12 | %retrieve the range in coords to find the smallest and largest coord 13 | %needed to fit everything, round it to remove small fraction errors 14 | [xWorldmin, xWorldmax] = bounds(round(XWorldLimitsArray)); 15 | [yWorldmin, yWorldmax] = bounds(round(YWorldLimitsArray)); 16 | %calculate size 17 | xSize = xWorldmax - xWorldmin; 18 | ySize = yWorldmax - yWorldmin; 19 | finalImgRef = imref2d([ySize xSize], [xWorldmin, xWorldmax], [yWorldmin, yWorldmax]); 20 | if finalImgRef.PixelExtentInWorldX ~= 1 || finalImgRef.PixelExtentInWorldY ~= 1 21 | error('the calculated Pixel extent is wrong, this is a bug'); 22 | end 23 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/dep/mergeStructs.m: -------------------------------------------------------------------------------- 1 | function options = mergeStructs(defaults, userOptions) 2 | % Get field names of both structs 3 | userFields = fieldnames(userOptions); 4 | 5 | % Copy default values 6 | options = defaults; 7 | 8 | % Overwrite defaults with user-specified values 9 | for i = 1:numel(userFields) 10 | options.(userFields{i}) = userOptions.(userFields{i}); 11 | end 12 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/dep/registerImgs.m: -------------------------------------------------------------------------------- 1 | function imgTForms = registerImgs(inputImages, inputFixed, metric, optimizer, options) 2 | arguments (Input) 3 | inputImages (:, 1) cell 4 | inputFixed (1, 1) cell = {0} 5 | metric = [] 6 | optimizer = [] 7 | options.levels double = 4 8 | options.transform string = "affine" 9 | options.crossCTransform string = "translation" 10 | options.progressBar = 0; 11 | end 12 | arguments (Output) 13 | imgTForms (:, 1) affinetform2d 14 | end 15 | 16 | progExist = true; 17 | if isequal(options.progressBar, 0) 18 | disp("we are here and we shouldn't") 19 | progExist = false; 20 | options.progressBar = waitbar(0, "Initialising ..."); 21 | end 22 | 23 | [defaultOptimizer, defaultMetric] = imregconfig("monomodal"); 24 | if isempty(optimizer) 25 | optimizer = defaultOptimizer; 26 | end 27 | if isempty(metric) 28 | metric = defaultMetric; 29 | end 30 | 31 | [fixedCell, movingCell, isPivot] = resolveImagePairs(inputFixed, inputImages); 32 | nImages = length(movingCell); 33 | 34 | imgTForms((nImages + 1), 1) = affinetform2d(); %one extra to include the fixed image, it will have a blank transform 35 | 36 | for i=1:nImages 37 | 38 | [fixedWarp, movingWarp] = warpPair(fixedCell{i}, movingCell{i}, imgTForms(i), isPivot); 39 | 40 | progress = struct('iter',i,'total',nImages,'progressBar',options.progressBar); 41 | 42 | newTForm = PyramidRegisterPair(fixedWarp, movingWarp, metric, optimizer, ... 43 | progress,levels=options.levels,transform=options.transform, ... 44 | crossCTransform=options.crossCTransform); 45 | 46 | nextTForm = affinetform2d(imgTForms(i).A*newTForm.A); 47 | 48 | imgTForms(i+1) = nextTForm; 49 | end 50 | 51 | if ~progExist 52 | close(options.progressBar) 53 | end 54 | 55 | function [fixedClean, movingClean, isPivot] = resolveImagePairs(fixed, images) 56 | %{ 57 | I want two arrays: 58 | A: B: 59 | FIXED : img1; img1; img1 - FIXED : img1; img2; img3; 60 | MOVING: img2; img3; img4 - MOVING: img2; img3; img4; 61 | 62 | Three scenarios: 63 | Fixed is not given - then we do option B 64 | Fixed is given - not duplicate in Images - option A 65 | Fixed is given - is duplicate in Images - option A 66 | %} 67 | %FLAG IS GIVEN AS THE MAIN LOOP NEEDS TO ACT DIFFERENTLY IF THE 68 | %PIVOT IS ALWAYS THE SAME OR NOT, otherwise it registers to a 69 | %basearray of actually unregistered images. 70 | 71 | if length(fixed) >= 2 72 | error("only one image can be selected as the 'pivot'"); 73 | elseif isequal(fixed{1}, 0) 74 | nPairs = length(images) - 1; 75 | fixedClean = cell(nPairs, 1); 76 | movingClean = cell(nPairs, 1); 77 | for j = 1:nPairs 78 | fixedClean{j} = images{j}; 79 | movingClean{j} = images{j + 1}; 80 | end 81 | isPivot = false; 82 | else 83 | %THIS IS THE BUG; THE DUPLICATE IS NOT NECESSARILY Images{1} SO 84 | %NEED TO LOOP THROUGH AND CHECK 85 | toRemove = []; 86 | for j=1:length(images) 87 | if isequal(images{j}, fixed{:}) 88 | toRemove = [toRemove; j]; 89 | end 90 | end 91 | for j=1:length(toRemove) 92 | warning("Removed image: %d; This image was the same as the pivot",toRemove(j)); 93 | images(toRemove(j)) = []; 94 | end 95 | nPairs = length(images); 96 | fixedClean = cell(nPairs, 1); 97 | movingClean = cell(nPairs, 1); 98 | for j = 1:nPairs 99 | fixedClean{j} = fixed{:}; 100 | movingClean{j} = images{j}; 101 | end 102 | isPivot = true; 103 | end 104 | end 105 | 106 | function [fixedWarp, movingWarp] = warpPair(fixed, moving, tForm, isPivot) 107 | noChange = affinetform2d(); 108 | fixedView = affineOutputView(size(fixed),noChange,"BoundsStyle","FollowOutput"); 109 | movingView = affineOutputView(size(moving),tForm,"BoundsStyle","FollowOutput"); 110 | finalOutputView = getLargestImgRef([fixedView, movingView]); 111 | if isPivot 112 | fixedWarp = imwarp(fixed, noChange, "OutputView", finalOutputView); 113 | else 114 | fixedWarp = imwarp(fixed, tForm, "OutputView", finalOutputView); 115 | end 116 | movingWarp = imwarp(moving, tForm, "OutputView", finalOutputView); 117 | end 118 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/finished_app/ImageReg2P.mlappinstall: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/chronic/ImageRegistrationApp/finished_app/ImageReg2P.mlappinstall -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/imgRegMain.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/chronic/ImageRegistrationApp/imgRegMain.mlapp -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/res/next-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/chronic/ImageRegistrationApp/res/next-button.png -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/res/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/chronic/ImageRegistrationApp/res/save.png -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/res/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/chronic/ImageRegistrationApp/res/upload.png -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/tester.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/chronic/ImageRegistrationApp/tester.m -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/util/getDate.m: -------------------------------------------------------------------------------- 1 | function filedates = getDate(filenames) 2 | % Find filedates that is hidden somewhere in filename 3 | % Format: yyyyMMdd = 20220708 4 | % 5 | % Leander de Kraker 6 | % 2022-7-8 7 | % 8 | % Update from the original code 9 | % Augustijn Vrolijk 10 | % 2025-02-13 11 | arguments (Input) 12 | filenames (:, 1) string 13 | end 14 | arguments (Output) 15 | filedates (:, 1) cell 16 | end 17 | 18 | desiredLength = 8; %hardcoded as this is the expected format 19 | desiredFormat = 'yyyyMMdd'; 20 | nFiles = length(filenames); 21 | 22 | filedates = cell(nFiles, 1); 23 | %NaT(nFiles, 1, 'Format',desiredFormat); 24 | for i=1:nFiles 25 | filename = filenames{i}; 26 | 27 | %find date automatically 28 | strdate = findDateAuto(filename); 29 | 30 | % can fail to find it automatically so check the found date 31 | isValidDate = checkDate(strdate); 32 | 33 | % if it failed ask user 34 | if ~ isValidDate 35 | strdate = AskForDate(filename); 36 | end 37 | 38 | try % try to decipher user input as a datetime 39 | filedates{i} = datetime(strdate, 'inputformat','yyyyMMdd'); 40 | catch METOO % another error: No date for this recording. 41 | warning('User input not recognized as date') 42 | end 43 | 44 | end 45 | 46 | function isValid = checkDate(inputDate) 47 | try 48 | tempVal = datetime(inputDate, 'inputformat',desiredFormat); 49 | if isnat(tempVal) 50 | isValid = false; 51 | else 52 | isValid = true; 53 | end 54 | catch METOO % Date extraction failed. Ask user for input 55 | isValid = false; 56 | end 57 | end 58 | 59 | function outputDate = AskForDate(filename) 60 | questionStr = sprintf('No date detected for file, \nfile:%s\n',... 61 | filename); 62 | questionStr = [questionStr, 'Please type its date here as yyyyMMdd:']; 63 | outputDate = inputdlg(questionStr); 64 | end 65 | 66 | function outputDate = findDateAuto(filestr) 67 | %findNNumInStr returns [], an empty array if it can't find a 68 | %sequence of consecutive numbers of desiredLength 69 | 70 | outputDate = FindNNumInStr(filestr, desiredLength); 71 | if isempty(outputDate) % Hope the date was not found because it has dashes 72 | filestr = strrep(filestr,'-',''); 73 | outputDate = FindNNumInStr(filestr, desiredLength); 74 | if isempty(outputDate) % Last hope, maybe different dashes? 75 | filestr = strrep(filestr,'_',''); 76 | outputDate = FindNNumInStr(filestr, desiredLength); 77 | end 78 | end 79 | end 80 | 81 | function strOut = FindNNumInStr(str, n) 82 | % Find a number that is exactly n digits long in a string 83 | % 84 | % 85 | % Leander de Kraker 86 | % 2022-7-15 87 | % 88 | 89 | % Get info about the digits in the string 90 | pos = regexp(str, '\d'); 91 | a=diff(pos); 92 | b=find([a inf]>1); 93 | c=diff([0 b]); % length of the sequences 94 | good = pos(b(c==n)); 95 | 96 | if isscalar(good) 97 | strOut = str(good-n+1:good); 98 | else 99 | strOut = []; 100 | end 101 | end 102 | 103 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/util/getIDName.m: -------------------------------------------------------------------------------- 1 | function filenamesShort = getIDName(filenames, filedates) 2 | arguments (Input) 3 | filenames (:,1) string 4 | filedates (:,1) cell 5 | end 6 | arguments (Output) 7 | filenamesShort (:, 1) cell 8 | end 9 | 10 | nfiles = length(filenames); 11 | filenamesShort = cell(nfiles, 1); 12 | 13 | for i = 1:nfiles 14 | temp_name = regexp(filenames(i), '^(.*?)_', 'tokens'); 15 | name = temp_name{1}{1}; % Extract the first matched token 16 | filenamesShort{i} = append(name, ' ', string(filedates{i})); 17 | end 18 | end -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/util/getImg.m: -------------------------------------------------------------------------------- 1 | function images = getImg(filenames, filepaths) 2 | arguments (Input) 3 | filenames (:, 1) string 4 | filepaths (:, 1) string 5 | end 6 | arguments (Output) 7 | images (:, 1) cell 8 | end 9 | fetchStr = 'BImg'; 10 | 11 | images = cell(length(filenames), 1); 12 | rawImagesTable = fetchData(filenames, filepaths, {fetchStr}); 13 | 14 | for i = 1:length(filenames) 15 | images{i} = cleanImage(rawImagesTable.(fetchStr){i}); 16 | end 17 | 18 | function cleanImg = cleanImage(Img) 19 | isClean = false; 20 | cleanImg = Img; 21 | 22 | while not (isClean) %trim outer image border 23 | 24 | isClean = true; 25 | if isequal(cleanImg(1,:),cleanImg(end,:)) 26 | cleanImg = cleanImg(2:end-1,:); 27 | isClean = false; 28 | end 29 | if isequal(cleanImg(:,1),cleanImg(:,end)) 30 | cleanImg = cleanImg(:,2:end-1); 31 | isClean = false; 32 | end 33 | end 34 | infMask = isinf(cleanImg); % create mask, 1 if value at index is inf, 0 if not 35 | [minVal, maxVal] = bounds(cleanImg(~infMask)); % check the bounds of the values not at inf 36 | cleanImg(infMask) = minVal; % clean inf values with true min vals 37 | cleanImg = (cleanImg - minVal) ./ range([minVal, maxVal]); % normalise image to have range [0, .., 1] 38 | end 39 | end 40 | 41 | 42 | -------------------------------------------------------------------------------- /chronic/ImageRegistrationApp/util/getMask.m: -------------------------------------------------------------------------------- 1 | function masks = getMask(filenames, filepaths) 2 | arguments (Input) 3 | filenames (:, 1) string 4 | filepaths (:, 1) string 5 | end 6 | arguments (Output) 7 | masks (:, 1) cell 8 | end 9 | fetchStr = 'Mask'; 10 | 11 | masks = cell(length(filenames), 1); 12 | rawMaskTable = fetchData(filenames, filepaths, {fetchStr}); 13 | 14 | for i = 1:length(filenames) 15 | mask = rawMaskTable.(fetchStr){i}; 16 | mask(rawMaskTable.(fetchStr){i} > 0) = 1; 17 | masks{i} = mask; 18 | end 19 | end -------------------------------------------------------------------------------- /chronic/MoveLikeChronicFun.m: -------------------------------------------------------------------------------- 1 | function imgs = MoveLikeChronicFun(imgs, tr) 2 | % Apply transformations to a cell array of pictures 3 | % 4 | % 5 | % Leander de Kraker 6 | % 2022-7-11 7 | 8 | 9 | %% Load the background images 10 | 11 | nfiles = length(imgs); 12 | 13 | for i = 1:length(tr) 14 | tri = tr(i); 15 | 16 | % Apply offsets 17 | regiVert = tri.vert; 18 | regiHori = tri.hori; 19 | imgNew = cell(1, nfiles); 20 | for f = 1:nfiles 21 | imgNew{f} = zeros(max(regiVert(:,2)), max(regiHori(:,2)), size(imgs{f},3)); 22 | imgNew{f}(regiVert(f,1):regiVert(f,2), regiHori(f,1):regiHori(f,2), :) = imgs{f}; 23 | end 24 | 25 | % Cut empty edges away 26 | imgs = CutEmptyEdgesImg(imgNew, tri.cutting); 27 | 28 | for f = find(abs(tri.rotation)>0.02)' % If rotation angle < 0.02, don't rotate 29 | imgs{f} = imrotate(imgs{f}, tri.rotation(f), 'bilinear', 'crop'); 30 | end 31 | 32 | end 33 | 34 | -------------------------------------------------------------------------------- /chronic/dep/BImgOverlapScore.m: -------------------------------------------------------------------------------- 1 | function [corrScore] = BImgOverlapScore(BImg) 2 | % Takes a cell array of 2D doubles as input. 3 | % outputs the correlation values 4 | % of the comparisons between the different 2D doubles. 5 | % 6 | % If the 2D double matrixes are not the same size, the larger ones will be 7 | % cut. 8 | % 9 | % Leander de Kraker 10 | % 2018-8-3 11 | 12 | nfiles = length(BImg); 13 | corrScore = zeros(nfiles); 14 | for i = 1:nfiles 15 | others = find((1:nfiles) < i); 16 | for j = others 17 | if all(size(BImg{i}) == size(BImg{j}))% The images are the same size :) 18 | corrScore(i, j) = corr(BImg{i}(:), BImg{j}(:)); % Get linear correlation value 19 | else 20 | % The images need to be cut 21 | minsize1 = 1:min(size(BImg{i}, 1), size(BImg{j},1)); 22 | minsize2 = 1:min(size(BImg{i}, 2), size(BImg{j},2)); 23 | BImgi = BImg{i}(minsize1, minsize2); 24 | BImgj = BImg{j}(minsize1, minsize2); 25 | corrScore(i, j) = corr(BImgi(:), BImgj(:)); 26 | end 27 | end 28 | end 29 | % To save time, only the lower triangle has been calculated by the for loop 30 | % fill upper triangle of matrix from lower triangle (output should be 31 | % symmetrical over diagonal) 32 | corrScore = corrScore + tril(corrScore,-1).'; 33 | 34 | end 35 | 36 | -------------------------------------------------------------------------------- /chronic/dep/CutEmptyEdges.m: -------------------------------------------------------------------------------- 1 | function [BImg2, Masks2, PP, cutting] = CutEmptyEdges(BImg2, Masks2, PP, nfiles) 2 | % [BImg2, Masks2, PP] = CutEmptyEdges(BImg2, Masks2, PP) 3 | % Cuts away edges which only contain zeros in the BImg2 from the BImg and 4 | % corresponding Masks, and also edits the contour information accordingly. 5 | % 6 | % This is desireable because consecutive registration rounds can cause 7 | % empty edges around the images. 8 | % 9 | % Output: 10 | % - Updated BImgs, Masks, PP 11 | % - cutting ([4 x 1] double): Described which how many pixels were cut from 12 | % which sides of the data: 13 | % [bottom cut (end 1st dimension), top cut, right cut (end 2nd 14 | % dimension), left cut (beginning 2nd dimension)], respectively. 15 | % 16 | % 17 | % Leander de Kraker 18 | % 2021 19 | 20 | BImgMat = cat(3, BImg2{:}); 21 | BImgMat = max(BImgMat,[],3); 22 | zeroCols = find(all(BImgMat'==0)); 23 | zeroRows = find(all(BImgMat==0)); 24 | 25 | cutting = nan(4, 1); 26 | 27 | if ~isempty(zeroCols) 28 | % Cut at the end (bottom) 29 | if ismember(size(BImgMat,1), zeroCols) % Does the end have columns with only zeros? 30 | skipper = find(diff(zeroCols)>1); 31 | if ~isempty(skipper) 32 | % Black columns at multiple different places in the BImgMat?! 33 | if length(skipper)>2 34 | warning('contact Leander'); 35 | skipper = skipper(end); 36 | end 37 | skipper = skipper + 1; 38 | else 39 | skipper = 1; 40 | end 41 | cutting(1) = zeroCols(skipper); 42 | 43 | for i = 1:nfiles 44 | BImg2{i}(zeroCols(skipper):end,:) = []; 45 | Masks2{i}(zeroCols(skipper):end,:) = []; 46 | end 47 | end 48 | % Cut at the beginning (top) (also change PP) 49 | if ismember(1, zeroCols) 50 | skipper = find(diff(zeroCols)>1); 51 | if ~isempty(skipper) 52 | % Black columns at multiple different places in the BImgMat?! 53 | if length(skipper)>2 54 | warning('contact Leander'); 55 | skipper = skipper(1); % Only delete until the first non-zero row 56 | end 57 | else 58 | skipper = length(zeroCols); 59 | end 60 | cutting(2) = zeroCols(skipper); 61 | 62 | 63 | for i = 1:nfiles 64 | BImg2{i}(1:zeroCols(skipper),:) = []; 65 | Masks2{i}(1:zeroCols(skipper),:) = []; 66 | PP(i).P(2,:) = PP(i).P(2,:) - skipper; 67 | for j = 1:PP(i).Cnt 68 | PP(i).Con(j).y = PP(i).Con(j).y - skipper; 69 | end 70 | end 71 | end 72 | end 73 | if ~isempty(zeroRows) 74 | % Cut at the end (right) 75 | if ismember(size(BImgMat,2), zeroRows) % Does the end have rows with only zeros? 76 | skipper = find(diff(zeroRows)>1); 77 | if ~isempty(skipper) 78 | % Black rows at multiple different places in the BImgMat?! 79 | if length(skipper)>2 80 | warning('contact Leander'); 81 | skipper = skipper(end); 82 | end 83 | skipper = skipper + 1; 84 | else 85 | skipper = 1; 86 | end 87 | cutting(3) = zeroRows(skipper); 88 | 89 | for i = 1:nfiles 90 | BImg2{i}(:,zeroRows(skipper):end) = []; 91 | Masks2{i}(:,zeroRows(skipper):end) = []; 92 | end 93 | end 94 | % Cut at the beginning (left) (also change PP) 95 | if ismember(1, zeroRows) 96 | skipper = find(diff(zeroRows)>1); 97 | if ~isempty(skipper) 98 | % Black columns at multiple different places in the BImgMat?! 99 | if length(skipper)>2 100 | warning('contact Leander'); 101 | skipper = skipper(1); % Only delete until the first non-zero row 102 | end 103 | else 104 | skipper = length(zeroRows); 105 | end 106 | cutting(4) = zeroRows(skipper); 107 | 108 | for i = 1:nfiles 109 | BImg2{i}(:,1:zeroRows(skipper)) = []; 110 | Masks2{i}(:,1:zeroRows(skipper)) = []; 111 | PP(i).P(1,:) = PP(i).P(1,:) - skipper; 112 | for j = 1:PP(i).Cnt 113 | PP(i).Con(j).x = PP(i).Con(j).x - skipper; 114 | end 115 | end 116 | end 117 | end 118 | 119 | -------------------------------------------------------------------------------- /chronic/dep/CutEmptyEdgesImg.m: -------------------------------------------------------------------------------- 1 | function img = CutEmptyEdgesImg(img, cutting) 2 | % img = CutEmptyEdgesImg(img) 3 | % Cuts away edges as denoted by the chronic registration 4 | % 5 | % input: 6 | % img (cell array with images of same size) 7 | % cutting ([4 x 1] double): 8 | % 9 | % output: 10 | % img (cell array with images of same size, cropped) 11 | % 12 | % 13 | % Leander de Kraker 14 | % 2022-7-11 15 | % 16 | 17 | nfiles = length(img); 18 | 19 | if ~isnan(cutting(1)) 20 | % Cut at the end (bottom) 21 | for i = 1:nfiles 22 | img{i}(cutting(1):end,:,:) = []; 23 | end 24 | end 25 | if ~isnan(cutting(2)) 26 | % Cut at the beginning (top) 27 | for i = 1:nfiles 28 | img{i}(1:cutting(2),:,:) = []; 29 | end 30 | end 31 | if ~isnan(cutting(3)) 32 | % Cut at the end (right) 33 | for i = 1:nfiles 34 | img{i}(:, cutting(3):end,:) = []; 35 | end 36 | end 37 | if ~isnan(cutting(4)) 38 | % Cut at the beginning (left) 39 | for i = 1:nfiles 40 | img{i}(:, 1:cutting(4),:) = []; 41 | end 42 | end -------------------------------------------------------------------------------- /chronic/dep/OverlapScore.m: -------------------------------------------------------------------------------- 1 | function score = OverlapScore(inRoi, linkMat, i) 2 | % Calculate the average % overlap between ROIs, 3 | % 4 | % input: 5 | % inRoi: cell array with cell arrays with overlap information 6 | % linkMat: Matrix with ROI numbers, for row i a score is calculated 7 | % i: digid. which row to calculate overlap score for 8 | % 9 | % iutput: 10 | % score: % overlap between the ROIs in row i of the linkMat 11 | % 12 | % Leander de Kraker 13 | % 14 | 15 | score = 0; 16 | counter = 0; 17 | present = find(linkMat(i,:)); 18 | if length(present) > 1 % If there are matches to be searched 19 | for m = present(1:end-1) 20 | for c = present(present>m) 21 | % Check overlap from roi i in recording m -> linked roi in recording c 22 | found = inRoi{m}{linkMat(i,m),c}; 23 | idx = found(:,1)==linkMat(i,c); 24 | if ~isempty(idx) && any(idx) % Maybe the ROI wasn't in the ROI, abort in that case 25 | try 26 | score = score + found(idx, 3); 27 | catch 28 | fprintf('Doubt for match %d: no overlap between %d and %d\n', i, m, c) 29 | end 30 | else 31 | fprintf('Doubt for match %d: no overlap for neuron %d and %d\n', i, m, c) 32 | end 33 | 34 | % Check overlap from roi i in recording c -> linked roi in 35 | % recording m (which is the roi i in recording m) 36 | found = inRoi{c}{linkMat(i,c),m}; 37 | idx = found(:,1)==linkMat(i,m); 38 | if ~isempty(idx) && any(idx) % Maybe the ROI wasn't in the ROI, abort in that case 39 | try 40 | score = score + found(idx, 3); 41 | catch 42 | fprintf('Doubt for match %d: no overlap between %d and %d\n', i, c, m) 43 | end 44 | end 45 | 46 | counter = counter + 2; 47 | 48 | end 49 | end 50 | score = score./counter; % calculate average overlap 51 | end 52 | 53 | end -------------------------------------------------------------------------------- /docs/Figure_Analysis_Pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/docs/Figure_Analysis_Pipeline.png -------------------------------------------------------------------------------- /docs/Figure_spectral-Delier_20190916_002-1-Declutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/docs/Figure_spectral-Delier_20190916_002-1-Declutter.png -------------------------------------------------------------------------------- /docs/RoiManagerGUI_Manual_V4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/docs/RoiManagerGUI_Manual_V4.pdf -------------------------------------------------------------------------------- /docs/Spectral-Segmentation_Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/docs/Spectral-Segmentation_Manual.pdf -------------------------------------------------------------------------------- /getSig/SealSignals.m: -------------------------------------------------------------------------------- 1 | function infoSigPar = SealSignals(filename) 2 | % Simple Estimate of Activity by Leander (seal) 3 | % 4 | % infoSigRetreival = SealSignal(filename) does a simple and fast 5 | % calculation on sig and sigCorrected in the file 'filename' 6 | % 7 | % Input: filename = (string) spectral filename, with sig variable present 8 | % In case no input is given the script will ask for the filename 9 | % 10 | % Output: infoSigPar = info on Signal retrieval Parameters (struct) 11 | % 12 | % SEAL smooths the signal a bit with a gaussian filter of windowSize 13 | % SEAL takes the derivative of the smoothed signal, 14 | % and removes negative values. 15 | % This is very super fast and will result in high signal when the 16 | % fluorescence signal is rising. 17 | % It will underestimate activity in case of 'sustained high 18 | % fluorescence because of longer activity'. 19 | % But the signal is not sparse like the spike estimate 20 | 21 | % Select file if code is being called as script 22 | try 23 | asfunction = nargin == 1; 24 | catch 25 | asfunction = false; 26 | end 27 | if ~asfunction 28 | [fn, pn] = uigetfile('*_SPSIG.mat'); 29 | if fn == 0 % if cancelled 30 | fprintf('no file selected: exiting\n') 31 | return 32 | end 33 | filename = [pn fn]; 34 | end 35 | 36 | % Load the data 37 | load(filename, 'sig', 'sigBack', 'infoSigPar', 'freq'); 38 | if ~exist('infoSigPar', 'var') 39 | infoSigPar.alpha = 0.7; 40 | end 41 | 42 | % Activate much tighter subplots 43 | % [subplot margin top&side],[figure bottomspace,topspace],[leftspace,rightspace] 44 | subplot = @(m,n,p) subtightplot (m, n, p, [0.05 0.06], [0.1 0.1], [0.1 0.02]); 45 | 46 | noiseFloor = 0; 47 | % filter parameters to reduce noise 48 | windowSize = 1; 49 | % b = (1/windowSize)*ones(1,windowSize); 50 | 51 | seal = imgaussfilt(sig, [windowSize, 0.01]); 52 | seal = diff(seal) - noiseFloor; 53 | seal(end+1, :) = 0; % fill at end 54 | seal(seal<0) = 0; 55 | sealBack = imgaussfilt(sigBack, [windowSize, 0.01]); 56 | sealBack = diff(sealBack) - noiseFloor; 57 | sealBack(end+1, :) = 0; 58 | sealBack(sealBack<0) = 0; 59 | sealCorrected = seal - infoSigPar.alpha * sealBack; 60 | sealCorrected(sealCorrected<0) = 0; 61 | 62 | % plot seal 63 | figure('units', 'normalized', 'position', [0.5 0.2 0.24 0.5], 'Name', 'SEAL') 64 | subplot(1,1,1) 65 | RGB = CreateRGB({seal', sealBack'}, 'rg b'); 66 | xas = (1:length(sig))./freq; 67 | imagesc(xas./60, 1:size(seal,2), RGB); 68 | title(sprintf('seal (Simple Estimate of Activity by Leander)\n%s',filename)) 69 | xlabel('time (minutes)') 70 | ylabel('ROI (n)') 71 | xlim([0 xas(end)/60]); 72 | 73 | 74 | %% save seal 75 | infoSigPar.noiseFloorSEAL = noiseFloor; 76 | infoSigPar.filterSizeSEAL = windowSize; 77 | 78 | save(filename, 'seal', 'sealBack', 'sealCorrected', 'infoSigPar', '-append') 79 | fprintf('saved the seal\n') 80 | 81 | 82 | -------------------------------------------------------------------------------- /getSig/autoRetrieveDecon.m: -------------------------------------------------------------------------------- 1 | % Retrieve signal and deconvolve for as many files as you want. 2 | % 3 | % Press 'cancel' when done selecting. 4 | % 5 | % 6 | 7 | filenames = {}; 8 | filepaths = {}; 9 | 10 | selecting = true; % true as long as files are being selected 11 | i = 0; 12 | while selecting 13 | i = i + 1; 14 | [filenames{i}, filepaths{i}] = uigetfile('*SPSIG.mat', sprintf('file %d',i)); 15 | 16 | if filenames{i} == 0 % Cancel is pressed probably: stop with selecting 17 | filenames(i) = []; 18 | filepaths(i) = []; 19 | selecting = false; 20 | end 21 | end 22 | filenames = filenames'; 23 | filepaths = filepaths'; 24 | nfiles = length(filenames); 25 | clearvars selecting 26 | 27 | %% Do retrieve signals and deconvolution 28 | for i = 1:nfiles 29 | retrievesignals([filepaths{i}, filenames{i}]); 30 | SealSignals([filepaths{i}, filenames{i}]); 31 | DeconvolveSignals([filepaths{i}, filenames{i}]); 32 | end 33 | -------------------------------------------------------------------------------- /getSig/dep/MLPest20210313.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/getSig/dep/MLPest20210313.mat -------------------------------------------------------------------------------- /getSig/dep/MLpest20180927.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/getSig/dep/MLpest20180927.mat -------------------------------------------------------------------------------- /getSig/dep/basecorrect.m: -------------------------------------------------------------------------------- 1 | function sig = basecorrect(sig, window) 2 | % Convert fluorescence signal to Df/f 3 | % Chris vd Togt. 4 | % 2023-2-22. Leander changed calculation from (F-F0)/linearfitF0 + 1 5 | % to (F-F0)/F0 6 | 7 | % 10th quantile interpolated baseline correction 8 | f0 = prctfilt(sig',10,window,window,0)'; 9 | sig = (sig - f0) ./ f0; -------------------------------------------------------------------------------- /getSig/dep/retrievesignals_parWB.m: -------------------------------------------------------------------------------- 1 | function retrievesignals_parWB(~) 2 | % Waitbar (WB) for use in a parfor loop in DeconvolveSignals.m 3 | global p N h 4 | waitbar(p/N, h, sprintf('Running MLspike (Runtime: %1.2f min)',toc/60)); 5 | p = p + 1; 6 | end -------------------------------------------------------------------------------- /sbxConversions/Hdf52Sbx.m: -------------------------------------------------------------------------------- 1 | % Convert hdf5 files to sbx. 2 | % Step 1: Select h5 file. 3 | % Step 2: Select filename and location to save sbx file. 4 | % Step 3: Type the data sampling rate in Hz 5 | % Step 4: Repeat step 1-3 for as many files as you want to convert. Press 6 | % cancel when done selecting files. 7 | % 8 | % Script is only tested on grayscale data. 9 | % 10 | % Leander de Kraker 11 | % 2021-4-6 12 | % 13 | 14 | % Load as many files as user wants 15 | % Get the tiff file and where to put the sbx file 16 | fileNameH5 = {}; 17 | filePathH5 = {}; 18 | fileNameSbx = {}; 19 | filePathSbx = {}; 20 | selecting = true; % true as long as files are being selected 21 | i = 0; 22 | while selecting 23 | i = i + 1; 24 | [fileNameH5{i}, filePathH5{i}] = uigetfile('*.h5',... 25 | sprintf('get h5 file %d, press cancel when done selecting',i)); 26 | 27 | 28 | if fileNameH5{i} == 0 % Cancel is pressed probably: stop with selecting 29 | fileNameH5(i) = []; 30 | filePathH5(i) = []; 31 | selecting = false; 32 | else % Ask where to save the sbx file 33 | [fileNameSbx{i}, filePathSbx{i}] = uiputfile([filePathH5{i} fileNameH5{i}(1:end-3) '.sbx'],... 34 | 'Where to save the sbx file'); 35 | Hz(i) = str2double(inputdlg('What is the framerate for this dataset? (Hz)')); 36 | end 37 | end 38 | nfiles = length(fileNameH5); 39 | clearvars selecting 40 | 41 | i = 1; 42 | %% process the files 43 | for i = 1:nfiles 44 | 45 | % global info variable may cause problems, thoroughly delete it 46 | clearvars -global info 47 | clearvars info 48 | 49 | fileH5 = [filePathH5{i}, fileNameH5{i}]; 50 | fileSbx = [filePathSbx{i}, fileNameSbx{i}]; 51 | 52 | h5Info = h5info(fileH5); 53 | 54 | dims = h5Info.Datasets.Dataspace.Size; 55 | dataName = ['/', h5Info.Datasets.Name]; 56 | ndims = length(dims); 57 | nframes = dims(3); 58 | 59 | if isfield(h5Info.Datasets.Datatype, 'Type') && strcmp(h5Info.Datasets.Datatype.Type, 'H5T_STD_U8LE') 60 | % Increase values by multiplying with 256 to allow increase in data 61 | % detail in later analysis 62 | multiplier = 2^8; 63 | fprintf("Increasing data's max values from 256 to 65536 to allow for more detail in 16 bit file\n") 64 | else 65 | multiplier = 1; 66 | end 67 | 68 | 69 | fileID = fopen(fileSbx, 'w'); % open sbx file 70 | 71 | 72 | % Read all frames of the tif and write them to the sbx file 73 | hwb = waitbar(0, 'writing sbx file'); 74 | countEl = [dims(1:end-1),1]; % How many elements to read along each dimension 75 | 76 | for f = 1:nframes 77 | startLoc = [ones(1,ndims-1),f]; % from which sample to start reading the data 78 | im = uint16(h5read(fileH5, dataName, startLoc, countEl)) .* multiplier; 79 | fwrite(fileID, im, 'uint16'); 80 | if mod(f, 500)==0 81 | waitbar(f/nframes, hwb, 'writing sbx file') 82 | imagesc(im); colormap(cmapL('inferno', 256)); title(sprintf('%d',f)) 83 | end 84 | end 85 | fclose(fileID); 86 | close(hwb) 87 | 88 | % Write the info (.mat) file that belongs to the sbx 89 | info = struct(); 90 | info.sz = dims(1:2); %image dimension 91 | info.channels = 2; %one channel 92 | info.Slices = 1; % One depth 93 | info.nchan = 1; 94 | info.Perm = [2 1 3 4]; 95 | info.Shape = [dims(1:2), 1]; 96 | info.nsamples = info.sz(2) * info.sz(1) * 2 * info.nchan; 97 | info.simon = 1; %don't invert with intmax 98 | info.scanbox_version = 2.5; 99 | info.max_idx = nframes; 100 | info.Freq = Hz(i); 101 | info.recordsPerBuffer = 0; 102 | info.strfp = [fileSbx(1:end-4)]; 103 | 104 | save([fileSbx(1:end-4) '.mat'], 'info'); 105 | fprintf('done saving %s\n', fileNameSbx{i}) 106 | end 107 | -------------------------------------------------------------------------------- /sbxConversions/Sbx2TiffStack.m: -------------------------------------------------------------------------------- 1 | % Select as many sbx files as you want to convert to tiff stack 2 | % tif stack will consist of many grayscale images. 3 | % Tif can't support files larger than 4 GB, sometimes not even larger 4 | % than 2 GB. So large sbx get split up into multiple different files 5 | % smaller than 3 GB... 6 | % 7 | % Sbx files currently supported: 1 split 8 | % Only 1 color will be written to tiff file 9 | % 10 | % 11 | % Leander de Kraker 12 | % 2021-2-24 13 | % 14 | 15 | maxSize = 3; % max tiff file size in GB 16 | 17 | % Load as many files as user wants 18 | % Get the tiff file and where to put the sbx file 19 | fileNameTif = {}; 20 | filePathTif = {}; 21 | fileNameSbx = {}; 22 | filePathSbx = {}; 23 | selecting = true; % true as long as files are being selected 24 | i = 0; 25 | while selecting 26 | i = i + 1; 27 | [fileNameSbx{i}, filePathSbx{i}] = uigetfile('*.sbx',... 28 | sprintf('get sbx file %d, press cancel when done selecting',i)); 29 | 30 | if fileNameSbx{i} == 0 % Cancel is pressed probably: stop with selecting 31 | fileNameSbx(i) = []; 32 | filePathSbx(i) = []; 33 | selecting = false; 34 | else % Ask where to save the sbx file 35 | fileNameSbx{i} = strsplit(fileNameSbx{i}, '.'); 36 | fileNameSbx{i} = fileNameSbx{i}{1}; 37 | [fileNameTif{i}, filePathTif{i}] = uiputfile([filePathSbx{i} fileNameSbx{i} '.tif'],... 38 | 'Where to save the tif file'); 39 | end 40 | end 41 | nfiles = length(fileNameTif); 42 | clearvars selecting 43 | i = 1; 44 | %% Convert the files to tif 45 | 46 | for i = 1:nfiles 47 | 48 | nametifBase = [filePathTif{i}, fileNameTif{i}]; 49 | namesbx = [filePathSbx{i}, fileNameSbx{i}]; 50 | 51 | % Get info of the sbx file 52 | clearvars -global info 53 | clearvars info 54 | load(namesbx) 55 | frame = sbxread(namesbx, 0, 1); 56 | 57 | sbxfileProperties = dir([namesbx '.sbx']); 58 | sbxfileSize = sbxfileProperties.bytes / 10^9; % GB 59 | if sbxfileSize > maxSize % if file size is over max size.. 60 | tn = ceil(sbxfileSize/ maxSize); % number of tif files to create 61 | framesForTifs = round(linspace(0, info.max_idx, tn+1)); % frames for each tif file 62 | nametif = cell(tn, 1); 63 | for tifi = 1:tn 64 | nametif{tifi} = strrep([nametifBase(1:end-4), sprintf('_%3d', tifi), '.tif'], ' ', '0'); 65 | end 66 | fprintf('sbx file is so large it requires %d tif files...\n', tn) 67 | wbar = waitbar(0, sprintf('converting sbx file %d to tif file (0/%d)', i, tn)); 68 | else % sbx file can be stored in 1 tif file 69 | framesForTifs = [0 info.max_idx]; 70 | tn = 1; 71 | nametif{1} = nametifBase; 72 | wbar = waitbar(0, sprintf('converting sbx file %d to tif', i)); 73 | end 74 | 75 | % tag struct for tif info 76 | tagstruct.ImageLength = size(frame,1); 77 | tagstruct.ImageWidth = size(frame,2); 78 | tagstruct.Photometric = Tiff.Photometric.MinIsBlack; 79 | if isa(frame, 'uint18') 80 | tagstruct.BitsPerSample = 8; 81 | elseif isa(frame, 'uint16') 82 | tagstruct.BitsPerSample = 16; 83 | elseif isa(frame, 'uint32') 84 | tagstruct.BitsPerSample = 32; 85 | else 86 | warning('Not an expected format, quiting\n\n') 87 | return 88 | end 89 | tagstruct.SampleFormat = Tiff.SampleFormat.UInt; 90 | tagstruct.SamplesPerPixel = 1; 91 | tagstruct.RowsPerStrip = 256; 92 | tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky; 93 | tagstruct.Software = 'MATLAB'; 94 | 95 | % Write sbx file to to tn tif files 96 | tic 97 | for tifi = 1:tn 98 | waitbar(framesForTifs(tifi)/info.max_idx, wbar,... 99 | sprintf('converting sbx file %d to tif file (%d/%d)', i, tifi, tn)) 100 | 101 | % Get which frames to put into this tif file 102 | if tn == 1 % All frames 103 | framesToDo = 0:info.max_idx-1; 104 | else % frames between file limit i and i+1 105 | framesToDo = framesForTifs(tifi):framesForTifs(tifi+1)-1; 106 | end 107 | 108 | % open tiff file 109 | t = Tiff(nametif{tifi},'w'); 110 | % write the frames 111 | for framej = framesToDo 112 | frame = sbxread(namesbx, framej, 1); 113 | t.setTag(tagstruct); 114 | t.write(squeeze(frame(:,:,1,:))); 115 | t.writeDirectory(); 116 | if mod(framej, 50)==0 117 | waitbar(framej/info.max_idx, wbar) 118 | end 119 | end 120 | t.close(); 121 | end 122 | toc 123 | delete(wbar) 124 | end 125 | 126 | -------------------------------------------------------------------------------- /sbxConversions/SbxCropTime.m: -------------------------------------------------------------------------------- 1 | function SbxCropTime(strPathIn, strSbxIn, strPathOut, frameStart, frameEnd) 2 | % SbxCropTime(strPathIn, strSbxIn, strPathOut, frameStart, frameEnd) 3 | % Cropping an sbx file in time, creating a copy of it. 4 | % Converting it from a long file, to a shorter file. 5 | % 6 | % Input: 7 | % - strPathIn (string) (ending with '\') 8 | % - strSbxIn (string) filename of sbx 9 | % - strPathOut (string) (folder to put output in, ending with '\') 10 | % - frameStart (scalar double): at which frame to start reading data 11 | % - frameEnd (scalar double): final frame to read data from 12 | % 13 | % Leander de Kraker 14 | % 2024-5-7 15 | % 16 | %% 17 | 18 | strSbxIn = strsplit(strSbxIn, {'.mat', '.sbx'}); 19 | strSbxIn = strSbxIn{1}; 20 | 21 | strIn = [strPathIn, strSbxIn]; 22 | strOut = [strPathOut, strSbxIn, '_cropT']; 23 | 24 | nframes = frameEnd-frameStart+1; 25 | 26 | fileID = fopen([strOut, '.sbx'], 'w'); % open sbx file 27 | ttoreport = max(100, round(nframes/10)); 28 | 29 | clearvars -global info 30 | clearvars info 31 | load(strIn, 'info') 32 | 33 | % Writing the data 34 | tic 35 | for i = 1:nframes 36 | frame = sbxread(strIn, frameStart+i-2, 1); 37 | fwrite(fileID, intmax('uint16')-frame', 'uint16'); 38 | if mod(i,ttoreport)==0 39 | fprintf('done with frame %d/%d (%.0f%%) ETA %.1f minutes\n',... 40 | i, nframes, (i/nframes*100), ETA(i, nframes, toc)/60) 41 | end 42 | end 43 | fprintf('Done\n') 44 | fclose(fileID); 45 | 46 | % Adjusting the info approperiately 47 | if isfield(info, 'frame') 48 | info.frame = info.frame - frameStart + 1; 49 | toDel = info.frame<1 | info.frame>nframes; 50 | info.frame(toDel) = []; 51 | if isfield(info, 'line') 52 | info.line(toDel) = []; 53 | end 54 | if isfield(info, 'event_id') 55 | info.event_id(toDel) = []; 56 | end 57 | end 58 | info.max_idx = nframes; 59 | rmfield(info, 'bytesPerBuffer'); 60 | save([strOut, '.mat'], 'info') 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /sbxConversions/TiffImages2Sbx.m: -------------------------------------------------------------------------------- 1 | % Converts one folder full of tif files which each consist of one frame 2 | % and converts those to one sbx file 3 | % 4 | % Step 1. Select the folder that contains all the tiff frames. press ok. 5 | % Step 2. Select the folder and filename for the output sbx file 6 | % 7 | % 8 | % Script is only tested on grayscale data. 9 | % 10 | % Chris v.d. Togt 11 | % 2022-8-15. Added info and better prompt names - Leander 12 | % 13 | 14 | fp = uigetdir('', 'Select folder that contains the tiff frames'); 15 | files = dir([fp '/*.tif*']); 16 | [~, fn] = fileparts(files(1).name); 17 | [Fn, strSavepath] = uiputfile([fn '.sbx'], 'Select folder and filename of output sbx file'); 18 | fileID = fopen([strSavepath Fn], 'w'); 19 | 20 | hwb = waitbar(0, 'writing sbx file'); 21 | for i = 1:length(files) 22 | fname = fullfile(fp, files(i).name); 23 | im = imread(fname); 24 | fwrite(fileID,im,'uint16'); 25 | waitbar(i/length(files), hwb, 'writing sbx file') 26 | end 27 | fclose(fileID); 28 | 29 | 30 | info.sz = size(im); %image dimension 31 | info.channels = 2; %one channel 32 | info.nchan = 1; 33 | info.Perm = [2 1 3 4]; 34 | info.Shape = [size(im), 1]; 35 | info.nsamples = info.sz(2) * info.sz(1) * 2 * info.nchan; 36 | info.simon = 1; %don't invert with intmax 37 | info.scanbox_version = 2.5; 38 | info.max_idx = length(files); 39 | Strfreq = inputdlg('What is the framerate for this image sequence?'); 40 | info.Freq = str2double(Strfreq); 41 | info.recordsPerBuffer = 0; 42 | 43 | save([strSavepath Fn(1:end-4) '.mat'], 'info'); 44 | close(hwb) 45 | -------------------------------------------------------------------------------- /sbxConversions/TiffStack2OneSbx.m: -------------------------------------------------------------------------------- 1 | % Takes multiple tiff file(s) which consists of multiple grayscale images 2 | % and converts all of them to one 16 bit unsigned integer sbx format, 3 | % with accompanying .mat info file 4 | % 5 | % This is to combine multiple tiff files of one long recording into one sbx 6 | % file. 7 | % 8 | % Step 1. Select a tiff file and press ok. Repeat this. 9 | % Step 2. Press cancel when done with selecting all the tiff files. 10 | % Step 3. Set filename and folder for the one sbx file to output. Press ok. 11 | % 12 | % 13 | % Script is only tested on grayscale data. 14 | % 15 | % Leander de Kraker 16 | % 2021-6-9 17 | % 18 | 19 | % Load as many files as user wants 20 | % Get the tiff file and where to put the sbx file 21 | fileNameTif = {}; 22 | filePathTif = {}; 23 | selecting = true; % true as long as files are being selected 24 | i = 0; 25 | while selecting 26 | i = i + 1; 27 | [fileNameTif{i}, filePathTif{i}] = uigetfile('*.tif',... 28 | sprintf('get tif file %d, press cancel when done selecting',i)); 29 | 30 | if fileNameTif{i} == 0 % Cancel is pressed probably: stop with selecting 31 | fileNameTif(i) = []; 32 | filePathTif(i) = []; 33 | selecting = false; 34 | end 35 | end 36 | 37 | nfiles = length(fileNameTif); 38 | clearvars selecting 39 | 40 | if fileNameTif{end} == 0 41 | warning('Sbx name not selected, select sbx file name. (Do not press cancel when asked where to save sbx file)') 42 | else 43 | [fileNameSbx, filePathSbx] = uiputfile([filePathTif{1} fileNameTif{1}(1:end-4) '.sbx'],... 44 | 'Where to save the sbx file'); 45 | 46 | fileSbx = [filePathSbx, fileNameSbx]; 47 | Hz = str2double(inputdlg('What is the framerate for this image sequence? (Hz)')); 48 | end 49 | 50 | i = 1; 51 | %% process the files 52 | tic 53 | 54 | 55 | fileID = fopen(fileSbx, 'w'); % open sbx file 56 | hwb = waitbar(0, 'writing sbx file'); 57 | 58 | for i = 1:nfiles 59 | 60 | % global info variable may cause problems, thoroughly delete it 61 | clearvars -global info 62 | clearvars info 63 | 64 | fileTif = [filePathTif{i}, fileNameTif{i}]; 65 | 66 | tiffInfo = imfinfo(fileTif); 67 | if isfield(tiffInfo(1), 'BitDepth') && tiffInfo(1).BitDepth == 8 68 | % Increase values by multiplying with 256 to allow increase in data 69 | % detail in later analysis 70 | multiplier = 2^8; 71 | fprintf("Increasing data's max values from 256 to 65536 to allow for more detail in 16 bit file\n") 72 | else 73 | multiplier = 1; 74 | end 75 | 76 | nframes = length(tiffInfo); 77 | for f = 1:nframes 78 | % Read all frames of the tif and write them to the sbx file 79 | im = uint16(imread(fileTif,f)) .* multiplier; 80 | fwrite(fileID, im, 'uint16'); 81 | end 82 | waitbar(i/nfiles, hwb, 'writing sbx file') 83 | end 84 | 85 | fclose(fileID); 86 | close(hwb) 87 | % Write the info (.mat) file that belongs to the sbx 88 | info = struct(); 89 | info.sz = size(im); %image dimension 90 | info.channels = 2; %one channel 91 | info.Slices = 1; % One depth 92 | info.nchan = 1; 93 | info.Perm = [2 1 3 4]; 94 | info.Shape = [size(im), 1]; 95 | info.nsamples = info.sz(2) * info.sz(1) * 2 * info.nchan; 96 | info.simon = 1; %don't invert with intmax 97 | info.scanbox_version = 2.5; 98 | info.max_idx = nframes; 99 | info.Freq = Hz; 100 | info.recordsPerBuffer = 0; 101 | info.strfp = fileSbx(1:end-4); 102 | 103 | save([fileSbx(1:end-4) '.mat'], 'info'); 104 | fprintf('done saving %s\n', fileNameSbx) 105 | 106 | toc 107 | -------------------------------------------------------------------------------- /sbxConversions/TiffStack2Sbx.m: -------------------------------------------------------------------------------- 1 | % Takes tiff file(s) which consists of multiple grayscale images 2 | % and converts it to 16 bit unsigned integer sbx format, with 3 | % accompanying .mat info file 4 | % Pop up enables loading of as many tif files as you want. Each selected 5 | % file will result in a seperate sbx file. 6 | % Press cancel when done with selecting. 7 | % 8 | % 9 | % Script is only tested on grayscale data. 10 | % 11 | % Leander de Kraker 12 | % 2020-11-5 13 | % 14 | 15 | % Load as many files as user wants 16 | % Get the tiff file and where to put the sbx file 17 | fileNameTif = {}; 18 | filePathTif = {}; 19 | fileNameSbx = {}; 20 | filePathSbx = {}; 21 | selecting = true; % true as long as files are being selected 22 | i = 0; 23 | while selecting 24 | i = i + 1; 25 | [fileNameTif{i}, filePathTif{i}] = uigetfile('*.tif',... 26 | sprintf('get tif file %d, press cancel when done selecting',i)); 27 | 28 | if fileNameTif{i} == 0 % Cancel is pressed probably: stop with selecting 29 | fileNameTif(i) = []; 30 | filePathTif(i) = []; 31 | selecting = false; 32 | else % Ask where to save the sbx file 33 | [fileNameSbx{i}, filePathSbx{i}] = uiputfile([filePathTif{i} fileNameTif{i}(1:end-4) '.sbx'],... 34 | 'Where to save the sbx file'); 35 | Hz(i) = str2double(inputdlg('What is the framerate for this image sequence? (Hz)')); 36 | end 37 | end 38 | nfiles = length(fileNameTif); 39 | clearvars selecting 40 | 41 | i = 1; 42 | %% process the files 43 | for i = 1:nfiles 44 | 45 | % global info variable may cause problems, thoroughly delete it 46 | clearvars -global info 47 | clearvars info 48 | 49 | fileTif = [filePathTif{i}, fileNameTif{i}]; 50 | fileSbx = [filePathSbx{i}, fileNameSbx{i}]; 51 | 52 | fileID = fopen(fileSbx, 'w'); % open sbx file 53 | 54 | tiffInfo = imfinfo(fileTif); 55 | if isfield(tiffInfo(1), 'BitDepth') && tiffInfo(1).BitDepth == 8 56 | % Increase values by multiplying with 256 to allow increase in data 57 | % detail in later analysis 58 | multiplier = 2^8; 59 | fprintf("Increasing data's max values from 256 to 65536 to allow for more detail in 16 bit file\n") 60 | else 61 | multiplier = 1; 62 | end 63 | 64 | nframes = length(tiffInfo); 65 | 66 | % Read all frames of the tif and write them to the sbx file 67 | hwb = waitbar(0, 'writing sbx file'); 68 | for f = 1:nframes 69 | im = uint16(imread(fileTif, f)) .* multiplier; 70 | fwrite(fileID, im, 'uint16'); 71 | waitbar(f/nframes, hwb, 'writing sbx file') 72 | end 73 | fclose(fileID); 74 | close(hwb) 75 | 76 | % Write the info (.mat) file that belongs to the sbx 77 | info = struct(); 78 | info.sz = size(im); %image dimension 79 | info.channels = 2; %one channel 80 | info.Slices = 1; % One depth 81 | info.nchan = 1; 82 | info.Perm = [2 1 3 4]; 83 | info.Shape = [size(im), 1]; 84 | info.nsamples = info.sz(2) * info.sz(1) * 2 * info.nchan; 85 | info.simon = 1; %don't invert with intmax 86 | info.scanbox_version = 2.5; 87 | info.max_idx = nframes; 88 | info.Freq = Hz(i); 89 | info.recordsPerBuffer = 0; 90 | info.strfp = [fileSbx(1:end-4)]; 91 | 92 | save([fileSbx(1:end-4) '.mat'], 'info'); 93 | fprintf('done saving %s\n', fileNameSbx{i}) 94 | end 95 | 96 | -------------------------------------------------------------------------------- /sbxConversions/WriteSbx.m: -------------------------------------------------------------------------------- 1 | function WriteSbx(fileSbx, data, varargin) 2 | % WriteSbx(fileSbx, data) 3 | % WriteSbx(fileSbx, data, Hz) 4 | % Write sbx file from workspace variable 5 | % 6 | % Input: 7 | % fileSbx (string): filename, with path possibly, 8 | % data (3D double | uint16): video data to write 9 | % Hz (double): sampling rate of data 10 | % 11 | % As script: 12 | % Step 1: Call the variable that has the 2p video data: data 13 | % Step 2: Select filename and location to save sbx file. 14 | % Step 3: Set the correct sampling rate 15 | % Step 4: run the code 16 | % 17 | % 18 | % 19 | % Leander de Kraker 20 | % 2021-9-17. 21 | % 2021-12-13 Turned into function 22 | % 23 | 24 | if exist('varargin', 'var') && nargin == 3 25 | fileNameSbx = strsplit(fileSbx, '\'); 26 | fileNameSbx = fileNameSbx{end}; 27 | Hz = varargin{1}; 28 | else 29 | Hz = 30; 30 | filePathSbx = 'D:\NAOMi data\MyData\'; 31 | fileNameSbx = 'typicalVolume'; 32 | fileSbx = [filePathSbx, fileNameSbx]; 33 | end 34 | 35 | %% process the files 36 | 37 | % global info variable may cause problems, thoroughly delete it 38 | clearvars -global info 39 | clearvars info 40 | 41 | dims = size(data); 42 | nframes = dims(3); 43 | 44 | fileID = fopen([fileSbx, '.sbx'], 'w'); % open sbx file 45 | 46 | 47 | % Read all frames of the tif and write them to the sbx file 48 | hwb = waitbar(0, 'writing sbx file'); 49 | 50 | for f = 1:nframes 51 | fwrite(fileID, uint16(data(:, :, f))', 'uint16'); 52 | if mod(f, 1000)==0 53 | waitbar(f/nframes, hwb, 'writing sbx file') 54 | imagesc(uint16(data(:, : , f))); 55 | colormap(cmapL('inferno', 256)); title(sprintf('%d',f)) 56 | end 57 | end 58 | fclose(fileID); 59 | close(hwb) 60 | 61 | % Write the info (.mat) file that belongs to the sbx 62 | info = struct(); 63 | info.sz = dims([2 1]); %image dimension 64 | info.channels = 2; %one channel 65 | info.Slices = 1; % One depth 66 | info.nchan = 1; 67 | info.Perm = [2 1 3 4]; 68 | info.Shape = [dims([2 1]), 1]; 69 | info.nsamples = info.sz(1) * info.sz(2) * 2 * info.nchan; 70 | info.simon = 1; %don't invert with intmax 71 | info.scanbox_version = 2.5; 72 | info.max_idx = nframes; 73 | info.Freq = Hz; 74 | info.recordsPerBuffer = 0; 75 | info.strfp = fileSbx; 76 | 77 | save([fileSbx '.mat'], 'info'); 78 | fprintf('done saving %s\n', fileNameSbx) 79 | 80 | 81 | -------------------------------------------------------------------------------- /sbxConversions/mp4vid2Sbx.m: -------------------------------------------------------------------------------- 1 | % Convert MPEG-4 (MP4) files to sbx. 2 | % The three color channels will be averaged into one grayscale video 3 | % 4 | % 5 | % Step 1: Select mp4 file. 6 | % Step 2: Select filename and location to save sbx file. 7 | % Step 3: Type the data sampling rate in Hz 8 | % Step 4: Repeat step 1-3 for as many files as you want to convert. Press 9 | % cancel when done selecting files. 10 | % 11 | % In my experience mp4 video suffers from compression artifacts which do 12 | % degrade data quality. The 8 bit integers also do not offer much quality. 13 | % 14 | % Leander de Kraker 15 | % 2022-4-19 16 | % 17 | 18 | % Load as many files as user wants 19 | % Get the tiff file and where to put the sbx file 20 | fileNameMP4 = {}; 21 | filePathMP4 = {}; 22 | fileNameSbx = {}; 23 | filePathSbx = {}; 24 | selecting = true; % true as long as files are being selected 25 | i = 0; 26 | while selecting 27 | i = i + 1; 28 | [fileNameMP4{i}, filePathMP4{i}] = uigetfile('*.mp4',... 29 | sprintf('get mp4 file %d, press cancel when done selecting',i)); 30 | 31 | 32 | if fileNameMP4{i} == 0 % Cancel is pressed probably: stop with selecting 33 | fileNameMP4(i) = []; 34 | filePathMP4(i) = []; 35 | selecting = false; 36 | else % Ask where to save the sbx file 37 | [fileNameSbx{i}, filePathSbx{i}] = uiputfile([filePathMP4{i} fileNameMP4{i}(1:end-4) '.sbx'],... 38 | 'Where to save the sbx file'); 39 | reader = VideoReader([filePathMP4{i}, fileNameMP4{i}]); 40 | Hz(i) = reader.FrameRate; 41 | Hz(i) = str2double(inputdlg('What is the framerate for this dataset? (Hz)','framerate?',1,{num2str(Hz(i))})); 42 | end 43 | end 44 | nfiles = length(fileNameMP4); 45 | clearvars selecting 46 | 47 | i = 1; 48 | %% process the files 49 | for i = 1:nfiles 50 | 51 | % global info variable may cause problems, thoroughly delete it 52 | clearvars -global info 53 | clearvars info 54 | 55 | fileMP4 = [filePathMP4{i}, fileNameMP4{i}]; 56 | fileSbx = [filePathSbx{i}, fileNameSbx{i}]; 57 | 58 | reader = VideoReader(fileMP4); 59 | 60 | 61 | dims = [reader.Width, reader.Height, reader.NumFrames]; 62 | nframes = dims(3); 63 | 64 | fileID = fopen(fileSbx, 'w'); % open sbx file 65 | 66 | 67 | % Read all frames of the tif and write them to the sbx file 68 | hwb = waitbar(0, 'writing sbx file'); 69 | countEl = [dims(1:end-1),1]; % How many elements to read along each dimension 70 | 71 | for f = 1:nframes 72 | im = uint16(mean(read(reader, f),3) * 4)'; 73 | fwrite(fileID, im, 'uint16'); 74 | if mod(f, 500)==0 75 | waitbar(f/nframes, hwb, 'writing sbx file') 76 | imagesc(im); colormap(cmapL('inferno', 256)); colorbar; title(sprintf('%d',f)) 77 | end 78 | end 79 | fclose(fileID); 80 | close(hwb) 81 | 82 | % Write the info (.mat) file that belongs to the sbx 83 | info = struct(); 84 | info.sz = dims(1:2); %image dimension 85 | info.channels = 2; %one channel 86 | info.Slices = 1; % One depth 87 | info.nchan = 1; 88 | info.Perm = [2 1 3 4]; 89 | info.Shape = [dims(1:2), 1]; 90 | info.nsamples = info.sz(2) * info.sz(1) * 2 * info.nchan; 91 | info.simon = 1; %don't invert with intmax 92 | info.scanbox_version = 2.5; 93 | info.max_idx = nframes; 94 | info.Freq = Hz(i); 95 | info.recordsPerBuffer = 0; 96 | info.strfp = [fileSbx(1:end-4)]; 97 | 98 | save([fileSbx(1:end-4) '.mat'], 'info'); 99 | fprintf('done saving %s\n', fileNameSbx{i}) 100 | end 101 | -------------------------------------------------------------------------------- /spectral/RoiManagerGUI.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/spectral/RoiManagerGUI.fig -------------------------------------------------------------------------------- /spectral/SpectralColorImg.m: -------------------------------------------------------------------------------- 1 | function [rgb, colors, colorbarVals] = SpectralColorImg(loadType, inData, varargin) 2 | % [rgb, colors, colorbarVals] = SpectralColorImg('file', filename, [0 0.5], true) 3 | % [rgb, colors, colorbarVals] = SpectralColorImg('data', {SPic, Sax, spar}, [], false) 4 | % [rgb, colors, colorbarVals] = SpectralColorImg('data', {SPic, Sax, spar}) 5 | % 6 | % Create a color coded image of the spectral images 7 | % 8 | % Input: 9 | % 1 - inputType (string). load data or get data in input? 'file', or 'data' 10 | % 2 - inData. In case of 'file': 11 | % filename (string). SPSIG filename, which should contain SPic and Sax. 12 | % 2 -inData. In case of 'data': 13 | % ([3 x 1] cell array): 1st SPic, 2nd Sax, 3rd (optional) spar. 14 | % (optional inputs 3 and 4) 15 | % 3 - freqToUse ([1 x 2] double). Frequencies in Hz to use. [min, max] 16 | % 4 - plotter (scalar logical). Plot the output? (in an existing axes) 17 | % 18 | % Output: 19 | % - rgb ([h x w x 3] double): The colored spectral image. 20 | % - colors ([n x 3] double): The colors that correspond to each selected 21 | % frequency. 22 | % - colorbarVals ([n x 1] double): The frequencies that are used. 23 | % 24 | % 25 | % Leander de Kraker 26 | % 2022-8-25 27 | % 28 | 29 | 30 | norma = true; % normalize each frequency? 31 | wbalance = false; % white balance red green and blue color channels? 32 | 33 | % Load data or use inputted data 34 | if strcmp(loadType, 'file') 35 | load(inData, 'Sax', 'SPic', 'spar') 36 | if ~exist('SPic', 'var') 37 | rgb = 'no SPic found in file'; 38 | colors = 'no SPic found in file'; 39 | colorbarVals = 'no SPic found in file'; 40 | warning('SPic & Sax variables are essential for SpectralColorImg') 41 | return 42 | end 43 | else 44 | SPic = inData{1}; 45 | Sax = inData{2}; 46 | if length(inData)==3 47 | spar = inData{3}; 48 | end 49 | end 50 | 51 | % Get frequencies to select 52 | if exist('varargin', 'var') && nargin >= 3 && ~isempty(varargin{1}) 53 | freqToUse = varargin{1}; 54 | if length(freqToUse) == 1 % In case of bad input 55 | freqToUse = [0, freqToUse]; 56 | end 57 | elseif exist('spar','var') 58 | if isfield(spar, 'cutOffHzMin') 59 | freqToUse = [spar.cutOffHzMin, spar.cutOffHzMax]; % Frequency needs to be within this range 60 | fprintf('Using frequencies selected by ROI selection: [%.2f %.2f Hz]\n',... 61 | spar.cutOffHzMin, spar.cutOffHzMax) 62 | else 63 | fprintf('spar seems outdated/ incomplete. Using entire specAxis\n') 64 | freqToUse = [-1 1000]; 65 | end 66 | else 67 | freqToUse = [-1 1000]; 68 | fprintf('Using entire specAxis\n') 69 | end 70 | 71 | if exist('varargin', 'var') && nargin == 4 72 | plotter = varargin{2}; 73 | else 74 | plotter = false; 75 | end 76 | 77 | idxToUse = Sax>freqToUse(1) & Sax 65 | spar.roundedness = str2double(answer{5}); 66 | spar.voxel = str2double(answer{6}); 67 | spar.cutOffCorr = str2double(answer{7}); 68 | 69 | if strcmpi(answer{8}, 'no') 70 | spar.useFluorescenceImg = false; 71 | else 72 | spar.useFluorescenceImg = true; 73 | end 74 | 75 | if strcmpi(answer(9), 'on') 76 | DISPLAY = true; 77 | end 78 | 79 | save('spar.mat', 'spar') 80 | end 81 | -------------------------------------------------------------------------------- /spectral/dep/SummaryGetRois.m: -------------------------------------------------------------------------------- 1 | function SummaryGetRois(rejlog, spar) 2 | % Report a summary of the automatic ROI creation from getSpectrois 3 | % 4 | % Chris v.d. Togt 5 | % 2020 6 | % 7 | 8 | total = size(rejlog,1); 9 | 10 | % valid rois 11 | 12 | vidx = (rejlog(:,1)== 2); 13 | valnm = sum(vidx); 14 | if valnm > 10 15 | valid = rejlog(vidx, :); 16 | 17 | %valid stats: 18 | vMd = round(valnm/2); 19 | v5 = ceil(valnm*0.05); 20 | v95 = floor(valnm*0.95); 21 | 22 | vSort = sort(valid(:,2)); % Areas 23 | vAm = vSort(vMd); 24 | Arange = [vSort(v5) vSort(v95)]; 25 | 26 | vSort = sort(valid(:,3)); % Roundedness 27 | vRm = vSort(vMd); 28 | Rrange = [vSort(v5) vSort(v95)]; 29 | 30 | vSort = sort(valid(:,4)); % Rvariance 31 | vRvarm = vSort(vMd); 32 | Rvarange = [vSort(v5) vSort(v95)]; 33 | end 34 | 35 | % invalid maxima 36 | rejected = sum(rejlog(:,1) ~= 2); % All 37 | notsignificant = sum(rejlog(:,1)== -1); % Not significant height 38 | 39 | remidx = ( rejlog(:,1)== 0 | rejlog(:,1)== 1 ); % rejected 40 | remaining = sum(remidx); 41 | notvalid = rejlog(remidx,:); 42 | 43 | tosmall = sum(notvalid(:,2) <= spar.areasz(1)); 44 | tolarge = sum(notvalid(:,2) > spar.areasz(2)); 45 | 46 | belowround = sum(notvalid(:,3) < spar.roundedness); 47 | % bad = sum(notvalid(:,4) > 0.3); 48 | 49 | someidx = isnan(rejlog(:,1)); 50 | Inother = sum(someidx); 51 | 52 | disp("Of " + total + " peaks(maxima), " + valnm + " were valid and " + rejected + " were rejected.") 53 | 54 | if valnm > 10 55 | disp("valid stats:") 56 | disp("Area(pixels) median and 95% range: " + vAm + " : " + Arange(1) + " - " + Arange(2)) 57 | disp("Roundedness median and 95% range: " + vRm + " : " + Rrange(1) + " - " + Rrange(2)) 58 | disp("Rvar median and 95% range: " + vRvarm + " : " + Rvarange(1) + " - " + Rvarange(2)) 59 | end 60 | 61 | disp("Of " + rejected + " rejected peaks:") 62 | disp(notsignificant + " were not significant") 63 | disp(Inother + " were within previously made rois" ) 64 | disp("Of the remaining " + remaining + " peaks the contours were not valid because;") 65 | disp(tosmall + " were too small, " + tolarge + " too large, " + belowround + " not round enough,") 66 | % disp("and " + bad + " had more than 40% below threshold pixel values") 67 | disp(" ") -------------------------------------------------------------------------------- /spectral/dep/XYgetZ.m: -------------------------------------------------------------------------------- 1 | function Z = XYgetZ(indices, sbxt, stacksz) 2 | %return array of traces, given XY coordinates 3 | % Chris van der Togt, 2017, 4 | % Netherlands Institute for Neuroscience 5 | 6 | if ~isobject(sbxt) 7 | return 8 | end 9 | 10 | lngth = length(indices); 11 | indices = indices(:)'; 12 | indices = (indices-1) .* stacksz; %each index is a startpoint for the next z pixel trace 13 | 14 | ix = repmat((1:stacksz)', 1, lngth) + repmat(indices, stacksz, 1); 15 | Z = sbxt.Data(ix(:)); -------------------------------------------------------------------------------- /spectral/dep/ZgetXY.m: -------------------------------------------------------------------------------- 1 | function I = ZgetXY(zx, nm, sbxt, dim) 2 | %return nm images given z coordinate 3 | % Chris van der Togt, 2017, 4 | % Netherlands Institute for Neuroscience 5 | 6 | if ~isobject(sbxt) 7 | return 8 | end 9 | Stacksz = dim(1); 10 | Colsz = dim(2); 11 | Rowsz = dim(3); 12 | 13 | Zx = (1:Stacksz:Stacksz*Colsz*Rowsz)+zx-1; 14 | 15 | if nm > 1 16 | nx = (0:nm-1)'; 17 | Imgx = repmat(Zx, nm, 1); %indices for each image 18 | Imgx = Imgx + repmat(nx, 1, length(Zx)); %indices for consecutive images 19 | else 20 | Imgx = Zx; 21 | end 22 | 23 | I = sbxt.Data(Imgx(:)); 24 | I = reshape(I, nm, Colsz, Rowsz); 25 | I = permute(I, [2 3 1]); %z order images -------------------------------------------------------------------------------- /spectral/dep/Zgetinfo.m: -------------------------------------------------------------------------------- 1 | function [Dim, Freq, Type] = Zgetinfo(strfn) 2 | % Chris van der Togt, 2017, 3 | % Netherlands Institute for Neuroscience 4 | 5 | Fl = memmapfile(strfn); 6 | Header = char(Fl.Data(1:64))'; 7 | strh = strsplit(Header,{' ', '\0'}); 8 | datestr = [strh{5} ' ' strh{6}]; 9 | 10 | Dim = [str2double(strh{1}) str2double(strh{2}) str2double(strh{3})]; 11 | Freq = str2double(strh{4}); 12 | Type = strh{7}; 13 | 14 | 15 | disp(datestr) 16 | disp(['Dimensions : ' num2str(Dim)]) 17 | disp(['Frequency : ' num2str(Freq)]) 18 | -------------------------------------------------------------------------------- /spectral/dep/Zorder.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/spectral/dep/Zorder.mexa64 -------------------------------------------------------------------------------- /spectral/dep/Zorder.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/spectral/dep/Zorder.mexmaci64 -------------------------------------------------------------------------------- /spectral/dep/Zorder.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/spectral/dep/Zorder.mexw64 -------------------------------------------------------------------------------- /spectral/dep/getCon.m: -------------------------------------------------------------------------------- 1 | function [Con, A, F, Pin, roundedness] = getCon(Imgin, th, area, Rof, py, px, Iy, Ix) 2 | % Chris van der Togt, 2017 3 | % Netherlands Institute for Neuroscience 4 | 5 | 6 | dim = size(Imgin); 7 | F = zeros(dim); 8 | % M = -Inf; 9 | 10 | c = contourc(Imgin,[th th]); 11 | s = getcontourlines(c); 12 | v = arrayfun(@(x) eq(x.c,1),s); %closed 13 | iv = find(v); 14 | A = 0; 15 | roundedness = 1; 16 | Pin = false; %is there a contour with peak inside 17 | Con = []; 18 | if ~isempty(iv) 19 | A = area(1); 20 | end 21 | for j = 1:length(iv) 22 | vx = s(iv(j)).x; 23 | vy = s(iv(j)).y; 24 | In = find(inpolygon(px,py,vx,vy),1); 25 | 26 | if ~isempty(In) 27 | Pin = true; 28 | At = polyarea(vx,vy); 29 | if At > area(1) 30 | A = At; 31 | roundedness = perimarea(vx, vy); 32 | if At < area(2) && roundedness > Rof 33 | Con.x = vx; 34 | Con.y = vy; 35 | F(inpolygon(Ix,Iy,vx,vy)) = 1; 36 | end 37 | end 38 | return; 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spectral/dep/getcontourlines.m: -------------------------------------------------------------------------------- 1 | function s = getcontourlines(c) 2 | % Chris van der Togt, 2017, 3 | % Netherlands Institute for Neuroscience 4 | 5 | sz = size(c,2); % Size of the contour matrix c 6 | ii = 1; % Index to keep track of current location 7 | jj = 1; % Counter to keep track of # of contour lines 8 | 9 | s =[]; 10 | while ii < sz % While we haven't exhausted the array 11 | n = c(2,ii); % How many points in this contour? 12 | s(jj).v = c(1,ii); % Value of the contour 13 | s(jj).x = c(1,ii+1:ii+n); % X coordinates 14 | s(jj).y = c(2,ii+1:ii+n); % Y coordinates 15 | s(jj).c = (c(1,ii+1) == c(1,ii+n)); % closed or not 16 | ii = ii + n + 1; % Skip ahead to next contour line 17 | jj = jj + 1; % Increment number of contours 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /spectral/dep/getcorpow.m: -------------------------------------------------------------------------------- 1 | function POW = getcorpow(CSpect, ASpect) 2 | % Chris van der Togt, 2017, 3 | % Netherlands Institute for Neuroscience 4 | 5 | [Lng, Width, Height] = size(ASpect); 6 | 7 | %CCOR = real(ifft(CSpect)); 8 | ACOR = real(ifft(ASpect)); %inverse fft, correlation function, 0 delay is variance 9 | VAR = squeeze(ACOR(1,:,:)); %estimate of total variance for each pixel 10 | 11 | TVAR = VAR(2:Width-1,2:Height-1); 12 | 13 | %surrounding 8 pixels 14 | winx = 1:Width-2; 15 | winy = 1:Height-2; 16 | SVAR = VAR(winx,winy); 17 | VAR2 = shiftdim(repmat(TVAR.*SVAR, 1, 1, Lng), 2); 18 | POW = CSpect(:,:,:,1).*conj(CSpect(:,:,:,1))./VAR2; 19 | 20 | 21 | winx = 2:Width-1; 22 | winy = 1:Height-2; 23 | SVAR = VAR(winx,winy); 24 | VAR2 = shiftdim(repmat(TVAR.*SVAR, 1, 1, Lng), 2); 25 | POW = POW + CSpect(:,:,:,2).*conj(CSpect(:,:,:,2))./VAR2; 26 | 27 | winx = 3:Width; 28 | winy = 1:Height-2; 29 | SVAR = VAR(winx,winy); 30 | VAR2 = shiftdim(repmat(TVAR.*SVAR, 1, 1, Lng), 2); 31 | POW = POW + CSpect(:,:,:,3).*conj(CSpect(:,:,:,3))./VAR2; 32 | 33 | winx = 1:Width-2; 34 | winy = 2:Height-1; 35 | SVAR = VAR(winx,winy); 36 | VAR2 = shiftdim(repmat(TVAR.*SVAR, 1, 1, Lng), 2); 37 | POW = POW + CSpect(:,:,:,4).*conj(CSpect(:,:,:,4))./VAR2; 38 | 39 | winx = 3:Width; 40 | winy = 2:Height-1; 41 | SVAR = VAR(winx,winy); 42 | VAR2 = shiftdim(repmat(TVAR.*SVAR, 1, 1, Lng), 2); 43 | POW = POW + CSpect(:,:,:,5).*conj(CSpect(:,:,:,5))./VAR2; 44 | 45 | winx = 1:Width-2; 46 | winy = 3:Height; 47 | SVAR = VAR(winx,winy); 48 | VAR2 = shiftdim(repmat(TVAR.*SVAR, 1, 1, Lng), 2); 49 | POW = POW + CSpect(:,:,:,6).*conj(CSpect(:,:,:,6))./VAR2; 50 | 51 | winx = 2:Width-1; 52 | winy = 3:Height; 53 | SVAR = VAR(winx,winy); 54 | VAR2 = shiftdim(repmat(TVAR.*SVAR, 1, 1, Lng), 2); 55 | POW = POW + CSpect(:,:,:,7).*conj(CSpect(:,:,:,7))./VAR2; 56 | 57 | winx = 3:Width; 58 | winy = 3:Height; 59 | SVAR = VAR(winx,winy); 60 | VAR2 = shiftdim(repmat(TVAR.*SVAR, 1, 1, Lng), 2); 61 | POW = POW + CSpect(:,:,:,8).*conj(CSpect(:,:,:,8))./VAR2; 62 | 63 | POW = POW/8.0; 64 | 65 | -------------------------------------------------------------------------------- /spectral/dep/getcsdf.m: -------------------------------------------------------------------------------- 1 | function [SDF, AUTO] = getcsdf(data, Seg, Width, Height, Win) 2 | % on parallel pool 3 | % Chris van der Togt, 2017, 4 | % Netherlands Institute for Neuroscience 5 | 6 | %Seg = round(Segment/4)+1; %reduce output 7 | SDF = zeros(Seg, Width-2, Height-2, 8); 8 | 9 | data = bsxfun(@times, data, Win); 10 | Fdata = fft(data); %Fdata = fft(data, [], 2); 11 | %Fdata(1,:,:) = 0; 12 | 13 | %Fdata = Fdata.'; %transposed 14 | Fdatat = conj(Fdata); %complex conjugated transposed 15 | wins = 1:Seg; 16 | 17 | TARG = Fdata(wins,2:Width-1,2:Height-1); 18 | AUTO = Fdata(wins,:,:).*Fdatat(wins,:,:); 19 | 20 | %surrounding 8 pixels 21 | winx = 1:Width-2; 22 | winy = 1:Height-2; 23 | SRC = Fdatat(wins,winx,winy); 24 | SDF(:,:,:,1) = TARG.*SRC; 25 | 26 | winx = 2:Width-1; 27 | winy = 1:Height-2; 28 | SRC = Fdatat(wins,winx,winy); 29 | SDF(:,:,:,2) = TARG.*SRC; 30 | 31 | winx = 3:Width; 32 | winy = 1:Height-2; 33 | SRC = Fdatat(wins,winx,winy); 34 | SDF(:,:,:,3) = TARG.*SRC; 35 | 36 | winx = 1:Width-2; 37 | winy = 2:Height-1; 38 | SRC = Fdatat(wins,winx,winy); 39 | SDF(:,:,:,4) = TARG.*SRC; 40 | 41 | winx = 3:Width; 42 | winy = 2:Height-1; 43 | SRC = Fdatat(wins,winx,winy); 44 | SDF(:,:,:,5) = TARG.*SRC; 45 | 46 | winx = 1:Width-2; 47 | winy = 3:Height; 48 | SRC = Fdatat(wins,winx,winy); 49 | SDF(:,:,:,6) = TARG.*SRC; 50 | 51 | winx = 2:Width-1; 52 | winy = 3:Height; 53 | SRC = Fdatat(wins,winx,winy); 54 | SDF(:,:,:,7) = TARG.*SRC; 55 | 56 | winx = 3:Width; 57 | winy = 3:Height; 58 | SRC = Fdatat(wins,winx,winy); 59 | SDF(:,:,:,8) = TARG.*SRC; 60 | 61 | -------------------------------------------------------------------------------- /spectral/dep/getcsdfnd.m: -------------------------------------------------------------------------------- 1 | function [SDF, AUTO] = getcsdfnd(data, Width, Height, Win, Seg) 2 | % on parallel pool 3 | % Chris van der Togt, 2017, 4 | % Netherlands Institute for Neuroscience 5 | 6 | %Seg = round(Segment/4)+1; %reduce output 7 | SDF = zeros(Seg, Width-2, Height-2, 8); 8 | 9 | data = bsxfun(@times, data, Win); 10 | Fdata = fft(data); %Fdata = fft(data, [], 2); 11 | %Fdata(1,:,:) = 0; 12 | 13 | %Fdata = Fdata.'; %transposed 14 | Fdatat = conj(Fdata); %complex conjugated transposed 15 | wins = 1:Seg; 16 | 17 | TARG = Fdata(wins,2:Width-1,2:Height-1); 18 | AUTO = Fdata(wins,:,:).*Fdatat(wins,:,:); 19 | 20 | %surrounding 8 pixels 21 | winx = 1:Width-2; 22 | winy = 1:Height-2; 23 | SRC = Fdatat(wins,winx,winy); 24 | SDF(:,:,:,1) = TARG.*SRC; 25 | 26 | winx = 2:Width-1; 27 | winy = 1:Height-2; 28 | SRC = Fdatat(wins,winx,winy); 29 | SDF(:,:,:,2) = TARG.*SRC; 30 | 31 | winx = 3:Width; 32 | winy = 1:Height-2; 33 | SRC = Fdatat(wins,winx,winy); 34 | SDF(:,:,:,3) = TARG.*SRC; 35 | 36 | winx = 1:Width-2; 37 | winy = 2:Height-1; 38 | SRC = Fdatat(wins,winx,winy); 39 | SDF(:,:,:,4) = TARG.*SRC; 40 | 41 | winx = 3:Width; 42 | winy = 2:Height-1; 43 | SRC = Fdatat(wins,winx,winy); 44 | SDF(:,:,:,5) = TARG.*SRC; 45 | 46 | winx = 1:Width-2; 47 | winy = 3:Height; 48 | SRC = Fdatat(wins,winx,winy); 49 | SDF(:,:,:,6) = TARG.*SRC; 50 | 51 | winx = 2:Width-1; 52 | winy = 3:Height; 53 | SRC = Fdatat(wins,winx,winy); 54 | SDF(:,:,:,7) = TARG.*SRC; 55 | 56 | winx = 3:Width; 57 | winy = 3:Height; 58 | SRC = Fdatat(wins,winx,winy); 59 | SDF(:,:,:,8) = TARG.*SRC; 60 | 61 | -------------------------------------------------------------------------------- /spectral/dep/localmax.m: -------------------------------------------------------------------------------- 1 | function pnt = localmax(IM, edge, vox) 2 | % retrieve local maxima in image after substracting median filtered image 3 | % 4 | % IM; the spectral image 5 | % edge; border of image to ignore 6 | % vox; voxel size to process 7 | % Pxd; number of pixels of separation between maxima 8 | % Chris van der Togt, 2021 9 | % Netherlands Institute for Neuroscience 10 | 11 | Pxd = 7; 12 | 13 | % median filter 14 | J = ordfilt2(IM, vox^2/2, ones(vox)); 15 | I = IM - J + mean(J(:), 'omitnan'); 16 | 17 | %remove border 18 | dsz = size(I); 19 | d = I(edge:dsz(1)-edge,edge:dsz(2)-edge); 20 | 21 | % max filter 22 | B = ordfilt2(d, Pxd^2, ones(Pxd)); 23 | peaks = (d >= B); 24 | 25 | %get maxima 26 | v = d(peaks); %values 27 | [i, j] = find(peaks); %coordinates 28 | x = i + edge-1; 29 | y = j + edge-1; 30 | pnt = [x, y, v]; 31 | 32 | %order by magnitude 33 | [~, ix] = sort(pnt(:,3), 'descend'); 34 | pnt = pnt(ix,:); 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /spectral/dep/perimarea.m: -------------------------------------------------------------------------------- 1 | function roundedness = perimarea(x, y) 2 | %calculate area to perimeter of a contour 3 | % roundedness = 1 for perfect circle 4 | % Chris van der Togt, 2017, 5 | % Netherlands Institute for Neuroscience 6 | 7 | fac = round(length(x)/50); 8 | if fac > 0 9 | p = smoothG([x(:) y(:)], fac); 10 | p = [p(end,:); p]; 11 | else 12 | p = [x(:) y(:)]; 13 | end 14 | dx = diff(p(:,1)); 15 | dy = diff(p(:,2)); 16 | A = polyarea(p(:,1), p(:,2)); 17 | P = sum(sqrt(dx.^2 + dy.^2)); 18 | roundedness = 4*pi*A/(P*P); 19 | %roundedness = sqrt(A)/P; -------------------------------------------------------------------------------- /spectral/dep/setminlevel.m: -------------------------------------------------------------------------------- 1 | function IM = setminlevel(IM) 2 | % Chris van der Togt, 2017, 3 | % Netherlands Institute for Neuroscience 4 | 5 | H = sort(IM(:)); 6 | Mn = find(H > -inf, 1, 'first'); 7 | IM(IM < H(Mn)) = H(Mn); 8 | IM = IM - H(Mn); 9 | 10 | -------------------------------------------------------------------------------- /spectral/dep/smoothG.m: -------------------------------------------------------------------------------- 1 | function RS = smoothG(RDtemp, se) 2 | % 3 | %RS = smoothG(RDtemp, se) 4 | %se is the standard deviation of the smoothing gaussian 5 | %column wise smoothing!!! 6 | %Chris van der Togt 7 | %Dept. of Vision and Cognition 8 | %Netherlands Institute for Neurosciences 9 | %10/2012 10 | 11 | 12 | [Segment, Nchan] = size(RDtemp); 13 | r = -3*se:3*se; 14 | G = 1/sqrt(2*pi*se).*exp(-r.^2/(2*se*se)); 15 | HS = conv(ones(Segment,1), G, 'same'); 16 | 17 | 18 | RS = RDtemp; 19 | for i = 1:Nchan 20 | RS(:,i) = conv(double(RDtemp(:,i)), G, 'same')./HS; 21 | end 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /spectral/dep/transmemap.m: -------------------------------------------------------------------------------- 1 | function [sbxt, dim, freq] = transmemap(varargin) 2 | % [sbxt, dim, freq] = transmemap(filename) returns transposed stack as 3 | % a memory mapped file 4 | % 5 | % input: string that contains the path- and filename of the transposed data 6 | % When no input is given, the script will ask for the transposed data file 7 | % 8 | % output: 9 | % sbxt: memorymapped file 10 | % freq (double): the sampling rate of the data in Hz 11 | % dim: The dimensions of the data, [time, X, Y] 12 | % 13 | % Transposed data can be decimated or non-decimated, whether the data is 14 | % decimated should be in the filename! The filename should contain 15 | % the text: DecTrans 16 | % Decimated data is in data format double, and will not be subsampled by 17 | % other scripts. 18 | % 19 | % Chris van der Togt, 2017, 20 | % Netherlands Institute for Neuroscience 21 | % edited by Leander de Kraker to include decimate recognition 2020-8-4 22 | 23 | 24 | % What file to ananlyse 25 | if nargin > 0 26 | filenm = varargin{1}; 27 | else 28 | [fn, pn] = uigetfile('*Trans.dat'); 29 | filenm = [pn fn]; 30 | end 31 | 32 | % Find out whether the trans file contains decimated data 33 | if nargin == 2 34 | decimated = varargin{2}; 35 | else 36 | % Find out whether the data is decimated 37 | decimated = false; 38 | strPos = regexp(filenm, 'Trans'); 39 | if (strPos - 3) >= 1 40 | if strcmp(filenm(strPos-3:strPos-1), 'Dec') 41 | decimated = true; 42 | end 43 | end 44 | end 45 | 46 | %load transposed data 47 | if decimated 48 | [dim, freq] = Zgetinfo(filenm); 49 | sbxt = memmapfile(filenm, 'Format', {'double' [dim(1) dim(2) * dim(3)], 'y'}, 'Offset', 500); 50 | 51 | else 52 | [dim, freq] = Zgetinfo(filenm); 53 | sbxt = memmapfile(filenm, 'Format', {'uint16' [dim(1) dim(2) * dim(3)], 'y'}, 'Offset', 500); 54 | 55 | end 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /spectral/spectralOld.m: -------------------------------------------------------------------------------- 1 | function spectral(varargin) 2 | % 3 | % calculate cross-spectral density for each pixel with it's surrounding 8 pixels 4 | % When input is not given a pop-up will ask for a filename 5 | % The file should contain binary data with time in the first dimension and decimated to 6 | % approximately 1Hz. 7 | % 8 | % Chris van der togt, 01-07-2020 9 | % Netherlands Institute for Neuroscience, 10 | % Amsterdam, the Netherlands 11 | 12 | %% Get the filename 13 | if exist('varargin', 'var') && nargin == 1 14 | strfp = varargin{1}; 15 | [fp,fn] = fileparts(strfp); 16 | fp = [fp '\']; 17 | else 18 | [fn, fp] = uigetfile('*_DecTrans.dat'); 19 | strfp = [fp fn]; 20 | end 21 | 22 | [dim, freq] = Zgetinfo(strfp); 23 | 24 | mfn = strsplit(fn, '_DecTrans'); 25 | 26 | gcp 27 | 28 | 29 | %% SPECTRAL POWER OF SURROUNDING 8 PIXELS 30 | 31 | %now open as memory mapped file 32 | sbxt = memmapfile(strfp, 'Format', 'double', 'Offset', 500); 33 | 34 | Wdth = dim(2);%horizontal orientation 35 | Lines = dim(3)-2; %number of lines to process = height - 2 36 | 37 | %find optimal number of lines to process simultaneusly(more lines - more memory) 38 | f = factor(Lines); %factorize line dimension 39 | c = combnk(1:length(f),2); %all combinations of 2 factors 40 | p = [prod(f(c')) f]; %the products of these combinations + individual factors 41 | [~, i] = min(abs(p-20)); %The closest to 10 42 | W = p(i); 43 | BW = W+2; 44 | steps = Lines/W; 45 | 46 | %total number of lines should be divisable by W 47 | if rem(Lines, W) > 0 48 | disp(['Error ' num2str(dim(3)) 'not divisible by ' num2str(W)]) 49 | end 50 | 51 | Segm = 128; 52 | Lng = dim(1); %length of image stack 53 | 54 | while Lng < (Segm * 2) 55 | warning('data is too short (%d), halving window, (%d -> %d)', Lng, Segm, Segm/2) 56 | Segm = Segm/2; 57 | end 58 | 59 | 60 | sampd2 = Segm/2; 61 | sampd4 = Segm/4; 62 | Sax = (0:sampd4)/(sampd4)/2*freq; 63 | 64 | 65 | cnt0 = length(1:Segm:Lng-Segm+1); 66 | cnt1 = length(sampd2+1:Segm:Lng-Segm+1); 67 | cnt = cnt0 + cnt1; 68 | SPic = zeros(sampd4+1, Wdth-2, W, Lines/W); 69 | Win = hamming(Segm); 70 | 71 | tic 72 | %% 73 | hw = waitbar(0, 'Estimating Cross-spectral Power'); 74 | for r = 1:steps 75 | %slice = (1:W)+(W-2)*(double(r)-1); %W vertical locations 76 | %D = ZT.Read(slice,b); %read horizontal lines of z ordered data 77 | indices = (1:Wdth*BW) + W * Wdth *(r-1); 78 | D = XYgetZ(indices, sbxt, Lng); 79 | Dec = reshape(D, Lng, Wdth, BW); 80 | 81 | %reshape to block of Width x BW with Lng length 82 | %to obtain 50% overlapping data segments and slicable for parallel computing 83 | D0 = Dec(1:cnt0*Segm,:,:); 84 | D0 = reshape(D0, Segm, cnt0, Wdth, BW); 85 | D1 = Dec(sampd2+1:sampd2+cnt1*Segm,:,:); 86 | D1 = reshape(D1, Segm, cnt1, Wdth, BW); 87 | 88 | Dc = cat(2, D0, D1); 89 | 90 | CSpect = zeros(sampd4+1, Wdth-2, W, 8); 91 | ASpect = zeros(sampd4+1, Wdth, BW); 92 | 93 | parfor j = 1:cnt 94 | Tmp = squeeze(Dc(:,j,:,:)); 95 | Tmp = reshape(Tmp, Segm, Wdth * BW); 96 | Tmp = detrend(Tmp); 97 | Tmp = reshape(Tmp, Segm, Wdth, BW); 98 | [C, A] = getcsdf(Tmp, Segm, Wdth, BW, Win); 99 | CSpect = CSpect + C; 100 | ASpect = ASpect + A; 101 | end 102 | 103 | CSpect = CSpect./cnt; 104 | ASpect = ASpect./cnt; 105 | 106 | Powsum = getcorpow(CSpect, ASpect); 107 | SPic(:, :, :, r) = Powsum; 108 | 109 | waitbar(r/steps, hw, ['Estimating Cross-spectral Power: ' num2str( round(r/steps * 1000)/10) '%' ], '%3.1f') 110 | end 111 | close(hw) 112 | 113 | SPic = reshape(SPic, sampd4+1, Wdth-2, Lines); 114 | SPic = shiftdim(SPic,1); 115 | SPic = padarray(SPic, [1 1 0]); %make original size by padding borders 116 | 117 | save([fp mfn{1} '_SPSIG.mat'], 'SPic', 'Sax', 'freq') 118 | toc 119 | fprintf('Done with spectral calculation\n') 120 | 121 | -------------------------------------------------------------------------------- /startup.m: -------------------------------------------------------------------------------- 1 | %{ 2 | Use on startup to add relevant SpectralSeg files to the matlab Path 3 | 4 | In the below excludedPaths variable can add folder extensions to ignore 5 | %} 6 | excludedPaths = {'\.git', '\docs'}; 7 | currentDir = pwd; 8 | 9 | excludePattern = cellfun(@(str) fullfile(currentDir, str), excludedPaths, 'UniformOutput', false); 10 | 11 | 12 | allPaths = genpath(currentDir); 13 | allPaths = strsplit(allPaths, pathsep); 14 | allPaths = allPaths(~cellfun('isempty', allPaths)); 15 | keepPaths = true(size(allPaths)); 16 | 17 | for i = 1: length(excludedPaths) 18 | keepPaths = keepPaths & ~contains(allPaths, excludedPaths{i}); 19 | end 20 | 21 | filteredPaths = allPaths(keepPaths); 22 | 23 | for i = 1: length(filteredPaths) 24 | addpath(filteredPaths{i}); 25 | end 26 | 27 | disp('Paths added to MATLAB:'); 28 | disp(filteredPaths'); 29 | 30 | clear -------------------------------------------------------------------------------- /util/Mask3D_Flatten.m: -------------------------------------------------------------------------------- 1 | % Flatten a 3D mask 2 | % Input: mask3d [3D double] (x, y, nROIs). Each ROI has a seperate image, 3 | % enabling weighing of pixels and ROI overlap 4 | % 5 | % output: Mask [2D double]. (x, y) Each pixel is assigned to a ROIid 6 | % 7 | % 8 | % 9 | % Leander de Kraker 10 | % 2021-6-9 11 | % 12 | 13 | % mask3d = compSpatial; 14 | % mask3d = compSpatialSc; 15 | d1 = size(mask3d, 1); 16 | d2 = size(mask3d, 2); 17 | nrois = size(mask3d, 3); 18 | 19 | 20 | %% Flatten the mask 21 | 22 | threshold = 0.03; % Weights lower than this get exluded from ROI mask. 23 | 24 | mask3d_firstadded = cat(3, ones(d1, d2).*threshold, mask3d); 25 | [BImg, Mask] = max(mask3d_firstadded, [], 3); 26 | Mask = Mask - 1; 27 | 28 | nroisNew = length(unique(Mask(:)))-1; 29 | nroisMax = max(Mask(:)); 30 | missingRoisByMaskFlattening = find(diff(unique([Mask(:); 0]))>1); 31 | fprintf('%d ROIs are now gone because flattening\n', length(missingRoisByMaskFlattening)); 32 | while nroisNew ~= nroisMax 33 | missingRoi = find(diff(unique([Mask(:); 0]))>1); 34 | Mask(Mask>missingRoi(1)) = Mask(Mask>missingRoi(1))-1; 35 | 36 | nroisMax = max(Mask(:)); 37 | end 38 | 39 | %% If you have signals and ROIs were deleted! Update sig. 40 | % sig = [oldnrois x time] -> [newnrois x time] 41 | sig(missingRoisByMaskFlattening, :) = []; 42 | 43 | %% Plot 44 | figure 45 | imagesc(Mask) 46 | title(sprintf('threshold for mask at %.5f. Original nr ROIs: %d, new %d', threshold, nrois, nroisNew)) 47 | cmap = [0 0 0; jet(nroisNew)]; 48 | colormap(cmap) 49 | 50 | figure 51 | imagesc(BImg) 52 | title('Representative image (weights of the masks): BImg') 53 | 54 | %% Save mask to file 55 | 56 | [filename, filepath] = uigetfile('*.mat','save the mask to a mat file'); 57 | save([filepath, filename], 'Mask','BImg','missingRoisByMaskFlattening', '-append') 58 | fprintf('\nsaved Mask to %s\n\n', filename) 59 | 60 | %% Get PP and stuff from Mask 61 | 62 | PPfromMask 63 | 64 | 65 | -------------------------------------------------------------------------------- /util/PPfromMask.m: -------------------------------------------------------------------------------- 1 | function PP = PPfromMask(Mask, varargin) 2 | % Find contours around 2D ROI mask 3 | % 4 | % PP = PPfromMask(Mask); 5 | % PP = PPfromMask(Mask, BImg); 6 | % PP = PPfromMask(Mask, BImg, PP); 7 | % 8 | % Input: 9 | % Mask (2D double): ROI mask with numbers indicating ROI id at each pixel 10 | % If BImg is inputted, that image will be used to find the location of 11 | % brightest pixel in each ROI: the seedpoint location. 12 | % If no BImg is inputted, the center of mass of the ROI will be used 13 | % If PP is inputted, Con and P will be updated with new data. 14 | % 15 | % Output: 16 | % PP.Con.x 17 | % PP.Con.y 18 | % PP.P ([2 x nrois]): x and y coordinates of seedpoint or COM 19 | % 20 | % See also: PPfromMaskFile, PPModernize 21 | % 22 | % Leander de Kraker 23 | % 2022-9-23 24 | % 25 | 26 | hasBImg = false; 27 | if exist('varargin', 'var') && nargin >= 2 && ~isempty(varargin{1}) 28 | BImg = varargin{1}; 29 | minval = min(BImg(:)); 30 | hasBImg = true; 31 | end 32 | 33 | nROIs = max(Mask(:)); 34 | 35 | if exist('varargin', 'var') && nargin >= 3 36 | PP = varargin{2}; 37 | if nROIs ~= PP.Cnt 38 | warning('number of ROIs in mask is different than in PP! Removing original PP') 39 | PP = []; 40 | end 41 | end 42 | 43 | PP.Cnt = nROIs; 44 | PP.Con = struct('x', [], 'y', []); 45 | PP.P = nan(2, nROIs); 46 | diskim = fspecial('disk', 1); % disk for smoothing mask for smoother contours 47 | for i = 1:nROIs 48 | maski = Mask==i; 49 | if hasBImg % Get ROI probable seedpoint 50 | [idxd1, idxd2] = find(maski); 51 | vals = BImg(maski); 52 | [~, maxidx] = max(vals); 53 | PP.P(:,i) = [idxd2(maxidx), idxd1(maxidx)]; 54 | end 55 | 56 | maski = filter2(diskim, double(maski)); 57 | thres = max(maski(:))./2.5; 58 | coni = contourc(maski, [thres thres]); 59 | coni = getcontourlines(coni); 60 | PP.Con(i).x = coni.x; 61 | PP.Con(i).y = coni.y; 62 | end 63 | 64 | if ~hasBImg % If BImg not present, get Center Of Mass of Mask ROI 65 | PP.P = GetRoiCoM(Mask); 66 | end 67 | 68 | -------------------------------------------------------------------------------- /util/PrintBImg.m: -------------------------------------------------------------------------------- 1 | function [img, s, m] = PrintBImg(img, varargin) 2 | % rgb = PrintBImg(img, lims, colors, doplot, saveName, {scaleBarX, scaleBarY}, doPerc); 3 | % 4 | % Apply brightness limits and colormap and Try to shift uneven lines so 5 | % they align best with the even lines of img. And Save the img in its 6 | % actual resolution. 7 | % 8 | % 9 | % input. All optional except first. All may be left empty except first 10 | % img (2D double). 11 | % limsPerc ([2 x 1] double). minimum and maximum brightness values. 12 | % Outside these values the brightness is cut 13 | % colors ([n x 3 double]). colormap to apply to img 14 | % doplot (boolean). Plot it in MATLAB for your eyes? 15 | % saveName (string). filename for picture (with folder) . 16 | % if empty, image will not be saved 17 | % scalebar ([2 x 1] cell with doubles idx inside). 18 | % doPerc (boolean). Calculate percentile using the lims input? 19 | % doLineShift (boolean). 20 | % pos 21 | % 22 | % Values above this percentile will be max color value. 2p data brightness 23 | % can be highly skewed % this causes most pixels to be dark. This is not 24 | % nice. So select lower than 100% to% cut off the brightness and thereby 25 | % making the image brighter/ more contrast. 26 | % 27 | % percentile of values below which the values will be the darkest color. 28 | % 29 | % Leander de Kraker 30 | % 2023-8-17 31 | % 32 | 33 | if exist('varargin', 'var') && nargin>1 && ~isempty(varargin{1}) 34 | lims = varargin{1}; 35 | else 36 | lims = [0.1, 99.9]; 37 | end 38 | if exist('varargin', 'var') && nargin>2 && ~isempty(varargin{2}) 39 | colors = varargin{2}; 40 | else 41 | colors = cmapL('greenFancy', 256); 42 | end 43 | if exist('varargin', 'var') && nargin>3 && ~isempty(varargin{3}) 44 | doplot = varargin{3}; 45 | else 46 | doplot = true; 47 | end 48 | if exist('varargin', 'var') && nargin>4 && ~isempty(varargin{4}) 49 | saveName = varargin{4}; 50 | else 51 | saveName = []; 52 | end 53 | if exist('varargin', 'var') && nargin>5 && ~isempty(varargin{5}) 54 | scaleBarx = varargin{5}{1}; 55 | scaleBary = varargin{5}{2}; 56 | doScalebar = true; 57 | else 58 | doScalebar = false; 59 | end 60 | if exist('varargin', 'var') && nargin>6 && ~isempty(varargin{6}) 61 | doPerc = varargin{6}; 62 | else 63 | doPerc = true; 64 | end 65 | if exist('varargin', 'var') && nargin>7 && ~isempty(varargin{7}) 66 | doLineShift = varargin{7}; 67 | else 68 | doLineShift = false; 69 | end 70 | if exist('varargin', 'var') && nargin>8 71 | pos = varargin{8}; 72 | else 73 | dims = size(img); 74 | pos = GetCenteredFigPos(dims([2 1])); % figure that does not get saved 75 | end 76 | 77 | 78 | 79 | 80 | if doPerc 81 | lims = prctile(img(:), lims); % color axis limits 82 | end 83 | 84 | if doLineShift 85 | [img, s, m] = ShiftLinesImg(img); 86 | [img, s(2), m(2)] = ShiftLinesImg(img); 87 | else 88 | s = [NaN, NaN]; m = [NaN, NaN]; 89 | end 90 | 91 | img = SetLimits(img, lims, colors); 92 | 93 | % Apply scalebar 94 | if doScalebar 95 | img(scaleBary, scaleBarx, :) = 1; 96 | end 97 | 98 | % For our eyes only 99 | if doplot 100 | figure('Units', 'Pixels', 'InnerPosition', pos) 101 | subplot('Position', [0 0 1 1]) 102 | image(img); 103 | end 104 | 105 | % save image 106 | if ~isempty(saveName) 107 | imwrite(img, saveName) 108 | end 109 | 110 | -------------------------------------------------------------------------------- /util/PrintBImgs.m: -------------------------------------------------------------------------------- 1 | function [s, m] = PrintBImgs(filepath, filename, filepathImg, zoom, varargin) 2 | % Quickly save the average & max fluorescence & colored spectral as png 3 | % with their actual resolution 4 | % BImgAverage, BImgMax and BImgRGB are created by FluorescenceImgSbx.m 5 | % 6 | % 7 | % Leander de Kraker 8 | % 2022-10-20 9 | % 10 | %% 11 | doPlotForOurEyes = true; 12 | if ~exist('varargin', 'var') || (exist('varargin', 'var') && nargin == 0) 13 | zoom = 1.3; % MICROSCOPE ZOOM LEVEL, FROM LOGBOOK 14 | [filename, filepath] = uigetfile('*SPSIG.mat'); 15 | filepathImg = filepath; 16 | doScalebarPlot = true; 17 | else 18 | doScalebarPlot = varargin{1}; 19 | if length(varargin)==2 20 | doPlotForOurEyes = varargin{2}; 21 | end 22 | end 23 | 24 | % Load data 25 | load([filepath, filename], 'BImgMax', 'BImgAverage', 'BImg', 'BImgRGB', 'SPic', 'Sax') 26 | 27 | 28 | delimeterPos = regexp(filename,{'_SPSIG','.mat','sbx'}); 29 | delimeterPos = delimeterPos(~cellfun('isempty',delimeterPos)); 30 | if ~isempty(delimeterPos) 31 | filename = filename(1:delimeterPos{1}-1); 32 | end 33 | 34 | lineShiftCorrection = 0; 35 | 36 | %% Scale bar 37 | 38 | dims = size(BImgMax); 39 | 40 | % Set these parameters manually! 41 | fov = 1000; % amount of um the microscope images with 1x zoom 42 | scale = dims(2) / (fov/zoom); % number of pixels / µm images (depends on zoom) 43 | um = 100; % How big you want your scalebar 44 | 45 | scaleBar = round(scale*um); 46 | 47 | scaleBary = round(dims(1)*0.9); % Set vertical position of scalebar 48 | scaleBary = scaleBary:scaleBary+2; % Set thickness of scalebar 49 | scaleBarx = round(dims(2)*0.9); % Setting the x position of scalebar 50 | scaleBarx = scaleBarx-scaleBar+1:scaleBarx; 51 | scaleBar = {scaleBarx, scaleBary}; 52 | 53 | 54 | %% Image settings 55 | baseName = [filepathImg, sprintf('img_scalebar%dum', um)]; 56 | 57 | ncolors = 256; 58 | colors = cmapL('greenFancy', ncolors); 59 | doPerc = true; % limits are given as percentiles of image values (not actual amount) 60 | doLineShift = false; 61 | pos = GetCenteredFigPos(dims([2 1])); % figure that does not get saved 62 | 63 | 64 | %% BImgMax (Maximum fluorescence projection) 65 | limsPerc = [0.1, 99.99]; 66 | saveName = [baseName, '_maxFluorescence_', filename, '.png']; 67 | img = MidtoneBalance(BImgMax, 0.3); 68 | [rgb, s, m] = PrintBImg(img, limsPerc, colors, doPlotForOurEyes, saveName, scaleBar, doPerc, doLineShift, pos); 69 | 70 | 71 | %% BImgAverage (average fluorescence projection) 72 | limsPerc = [0.1, 99.99]; 73 | saveName = [baseName, '_averageFluorescence_', filename, '.png']; 74 | rgb = PrintBImg(BImgAverage, limsPerc, colors, doPlotForOurEyes, saveName, scaleBar, doPerc, doLineShift, pos); 75 | 76 | 77 | %% Spectral image 78 | limsPerc = [0.1, 99.99]; 79 | saveName = [baseName, '_spectral_', filename, '.png']; 80 | rgb = BImg; 81 | if sum(rgb(:)==-inf)>0 82 | vals = unique(rgb(:)); 83 | rgb(rgb==-inf) = vals(2); 84 | end 85 | rgb = PrintBImg(rgb, limsPerc, gray(256), doPlotForOurEyes, saveName, scaleBar, doPerc, doLineShift, pos); 86 | 87 | 88 | %% colored spectral image 89 | 90 | % imgRGB = BImgRGB; 91 | freqToUse = [0, 0.25]; % frequency range in Hz 92 | 93 | figure('Units', 'Pixels', 'InnerPosition', pos) 94 | subplot('Position', [0 0 1 1]) 95 | [imgRGB, colorsSpectral, colorbarVals] = SpectralColorImg('data', {SPic, Sax}, freqToUse, true); 96 | imgRGB = MidtoneBalance(imgRGB, 0.4); 97 | imgRGB(scaleBary, scaleBarx, :) = 1; 98 | h = gca; 99 | h.Children.CData = imgRGB; 100 | 101 | % save image 102 | imwrite(imgRGB, [baseName, '_coloredSpectral', filename, '.png']) 103 | 104 | %% Color spectral image colorbar 105 | 106 | if doScalebarPlot 107 | im = Colorbar2D(colorsSpectral, MidtoneBalance(gray(100), 0.6)); 108 | 109 | figure('Position', [680 638 120 340]) 110 | imagesc(1:size(im,2), colorbarVals, im) 111 | h = gca; 112 | h.YDir = 'normal'; 113 | h.YTick = colorbarVals([1 end]); % prevent ticks from changing 114 | h.YTickLabel = num2str(colorbarVals([1 end]), '%.2f'); 115 | h.XTick = []; 116 | xlabel('spectral power'); 117 | ylabel('spectral frequency') 118 | h.FontSize = 11; 119 | h.XLabel.Position = [0, 0.0129, 1]; 120 | 121 | SaveImg({'svg', 'png'}, [baseName, '_colorSpectralLegend']) 122 | end 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /util/RunPrintBImgs.m: -------------------------------------------------------------------------------- 1 | % Run printBImgs on many files 2 | % 3 | % 4 | 5 | 6 | 7 | picFolder = 'D:\2Pdata\Leander\Koen\'; 8 | 9 | % Data on helero2p 10 | miceChronicPath = {'C:\Users\Leander\Documents\Baan\PICLe\17.20.12\Line\';... 11 | 'C:\Users\Leander\Documents\Baan\PICLe\17.20.12\Monster\';... 12 | 'C:\Users\Leander\Documents\Baan\PICLe\17.20.12\Venus\';... 13 | 'C:\Users\Leander\Documents\Baan\PICLe\14.90\Mickey\';... 14 | 'C:\Users\Leander\Documents\Baan\PICLe\14.90\Timor\';... 15 | 'C:\Users\Leander\Documents\Baan\PICLe\14.90\Zebedeus\'}; 16 | miceChronicName = {'Line_The12_chronic';... 17 | 'Monster_The12_Chronic';... 18 | 'Venus_The12(9)_chronic';... 19 | 'Mickey_The12_Chronic';... 20 | 'Timor_The12_Chronic';... 21 | 'Zebedeus_The12_Chronic'}; 22 | 23 | miceChronicPath = {'D:\2Pdata\Koen\Muckli\Kopernik\'}; 24 | miceChronicName = {'Kopernik_gray_v3_chronic'}; 25 | 26 | nMice = length(miceChronicPath); 27 | 28 | doScalebarPlot = false; 29 | doPlotForOurEyes = false; 30 | zoom = 2; % ZOOM FACTOR from logbook, info.config.magnification_list(info.config.magnification) 31 | 32 | 33 | 34 | for m = 1 35 | load([miceChronicPath{m}, miceChronicName{m}], 'filenames', 'filepaths', 'nfiles') 36 | shiftAmount = zeros(nfiles, 2); shiftMethod = zeros(nfiles, 2); 37 | for i = 1:nfiles 38 | [shiftAmount(i,:), shiftMethod(i,:)] = PrintBImgs(filepaths{i}, filenames{i}, picFolder, zoom, doScalebarPlot, doPlotForOurEyes); 39 | end 40 | end -------------------------------------------------------------------------------- /util/SbxCropTimeTest.m: -------------------------------------------------------------------------------- 1 | % Executing time crop of sbx file 2 | % 3 | % 4 | % SbxCropTime(strPathIn, strSbxIn, strPathOut, frameStart, frameEnd) 5 | % 6 | % Leander de Kraker 7 | % 2024-5-7 8 | % 9 | 10 | clear 11 | clc 12 | 13 | strSbxIn = 'Lambrusco_20230404_003'; 14 | strPathIn = '\\vs03\VS03-MVP-1\GluA3_VR\Data_Collection\KOinV1SST_2P\Lambrusco\20230404\'; 15 | strPathOut = 'D:\2Pdata\Leander\ShiftedLines\'; 16 | frameStart = 2; 17 | frameEnd = round(30.9141*60*5); % 5 minutes at 30.9141 Hz 18 | 19 | nframes = frameEnd-frameStart+1; 20 | 21 | SbxCropTime(strPathIn, strSbxIn, strPathOut, frameStart, frameEnd) -------------------------------------------------------------------------------- /util/SbxZStack.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/util/SbxZStack.m -------------------------------------------------------------------------------- /util/ShiftLinesCheck.m: -------------------------------------------------------------------------------- 1 | function s = ShiftLinesCheck(im, varargin) 2 | % Figure out how much a recording's alternating lines should be shifted to 3 | % correct for bidirectional scanning misalignment 4 | % 5 | % input: 6 | % - im (2D, 3D or 4D double): The image where to figure out the shift. 7 | % if 3D, please no more than 2 elements. 8 | % - trans (string): do 9 | % output: s (digid integer): shift in px that the lines should have 10 | % 11 | % Leander de Kraker 12 | % 2022-12-2 13 | % 14 | %% 15 | 16 | if exist('varargin', 'var') && nargin >= 2 17 | trans = varargin{1}; 18 | else 19 | trans = false; 20 | end 21 | if exist('varargin', 'var') && nargin == 3 22 | doPlot = varargin{1}; 23 | else 24 | doPlot = true; 25 | end 26 | if doPlot 27 | figure('WindowStyle','docked') 28 | fprintf('\nplotting the different line shifts.. check for plot\n') 29 | end 30 | 31 | % im(im>65500) = median(im(:)); 32 | 33 | imdim = size(im); 34 | if length(imdim)>3 % if 4D or more, average the 4th dimension (should be frames) 35 | im = mean(im, 4); 36 | end 37 | 38 | if trans 39 | im = permute(im, [2 1 3]); 40 | strTrans = 'data is transposed'; 41 | else 42 | strTrans = ''; 43 | end 44 | 45 | imdim = size(im); 46 | xlims = [1 imdim(2)]; 47 | % xlims = [1 300]; 48 | ylims = [100 300]; % zoom in 49 | % clims = [2000 20000]; % color limits 50 | clims = [min(im(:)), max(im(:))]; 51 | 52 | 53 | shifts = -5:5; 54 | buf = 20; 55 | nshifts = length(shifts); 56 | correl = zeros(nshifts, 2); 57 | correls = zeros(nshifts, 1); 58 | 59 | d1 = imdim(1); 60 | if mod(d1, 2) % even: select data to 1 line less 61 | d1 = d1 - 1; 62 | end 63 | 64 | 65 | for i = 1:nshifts 66 | if shifts(i) < 1 67 | y = 1; 68 | else 69 | y = 2; 70 | end 71 | x = abs(shifts(i)); 72 | 73 | imS = im; % image with shifted lines 74 | imS(y:2:d1, 1:end-x) = imS(y:2:d1, 1+x:end); 75 | 76 | imSH = imS(1:2:d1, buf:end-buf); 77 | imH1 = imS(2:2:d1, buf:end-buf); 78 | 79 | correl(i, :) = [corr2(imH1, imSH), corr2(imH1(2:end), imSH(1:end-1))]; 80 | correls(i) = mean(correl(i, :)); 81 | % PLOTTING 82 | if doPlot 83 | if size(imS, 3)==2; imS = CreateRGB2_mat(imS, [1 0 0; 0 1 0]);end 84 | imagesc(MidtoneBalance(imS, 0.2)) 85 | colormap(cmapL('greenFancy', 256)); colorbar 86 | title(sprintf('shift %dpx. correl %.5f %s. Press enter to continue checking!',... 87 | shifts(i), correls(i), strTrans)) 88 | if length(size(imS))==2; clim(clims); end 89 | xlim(xlims) 90 | ylim(ylims) 91 | % pause(0.05) 92 | pause() 93 | end 94 | end 95 | [maxCor, idx] = max(correls); 96 | s = shifts(idx); 97 | 98 | % Plotting 99 | if s < 1; y = 1; 100 | else; y = 2; 101 | end 102 | x = abs(s); 103 | imS = im; % image with shifted lines 104 | imS(y:2:d1, 1:end-x) = imS(y:2:d1, 1+x:end); 105 | if size(imS, 3)==2; imS = CreateRGB2_mat(imS, [1 0 0; 0 1 0]); end 106 | imagesc(MidtoneBalance(imS, 0.2)) 107 | colormap(cmapL('greenFancy', 256)); colorbar 108 | title(sprintf('shift %dpx. correl %.5f', s, maxCor)) 109 | if length(size(imS))==2; clim(clims); end 110 | xlim(xlims) 111 | ylim(ylims) 112 | 113 | % printing 114 | fprintf('best shift = %d pixels\n', s) 115 | if s>0; stri = 'un'; 116 | else; stri = ''; 117 | end 118 | if s~=0 119 | if trans 120 | strOri = 'columns'; 121 | strDirection = 'up'; 122 | else 123 | strOri = 'rows'; 124 | strDirection = 'the left'; 125 | end 126 | fprintf('going to shift %seven %s %d pixels to %s\n', stri, strOri, abs(s), strDirection) 127 | fprintf('which is %.5f better than no shift\n', maxCor-correls(shifts==0)) 128 | else 129 | fprintf('no shift recommended I guess') 130 | end 131 | 132 | -------------------------------------------------------------------------------- /util/SpatialCorrCalcRun.m: -------------------------------------------------------------------------------- 1 | % Calculate spatial corr image and inner correlation variance: 2 | % correlation of signal in existing ROIs with the signal from the spectral 3 | % maximum / origin point of the ROI 4 | % 5 | % To calculate these variables the transposed motioncorrected raw data is 6 | % necessary, together with the PP and Mask variable from the SPSIG.mat file 7 | % 8 | % 9 | % Leander de Kraker 10 | % 2020-1-20 11 | % 12 | 13 | % CALCULATE variance of correlation for PP update?? % % % 14 | calcRvar = true; 15 | 16 | % Load the mask and contour data, and the old spatialcorr 17 | [fnSpsig, pnSpsig] = uigetfile('*SPSIG.mat','load mask data (SPSIG file)'); 18 | nameSpsig = [pnSpsig, fnSpsig]; 19 | load(nameSpsig, 'PP', 'Mask', 'SpatialCorr') 20 | 21 | % Load transposed sbx data 22 | [fnSbx, pnSbx] = uigetfile('*DECTRANS.dat', 'load raw data (sbx file)'); 23 | nameSbx = [pnSbx, fnSbx]; 24 | [sbxt, dim, freq] = transmemap(nameSbx); 25 | 26 | % % enlarge the ROI masks for extra viewing pleasure! 27 | % [~,~,maskExtra] = BufferMask(Mask, 2); 28 | % Mask = Mask + maskExtra; 29 | 30 | % Checking whether or not SpatialCorr already exists 31 | if exist('SpatialCorr', 'var') 32 | fprintf('spatialcorr already exists\n') 33 | oldExists = true; % Old spatial corr already exists! 34 | else 35 | oldExists = false; 36 | end 37 | 38 | % Calculate the new SpatialCorr 39 | SpatialCorrNew = zeros(size(Mask)); 40 | rvar = zeros(PP.Cnt, 1); 41 | figure 42 | imagesc(SpatialCorrNew); 43 | colormap(jet) 44 | tic 45 | for i = 1:PP.Cnt 46 | [Corri, idx, rvari] = SpatialCorrCalcFun(sbxt, freq, Mask, i, PP.P([1 2], i), calcRvar); 47 | SpatialCorrNew(idx) = Corri(idx); % 1D indexing in 2D matrix 48 | rvar(i) = rvari; 49 | if mod(i, 10)==1 50 | imagesc(SpatialCorrNew) 51 | colorbar 52 | hold on 53 | for j = 1:i 54 | plot(PP.Con(j).x, PP.Con(j).y, 'color', [1 0.2 1]) 55 | end 56 | hold off 57 | title(sprintf('done with ROI %d/%d: elapsed time: %.2fminutes\n', i, PP.Cnt, toc/60)) 58 | pause(0.01) 59 | end 60 | end 61 | toc 62 | 63 | % Compare with old existing spatialCorr 64 | if oldExists 65 | figure 66 | imagesc(CreateRGB({SpatialCorr, SpatialCorrNew}, 'r gb')) 67 | hold on 68 | plot(PP.P(1,:), PP.P(2,:), '.g') % ROI center/ origin points 69 | for i = 1:PP.Cnt % plot ROI contours 70 | plot(PP.Con(i).x, PP.Con(i).y, 'color', [1 1 1 0.25]) 71 | end 72 | title('old spatialCorr = r, new spatialCorr = cyan') 73 | end 74 | 75 | 76 | %% Save the new SpatialCorr 77 | SpatialCorr = SpatialCorrNew; 78 | 79 | fprintf('\nSaving the data to the SPSIG file\n') 80 | if calcRvar 81 | PP.Rvar = rvar; 82 | save(nameSpsig, 'SpatialCorr', 'PP', '-append') 83 | else 84 | save(nameSpsig, 'SpatialCorr', '-append') 85 | end 86 | fprintf('\nSaved %s\n', fnSpsig) 87 | 88 | 89 | -------------------------------------------------------------------------------- /util/SpecProfileCalcRun.m: -------------------------------------------------------------------------------- 1 | % This script runs SpecProfileCalcFun.m to calculate the PP.SpecProfile 2 | % and PP.peakFreq and PP.peakVal variable 3 | % 4 | % PP.SpecProfile: 2D double [ROIs x frequency]: average spectral power 5 | % values of each ROI for each spectral frequency/ component 6 | % PP.peakFreq: 1D vector [ROIs]: which frequency has the highest power 7 | % PP.peakVal : 1D vector [ROIs]: what's the highest spectral value after 8 | % smoothing 9 | % 10 | % Leander de Kraker 11 | % 2020-1-21 12 | % 13 | 14 | % Load the mask, contour and spectral data 15 | [fnSpsig, pnSpsig] = uigetfile('*SPSIG.mat','load mask data (SPSIG file)'); 16 | nameSpsig = [pnSpsig, fnSpsig]; 17 | load(nameSpsig, 'PP', 'Mask', 'SPic', 'Sax') 18 | 19 | spec = log(SPic); % spectral data 20 | vals = sort(unique(spec(:))); % remove -inf values 21 | if vals(1)==-inf 22 | spec(spec==-inf) = vals(2); 23 | end 24 | 25 | % Check if SpecProfile is already present etc 26 | if isfield(PP, 'SpecProfile') 27 | fprintf('Specprofile is already present in the datasets PP variable\n') 28 | if size(PP.SpecProfile,2) ~= PP.Cnt 29 | fprintf('But there seems to be an incorrect number of ROIs in PP.specProfile\n') 30 | end 31 | end 32 | 33 | 34 | % Delete the 0Hz component if it's present 35 | if Sax(1) == 0 36 | if size(spec, 3) == length(Sax) 37 | spec = spec(:, :, 2:end); 38 | end 39 | Sax = Sax(2:end); 40 | end 41 | 42 | % Get the Specprofile & peak frequency 43 | tic 44 | [PP.SpecProfile, PP.peakFreq, PP.peakVal] = SpecProfileCalcFun(spec, Mask, Sax); 45 | fprintf('done (%.1f seconds)\n', toc) 46 | 47 | 48 | %% Save the updated PP variable 49 | 50 | fprintf('saving the updated PP to the SPSIG file\n') 51 | save(nameSpsig, 'PP', '-append') 52 | fprintf('saved %s\n', fnSpsig) 53 | 54 | -------------------------------------------------------------------------------- /util/dep/AskDate.m: -------------------------------------------------------------------------------- 1 | function filedate = AskDate(filepath, filename) 2 | % Prompt for getting a date 3 | % If only it was this easy 4 | % 5 | % Leander de Kraker 6 | % 2022-7-18 7 | % 8 | 9 | questionStr = sprintf('No date detected for file, \nfile:%s\nfolder: %s\n',... 10 | filename, filepath); 11 | questionStr = [questionStr, 'Please type its date here as yyyyMMdd:']; 12 | 13 | answerStr = inputdlg(questionStr); 14 | 15 | try % try to decipher user input as a datetime 16 | filedate = datetime(answerStr, 'inputformat','yyyyMMdd'); 17 | catch METOO % another error: No date for this recording. 18 | warning('User input not recognized as date') 19 | filedate = answerStr; 20 | end -------------------------------------------------------------------------------- /util/dep/BufferMask.m: -------------------------------------------------------------------------------- 1 | function [contours, zones, mask2] = BufferMask(Mask,bufSize) 2 | % Creates a contour and a mask around each ROI in the given mask. 3 | % The contour/ masks will be bufSize pixels wide around the original mask. 4 | % The contours/ masks will not cover ROIs from the input. 5 | % 6 | % input: 7 | % - Mask (2D double) 8 | % - bufSize (digid) 9 | % output: 10 | % - contours: a struct with contours for each ROI, and the size 11 | % and number of these contours. 12 | % - C: contour line coordinates 13 | % - A: number of pixels inside the contours 14 | % - zones: a struct with a mask for each ROI and its offset 15 | % - mask: A small mask for each ROI 16 | % - x: the x coordinates that mask has in the original mask 17 | % - y: the y coordinates that mask has in the original mask 18 | % - A: number of pixels inside the contours 19 | % - mask2: New expanded mask (2D double). Many ROIs should be 20 | % overlapping, which is not possible in this mask. Only use this 21 | % when the ROI numbers do not matter (for quick images etc.) 22 | % 23 | % Leander de Kraker 24 | % 2018-2 25 | % 26 | 27 | nMasks = max(max(Mask)); 28 | dimsM = size(Mask); 29 | Mask = padarray(Mask,[bufSize+1,bufSize+1]); 30 | contours = struct('C', struct('v',[],'x',[],'y',[],'c',[]), 'A', cell(1, nMasks)); 31 | zones = struct('mask',cell(1, nMasks),... 32 | 'x',cell(1, nMasks),'y',cell(1, nMasks),'A',cell(1, nMasks)); 33 | mask2 = zeros(dimsM); 34 | 35 | % Create circular filter 36 | [columns, rows] = meshgrid(1:bufSize*2, 1:bufSize*2); 37 | radius = bufSize; 38 | filt = (rows - bufSize).^2 + (columns - bufSize).^2 <= radius.^2; 39 | 40 | for m = 1:nMasks 41 | [x, y] = find(Mask==m); % Where to expand this mask 42 | xbeg = min(x) - bufSize - 1; 43 | xend = max(x) + bufSize + 1; 44 | ybeg = min(y) - bufSize - 1; 45 | yend = max(y) + bufSize + 1; 46 | 47 | zone = Mask(xbeg:xend, ybeg:yend); % Take small window of dataset 48 | zone(zone ~= m) = 0; % Only focus on ROI m 49 | 50 | % Create mask using circular filter 51 | zone = filter2(filt, zone); 52 | zone(zone>0) = m; 53 | 54 | % remove parts that fall inside ROIs 55 | zone(Mask(xbeg:xend, ybeg:yend)>0) = 0; 56 | 57 | 58 | % Save contours 59 | % Number of pixels that will be in this contour 60 | contours(m).A = length(find(zone==m)); 61 | % Get contour of this mask 62 | C = contourc(zone, [m m]); 63 | C = getcontourlines(C); 64 | for i = 1:length(C) % correct x & y positions of this contour 65 | C(i).x = C(i).x + ybeg - bufSize-2; % (x - y = correction?) 66 | C(i).y = C(i).y + xbeg - bufSize-2; 67 | end 68 | contours(m).C = C; 69 | 70 | 71 | % Save search zone masks 72 | % the coordinates of this zone 73 | zones(m).x = xbeg-bufSize-1:xend-bufSize-1; 74 | zones(m).y = ybeg-bufSize-1:yend-bufSize-1; 75 | % If the zone is actually outside unpadded image bounds, cut the zone 76 | if zones(m).x(1) <= 0 % Cut from x beginning 77 | cut = 1 - zones(m).x(1); 78 | zones(m).x(1:cut) = []; 79 | zone(1:cut,:) = []; 80 | end 81 | if zones(m).x(end) > dimsM(1) % Cut from x ending 82 | cut = zones(m).x(end) - dimsM(1); 83 | zones(m).x(end-cut:end) = []; 84 | zone(end-cut:end,:) = []; 85 | end 86 | if zones(m).y(1) <= 0 % Cut from y beginning 87 | cut = 1 - zones(m).y(1); 88 | zones(m).y(1:cut) = []; 89 | zone(:,1:cut) = []; 90 | end 91 | if zones(m).y(end) > dimsM(2) % Cut from y ending 92 | cut = zones(m).y(end) - dimsM(2); 93 | zones(m).y(end-cut:end) = []; 94 | zone(:,end-cut:end) = []; 95 | 96 | end 97 | zones(m).mask = zone; 98 | zones(m).A = length(find(zone==m)); 99 | 100 | 101 | % Update the mask2 (without overwriting older masks with zeros) 102 | maskTemp = mask2(zones(m).x, zones(m).y); 103 | maskTemp(maskTemp==0) = zone(maskTemp==0); 104 | mask2(zones(m).x, zones(m).y) = maskTemp; 105 | end 106 | end -------------------------------------------------------------------------------- /util/dep/Colorbar2D.m: -------------------------------------------------------------------------------- 1 | function [im, h] = Colorbar2D(colors1, colors2, varargin) 2 | % Create a colorbar image based on two colormaps which are combined 3 | % [im, h] = Colorbar2D(colors1, colors2, varargin) 4 | % 5 | % 6 | % input: 7 | % colors1 ([n x 3] double): rgb colormap 8 | % colors2 ([m x 3] double): different rgb colormap 9 | % 10 | % ouput: 11 | % im ([n x m x 3] double): 2D colorbar image 12 | % 13 | % Leander de Kraker 14 | % 2022-10-20 15 | % 16 | 17 | %% 18 | ncolors1 = size(colors1, 1); 19 | ncolors2 = size(colors2, 1); 20 | 21 | im1 = repmat(permute(colors1, [1 3 2]), [1, ncolors2, 1]); 22 | im2 = repmat(permute(colors2, [3 1 2]), [ncolors1, 1, 1]); 23 | 24 | % Different mixing options.. 25 | im = im1.*im2; 26 | % im = mean(cat(4, im1, im2), 4); 27 | % im = max(cat(4, im1, im2), [], 4); 28 | 29 | -------------------------------------------------------------------------------- /util/dep/CorrRoiCorners.m: -------------------------------------------------------------------------------- 1 | function varargout = CorrRoiCorners(corner, check, Mask, sbxt, dim) 2 | % This function correlates signals of each pixel from the ROIs in check 3 | % with the signals of the 'corner' coordinates which are part of the 4 | % same ROI. 5 | % 6 | % output: - corrImg: cells with 2D arrays, each cell containing the 7 | % correlation coefficients resulting from a corner signal with 8 | % all pixels of the ROIs 9 | % - pieceSigs: the fluoresence signals of the corners 10 | % - corrs: the correlation coefficients for each ROI, with each 11 | % corner (columns) correlated to all pixels in the ROI (rows) 12 | % - corrsSub: The correlation coefficients with the correlation 13 | % coefficients from other corners subtracted, so similar 14 | % correlations result in values near 0, instead of positive 15 | % correlation. (important for clustering) 16 | % - pos: struct with the pixel coordinates of the ROI (1D, x and y) 17 | % 18 | 19 | 20 | nCheck = length(check); 21 | if nCheck > 10 22 | f = waitbar(0,'Initializing...'); 23 | tic 24 | end 25 | 26 | Mt = Mask'; %the mask needs to be transposed 27 | indices = find(ismember(Mt(:), check)); 28 | % indices = indices + double(dim(2)); %add a line?! OR NO LINE ?!?!! 29 | 30 | Sigrois = sbxt.Data.y(:,indices); 31 | Sigrois = double(Sigrois); 32 | % sig2 = cell(nCheck,1); % This sig keeps the signal of every pixel in all ROI 33 | pos = struct('d1', [], 'x', [], 'y', []); 34 | pos(nCheck).x = []; 35 | 36 | ncorners = size(corner,2); 37 | 38 | pieceSigs = cell(nCheck,1); 39 | corrs = cell(nCheck,1); 40 | corrsSub = cell(nCheck,1); 41 | corrImg = zeros(numel(Mt), ncorners); 42 | 43 | for i = 1:nCheck 44 | % Retrieve signal and get 1D indexes to the ROIs 45 | pos(i).d1 = find(Mt(:)== check(i)); 46 | [~, ia] = intersect(indices, pos(i).d1); % get indices of to this roi 47 | sig2 = Sigrois(:,ia); % get data from this selection 48 | 49 | % Get the mean signal from 9 pixels around the corner coordinates 50 | pieceSigs{i} = zeros(ncorners,dim(1)); 51 | for j = 1:ncorners 52 | xmesh = reshape(meshgrid(corner(1,j,i)-1:corner(1,j,i)+1), [9,1]); 53 | ymesh = reshape(meshgrid(corner(2,j,i)-1:corner(2,j,i)+1)', [9,1]); 54 | corner1D = (ymesh-1).*dim(2)+xmesh; % convert to 1D 55 | corner1D = ismember(pos(i).d1, corner1D); % find the actual ROI pixels 56 | 57 | pieceSigs{i}(j,:) = mean(sig2(:, corner1D),2); 58 | end 59 | 60 | % Correlate the four 'start-correlation' with rest of the ROI 61 | corrs{i} = corr(double(sig2), double(pieceSigs{i})',... 62 | 'rows','pairwise'); 63 | 64 | % Subtract correlation of others from each other, so positive 65 | % correlations are cancelled out. 66 | corrsSub{i} = zeros(size(corrs{i})); 67 | for j = 1:ncorners 68 | others = 1:ncorners~=j; 69 | corrsSub{i}(:,j) = corrs{i}(:,j) - mean(corrs{i}(:,others),2); 70 | end 71 | 72 | corrImg(pos(i).d1,:) = corrs{i}; 73 | 74 | % Convert 1D indexes to 2D 75 | pos(i).x = mod(pos(i).d1, dim(2)); 76 | pos(i).y = floor(pos(i).d1 / dim(2)) + 1; 77 | 78 | if mod(i,11)==0 79 | waitbar(i/(nCheck*1.1),f,'Calculating...'); 80 | end 81 | end 82 | 83 | corrImg = reshape(corrImg, [size(Mt), ncorners]); 84 | 85 | 86 | varargout = {corrImg, pieceSigs, corrs, corrsSub, pos}; 87 | 88 | if nCheck>10 89 | close(f) 90 | toc 91 | end 92 | end 93 | 94 | -------------------------------------------------------------------------------- /util/dep/CreateRGB.m: -------------------------------------------------------------------------------- 1 | function [RGB, cvals] = CreateRGB(data, colors, varargin) 2 | % Create an RGB image (length x width x 3) array from a cell array 3 | % 4 | % input: 5 | % - data: cell array with 2D matrixes 6 | % - colors: In which color channels to put the slices. 7 | % - optional - 'binary': make the image binary, anything above 0 becomes 8 | % 1, all other values are 0, per dataslice 9 | % 10 | % output: 11 | % - RGB: (length x width x 3) array 12 | % - cvals: the color value of each slice of data 13 | % 14 | % examples: 15 | % When you want to create an RGB images of only two of four arrays: 16 | % data = 1x2 cell 17 | % colors = 'rg gb' 18 | % 19 | % imagesc(CreateRGB(data, colors)) 20 | % 21 | % Puts the insides of cell 1 in the red and green color channels, and the 22 | % insides of cell 4 in the green and blue color channels. And plots the 23 | % resulting image 24 | % 25 | % data = 1x4 cell 26 | % colors = 'r rg gb b' 27 | % Puts the four images in red, red&green(yellow), green&blue(cyan) 28 | % and blue color channels. 29 | % 30 | % Leander de Kraker 31 | % 2018-2-15 32 | % Last update: 2019-7-10 !slices variable is now not an input anymore! 33 | % 34 | % 35 | 36 | 37 | if nargin == 3 38 | if varargin{1} == 'binary' 39 | for i = 1:length(data) 40 | data{i}(data{i}>0) = 1; 41 | data{i}(data{i}<1) = 0; 42 | end 43 | end 44 | end 45 | 46 | dims = (cellfun(@size, data,'UniformOutput',false)); 47 | dims = cat(1,dims{:}); 48 | maxdim(1) = max(dims(:,1)); 49 | maxdim(2) = max(dims(:,2)); 50 | RGB = zeros(maxdim(1), maxdim(2), 3); 51 | slices = 1:length(data); 52 | cvals = zeros(length(slices),3)+0.4; 53 | if ~iscell(colors) 54 | colors = strsplit(colors); 55 | end 56 | 57 | % Checking input quality 58 | if length(colors) ~= length(slices) 59 | warning('specify as many color channel allocations as data slices') 60 | return 61 | end 62 | 63 | % 64 | c = {'r', 'g', 'b'}; 65 | 66 | % Put slices in requested color channels 67 | for i = slices 68 | for channel = 1:3 69 | % Put in the colorchannel if requested 70 | if ismember(c{channel}, colors{i}) 71 | RGB(1:dims(i, 1), 1:dims(i, 2), channel) = ... 72 | RGB(1:dims(i,1), 1:dims(i,2), channel) + data{i}; 73 | cvals(i,channel) = 1; 74 | end 75 | end 76 | end 77 | 78 | % Normalize colors 79 | maxvals = squeeze(max(squeeze(max(RGB)))); 80 | minvals = squeeze(min(squeeze(min(RGB)))); 81 | for i = 1:3 82 | % Delete -infs and infs if found 83 | if minvals(i) == -inf 84 | vals = unique(RGB(:,:,i)); 85 | minvals(i) = vals(2); % second smallest value (not -inf) 86 | idx = RGB(:,i) < minvals(i); % indexes of -inf values in this colorchannel 87 | RGB(idx,i) = minvals(i); 88 | end 89 | if maxvals(i) == inf 90 | vals = unique(RGB(:,:,i)); 91 | maxvals(i) = vals(end-1); 92 | idx = RGB(:,i) > maxvals(i); % indexes of -inf values in this colorchannel 93 | RGB(idx,i) = maxvals(i); 94 | end 95 | 96 | % Normalize 97 | RGB(:,:,i) = (RGB(:,:,i)-minvals(i)) ./ range([minvals(i), maxvals(i)]); 98 | end 99 | 100 | end 101 | 102 | -------------------------------------------------------------------------------- /util/dep/CreateRGB2.m: -------------------------------------------------------------------------------- 1 | function [RGB] = CreateRGB2(data, colors, varargin) 2 | % Create a colorfull image by overlaying 2D images from a cell array using 3 | % a requested specific colormap 4 | % 5 | % RGB = CreateRGB2(data, colors, normalization, whitebalance, selected) 6 | % 7 | % input: 8 | % - data: ([n x 1] cell array), with 2D or 3D doubles. 9 | % - colors ([n x 3] double): color values to give to corresponding data. 10 | % Optional input: can be left empty [] or disregarded completely 11 | % - normalize: true or false. Normalizes each data slice 12 | % - wbalance : true or false. White balances final RGB image. Can make 13 | % the images not correspond to their intended colors. 14 | % - selected ([n x 1] double): In case each cell contains a 3D matrix 15 | % select which image of the 3rd dimension to use. 16 | % 17 | % 18 | % output: 19 | % - RGB: 3D double [height x width x 3] of largest 2D double in data 20 | % 21 | % 22 | % See also CreateRGB, CreateRGB2_mat 23 | % 24 | % Leander de Kraker 25 | % 2019-3-1 26 | % 27 | 28 | % normalize? 29 | if (nargin > 3) && ~isempty(varargin{1}) 30 | norma = varargin{1}; 31 | else 32 | norma = false; 33 | end 34 | if (nargin >= 4) && ~isempty(varargin{2}) 35 | wbalance = varargin{2}; 36 | else 37 | wbalance = false; 38 | end 39 | if (nargin == 5) 40 | selected = varargin{3}; 41 | else 42 | selected = 1; 43 | end 44 | 45 | nslices = length(data); 46 | dims = (cellfun(@size, data,'UniformOutput',false)); 47 | dims = cat(1,dims{:}); 48 | if size(dims, 2)==3 49 | for i = 1:nslices 50 | data{i} = data{i}(:,:,selected); 51 | end 52 | end 53 | 54 | maxdim(1) = max(dims(:,1)); 55 | maxdim(2) = max(dims(:,2)); 56 | RGB = zeros(maxdim(1), maxdim(2), 3); 57 | 58 | 59 | for i = 1:nslices 60 | 61 | if norma % normalize intensities of the channel 62 | data{i} = (data{i}-min(data{i}(:)))./ range(data{i}(:)); 63 | else % Set the data to minimum 0 64 | data{i} = data{i}-min(data{i}(:)); 65 | end 66 | 67 | for c = 1:3 68 | if colors(i,c)>0 69 | % RGB update = old colorchannel values + imgage i * colormap value 70 | RGB(1:dims(i,1),1:dims(i,2),c) = RGB(1:dims(i,1),1:dims(i,2),c) + ... 71 | data{i} .* colors(i,c); 72 | end 73 | end 74 | end 75 | 76 | 77 | % Normalize colors 78 | minvals = min(RGB(:)); 79 | maxvals = max(RGB(:)); 80 | % Delete -infs and infs if found 81 | if minvals == -inf 82 | vals = unique(RGB); 83 | minvals = vals(2); % second smallest value (not -inf) 84 | idx = RGB < minvals; % indexes of -inf values in this colorchannel 85 | RGB(idx) = minvals; 86 | end 87 | if maxvals == inf 88 | vals = unique(RGB); 89 | maxvals(i) = vals(end-1); 90 | idx = RGB > maxvals; % indexes of -inf values in this colorchannel 91 | RGB(idx) = maxvals; 92 | end 93 | 94 | % normalize 95 | RGB = (RGB-minvals) ./ range([minvals, maxvals]); 96 | 97 | if wbalance 98 | % Normalize colors (per color channel)(results in unrequested colors... 99 | % ...but it's "white balanced") 100 | maxvals = squeeze(max(squeeze(max(RGB)))); 101 | minvals = squeeze(min(squeeze(min(RGB)))); 102 | for i = 1:3 103 | % Normalize 104 | if range([minvals(i), maxvals(i)])>0 105 | RGB(:,:,i) = (RGB(:,:,i)-minvals(i)) ./ range([minvals(i), maxvals(i)]); 106 | end 107 | end 108 | end 109 | 110 | end 111 | 112 | 113 | -------------------------------------------------------------------------------- /util/dep/CreateRGB2_mat.m: -------------------------------------------------------------------------------- 1 | function [RGB] = CreateRGB2_mat(data, colors, varargin) 2 | % Create a colorfull image by overlaying 2D images from a 3D matrix data 3 | % using a SPECIFIC COLORMAP colors 4 | % CreateRGB2_mat uses a matrix, while CreateRGB2 uses a cell matrix as 5 | % input. 6 | % 7 | % RGB = CreateRGB2_mat(data, colors, normalization, whitebalance) 8 | % input: 9 | % - data: 3D matrix [height x width x nslices] 10 | % - colors: [nslices x 3] RGB color values for every slice of data 11 | % - optional - 'normalize': true or false. Normalizes each data slice 12 | % - - 'wbalance' : true of false. White balances final RGB image 13 | % 14 | % output: 15 | % - RGB: 3D double [height x width x 3] 16 | % 17 | % 18 | % See also CreateRGB2, CreateRGB 19 | % 20 | % Leander de Kraker 21 | % 2020-9-17 22 | 23 | % normalize? 24 | if (nargin > 3) && (varargin{1} == true) 25 | norma = true; 26 | else 27 | norma = false; 28 | end 29 | if (nargin == 5) && (varargin{2} == true) 30 | wbalance = true; 31 | else 32 | wbalance = false; 33 | end 34 | 35 | dims = size(data); 36 | RGB = zeros(dims(1), dims(2), 3); 37 | if length(dims)>2 38 | nslices = dims(3); 39 | else 40 | nslices = 1; 41 | end 42 | 43 | 44 | % Remove -inf and replace with lowest actual value 45 | minval = min(data(:)); 46 | maxval = max(data(:)); 47 | if minval == -inf 48 | vals = mink(data,2); 49 | data(datavals(2)) = vals(2); 56 | maxval = vals(2); 57 | fprintf('CreateRGB2mat: replacing inf value from data with second highest\n') 58 | end 59 | 60 | % Normalize every slice to amplitude range [0 - 1] if norma is requested 61 | minvals = min(min(data)); 62 | maxvals = max(max(data)); 63 | if norma 64 | data = (data - minvals) ./ (maxvals-minvals); 65 | else % Otherwise only lower the lowest value to 0, but keeping range 66 | data = data - minvals; 67 | end 68 | 69 | 70 | % Create the RGB image of all the slices 71 | for i = 1:nslices 72 | for c = 1:3 73 | if colors(i,c)>0 74 | % RGB update = old colorchannel values + imgage i * colormap value 75 | RGB(:,:,c) = RGB(:,:,c) + data(:,:,i) .* colors(i,c); 76 | end 77 | end 78 | end 79 | 80 | minval = min(RGB(:)); 81 | maxval = max(RGB(:)); 82 | % normalize so Matlab can plot the image correctly 83 | RGB = (RGB-minval) ./ range([minval, maxval]); 84 | 85 | if wbalance 86 | % Normalize colors (per color channel)(results in unrequested colors... 87 | % ...but it's "white balanced") 88 | maxval = squeeze(max(squeeze(max(RGB)))); 89 | minval = squeeze(min(squeeze(min(RGB)))); 90 | for i = 1:3 91 | % Normalize 92 | if range([minval(i), maxval(i)])>0 93 | RGB(:,:,i) = (RGB(:,:,i)-minval(i)) ./ range([minval(i), maxval(i)]); 94 | end 95 | end 96 | end 97 | 98 | end 99 | 100 | 101 | -------------------------------------------------------------------------------- /util/dep/ETA.m: -------------------------------------------------------------------------------- 1 | function t = ETA(i, iend, telapsed) 2 | % Calculated the Estimated Time to Arrival of your executing code 3 | % 4 | % input: 5 | % i (scalar double): current iteration 6 | % iend (scalar double): number of total iterations to do 7 | % telapsed (scalar double): how long it took to get to i 8 | % 9 | % output: 10 | % t (scalar double): time to completion probably 11 | % 12 | % Leander de Kraker 13 | % 2023-2-9 14 | % 15 | 16 | t = (iend-i) / (i/telapsed); -------------------------------------------------------------------------------- /util/dep/FindNNumInStr.m: -------------------------------------------------------------------------------- 1 | function strOut = FindNNumInStr(str, n) 2 | % Find a number that is exactly n digits long in a string 3 | % 4 | % 5 | % Leander de Kraker 6 | % 2022-7-15 7 | % 8 | 9 | % Get info about the digits in the string 10 | pos = regexp(str, '\d'); 11 | a=diff(pos); 12 | b=find([a inf]>1); 13 | c=diff([0 b]); % length of the sequences 14 | good = pos(b(c==n)); 15 | 16 | if isscalar(good) 17 | strOut = str(good-n+1:good); 18 | else 19 | strOut = []; 20 | end 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /util/dep/GetCenteredFigPos.m: -------------------------------------------------------------------------------- 1 | function pos = GetCenteredFigPos(desiredSize) 2 | % pos = GetCenteredFigPos(desiredSize) 3 | % Get pixel positions for a figure that is centered on your screen with 4 | % desired size 5 | % 6 | % input: 7 | % desiredSize ([2 x 1] double): width and height in pixels of desired 8 | % figure size limited by screen size 9 | % 10 | % output: 11 | % pos ([1 x 4] double): position of figure 12 | % 13 | % 14 | % Leander de Kraker 15 | % 2022-7-12 16 | % 17 | 18 | scrnSz = get(0,'ScreenSize'); 19 | desiredSz = [min(desiredSize(1), scrnSz(3)),... 20 | min(desiredSize(2), scrnSz(4))]; 21 | p1 = round(scrnSz(3)/2)-round(desiredSz(1)/2); 22 | p2 = round(scrnSz(4)/2)-round(desiredSz(2)/2); 23 | pos = [p1 p2 desiredSz(1) desiredSz(2)-25]; -------------------------------------------------------------------------------- /util/dep/GetRoiCoM.m: -------------------------------------------------------------------------------- 1 | function com = GetRoiCoM(Mask) 2 | % com = GetRoiCoM(Mask) 3 | % Get the Center of Masses (CoM) from ROIs in a Mask 4 | % 5 | % Input: 6 | % Mask (2D double): field of view with numbers indicating which pixels 7 | % are occupied by which ROI 8 | % 9 | % Output: 10 | % com ([n x 2] double): Center of Masses of all n ROIs inside the Mask. 11 | % first column = x values, second = y values. 12 | % 13 | % Leander de Kraker 14 | % 2022-4-10 15 | % 16 | 17 | cnt = max(Mask(:)); 18 | com = zeros(2, cnt); 19 | for i = 1:cnt 20 | [y, x] = find(Mask == i); 21 | com(1, i) = mean(x); 22 | com(2, i) = mean(y); 23 | end -------------------------------------------------------------------------------- /util/dep/GetRoiCorners.m: -------------------------------------------------------------------------------- 1 | function [corner, check] = GetRoiCorners(Mask, PP, decreSize, checkSize, varargin) 2 | % Get coordinates of corners of ROIs. 3 | % 4 | % which ROIs? Well.. This can be selected based on size, or on ROI number 5 | % If you want to select on size, call the function with 'size' as 5th input 6 | % argument, and the 4th input will be minimum size to be analyzed 7 | % If there is no 5th input argument the 4th input argument should be the 8 | % ROI number(s) of the ROIs to check, in a vector 9 | % 10 | % 11 | % I'll pick the most extreme coordinates in a ROI to start checking 12 | % correlation with the rest of the ROI. But the points shouldn't be 13 | % outside of neurons. To ensure this, I decrease the size of the masks, 14 | % using my BufferMask function in a reverse way 15 | % 16 | % Leander de Kraker 17 | % 2019 18 | % 19 | 20 | rMask = Mask; % reverse valued Mask (0 -> 1), (>=1 -> 0) 21 | rMask(rMask>0) = 1; 22 | rMask = 1-rMask; 23 | [~,~,rMask] = BufferMask(rMask,decreSize); % Finding inner pixels on ROI boundries 24 | uMask = Mask; % useMask 25 | uMask(rMask>0)=0; 26 | 27 | if nargin > 4 28 | if strcmpi(varargin{1}, 'size') 29 | % When ROI is bigger than given pixels in area, check it for splitting 30 | check = find(PP.A > checkSize(1)); 31 | if length(checkSize) > 1 32 | warning('when "size" selection modus is enabled, input only minimum size\n') 33 | end 34 | else % for some strange reason the 5th input argument was not "size" 35 | % Check the requested neuron(s) 36 | check = checkSize; 37 | end 38 | else 39 | % Check the requested neuron(s) 40 | check = checkSize; 41 | end 42 | 43 | corner = zeros(2,4,length(check)); 44 | 45 | % Get coordinates to start the correlation from 46 | for i = 1:length(check) 47 | [y, x] = find(uMask==check(i)); 48 | [corner(1,1,i), idx] = min(x); 49 | corner(2,1,i) = y(idx); 50 | [corner(1,2,i), idx] = max(x); 51 | corner(2,2,i) = y(idx); 52 | [corner(2,3,i), idx] = min(y); 53 | corner(1,3,i) = x(idx); 54 | [corner(2,4,i), idx] = max(y); 55 | corner(1,4,i) = x(idx); 56 | end 57 | 58 | end 59 | 60 | -------------------------------------------------------------------------------- /util/dep/MidtoneBalance.m: -------------------------------------------------------------------------------- 1 | function img = MidtoneBalance(img, m, varargin) 2 | % img = MidtoneBalance(img, m) 3 | % Balancing midtone/ contrast/ brightnesses of an image using a formula 4 | % derived from the Bulirsch-Stoer algorithm. For evaluation of diagonal 5 | % rational function.. 6 | % 7 | % Input: 8 | % img (double): data to midtone balance 9 | % m (scalar, double): value between 0 and 1. 0.5 Means same image gets 10 | % outputted. lower values result in brighter image, 11 | % higher values darker image. 12 | % doScale (scalar, boolean): Scale data between 0 and 1, for accurate 13 | % midtone balancing. But perhaps your data values 14 | % is already nearly between 0 and 1, in which 15 | % case you could set soScale to false, for 16 | % slightly faster 17 | % 18 | % Leander de Kraker 19 | % 2022-7-20 20 | % 21 | 22 | doScale = true; 23 | if exist('varargin', 'var') && nargin == 3 24 | doScale = varargin{1}; 25 | end 26 | if doScale 27 | mini = min(img(:)); 28 | maxi = max(img(:)); 29 | img = (img-mini) ./ (maxi-mini); % normalize to range [0 - 1] 30 | end 31 | 32 | % Do the midtone balance 33 | img = ((m-1)*img) ./ ((2*m-1)*img - m); 34 | 35 | if doScale 36 | img = (img .* (maxi-mini)) + mini; % Scale values to original limits 37 | end 38 | -------------------------------------------------------------------------------- /util/dep/PlotCon.m: -------------------------------------------------------------------------------- 1 | function [h, cons] = PlotCon(PP, colors, varargin) 2 | % [h, cons] = PlotCon(PP, colors, xshift, yshift); 3 | % PlotCon(PP, colors) 4 | % 5 | % Quickly plot the ROI contours 6 | % Is accelerated by concatenating the different ROIs and seperating them by 7 | % a nan so no connecting line is drawn between the ROIs. But it is plotted 8 | % as one graphical object for MATLAB. 9 | % 10 | % Input: 11 | % - PP (struct): with fields Cnt and Con.x and Con.y 12 | % - colors ([1 x 3 double] or [1 x 4 double] or [scalar color]): e.g. 13 | % [1 0 0] or [1 0 0 0.2] or 'r' 14 | % Optional: 15 | % - xshift: shift to apply to data 16 | % - yshift: shift to apply to data 17 | % 18 | % 19 | % Ouput: 20 | % - h ([scalar] graphics handle) 21 | % - cons (struct): with fields x and y 22 | % 23 | % Leander de Kraker 24 | % 2023-4-3 25 | % 26 | 27 | if nargin>2 28 | xshift = varargin{1}; 29 | yshift = varargin{2}; 30 | else 31 | xshift = 0; 32 | yshift = 0; 33 | end 34 | 35 | cons = struct(); 36 | cons.x = []; 37 | cons.y = []; 38 | for r = 1:PP.Cnt 39 | cons.x = cat(2, cons.x, [PP.Con(r).x, NaN]); 40 | cons.y = cat(2, cons.y, [PP.Con(r).y, NaN]); 41 | end 42 | h = plot(cons.x-xshift, cons.y-yshift, 'color', colors); 43 | -------------------------------------------------------------------------------- /util/dep/PlotManyImgs.m: -------------------------------------------------------------------------------- 1 | function [hAxes, hImgs, xidx, yidx] = PlotManyImgs(imgs, varargin) 2 | % [hAxes, hImgs] = PlotManyImgs(imgs, pos, distr, buffer, titles, cut, selected) 3 | % [hAxes, hImgs] = PlotManyImgs(imgs) 4 | % 5 | % Plot many images in seperate 6 | % Input: 7 | % - imgs (cell array with 2D or 3D doubles inside): the images to plot. 8 | % - pos([1x4 double]): Vector saying position limits inside figure: 9 | % [from left, from bottom, width, height]. 10 | % - distr([1 x 2 double] or string): How to distribute the subplots: 11 | % [n columns, n rows], or let function figure it out as: 12 | % 'horizontal', 'vertical', 'rect' (default). 13 | % - buffer([1x4 double]): Space between individual subplots: 14 | % [top, left, right, bottom]. 15 | % - titles (cell array with strings): titles for the plots. 16 | % - cut([1x4 double]): Vector saying how to crop every img in px: 17 | % [vertical top, to vertical down, horizontal left, to horizontal right] 18 | % - selected ([n x 1 double]): which of the 3rd dimension in each cell of 19 | % imgs to select: default: 1 (or 3 for RGB) 20 | % 21 | % 22 | % Output: 23 | % - hAxes (array of handles to the axes) 24 | % - hImgs (array of handles to the images) 25 | % - xidx (the x position index of the axes) 26 | % - yidx (the y position index of the axes)% 27 | % 28 | % Leander de Kraker 29 | % 2022-10-7, updated 2023-11-22 30 | % 31 | 32 | nimgs = numel(imgs); 33 | 34 | if (nargin >= 2) && ~isempty(varargin{1}) % outer position inside figure 35 | pos = varargin{1}; 36 | else 37 | pos = [0.1000 0.1100 0.7750 0.8150]; 38 | end 39 | if (nargin >= 3) && ~isempty(varargin{2}) % Subplot distribution 40 | distr = varargin{2}; 41 | else 42 | distr = 'rect'; 43 | end 44 | if (nargin >= 4) && ~isempty(varargin{3}) % space between individual subplots 45 | buffer = varargin{3}; 46 | else 47 | buffer = [0.1 0.1 0 0]; 48 | end 49 | if (nargin >= 5) && ~isempty(varargin{4}) % titles 50 | titles = varargin{4}; 51 | doTitles = true; 52 | else 53 | doTitles = false; 54 | end 55 | if (nargin >= 6) && ~isempty(varargin{5}) % cropping/ zooming the images 56 | cut = varargin{5}; 57 | else 58 | cut = []; 59 | end 60 | if (nargin >= 7) && ~isempty(varargin{6}) % 3rd dimensions of image matrix to select 61 | selected = varargin{6}; 62 | else 63 | if size(imgs{1}, 3) == 3 64 | selected = [1 2 3]; 65 | else 66 | selected = 1; 67 | end 68 | end 69 | 70 | 71 | if ischar(distr) 72 | if strcmpi(distr, 'rect') 73 | distr = [ceil(sqrt(nimgs)), round(sqrt(nimgs))]; 74 | elseif strcmpi(distr, 'horizontal') 75 | distr = [1, nimgs]; 76 | elseif strcmpi(distr, 'vertical') 77 | distr = [nimgs, 1]; 78 | else 79 | warning('non valid distr input') 80 | end 81 | end 82 | 83 | % CALCULATE SUBPLOT POSITIONS 84 | [xidx, yidx] = find(ones(distr)); 85 | yidx = distr(2)+1-yidx; 86 | positionx = linspace(pos(1)+buffer(2)/distr(1), pos(1)+pos(3).*(1+buffer(2)), distr(1)+1); 87 | positiony = linspace(pos(2)+buffer(4)/distr(2), pos(2)+pos(4).*(1+buffer(4)), distr(2)+1); 88 | 89 | positionh = [positiony(2)-positiony(1)] .* (1-(buffer(1)+buffer(4))); 90 | positionw = [positionx(2)-positionx(1)] .* (1-(buffer(3)+buffer(2))); 91 | 92 | positionx = positionx(xidx); 93 | positiony = positiony(yidx); 94 | 95 | positionx = positionx(1:nimgs); 96 | positiony = positiony(1:nimgs); 97 | xidx = xidx(1:nimgs); 98 | yidx = yidx(1:nimgs); 99 | 100 | positions = [positionx', positiony', repmat([positionw, positionh], [nimgs, 1])]; 101 | 102 | 103 | 104 | hAxes = gobjects(nimgs, 1); 105 | hImgs = gobjects(nimgs, 1); 106 | for i = 1:nimgs 107 | if ~isempty(imgs{i}) 108 | if ~isempty(cut) 109 | img = imgs{i}(cut(1):cut(2), cut(3):cut(4), selected); 110 | else 111 | img = imgs{i}(:,:,selected); 112 | end 113 | end 114 | 115 | hAxes(i) = subplot('Position', positions(i,:)); 116 | 117 | if ~isempty(imgs{i}) 118 | hImgs(i) = imagesc(img); 119 | end 120 | if doTitles 121 | title(titles{i}) 122 | end 123 | end 124 | 125 | 126 | -------------------------------------------------------------------------------- /util/dep/Register2Imgs.m: -------------------------------------------------------------------------------- 1 | function [image2, transformation] = Register2Imgs(reference,image2,varargin) 2 | % Register the second image to the first image, cut and/or pad image 2 3 | % to the same size as image 1 4 | % Uses the 2D cross-correlation then the 'check for best rotation' 5 | % technique. 6 | % 7 | % 8 | % input: image1: this 2D matrix is the reference 9 | % image2: this 2D matrix will be moved 10 | % 11 | % output: image2: 2D double with the size of image1. Registration 12 | % result 13 | % transformation: which x shift, y shift (in pixels) was applied. 14 | % which rotation was applied(in degrees) 15 | % 16 | % Leander de Kraker 17 | % 2018-10-3 18 | 19 | 20 | if exist('varargin','var') && nargin==3 21 | interpMethod = varargin{1}; 22 | else 23 | interpMethod = 'nearest'; 24 | end 25 | 26 | 27 | dims = size(reference); 28 | 29 | % Remove -infs if there are any 30 | vals = unique(reference); 31 | if vals(1) == -inf 32 | reference(reference150 41 | buffer = 30; % Hardcoded buffer to remove from the image 42 | else 43 | buffer = 1; 44 | end 45 | 46 | % Register the chronic dataset to this dataset 47 | correl = xcorr2_fft(reference,... 48 | (image2(buffer:dims(1)-buffer, buffer:dims(2)-buffer)-img2mean)/img2range); 49 | [~,snd] = max(correl(:)); 50 | [ij, ji] = ind2sub(size(correl),snd); 51 | x = dims(1) - ij - buffer; 52 | y = dims(2) - ji - buffer; 53 | 54 | 55 | % Cutting or padding the chornic image if necessary 56 | if x>=1 % Cut top 57 | image2 = image2(x:end, :); 58 | else % Padd top 59 | image2(-x+1:-x+size(image2,1),:) = image2; 60 | end 61 | if y>=1 % Cut left beginning 62 | image2 = image2(:, y:end); 63 | else % Padd left beginning 64 | image2(:,-y+1:-y+size(image2,2)) = image2; 65 | end 66 | if size(image2,1) > dims(1) % Cut bottom 67 | image2(dims(1)+1:end,:) = []; 68 | else % padd bottom 69 | image2(dims(1),1) = 0; 70 | end 71 | if size(image2,2) > dims(2) % Cut right side 72 | image2(:,dims(2)+1:end) = []; 73 | else % padd right side 74 | image2(1,dims(2)) = 0; 75 | end 76 | 77 | % Rotation by checking rotations 78 | rotation = -1:0.1:1; % rotations to apply: counterclockwise to clockwise degrees 79 | correl = zeros(1, length(rotation)); 80 | for i = 1:length(rotation) 81 | BImgRot = imrotate(image2, rotation(i), interpMethod,'crop'); 82 | correl(i)= corr2(BImgRot, reference); 83 | end 84 | 85 | % Best rotations 86 | [~, rotIdx] = max(correl); 87 | rotAng = rotation(rotIdx); 88 | if rotAng ~= 0 89 | image2 = imrotate(image2, rotAng, interpMethod, 'crop'); 90 | end 91 | 92 | transformation = struct('rotAng',rotAng,'x',x,'y',y); 93 | -------------------------------------------------------------------------------- /util/dep/Register2ImgsNew.m: -------------------------------------------------------------------------------- 1 | function [image2, transformation, correl] = Register2ImgsNew(reference,image2,varargin) 2 | % Register the second image to the first image, cut and/or pad image 2 3 | % to the same size as image 1 4 | % Uses the 2D cross-correlation then the 'check for best rotation' 5 | % technique. 6 | % 7 | % 8 | % input: reference: this 2D matrix is the reference 9 | % image2: this 2D matrix will be moved 10 | % (optional)interpMethod: interpolation for rotation(default=nearest) 11 | % 12 | % output: image2: 2D double with the size of image1. Registration 13 | % result 14 | % transformation: which x shift, y shift (in pixels) was applied. 15 | % which rotation was applied(in degrees) 16 | % 17 | % 18 | % See also, Register2Imgs. This new version can deal with different image 19 | % sizes but I still have to check if that goes right in every case. 20 | % 21 | % Leander de Kraker 22 | % 2018-10-3 23 | 24 | 25 | if exist('varargin','var') && nargin==3 26 | interpMethod = varargin{1}; 27 | else 28 | interpMethod = 'nearest'; 29 | end 30 | 31 | dimsRef = size(reference); 32 | dims2 = size(image2); 33 | 34 | % Scale the values of the images 35 | reference = (reference - mean(reference(:))) ./ range(reference(:)); 36 | image2 = (image2 - mean(image2(:))) ./ range(image2(:)); 37 | 38 | % Crop the image that has to be moved to make the proces faster 39 | if min(dims2)>150 40 | buffer = 30; % Hardcoded buffer to remove from the image 41 | else 42 | buffer = 1; 43 | end 44 | 45 | % Register the chronic dataset to this dataset 46 | correl = xcorr2_fft(reference, image2(buffer:dims2(1)-buffer, buffer:dims2(2)-buffer)); 47 | [~,snd] = max(correl(:)); 48 | [ij, ji] = ind2sub(size(correl),snd); 49 | x = dims2(1) - ij - buffer; 50 | y = dims2(2) - ji - buffer; 51 | 52 | % Cutting or padding the chornic image if necessary 53 | if x>=1 % Cut top 54 | image2 = image2(x:end, :); 55 | else % Padd top 56 | image2(-x+1:-x+size(image2,1),:) = image2; 57 | end 58 | if y>=1 % Cut left beginning 59 | image2 = image2(:, y:end); 60 | else % Padd left beginning 61 | image2(:,-y+1:-y+size(image2,2)) = image2; 62 | end 63 | if size(image2,1) > dimsRef(1) % Cut bottom 64 | image2(dimsRef(1)+1:end,:) = []; 65 | else % padd bottom 66 | image2(dimsRef(1),1) = 0; 67 | end 68 | if size(image2,2) > dimsRef(2) % Cut right side 69 | image2(:,dimsRef(2)+1:end) = []; 70 | else % padd right side 71 | image2(1,dimsRef(2)) = 0; 72 | end 73 | 74 | % Rotation by checking rotations 75 | rotation = -1:0.1:1; % rotations to apply: counterclockwise to clockwise degrees 76 | correl = zeros(1, length(rotation)); 77 | for i = 1:length(rotation) 78 | BImgRot = imrotate(image2, rotation(i), interpMethod,'crop'); 79 | correl(i)= corr2(BImgRot, reference); 80 | end 81 | 82 | % Best rotations 83 | [~, rotIdx] = max(correl); 84 | rotAng = rotation(rotIdx); 85 | if rotAng ~= 0 86 | image2 = imrotate(image2, rotAng, interpMethod, 'crop'); 87 | end 88 | 89 | transformation = struct('rotAng',rotAng,'x',x,'y',y); 90 | 91 | -------------------------------------------------------------------------------- /util/dep/RemoveROIs.m: -------------------------------------------------------------------------------- 1 | function [Mask, PP] = RemoveROIs(Mask, PP, badROIs) 2 | % Remove the ROIs indicated by badROIs 3 | % [Mask, PP] = RemoveROIs(Mask, PP, badROIs) 4 | % 5 | % Input: 6 | % Mask - a 2D ROI Mask. 7 | % PP - The standard ROI information struct from SpecSeg 8 | % badROIs ([n x 1] double) - numbers indicating which ROIs should be 9 | % deleted 10 | % 11 | % Output: 12 | % Mask - Updated Mask. 13 | % PP - Updated ROI information struct 14 | % 15 | % Leander de Kraker 16 | % 2022-5-31 17 | % 18 | 19 | 20 | PP.Con(badROIs) = []; 21 | PP.A(badROIs) = []; 22 | PP.P(:,badROIs) = []; 23 | if isfield(PP, 'SpecProfile') 24 | PP.SpecProfile(:,badROIs) = []; 25 | end 26 | if isfield(PP, 'peakFreq') 27 | PP.peakFreq(badROIs) = []; 28 | end 29 | if isfield(PP, 'peakVal') 30 | PP.peakVal(badROIs) = []; 31 | end 32 | if isfield(PP, 'Roundedness') 33 | PP.Roundedness(badROIs) = []; 34 | end 35 | if isfield(PP, 'Rvar') 36 | PP.Rvar(badROIs) = []; 37 | end 38 | if isfield(PP, 'creationMethod') 39 | PP.creationMethod(badROIs) = []; 40 | end 41 | PP.Cnt = size(PP.P, 2); 42 | 43 | 44 | Mask(ismember(Mask, badROIs)) = 0; % Set all badROIs to 0 45 | vals = unique(Mask(:)); % which ROIs are left in the Mask 46 | vals = vals(2:end); % remove the 0 47 | % Update the ROI ID numbers 48 | for i = 1:length(vals) 49 | if vals(i) ~= i 50 | Mask(Mask == vals(i)) = i; 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /util/dep/RotatePPCoordinates.m: -------------------------------------------------------------------------------- 1 | function PP = RotatePPCoordinates(PP, rotation, dims) 2 | % PP = RotatePPCoordinates(PP, rotation, dims) 3 | % Rotate ROI contour coordinates from PP struct 4 | % 5 | % Input: 6 | % PP: struct with fields: 7 | % PP.Con: which has is a struct array with fields 8 | % PP.Con.x, PP.Con.y. Which hold the contour coordinates 9 | % from all ROIs in a dataset. 10 | % PP.P: a matrix where the first row has the x coordinates for 11 | % the seed points from all the ROIs, and a second row for 12 | % the y coordinates for the seedPoints from all the ROIs. 13 | % PP.Cnt: number of ROIs. 14 | % rotation: double. 15 | % Rotation that has to be applied to the coordinates in degrees. 16 | % dims: dimension of the image that belongs to the contour coordinates 17 | % 2 element double [height x width] 18 | % 19 | % Output: 20 | % PP: struct with updated coordinates 21 | % 22 | % 23 | % Leander de Kraker 24 | % 2020-5-22 25 | % 26 | 27 | shift = dims./2; 28 | rotRad = deg2rad(rotation); 29 | 30 | for j = 1:PP.Cnt 31 | % shift the coordinate points so the centre coordinate is 0 32 | x = PP.Con(j).x - shift(1); % Adjust the contour coordinates 33 | y = PP.Con(j).y - shift(2); 34 | % Rotate the shifted coordinates (around the new centre [0, 0]) 35 | x = x * cos(rotRad) - y * sin(rotRad); 36 | y = x * sin(rotRad) + y * cos(rotRad); 37 | % Shift them back where they should be 38 | PP.Con(j).x = x + shift(1); 39 | PP.Con(j).y = y + shift(2); 40 | end 41 | 42 | % Also adjust the contour 'centres' / seed points 43 | xp = PP.P(1,:) - shift(1); 44 | yp = PP.P(2,:) - shift(2); 45 | xp = xp * cos(rotRad) - yp * sin(rotRad); 46 | yp = xp * sin(rotRad) + yp * cos(rotRad); 47 | PP.P(1,:) = xp + shift(1); 48 | PP.P(2,:) = yp + shift(2); 49 | 50 | end 51 | 52 | -------------------------------------------------------------------------------- /util/dep/SaveImg.m: -------------------------------------------------------------------------------- 1 | function SaveImg(requested, varargin) 2 | % 3 | % SaveImg(requested) saves the current matlab figure as the requested image 4 | % formats. formats should be string(s in a cell array) 5 | % Possible formats are 'png', 'epsc', 'fig', 'eps', 'svg', 'pdf' 6 | % 7 | % Input: 8 | % - requested [cell array with strings] image formats to save figure with 9 | % - savename [string] (optional) 10 | % - resolution [scalar value] (optional) Only applies for png images 11 | % 12 | % SaveImg({'png', 'fig', 'svg'}) saves the current figure as a high quality png, 13 | % a matlab figure and a Scalable Vector Graphics file. 14 | % 15 | % SaveImg({'png', 'fig', 'epsc'}, figName, 500) saves the current figure with 16 | % the given figName as the filename, with a good resolution of 500 for png 17 | % 18 | % Leander de Kraker 19 | % 2019-9-12 20 | % 2022-8-17: added resolution as optional input. 21 | % 22 | 23 | h = gcf; 24 | figure(h) % bring the figure that is about to be saved to the top 25 | 26 | if nargin == 3 27 | resolution = ['-r' num2str(varargin{2})]; 28 | else 29 | resolution = '-r450'; 30 | end 31 | if nargin >= 2 % Use 4th input as savename 32 | savename = varargin{1}; 33 | elseif nargin == 1 % Ask for name that the picture should have 34 | [savefilename, savepathname] = uiputfile('*'); 35 | if savefilename==0 36 | fprintf('No file selected, not saving picture\n') 37 | return 38 | end 39 | savefilename = strsplit(savefilename, '.'); 40 | savefilename = savefilename{1}; 41 | savename = [savepathname savefilename]; 42 | else 43 | fprintf('Incorrect input, please read:\n') 44 | help SaveImg 45 | return 46 | end 47 | 48 | nr = get(gcf, 'Number'); 49 | fprintf('\n') 50 | % Save the current figure 51 | if any(strcmp(requested, 'png')) 52 | h.Renderer = 'painters'; % painters renderer does anti-aliasing 53 | print(h, '-dpng',[savename '.png'], resolution) 54 | fprintf('saved current figure (%d) as HQ png\nin: %s\n\n', nr, savename) 55 | end 56 | if any(strcmp(requested, 'jpg')) 57 | saveas(h, savename, 'jpg') 58 | fprintf('saved current figure (%d) as shit jpg\nin: %s\n\n', nr, savename) 59 | end 60 | if any(strcmp(requested, 'fig')) 61 | savefig(savename) 62 | fprintf('saved current figure (%d) as matlab figure\nin: %s\n\n', nr, savename) 63 | end 64 | if any(strcmp(requested, 'epsc')) 65 | h.Renderer = 'opengl'; 66 | saveas(h, savename, 'epsc') 67 | fprintf('saved current figure (%d) as colored vector graphics epsc\nin: %s\n\n', nr, savename) 68 | end 69 | if any(strcmp(requested, 'eps')) 70 | h.Renderer = 'opengl'; 71 | saveas(h, savename, 'eps') 72 | fprintf('saved current figure (%d) as grayscale vector graphics eps\nin: %s\n\n', nr, savename) 73 | end 74 | if any(strcmp(requested, 'svg')) 75 | h.Renderer = 'painters'; 76 | saveas(h, savename, 'svg') 77 | fprintf('saved current figure (%d) as Scalable Vector Graphics SVG\nin: %s\n\n', nr, savename) 78 | end 79 | if any(strcmp(requested, 'pdf')) 80 | h.Renderer = 'opengl'; 81 | saveas(h, savename, 'pdf') 82 | fprintf('saved current figure (%d) as PDF\nin: %s\n\n', nr, savename) 83 | end 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /util/dep/SetLimits.m: -------------------------------------------------------------------------------- 1 | function img = SetLimits(img, lims, varargin) 2 | % Set the range limits of the img, changing the values to between 0 and 1 3 | % And if a colormap is inputted, apply that colormap to the image 4 | % 5 | % img = SetLimits(img, lims, colors) 6 | % 7 | % input: 8 | % - img (2D double). 9 | % - lims ([1 x 2] double, or empty, to just apply the colormap to img) 10 | % Optional: 11 | % - colors ([n x 3] double), colormap 12 | % 13 | % output: 14 | % - img (2D double) 15 | % 16 | % Leander de Kraker 17 | % 2022-10-20 18 | % 19 | 20 | if isempty(lims) 21 | lims = [min(img(:)), max(img(:))]; 22 | end 23 | img = (img-lims(1))./range(lims); 24 | img(img<0) = 0; 25 | img(img>1) = 1; 26 | if exist('varargin', 'var') && nargin ==3 27 | colors = varargin{1}; 28 | ncolors = size(colors, 1); 29 | dims = size(img); 30 | img = ceil(img*(ncolors-1))+1; 31 | img = colors(img(:),:); 32 | img = reshape(img, [dims, 3]); 33 | end -------------------------------------------------------------------------------- /util/dep/ShiftLinesImg.m: -------------------------------------------------------------------------------- 1 | function [img, bestS, bestMethod, p] = ShiftLinesImg(img, varargin) 2 | % [img, bestS, bestMethod, p] = ShiftLinesImg(img, varargin) 3 | % Some bi-directionally scanned 2P images are misaligned between the even 4 | % and uneven rows. 5 | % This script tries to estimate the best way of re-aligning the rows and 6 | % applies this to the image 7 | % 8 | % Input: 9 | % - img (2D double) 10 | % OPTIONAL may be left empty [] 11 | % - shift to apply (scalar double). 12 | % - method to use (scalar double): 1 = shifting, 2= via resizing 13 | % - plotting (boolean): to plot or not to plot (default = false) 14 | % - trans (string): to correct vertical lines, or horizontal lines 15 | % 'horizontal' (default) | 'vertical' 16 | % 17 | % Leander de Kraker 18 | % 2023-8-6 19 | % 20 | %% 21 | 22 | plotting = false; 23 | bestS = []; 24 | bestMethod = []; 25 | trans = false; 26 | 27 | if exist('varargin', 'var') 28 | if nargin>1 && ~isempty(varargin{1}) 29 | bestS = varargin{1}; 30 | end 31 | if nargin>2 && ~isempty(varargin{2}) 32 | bestMethod = varargin{2}; 33 | else 34 | bestMethod = 1; 35 | end 36 | if nargin==4 && ~isempty(varargin{3}) 37 | plotting = varargin{3}; 38 | end 39 | if nargin==5 && ~isempty(varargin{4}) 40 | trans = varargin{4}; 41 | if strcmpi(trans, 'horizontal') 42 | trans = false; 43 | else 44 | trans = true; 45 | end 46 | end 47 | end 48 | 49 | if trans 50 | img = img'; 51 | end 52 | 53 | dims = size(img); 54 | dimsTake = [floor(dims(1)./2)*2, dims(2)]; % for check 55 | dimsScheck = [floor(dims(1)/2), dims(2)]; 56 | dimsS = [ceil(dims(1)/2), dims(2)]; 57 | 58 | if isempty(bestS) % Do check of how best to shift the lines 59 | s = -5:5; 60 | b = max(s); 61 | bt = b*2; 62 | n = length(s); 63 | p = zeros(n, 2); 64 | 65 | imgRest = img(2:2:end, bt:end-bt); 66 | dimsRest = size(imgRest); 67 | 68 | % shifting simply 69 | for i = 1:n 70 | imgS = img(1:2:dimsTake(1), s(i)+bt:end-bt+s(i)); 71 | p(i,1) = corr(imgRest(:), imgS(:)); 72 | 73 | if plotting 74 | imgRecon = zeros(dimsTake(1), dimsRest(2)); 75 | imgRecon(2:2:end, :) = imgRest; imgRecon(1:2:end, :) = imgS; 76 | subplot(4,1,[1 3]); imagesc(imgRecon(1:end/3,:)) 77 | title(sprintf('shifting %d', s(i))) 78 | subplot(4,1,4); imagesc(s, [1 2], p'); 79 | title(p(i,1)) 80 | end 81 | end 82 | % Resizing to the right 83 | imgRest = img(2:2:end, :); 84 | for i = 1:b+1 85 | imgS = imresize(img(1:2:dimsTake(1), 1:end+s(i)), dimsScheck); 86 | p(i,2) = corr(imgRest(:), imgS(:)); 87 | 88 | if plotting 89 | imgRecon = zeros(dimsTake); imgRecon(2:2:end, :) = imgRest; imgRecon(1:2:end, :) = imgS; 90 | subplot(4,1,[1 3]); imagesc(imgRecon(1:end/3,:)) 91 | title(sprintf('resizing to right %d', -s(i))) 92 | subplot(4,1,4); imagesc(s, [1 2], p'); colorbar 93 | title(p(i,2)); pause 94 | end 95 | end 96 | % Resizing to the left 97 | for i = 1:b 98 | imgS = imresize(img(1:2:dimsTake(1), 1+i:end), dimsScheck); 99 | p(i+b+1, 2) = corr(imgRest(:), imgS(:)); 100 | 101 | if plotting 102 | imgRecon = zeros(dimsTake); imgRecon(2:2:end, :) = imgRest; imgRecon(1:2:end, :) = imgS; 103 | subplot(4,1,[1 3]); imagesc(imgRecon(1:end/3,:)) 104 | title(sprintf('resizing to left %d', s(b+i+1))) 105 | subplot(4,1,4); imagesc(s, [1 2], p'); colorbar 106 | title(p(i+b+1,2)); pause 107 | end 108 | end 109 | 110 | [bestp, bestpidx] = max(p(:)); 111 | [bestS, bestMethod] = ind2sub(size(p), bestpidx); 112 | bestS = s(bestS); 113 | end 114 | 115 | if bestS~=0 116 | if bestMethod == 1 % Using shifting 117 | if bestS<0 118 | img(1:2:end, -bestS+1:end) = img(1:2:end, 1:end+bestS); 119 | else 120 | img(1:2:end, 1:end-bestS) = img(1:2:end, 1+bestS:end); 121 | end 122 | else % Using shifting-resizing 123 | if bestS<0 124 | img(1:2:end, :) = imresize(img(1:2:end, 1:end+bestS), dimsS); 125 | else 126 | img(1:2:end, :) = imresize(img(1:2:end, bestS:end), dimsS); 127 | end 128 | end 129 | end 130 | 131 | if trans 132 | img = img'; 133 | end 134 | -------------------------------------------------------------------------------- /util/dep/Showsbx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Untitled Document 6 | 7 | 8 | 9 |
10 |

Showsbx 11 |

12 |

Showsbx is used to display image sequences recorded with a neurolabware 2 photon microscoop. Sbx files contain image data in a continuous binary format and to open and display the images, the program needs to import parameters form an accompanying mat file with the same file name.

13 |

Showsbx can display individual images at any position or as a movie if you press the run button. It also can display different channels if you press the chan button in the lower right corner. However only one channel can be displayed at the same time.

14 |

If the mmage data contains several depth sections, it will try to import the the neccessary parameters to slice the data appropriately, and you are given the choice to select one depth.

15 |

Pressing the right mouse button on the image area opens a context menu giving you two menu choices.

16 |

The first gives you the possibility to delete the frame presently diplayed (Deleting a frame involves rewriting the whole file exluding the selected frame which can take a lot of time!!).

17 |

With the second item you can change the data value range that is diplayed (effectively changing brightness and contrast of the images).

18 |

Below the menu bar is a series of tools for cropping, averging, splitting, aligning, exporting the signal from a selected region and to export an mp4 movie.

19 |

toolbar

20 |

The cropping tool allows you to select a square region within the images. This has no immediate effect, but the values saved will be used to crop each image when aligning the images.

21 |

Average The averging tool allows you to average a selected number of images beginning at the image displayed.

22 |

The splitting tool is used to split the image sequences in separate files for each imaging depth (this has become obsolete because a selected depth can be directly exported to Normcorre).

23 |

Align The align tool calls Normcorre, developed by the Simons foundation, to align the images after selecting a depth and defining the optimal crop.

24 |

The export ROI signal tool is used to export the signal of a selected region to the matlab work space. After pressing this button an area selector is shown that can be used to select a desired region. After clicking in this region the signal is exported.

25 |

Movie The movie button simply converts the image sequence at the selected depth, cropped and with the contrast and brightness presently selected to an mp4 movie file.

26 |

 

27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /util/dep/SortROIsMask.m: -------------------------------------------------------------------------------- 1 | function Mask = SortROIsMask(Mask, idx) 2 | % Re-Sort the ROIs in Mask and PP 3 | % [Mask, PP] = RemoveROIs(Mask, PP, badROIs) 4 | % 5 | % Input: 6 | % Mask - a 2D ROI Mask. 7 | % idx ([n x 1] double) - numbers indicating how to sort the ROIs 8 | % 9 | % Output: 10 | % Mask - Updated Mask. 11 | % 12 | % Leander de Kraker 13 | % 2023-9-6 14 | % 15 | 16 | 17 | maskNew = zeros(size(Mask)); 18 | for i = 1:length(idx) 19 | maskNew(Mask==i) = idx(i); 20 | end 21 | 22 | 23 | -------------------------------------------------------------------------------- /util/dep/SortROIsPP.m: -------------------------------------------------------------------------------- 1 | function PP = SortROIsPP(PP, idx) 2 | % Re-Sort the ROIs in Mask and PP 3 | % [Mask, PP] = RemoveROIs(Mask, PP, badROIs) 4 | % 5 | % Input: 6 | % PP - The standard ROI information struct from SpecSeg 7 | % idx ([n x 1] double) - numbers indicating how to sort the ROIs 8 | % 9 | % Output: 10 | % PP - Updated ROI information struct 11 | % 12 | % Leander de Kraker 13 | % 2023-9-6 14 | % 15 | 16 | 17 | PP.Con = PP.Con(idx); 18 | PP.A = PP.A(idx); 19 | PP.P = PP.P(:,idx); 20 | if isfield(PP, 'SpecProfile') 21 | PP.SpecProfile = PP.SpecProfile(idx); 22 | end 23 | if isfield(PP, 'peakFreq') 24 | PP.peakFreq = PP.peakFreq(idx); 25 | end 26 | if isfield(PP, 'peakVal') 27 | PP.peakVal = P.peakVal(idx); 28 | end 29 | if isfield(PP, 'Roundedness') 30 | PP.Roundedness = PP.Roundedness(idx); 31 | end 32 | if isfield(PP, 'Rvar') 33 | PP.Rvar = PP.Rvar(idx); 34 | end 35 | if isfield(PP, 'creationMethod') 36 | PP.creationMethod = PP.creationMethod(idx); 37 | end 38 | PP.Cnt = size(PP.P, 2); 39 | 40 | 41 | -------------------------------------------------------------------------------- /util/dep/SpatialCorrCalcFun.m: -------------------------------------------------------------------------------- 1 | function [cor, roiidx, r2] = SpatialCorrCalcFun(sbxt, freq, mask, roiNr, originPos, varargin) 2 | % [cor, roiidx, rvar] = SpatialCorrCalcFun(sbxt, freq, mask, roiNr, originPos, true) 3 | % Calculate the spatial corr of a ROI: correlation of the signal of 4 | % individual pixels with the signal of the median of 9 central ROI pixels 5 | % 6 | % Can also calculate the square of the correlation! 7 | % 8 | % inputs: 9 | % sbxt: transposed memorymapped sbxt from transmemap(transfile), 10 | % freq: 1x1 double, acuisition frequency of 2P data 11 | % mask: 2D double [height x width], the positions/ id's of ROIs 12 | % roiNr: which ROI to calculate the spatialcorr etc from 13 | % originPos: 1D vector [2 x 1] or 2D double [2 x nROIs] which x & y 14 | % coordinates are the 'origin position' 15 | % calcRvar (optional): boolean: true = return rvar 16 | % false = don't calculate rvar (default) 17 | % 18 | % outputs: 19 | % cor: 2D double, contains the correlation values, same size as mask 20 | % roiidx: the 1D indexes of where the ROI is located 21 | % rvar: variance of correlation values, after median filtering 22 | % 23 | % 24 | % Leander de Kraker 25 | % 2020-1-20 26 | % 27 | 28 | % Get whether to calculate rvar or not 29 | if nargin == 6 30 | calcR2 = varargin{1}; 31 | else 32 | calcR2 = false; 33 | end 34 | 35 | % Check if we got the actual coordinates for this ROI, or all coordinates 36 | if size(originPos, 1)>1 && size(originPos, 2)>1 37 | % Check if we need to transpose the coordinates... 38 | if size(originPos, 2)==2 && size(originPos, 1)>2 39 | originPos = originPos'; 40 | end 41 | originPos = originPos([1 2], roiNr); 42 | end 43 | 44 | % And round the coordinates to integers 45 | originPos = round(originPos); 46 | 47 | 48 | maskT = mask'; 49 | roiidx = find(maskT==roiNr); % The 2D indexes of the ROI, from transposed mask 50 | sigs = sbxt.Data.y(:,roiidx); % signal of all the pixels in the ROI 51 | 52 | % subsample the signal to ~1 sample / sec if the frequency is higher 53 | freq = floor(freq); 54 | if freq > 1.5 55 | sigSubsampled = zeros(ceil(size(sigs,1)/freq), size(sigs,2)); 56 | for q = 1:size(sigs,2) 57 | sigSubsampled(:,q) = decimate(double(sigs(:,q)), freq); 58 | end 59 | sigs = sigSubsampled; 60 | clearvars sigSubsampled 61 | end 62 | 63 | % Get the origin point of the ROI with 8 surrounding pixels: seedpixels 64 | seed = zeros(size(maskT), 'logical'); 65 | seedy = originPos(1)-1:originPos(1)+1; 66 | seedx = originPos(2)-1:originPos(2)+1; 67 | seedy(seedy<1 | seedy>size(maskT,1)) = []; % remove indexes that are outside mask 68 | seedx(seedx<1 | seedx>size(maskT,2)) = []; 69 | seed(seedy, seedx) = true; 70 | seedidx = find(seed); 71 | [~, seedidx] = intersect(roiidx, seedidx); % exlude pixels outside ROI 72 | 73 | % take median of signal seedpixels to reduce noise 74 | seedSig = median(sigs(:,seedidx), 2); 75 | 76 | % Fill the spatial correlation image with the correlation values 77 | cor = zeros(size(maskT)); 78 | cor(roiidx) = corr(seedSig, sigs, 'rows', 'pairwise'); 79 | 80 | 81 | % Calculate the mean R squared 82 | if calcR2 83 | thr = 0.5 * max(abs(cor(:))); 84 | if thr < 0.5 85 | %smooth with median filter, since with lower cutoff more variable 86 | %correlations are included leading to noisy contours 87 | m = floor((1-thr)*3)* 2 + 1; % let median filter depend on threshold height 88 | corFiltered = medfilt2(cor, [m m]); 89 | else 90 | corFiltered = cor; 91 | end 92 | r2 = mean(corFiltered(roiidx).^2); 93 | else 94 | r2 = nan; 95 | end 96 | 97 | % Transpose to the original size 98 | cor = cor'; 99 | roiidx = find(mask==roiNr); % The 2D indexes of the ROI 100 | 101 | -------------------------------------------------------------------------------- /util/dep/SpecProfileCalcFun.m: -------------------------------------------------------------------------------- 1 | function [specProfiles, peakFreq, peakVal] = SpecProfileCalcFun(spec, mask, rois, specAx) 2 | % specProfiles = SpecProfileCalcFun(spec, mask, specAx) calculates the 3 | % spectral profiles for all the ROIs in the mask. 4 | % [specProfiles, peakFreq] = SpecProfileCalcFun(spec, mask, specAx) also 5 | % returns the frequency which has the highest spectral power values for 6 | % each ROI in peakFreq 7 | % 8 | % This function can be executed via SpecProfileCalcRun.m 9 | % 10 | % inputs: 11 | % spec: spectral components: 3D matrix [width x height x frequency] 12 | % The 0Hz component should be removed to conform with standard way 13 | % mask: 2D double: with ROI IDs [height x width] 14 | % rois: 1D double: which rois to analyze? 15 | % specAx: spectral axis: 1D double with the frequency of each spectral 16 | % component (0 Hz should already be removed) 17 | % 18 | % outputs: 19 | % specProfiles: 2D double [frequency x ROIs], with the average spectral 20 | % power of each ROI for all the frequencies (except 0Hz). 21 | % peakFreq: 1D double [ROIs] with the frequency at which each the 22 | % spectral power was highest. 23 | % 24 | % 25 | % Leander de Kraker 26 | % 2020-1-21 27 | % Adapted , added smoothing 28 | % Chris van der togt 29 | % 2020-4-30 30 | 31 | % Does the spec need transposing (permuting)? 32 | if size(spec, 1) ~= size(mask, 1) 33 | if size(spec, 1) == size(mask, 2) 34 | fprintf('permuted spec to enable analysis\n') 35 | spec = permute(spec, [2 1 3]); 36 | else 37 | warning('sizes of spec and mask seem incompatible!') 38 | return 39 | end 40 | end 41 | 42 | nSpec = size(spec, 3); 43 | nRois = length(rois); 44 | 45 | if length(specAx) ~= nSpec 46 | warning('difference between spectral frequency axis and spec 3rd dimension!') 47 | end 48 | 49 | 50 | SP = reshape(spec, [], nSpec); 51 | % Retrieve the spectral profiles 52 | specProfiles = zeros(nSpec, nRois); 53 | for i = 1:nRois 54 | roii = mask == rois(i); 55 | roii = roii(:); 56 | spfl = SP(roii, :); 57 | specProfiles(:,i) = mean(spfl); 58 | end 59 | 60 | % Calculate which frequency had the highest spectral power values 61 | [peakVal, peakFreqidx] = max(smoothG(specProfiles,2)); 62 | peakFreq = specAx(peakFreqidx); 63 | 64 | 65 | -------------------------------------------------------------------------------- /util/dep/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/util/dep/a.png -------------------------------------------------------------------------------- /util/dep/cmapLimsAround0.m: -------------------------------------------------------------------------------- 1 | function extend = cmapLimsAround0(img, n) 2 | % extend = cmapLimsAround0(img, n) 3 | % Get how many colors should be used for which color to center the colors 4 | % around the value 0 of the img 5 | % 6 | % input: 7 | % - img (xD double): data to base colormap around 8 | % - n (number of colors in colormap) 9 | % 10 | % Output: 11 | % - extend ([n-1 x 1] double): amount of colors to take for each 12 | % 13 | % Example: 14 | % img = randn(25,25)+2; 15 | % colors1 = [0 1 0; 0 0 0; 1 0 0]; 16 | % n1 = 3; 17 | % 18 | % n = cmapLimsAround0(img, n1); % Get how many colors to take for each color 19 | % colorsMap = cmapL(colors1, n); % Use that to get the colormap 20 | % imagesc(img) 21 | % colormap(colorsMap); 22 | % colorbar 23 | % % Another set of colors 24 | % colors1 = 'blue roast'; % italian roast has 7 colors 25 | % n1 = 7; 26 | % n = cmapLimsAround0(img, n1); % Get how many colors to take for each color 27 | % colorsMap = cmapL(colors1, n); 28 | % colormap(colorsMap) 29 | % 30 | % Leander de Kraker 31 | % 2024-4-23 32 | % 33 | 34 | extend = [max(img(:)), min(img(:))]; 35 | extend = abs(round(extend./abs(diff(extend)).*256)); 36 | if n > 3 37 | n = floor(n/2); 38 | extend = floor([repmat(extend(1), [1 n]), repmat(extend(2),[1 n])]./n); 39 | end -------------------------------------------------------------------------------- /util/dep/figtitle.m: -------------------------------------------------------------------------------- 1 | function [ fth ] = figtitle(titlestring,varargin) 2 | % FIGTITLE creates a title centered at the top of a figure. This may be used 3 | % to add a title to a figure with several subplots. 4 | % 5 | % 6 | %% Syntax 7 | % 8 | % figtitle('TitleString') 9 | % figtitle('TitleString','TextProperty','TextValue') 10 | % h = figtitle(...) 11 | % 12 | % 13 | %% Description 14 | % 15 | % figtitle('TitleString') centers a title at the top of a figure and sets 16 | % the figure name to TitleString. 17 | % 18 | % figtitle('TitleString','TextProperty',TextValue) formats the title with 19 | % property name value pairs (e.g., 'FontSize',20) 20 | % 21 | % h = figtitle(...) returns a handle of the newly-created title. 22 | % 23 | %% EXAMPLE 1: 24 | % 25 | % x = 1:.01:7; 26 | % y = sin(x); 27 | % 28 | % figure; 29 | % subplot(2,2,1) 30 | % plot(3*x,y) 31 | % title('Exp. 1') 32 | % 33 | % subplot(2,2,2) 34 | % plot(x,2*y+x) 35 | % title('Exp. 2') 36 | % 37 | % subplot(2,2,3) 38 | % plot(x,y) 39 | % title('Exp. 3') 40 | % 41 | % subplot(2,2,4) 42 | % plot(x,2*y) 43 | % title('Exp. 4') 44 | % 45 | % figtitle('My Experimental Results','fontweight','bold'); 46 | % 47 | %% EXAMPLE 2: A prettier example using ntitle: 48 | % 49 | % x = 1:.01:7; 50 | % y = sin(x); 51 | % 52 | % figure; 53 | % subplot(2,2,1) 54 | % plot(3*x,y) 55 | % ntitle('experiment 1','fontsize',12) 56 | % box off 57 | % 58 | % subplot(2,2,2) 59 | % plot(x,2*y+x) 60 | % ntitle('experiment 2','fontsize',12) 61 | % box off 62 | % 63 | % subplot(2,2,3) 64 | % plot(x,-y+5*x) 65 | % ntitle('experiment 3','fontsize',12) 66 | % box off 67 | % 68 | % subplot(2,2,4) 69 | % plot(x,2*y-3*x) 70 | % ntitle('experiment 4','fontsize',12); 71 | % box off 72 | % 73 | % figtitle(' My Experimental Results') 74 | % 75 | % * * * * * * * * * * * * * * * * * * * * * * * * * * * * * % 76 | % 77 | % In many cases a figure title may overlap a subplot title 78 | % To reduce the possibility of a figure title overlapping subplot 79 | % titles, try pairing this function with the ntitle function, which 80 | % is available on the Mathworks File Exchange here: 81 | % http://www.mathworks.com/matlabcentral/fileexchange/42114-ntitle 82 | % 83 | % 84 | % * * * * * * * * * * * * * * * * * * * * * * * * * * * * * % 85 | % Written by Chad A. Greene of the University of Texas at Austin 86 | % Institute for Geophysics, July 2013. 87 | % 88 | % Updated August 2014 to include support for invisible figures 89 | % and now also sets the figure name to the title string. 90 | % 91 | % * * * * * * * * * * * * * * * * * * * * * * * * * * * * * % 92 | % 93 | % See also title, text, and ntitle. 94 | 95 | 96 | % Get the handle of the current axes and properties: 97 | hca = gca; 98 | fontsize = get(hca,'fontsize'); 99 | 100 | % Create a new set of axes the size of the entire figure: 101 | h = axes('position',[0 0 1 1],'units','normalized'); 102 | 103 | axes('Units','normalized',... 104 | 'Position',[0 0 1 1],... 105 | 'Visible','off',... 106 | 'XTick',[],... 107 | 'YTick',[],... 108 | 'Box','off'); 109 | 110 | % Make a title: 111 | fth = text(.5,1,titlestring,... 112 | 'units','normalized',... 113 | 'horizontalalignment','center',... 114 | 'verticalalignment','top',... 115 | 'fontsize',fontsize+2); 116 | 117 | % Set optional inputs: 118 | if nargin>1 119 | set(fth,varargin{:}); 120 | end 121 | 122 | % Now go back to from where we came: 123 | delete(h) 124 | 125 | set(gcf,'CurrentAxes',hca,'name',titlestring); 126 | 127 | % Return the title handle only if it is desired: 128 | if nargout==0 129 | clear fth; 130 | end 131 | 132 | end 133 | 134 | -------------------------------------------------------------------------------- /util/dep/getSystemMem.m: -------------------------------------------------------------------------------- 1 | function SysMem = getSystemMem() 2 | % get available memory 3 | 4 | SysMem = []; 5 | archstr = computer('arch'); 6 | %only for fwindows available 7 | if strcmp(archstr, 'win64') 8 | usr = memory(); 9 | SysMem = usr.MemAvailableAllArrays; 10 | 11 | elseif strcmp(archstr, 'glnxa64') 12 | [~, Memstr] = system("free -b | awk '/^Mem/ {print $4}'"); 13 | SysMem = str2double(Memstr); 14 | 15 | elseif strcmp(archstr, 'maci64') 16 | [~, Memstr] = system("sysctl hw.memsize | awk '{print $2}'"); 17 | SysMem = str2double(Memstr); 18 | end -------------------------------------------------------------------------------- /util/dep/iconvideo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/util/dep/iconvideo.png -------------------------------------------------------------------------------- /util/dep/largestmemblock.m: -------------------------------------------------------------------------------- 1 | function largestmemblock(varargin) 2 | % LARGESETMEMBLOCK(VERBOSITY,PRECISION) 3 | % Finds (roughly) the largest memory block available by 4 | % trying to allocate successively larger contiguous blocks of memory. 5 | % Precise roughly to about 90% of the largest memory block available. 6 | % 7 | % Arguments: 8 | % VERBOSITY: '-v' flag. Specify all iterations tried 9 | % PRECISION: Fraction between [0.7, 0.9999]. 10 | % Value closer to 0.7 return a quicker result, but up to 70% precision 11 | % Value closer to 1 returns a more precise result, but takes much 12 | % longer to converge 13 | % Default is 0.95 14 | % 15 | % Not as accurate as feature('memstats'), but useful as an approximation 16 | % on 32-bit and 64-bit Mac and Linux distributions 17 | % 18 | % % No verbosity 19 | % >> largestmemblock 20 | % 21 | % % Verbose output 22 | % >> largestmemblock('-v') 23 | % 24 | % % More accurate estimate of largest memory block available, no verbosity 25 | % >> largestmemblock([],0.999) 26 | % 27 | % % More accurate value, longer execution time 28 | % 29 | % v1.0 - November 2009, Manu Raghavan 30 | 31 | if nargin>=1 && ~isempty(varargin{1}) 32 | verbosity = true; 33 | else 34 | verbosity = false; 35 | end 36 | 37 | precision = 0.95; 38 | if nargin==2 39 | precision = varargin{2}; 40 | if(precision>0.9999 || precision<0.7) 41 | error('Optional second argument PRECISION must range between 0.7 and 0.9999'); 42 | end 43 | end 44 | 45 | mexExtension = mexext; 46 | 47 | if (strcmp(mexExtension,'mexglx') || ... 48 | strcmp(mexExtension,'mexmaci') || ... 49 | strcmp(mexExtension,'mexw32')) 50 | % Initial size 51 | B = intmax('int32'); %2 Gigabytes 52 | end 53 | 54 | if (strcmp(mexExtension,'mexa64') || ... 55 | strcmp(mexExtension,'mexmaci64') || ... 56 | strcmp(mexExtension,'mexw64')) 57 | % Initial size 58 | %B = 8*2^40; %8 Terabytes 59 | B = 60*2^30; %8 Gigabytes 60 | end 61 | 62 | % Iterative memory allocation attempts 63 | while true 64 | try 65 | if(verbosity) 66 | fprintf(1,'Trying to allocate %d KB.', B/1024); 67 | end 68 | A = zeros(round(B), 1, 'uint8'); 69 | break; 70 | catch ME 71 | if(verbosity) 72 | fprintf(2,'\n Unsuccessful. Reducing block size and trying again...\n'); 73 | end 74 | % Rethrow any non-out-of-memory errors 75 | if ~strcmp(ME.identifier, 'MATLAB:nomem'); 76 | rethrow(ME); 77 | end 78 | end 79 | % Reduce by a factor of 10% and try again 80 | B = B*precision; 81 | end 82 | 83 | % Report the results 84 | fprintf(... 85 | '\nMaximum contiguous block is approximately:\n (Accurate to %2.2f %% of real memory value)\n %15.0f KB\n %15.0f MB\n', ... 86 | precision*100, B/1024, B/(1024^2)); 87 | 88 | % Clear the big variable 89 | clear A 90 | -------------------------------------------------------------------------------- /util/dep/license_xcorr2_ftt.txt: -------------------------------------------------------------------------------- 1 | Alessandro Masullo (2020). xcorr2_fft(a,b) (https://www.mathworks.com/matlabcentral/fileexchange/53570-xcorr2_fft-a-b), MATLAB Central File Exchange. Retrieved May 18, 2020. 2 | 3 | Copyright (c) 2015, Alessandro Masullo 4 | All rights reserved. 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the distribution 14 | * Neither the name of the University of Bristol nor the names 15 | of its contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /util/dep/prctfilt.m: -------------------------------------------------------------------------------- 1 | function Y = prctfilt(X,p,window,shift,mode) 2 | 3 | % percentile filtering along the last dimension 4 | % INPUTS 5 | % X: input data 6 | % p: percentile 7 | % window: window over which to compute the percentile 8 | % shift: length of window shifting (default: window) 9 | % mode: if mode == 1 then returns Y - baseline, otherwise returns baseline 10 | 11 | % OUTPUT 12 | % Y: filtered version 13 | 14 | if nargin < 2 || isempty(p); p = 20; end 15 | if nargin < 3 || isempty(window); window = 200; end 16 | if nargin < 4 || isempty(shift); shift = 200; end 17 | if nargin < 5 || isempty(mode); mode = 1; end 18 | 19 | sizX = size(X); 20 | if ndims(X) == 1 21 | X = X(:)'; 22 | elseif ~ismatrix(X) 23 | X = reshape(X,[],sizX(end)); 24 | end 25 | 26 | window = min(window,sizX(end)); 27 | shift = min(shift,window); 28 | 29 | Xpad = [X(:,1:ceil((window-1)/2)),X,X(:,sizX(end) - (ceil((window-1)/2)-1:-1:0))]; 30 | 31 | blocks_end = window:shift:size(Xpad,2); 32 | blocks_start = 1:shift:size(Xpad,2); 33 | ln = length(blocks_end); 34 | blocks_start(ln+1:end) = []; 35 | 36 | Xpcs = zeros(size(Xpad,1),ln); 37 | for i = 1:ln 38 | Xpcs(:,i) = prctile(Xpad(:,blocks_start(i):blocks_end(i)),p,2); 39 | end 40 | 41 | dx = diff(Xpcs,1,2); 42 | 43 | Xf = kron(Xpcs(:,1:end-1),ones(1,shift)) + kron(dx,1/shift*(0:shift-1)); 44 | Xf = padarray(Xf,[0,size(X,2)-shift*(ln-1)],'post','symmetric'); 45 | if mode == 1 46 | Y = X - Xf; 47 | else 48 | Y = Xf; 49 | end 50 | Y = reshape(Y,sizX); -------------------------------------------------------------------------------- /util/dep/sbxread.m: -------------------------------------------------------------------------------- 1 | function x = sbxread(fname,k,N,varargin) 2 | 3 | % img = sbxread(fname,k,N,varargin) 4 | % 5 | % Reads from frame k to k+N-1 in file fname 6 | % 7 | % fname - the file name (e.g., 'xx0_000_001') 8 | % k - the index of the first frame to be read. The first index is 0. 9 | % N - the number of consecutive frames to read starting with k. 10 | % 11 | % If N>1 it returns a 4D array of size = [#pmt rows cols N] 12 | % If N=1 it returns a 3D array of size = [#pmt rows cols] 13 | % 14 | % gpu version [rows cols #pmt N] 15 | % 16 | % #pmts is the number of pmt channels being sampled (1 or 2) 17 | % rows is the number of lines in the image 18 | % cols is the number of pixels in each line 19 | % 20 | % 21 | % The function also creates a global 'info' variable with additional 22 | % informationi about the file 23 | 24 | global info 25 | 26 | persistent Perm Shape 27 | 28 | 29 | % check if already loaded... 30 | if isempty(info) || (~isempty(info) && ~strcmp(fname, info.strfp)) 31 | if ~isempty(info) 32 | try 33 | fclose(info.fid); 34 | catch 35 | end 36 | info = []; 37 | end 38 | 39 | load(fname); 40 | info.strfp = fname; 41 | 42 | % if(exist([fname ,'.align'])) % aligned? 43 | % info.aligned = load([fname ,'.align'],'-mat'); 44 | % else 45 | % info.aligned = []; 46 | % end 47 | 48 | if(~isfield(info,'sz')) 49 | info.sz = [512 796]; % it was only sz = .... 50 | end 51 | 52 | switch info.channels 53 | case 1 54 | info.nchan = 2; % both PMT0 & 1 55 | case 2 56 | info.nchan = 1; % PMT 0 57 | case 3 58 | info.nchan = 1; % PMT 1 59 | end 60 | 61 | 62 | if ~isfield(info,'Perm') 63 | Perm = [1 3 2 4]; %1st dim is channel 64 | Shape = [info.nchan info.sz(2) info.sz(1)]; 65 | if info.scanbox_version == 2.5 || isfield(info, 'simon') %gpu or processed 66 | Perm = [2 1 3 4]; %3rd dim is channel 67 | Shape = [info.sz(2) info.sz(1) info.nchan]; 68 | end 69 | info.Perm = Perm; 70 | info.Shape = Shape; 71 | else 72 | if length(info.Perm) == 3 %there is a bug somewhere! 73 | disp('info.Perm was incorrect!!') 74 | info.Perm = [info.Perm 4]; 75 | % save(fname, 'info'); 76 | end 77 | Perm = info.Perm; 78 | Shape = info.Shape; 79 | end 80 | 81 | info.fid = fopen([fname '.sbx']); 82 | d = dir([fname '.sbx']); 83 | info.max_idx = round(d.bytes/info.sz(2)/info.sz(1)/info.nchan/2); 84 | info.nsamples = (info.sz(2) * info.sz(1) * 2 * info.nchan); % bytes per frame 85 | 86 | elseif isempty(Perm) || isempty(Shape) 87 | Perm = info.Perm; 88 | Shape = info.Shape; 89 | end 90 | 91 | if(isfield(info,'fid') && info.fid ~= -1 && k + N > 0) 92 | 93 | % nsamples = info.postTriggerSamples * info.recordsPerBuffer; 94 | try 95 | fseek(info.fid,k*info.nsamples,'bof'); 96 | x = fread(info.fid,info.nsamples/2 * N,'uint16=>uint16'); 97 | %changed for gpu version 98 | x = reshape(x,[Shape N]); 99 | 100 | catch 101 | error('Cannot read frame. Index range likely outside of bounds.'); 102 | end 103 | %changed for gpu version 104 | if isfield(info, 'simon') 105 | x = permute(x,Perm); 106 | else 107 | x = intmax('uint16')-permute(x,Perm); 108 | end 109 | 110 | else 111 | x = []; 112 | end -------------------------------------------------------------------------------- /util/dep/sbxsigout.m: -------------------------------------------------------------------------------- 1 | function sbxsigout(~,~) 2 | 3 | global info 4 | persistent Sbx filenm 5 | 6 | h = imrect(); 7 | pos = round(wait(h)); 8 | x = pos(1):pos(1)+pos(3); 9 | y = pos(2):pos(2)+pos(4); 10 | 11 | dim = [info.Shape, info.max_idx]; 12 | 13 | disp('Memory mapping file.....') 14 | if isempty(Sbx) || ~strcmp(filenm, info.strfp) 15 | Sbx = memmapfile([info.strfp '.sbx'], 'Format',{'uint16', dim, 'Y'}, 'Writable', true); 16 | filenm = info.strfp; 17 | end 18 | 19 | disp('Retrieving data....') 20 | if dim(1) < 3 21 | Sig = squeeze(mean(mean(Sbx.Data.Y(:,x,y,:),3),2)); 22 | else 23 | Sig = squeeze(mean(mean(Sbx.Data.Y(x,y,:,:),2))); 24 | end 25 | 26 | if ~isfield(info, 'simon') 27 | Sig = double(intmax('uint16'))- Sig; 28 | end 29 | if size(Sig,1) < size(Sig,2) 30 | Sig = Sig'; %put signal on first dim 31 | end 32 | 33 | if info.bsplit 34 | disp('Splitting signals....') 35 | S = cell(info.Slices,1); 36 | for i = 1:info.Slices 37 | S{i} = Sig(i:info.Slices:end,:); 38 | end 39 | Sig = S; 40 | end 41 | disp('Done') 42 | 43 | % tic 44 | % Sig1 = zeros(info.max_idx,1); 45 | % for i = 0:info.max_idx-1 46 | % Img = sbxread(fn, i,1); 47 | % if dim(1) < 3 48 | % Sig1(i+1) = mean(mean(Img(:,y,x),3),2); 49 | % else 50 | % Sig1(i+1) = mean(mean(Img(y,x,:),2)); 51 | % end 52 | % end 53 | % toc 54 | 55 | assignin('base', 'Sig', Sig) 56 | 57 | delete(h) 58 | 59 | -------------------------------------------------------------------------------- /util/dep/sbxsplit.m: -------------------------------------------------------------------------------- 1 | function sbxsplit(~,~,info, fn) 2 | % Split an sbx file into multiple sbx files, for different depths 3 | 4 | %[fn, pn] = uigetfile('*.mat'); 5 | % sbxread(fn, 0, 1); %gets info and intializes other parameters 6 | 7 | def = {'2', num2str(info.max_idx)}; 8 | if isfield(info, 'otparam') 9 | try 10 | def{1} = num2str(info.otparam(3)); 11 | disp(['This stack contains ' num2str(info.otparam(3)) ' depth slices']) 12 | catch 13 | def{1} = '1'; 14 | end 15 | end 16 | prompt = {'Slices', 'Stacklength'}; 17 | dlg_title = 'Split Sbx file in slices:'; 18 | num_lines = [1 50]; 19 | 20 | answer = inputdlg(prompt,dlg_title,num_lines,def); 21 | if isempty(answer) 22 | return; %cancel button was pressed 23 | end 24 | 25 | nmslices = str2double(answer{1}); 26 | mxidx = str2double(answer{2}); 27 | 28 | 29 | stackln = floor(mxidx / nmslices); 30 | N = info.nchan; 31 | info.Slices = nmslices; 32 | 33 | savefl = zeros(nmslices,1); 34 | for i = 1:nmslices 35 | savefl(i) = fopen([fn '_split' num2str(i) '.sbx'], 'a'); 36 | end 37 | 38 | 39 | if(isfield(info,'fid') && info.fid ~= -1) 40 | strfn = strrep(fn, '\', '\\'); 41 | hl = waitbar(1/stackln, ['Slicing ' strfn]); 42 | for i = 1:stackln %the first image of the stack is always bad 43 | for j = 1:nmslices 44 | try %nsamples = number of bytes 45 | fseek(info.fid,(i*nmslices+j-1)*info.nsamples,'bof'); 46 | x = fread(info.fid,info.nsamples/2,'uint16=>uint16'); 47 | 48 | catch 49 | error('Cannot read frame. Index range likely outside of bounds.'); 50 | end 51 | 52 | fwrite(savefl(j), x, 'uint16'); 53 | end 54 | waitbar(i/stackln, hl); 55 | end 56 | end 57 | close(hl) 58 | 59 | info.max_idx = stackln-1; 60 | for i = 1:nmslices 61 | fclose(savefl(i)); 62 | info.Section = i; %which section was this 63 | save([fn '_split' num2str(i) ], 'info' ) 64 | end 65 | 66 | end 67 | 68 | -------------------------------------------------------------------------------- /util/dep/subtightplot.m: -------------------------------------------------------------------------------- 1 | function h=subtightplot(m,n,p,gap,marg_h,marg_w,varargin) 2 | %function h=subtightplot(m,n,p,gap,marg_h,marg_w,varargin) 3 | % 4 | % Functional purpose: A wrapper function for Matlab function subplot. Adds the ability to define the gap between 5 | % neighbouring subplots. Unfotrtunately Matlab subplot function lacks this functionality, and the gap between 6 | % subplots can reach 40% of figure area, which is pretty lavish. 7 | % 8 | % Input arguments (defaults exist): 9 | % gap- two elements vector [vertical,horizontal] defining the gap between neighbouring axes. Default value 10 | % is 0.01. Note this vale will cause titles legends and labels to collide with the subplots, while presenting 11 | % relatively large axis. 12 | % marg_h margins in height in normalized units (0...1) 13 | % or [lower uppper] for different lower and upper margins 14 | % marg_w margins in width in normalized units (0...1) 15 | % or [left right] for different left and right margins 16 | % 17 | % Output arguments: same as subplot- none, or axes handle according to function call. 18 | % 19 | % Issues & Comments: Note that if additional elements are used in order to be passed to subplot, gap parameter must 20 | % be defined. For default gap value use empty element- []. 21 | % 22 | % Usage example: h=subtightplot((2,3,1:2,[0.5,0.2]) 23 | 24 | if (nargin<4) || isempty(gap), gap=0.01; end 25 | if (nargin<5) || isempty(marg_h), marg_h=0.05; end 26 | if (nargin<5) || isempty(marg_w), marg_w=marg_h; end 27 | if isscalar(gap), gap(2)=gap; end 28 | if isscalar(marg_h), marg_h(2)=marg_h; end 29 | if isscalar(marg_w), marg_w(2)=marg_w; end 30 | gap_vert = gap(1); 31 | gap_horz = gap(2); 32 | marg_lower = marg_h(1); 33 | marg_upper = marg_h(2); 34 | marg_left = marg_w(1); 35 | marg_right = marg_w(2); 36 | 37 | %note n and m are switched as Matlab indexing is column-wise, while subplot indexing is row-wise :( 38 | [subplot_col,subplot_row]=ind2sub([n,m],p); 39 | 40 | % note subplot suppors vector p inputs- so a merged subplot of higher dimentions will be created 41 | subplot_cols=1+max(subplot_col)-min(subplot_col); % number of column elements in merged subplot 42 | subplot_rows=1+max(subplot_row)-min(subplot_row); % number of row elements in merged subplot 43 | 44 | % single subplot dimensions: 45 | %height=(1-(m+1)*gap_vert)/m; 46 | %axh = (1-sum(marg_h)-(Nh-1)*gap(1))/Nh; 47 | height=(1-(marg_lower+marg_upper)-(m-1)*gap_vert)/m; 48 | %width =(1-(n+1)*gap_horz)/n; 49 | %axw = (1-sum(marg_w)-(Nw-1)*gap(2))/Nw; 50 | width =(1-(marg_left+marg_right)-(n-1)*gap_horz)/n; 51 | 52 | % merged subplot dimensions: 53 | merged_height=subplot_rows*( height+gap_vert )- gap_vert; 54 | merged_width= subplot_cols*( width +gap_horz )- gap_horz; 55 | 56 | % merged subplot position: 57 | merged_bottom=(m-max(subplot_row))*(height+gap_vert) +marg_lower; 58 | merged_left=(min(subplot_col)-1)*(width+gap_horz) +marg_left; 59 | pos_vec=[merged_left merged_bottom merged_width merged_height]; 60 | 61 | % h_subplot=subplot(m,n,p,varargin{:},'Position',pos_vec); 62 | % Above line doesn't work as subplot tends to ignore 'position' when same mnp is utilized 63 | h=subplot('Position',pos_vec,varargin{:}); 64 | 65 | if (nargout < 1), clear h; end 66 | 67 | end 68 | -------------------------------------------------------------------------------- /util/dep/sum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/util/dep/sum.png -------------------------------------------------------------------------------- /util/dep/toolbar.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leveltlab/SpectralSegmentation/145eac1dc90475f0d0b06456a9fe386d8ef9e227/util/dep/toolbar.PNG -------------------------------------------------------------------------------- /util/dep/xcorr2_fft.m: -------------------------------------------------------------------------------- 1 | function c = xcorr2_fft(a,b) 2 | %XCORR2_FFT Two-dimensional cross-correlation evaluated with FFT algorithm. 3 | % XCORR2_FFT(A,B) computes the cross-correlation of matrices A and B. 4 | % XCORR2(A) is the autocorrelation function. 5 | % 6 | % When matrices A and B are real, XCORR2_FFT is numerically equivalent to 7 | % XCORR2 but much faster. 8 | % 9 | % % Example: 10 | % a = rand(122); b=rand(332); 11 | % a = a-mean(a(:)); 12 | % b = b-mean(b(:)); 13 | % 14 | % tic,cl = xcorr2(a,b);toc 15 | % Elapsed time is 0.223502 seconds. 16 | % tic,cf = xcorr2_fft(a,b);toc 17 | % Elapsed time is 0.030935 seconds. 18 | % 19 | % max(abs(cf(:)-cl(:))) 20 | % ans = 4.1922e-13 21 | % 22 | % Author: Alessandro Masullo, 2015 23 | % Version 1.2 24 | % 25 | % See also CONV2, XCORR, XCORR2 and FILTER2. 26 | 27 | if nargin == 1 28 | b = a; 29 | end 30 | 31 | % Matrix dimensions 32 | adim = size(a); 33 | bdim = size(b); 34 | % Cross-correlation dimension 35 | cdim = adim+bdim-1; 36 | 37 | bpad = zeros(cdim); 38 | apad = zeros(cdim); 39 | 40 | apad(1:adim(1),1:adim(2)) = a; 41 | bpad(1:bdim(1),1:bdim(2)) = b(end:-1:1,end:-1:1); 42 | ffta = fft2(apad); 43 | fftb = fft2(bpad); 44 | c = real(ifft2(ffta.*fftb)); -------------------------------------------------------------------------------- /util/sbx2ij.m: -------------------------------------------------------------------------------- 1 | % Chris van der Togt, 2017, 2 | % Netherlands Institute for Neuroscience 3 | 4 | %Miji 5 | %IJ = ij.IJ; 6 | 7 | [fn , pn] = uigetfile('*.sbx'); 8 | filename = strsplit(fn, '.'); 9 | strfp = [pn filename{1}]; 10 | sbxread(strfp, 0,1); 11 | global info 12 | 13 | d = dir([strfp '.sbx']); 14 | lngth = d.bytes/info.sz(2)/info.sz(1)/info.nchan/2; 15 | if isfield(info, 'Shape') && info.scanbox_version == 2 && info.nchan == 1 && ~isfield(info, 'simon') 16 | dim = info.Shape([3 2]); 17 | elseif isfield(info, 'Shape') 18 | dim = info.Shape([1 2]); 19 | else 20 | dim = info.sz; 21 | end 22 | 23 | if isfield(info, 'simon') %values have been subracted from maxint6 24 | IJ.run('Raw...', ['open=' strfp '.sbx image=[16-bit Unsigned] width=' num2str(dim(1)) ' height=' num2str(dim(2)) ' number=' num2str(lngth*info.nchan) ' little-endian use']); 25 | elseif info.scanbox_version== 2.5 26 | IJ.run('Raw...', ['open=' strfp '.sbx image=[16-bit Unsigned] width=' num2str(dim(1)) ' height=' num2str(dim(2)) ' number=' num2str(lngth*info.nchan) ' white little-endian use']); 27 | else 28 | IJ.run('Raw...', ['open=' strfp '.sbx image=[16-bit Unsigned] width=' num2str(dim(2)) ' height=' num2str(dim(1)) ' number=' num2str(lngth*info.nchan) ' white little-endian use']); 29 | end 30 | 31 | 32 | %has to be transposed for ImageJ 33 | % IStack = ij.ImageStack(info.sz(2), info.sz(1)); 34 | % 35 | % for i = 0:lngth 36 | % pixels = sbxread(strfp,i,1); 37 | % if info.nchan == 2 38 | % pixels = pixels(:,:,1); 39 | % end 40 | % pixels = pixels'; %transpose 41 | % ImageProc = ij.process.ShortProcessor( info.sz(2), info.sz(1)); 42 | % ImageProc.setPixels(pixels(:)); 43 | % 44 | % IStack.addSlice(num2str(i),ImageProc); 45 | % end 46 | % 47 | % IP = ij.ImagePlus('new', IStack); 48 | % IP.show() 49 | --------------------------------------------------------------------------------