├── LICENSE ├── README.md ├── README.mlx ├── README.pdf ├── artificial-calcium-fluorescence ├── ARTIFICIAL_CALCIUM_FLUORESCENCE_GENERATION.m ├── CALCIUM_FLUORESCENCE_CONVERSION.m ├── assembly-configurations │ ├── HEX12_K10_large.m │ ├── HEX12_K10_large_overlap.m │ ├── HEX12_K10_medium.m │ ├── HEX12_K10_medium_overlap.m │ ├── HEX12_K10_small.m │ ├── HEX12_K10_small_overlap.m │ ├── HEX12_K10_var.m │ ├── HEX12_varK_medium_N.m │ ├── HEX16_varK_large.m │ ├── HEX16_varK_medium.m │ ├── HEX16_varK_small.m │ ├── HEX5_K5_medium.m │ ├── HEXv_K0.m │ ├── HEXv_K10_large.m │ ├── HEXv_K10_medium.m │ ├── HEXv_K10_medium_N.m │ ├── HEXv_K10_small.m │ └── HEXv_K5_medium_N.m ├── generateArtificialCalciumFluorescence.m ├── inc_generateArtificialCalciumFluorescence │ └── HaasLab_fitF0smoother │ │ ├── KalmanAll │ │ ├── KPMstats │ │ │ └── gaussian_prob.m │ │ └── Kalman │ │ │ ├── kalman_filter.m │ │ │ ├── kalman_smoother.m │ │ │ ├── kalman_update.m │ │ │ └── smooth_update.m │ │ ├── README__KalmanAll │ │ ├── README__fitF0smoother │ │ └── fitF0smoother │ │ ├── estimatenoise.m │ │ └── fitF0smoother.m └── make-assembly-configurations │ ├── hexagonal_tiling.m │ └── random_assembly.m ├── assembly-detection ├── ASSEMBLIES_COLLECTION.m ├── CORE_ASSEMBLY_DETECTION.m ├── FIM_PSF_PSR_ASSEMBLY_DETECTION │ ├── README__psf+psr │ ├── parse_FIM_PSF_PSR_ASSEMBLIES.m │ ├── psf+psr │ │ ├── LICENSE │ │ ├── fim │ │ │ ├── patred.py │ │ │ ├── patspec.py │ │ │ └── pyfim.py │ │ └── psf+psr │ │ │ └── fim+psf+psr.py │ ├── py__FIM_PSF_PSR_ASSEMBLY_DETECTION.sh │ └── pyfim.tar.gz ├── ICA_ASSEMBLY_DETECTION.m ├── PROMAX_CS_ASSEMBLY_DETECTION.m ├── PROMAX_MP_ASSEMBLY_DETECTION.m ├── SGC_ASSEMBLY_DETECTION.m ├── SVD_ASSEMBLY_DETECTION.m ├── findCOREassemblies.m ├── findICAAssemblies.m ├── helper │ ├── interactive_PROMAX_ASSEMBLY_DETECTION.m │ └── interactive_PROMAX_ASSEMBLY_DETECTION_VALIDATION.m ├── inc_findICAAssemblies │ ├── README__toolbox │ └── toolbox │ │ ├── assembly_activity.m │ │ ├── assembly_patterns.m │ │ ├── bin_shuffling.m │ │ ├── caller_1.m │ │ ├── circular_shift.m │ │ ├── fast_ica.m │ │ └── toy_simulation.m ├── inc_findPROMAXAssemblies │ ├── CheckAssemblies.m │ ├── README__Toolbox-Romano-et-al │ └── Toolbox-Romano-et-al │ │ ├── AssembliesActivations.m │ │ ├── FindAssemblies.m │ │ ├── LICENSE │ │ └── pValueSynch.m ├── inc_findSGCAssemblies │ ├── analyseGraphCommunityStructure │ │ ├── analyseGraphCommunityStructure.m │ │ ├── computeGraphCommunityStructureMarginals.m │ │ ├── estimate.m │ │ ├── estimateGraphCommunityStructure.m │ │ ├── graph2NETWORK.m │ │ └── normalisePatternEnumeration.m │ ├── buildPatternSimilarityGraph.m │ ├── findAssemblyPatterns.m │ ├── inferAssemblyPatterns.m │ ├── meanActivityPattern.m │ ├── normalisePatternEnumeration.m │ ├── refreshAssemblyPatterns.m │ └── spectralclustering.m ├── inc_findSVDAssemblies │ ├── README__SVDEnsemble │ └── SVDEnsemble │ │ ├── LICENSE │ │ ├── README.md │ │ ├── SVDStateBinary.m │ │ ├── calcTFIDF.m │ │ ├── calc_jcut.m │ │ ├── calc_scut.m │ │ ├── findActiveFrames.m │ │ ├── findSVDensemble.m │ │ └── shuffle.m └── test__printAssemblies.m ├── calcium-fluorescence-processing ├── CALCIUM_FLUORESCENCE_PROCESSING.m ├── findDF_FSpikeProbability.m ├── findSignificantDF_FCoactivity.m ├── findSignificantFluorescenceTraces.m ├── inc_findDF_FSpikeProbability │ ├── README__oopsi │ └── oopsi │ │ ├── CONTRIBUTING │ │ ├── Hill_v1.m │ │ ├── LICENSE │ │ ├── README.md │ │ ├── demo.m │ │ ├── fast_oopsi.m │ │ ├── license.md │ │ ├── run_oopsi.m │ │ ├── smc_oopsi.m │ │ ├── smc_oopsi_backward.m │ │ ├── smc_oopsi_forward.m │ │ ├── smc_oopsi_m_step.m │ │ └── z1.m ├── inc_findSignificantDF_FCoactivity │ ├── README__peakfinder │ ├── findSignificantCoactivity.m │ └── peakfinder │ │ ├── LICENSE │ │ ├── README │ │ └── peakfinder.m └── inc_findSignificantFluorescenceTraces │ ├── README__Toolbox-Romano-et-al │ └── Toolbox-Romano-et-al │ ├── EstimateBaselineNoise.m │ ├── LICENSE │ ├── NoiseModel.m │ ├── Rasterize.m │ ├── SignificantOdds.m │ └── mygaussfit.m ├── examples ├── HEX5_K5_medium__T1800s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0.zip ├── HEX5_K5_medium__T1800s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0.zip.sha256 ├── ZEBRAFISH-9DPF.zip └── ZEBRAFISH-9DPF.zip.sha256 ├── include ├── bestmatch.m ├── bestmatch_expectation.m ├── cell_union.m ├── cross_evaluation.m ├── iif.m ├── io │ ├── printConsoleSection.m │ ├── print_progress.m │ ├── print_timeinterval.m │ └── read.m ├── math │ ├── largest_positive.m │ └── num_range.m └── random │ ├── seed_devrandom.m │ └── shuffle_vector.m └── scripts └── GENERATE_ALL_DATASETS.m /README.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoodhillLab/neural-assembly-detection/f5415317aec2cf141e8f48ef816cddac0547cac3/README.mlx -------------------------------------------------------------------------------- /README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoodhillLab/neural-assembly-detection/f5415317aec2cf141e8f48ef816cddac0547cac3/README.pdf -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/ARTIFICIAL_CALCIUM_FLUORESCENCE_GENERATION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = ARTIFICIAL_CALCIUM_FLUORESCENCE_GENERATION( output_directory , id , N_units , T_durationRange , dT_durationRange , assembly_configuration_list , i_assembly_configuration , calcium_T1_2Range , eventFreqRange , eventMultRange , noiseSTDRange , saturationKRange ) 2 | %ARTIFICIAL_CALCIUM_FLUORESCENCE_GENERATION( output_directory , id , N_units , T_durationRange , dT_durationRange , assembly_configuration_list , i_assembly_configuration , calcium_T1_2Range , eventFreqRange , eventMultRange , noiseSTDRange , saturationKRange ) 3 | % 4 | % PARAMETERS: 5 | % \_ output_directory: output directory for the calcium fluorescence dataset 6 | % \_ id: id (name) of the calcium fluorescence dataset 7 | % \_ N_units: number of neuronal units to be simulated ( -- obsolete -- ) 8 | % \_ T_durationRange: duration of the simulation in units of seconds 9 | % \_ dT_durationRange: temporal resolution (width of a time step) in units 10 | % of seconds 11 | % \_ assembly_configuration_list: list of assembly configurations 12 | % \_ i_assembly_configuration: assembly configuration index from list 13 | % \_ calcium_T1_2Range: calcium-indicator fluorescence half-life in units of 14 | % seconds 15 | % \_ eventFreqRange: frequency at which a unit is particularly active in units 16 | % of inverse seconds 17 | % \_ eventMultRange: firing rate multiplier at active events 18 | % \_ noiseSTDRange: standard deviation of the Gaussian noise on the fluorescence 19 | % \_ saturationKRange: saturation constant 20 | % 21 | % Note: When given a range for any of the parameters "*Range", a value is 22 | % selected uniformly from this range. 23 | % 24 | % EXAMPLE: 25 | % ARTIFICIAL_CALCIUM_FLUORESCENCE_GENERATION( '~/Desktop/' , 'TEST_1' , 0 , 120 , 0.5 , 'HEX12_K10_medium' , 1 , 1 , 0.1 , 6 , 0 , Inf ) 26 | % 27 | % 28 | % === Jan Moelter, The University of Queensland, 2018 =================== 29 | % 30 | 31 | if( exist( output_directory , 'dir' ) ~= 7 ) 32 | output_directory = '~/'; 33 | end 34 | 35 | fprintf( 1 , [ '\n' ] ); 36 | 37 | %% > PRINT FUNCTION-CALL 38 | if( isdeployed ) 39 | printConsoleSection( 'FUNCTION CALL' ); 40 | 41 | fprintf( 1 , [ 'ARTIFICIAL_CALCIUM_FLUORESCENCE_GENERATION( %s , %s , %s , %s , %s , %s , %s , %s , %s , %s , %s , %s )' '\n' ] , output_directory , id , N_units , T_durationRange , dT_durationRange , assembly_configuration_list , i_assembly_configuration , calcium_T1_2Range , eventFreqRange , eventMultRange , noiseSTDRange , saturationKRange ); 42 | fprintf( 1 , [ '\n' ] ); 43 | end 44 | 45 | %% > INITIALISE RANDOM-NUMBER-GENERATOR 46 | printConsoleSection( 'INITIALISE RANDOM-NUMBER-GENERATOR' ); 47 | 48 | seed_devrandom(); 49 | 50 | %% > SET PARAMETERS 51 | printConsoleSection( 'SET PARAMETERS' ); 52 | 53 | if( isdeployed ) 54 | N_units = str2double( N_units ); 55 | T_durationRange = str2num( T_durationRange ); 56 | dT_durationRange = str2num( dT_durationRange ); 57 | i_assembly_configuration = str2double( i_assembly_configuration ); 58 | calcium_T1_2Range = str2num( calcium_T1_2Range ); 59 | eventFreqRange = str2num( eventFreqRange ); 60 | eventMultRange = str2num( eventMultRange ); 61 | noiseSTDRange = str2num( noiseSTDRange ); 62 | saturationKRange = str2num( saturationKRange ); 63 | end 64 | 65 | X_ASSEMBLY_CONFIGURATIONS.( 'HEXv_K0' ) = HEXv_K0(); 66 | 67 | %X_ASSEMBLY_CONFIGURATIONS.( 'HEXv_K10_small' ) = HEXv_K10_small(); 68 | %X_ASSEMBLY_CONFIGURATIONS.( 'HEXv_K10_medium' ) = HEXv_K10_medium(); 69 | %X_ASSEMBLY_CONFIGURATIONS.( 'HEXv_K10_large' ) = HEXv_K10_large(); 70 | 71 | X_ASSEMBLY_CONFIGURATIONS.( 'HEXv_K10_medium_N' ) = HEXv_K10_medium_N(); 72 | X_ASSEMBLY_CONFIGURATIONS.( 'HEXv_K5_medium_N' ) = HEXv_K5_medium_N(); 73 | 74 | %X_ASSEMBLY_CONFIGURATIONS.( 'HEX16_varK_small' ) = HEX16_varK_small(); 75 | %X_ASSEMBLY_CONFIGURATIONS.( 'HEX16_varK_medium' ) = HEX16_varK_medium(); 76 | %X_ASSEMBLY_CONFIGURATIONS.( 'HEX16_varK_large' ) = HEX16_varK_large(); 77 | 78 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX12_varK_medium_N' ) = HEX12_varK_medium_N(); 79 | 80 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX12_K10_var' ) = HEX12_K10_var(); 81 | 82 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX12_K10_small_overlap' ) = HEX12_K10_small_overlap(); 83 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX12_K10_medium_overlap' ) = HEX12_K10_medium_overlap(); 84 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX12_K10_large_overlap' ) = HEX12_K10_large_overlap(); 85 | 86 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX12_K10_small' ) = HEX12_K10_small(); 87 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX12_K10_medium' ) = HEX12_K10_medium(); 88 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX12_K10_large' ) = HEX12_K10_large(); 89 | 90 | X_ASSEMBLY_CONFIGURATIONS.( 'HEX5_K5_medium' ) = HEX5_K5_medium(); 91 | 92 | X = X_ASSEMBLY_CONFIGURATIONS.( assembly_configuration_list ); 93 | 94 | assembly_configuration = X{i_assembly_configuration}.A; 95 | topology = X{i_assembly_configuration}.T; 96 | 97 | % > OVERRIDE ASSEMBLY CONFIGURATION 98 | %v = 5; 99 | %topology = hexagonal_tiling( v ); 100 | %assembly_configuration = cellfun( @uint16 , mat2cell( 1:( 3 * ( v + 1 ) * v + 1 ) , 1 , [ 1 , 6 * [ 1:v ] ] ) , 'UniformOutput' , false ); 101 | % \_ "hexagonal rings"-layout 102 | 103 | 104 | uniform_transform = @( x , X ) ( max( X ) - min( X ) ) .* x + min( X ); 105 | % \_ uniform_transform( x , X ): maps a uniform random variable x on [0 1] 106 | % to the range X, so that uniform_transform( x , X ) is uniformly 107 | % distributed on X 108 | 109 | 110 | 111 | N_units = numel( topology ); 112 | 113 | PARAMS.units = N_units; 114 | %PARAMS.dT_step = dT_duration; 115 | PARAMS.dT_step = round( iif( numel( dT_durationRange ) == 1 , dT_durationRange , uniform_transform( rand() , num_range(dT_durationRange) ) ) , 3 , 'decimals' ); 116 | %PARAMS.time_steps = T_duration / PARAMS.dT_step; 117 | PARAMS.time_steps = ceil( iif( numel( T_durationRange ) == 1 , T_durationRange , uniform_transform( rand() , num_range(T_durationRange) ) ) / PARAMS.dT_step ); 118 | fprintf( 1 , [ '> %u neuronal units over a time of %.1f s and %u time steps' '\n' ] , PARAMS.units , PARAMS.time_steps * PARAMS.dT_step , PARAMS.time_steps ); 119 | 120 | %if( any( ismember( 1:numel( assembly_configurations ) , i_assembly_configuration ) ) ) 121 | PARAMS.assembly_configuration = assembly_configuration; 122 | PARAMS.assembly_configuration = cellfun( @(a) a( a <= PARAMS.units ) , PARAMS.assembly_configuration , 'UniformOutput' , false ); 123 | %else 124 | % PARAMS.assembly_configuration = {}; 125 | %end 126 | 127 | % > OVERRIDE ASSEMBLY CONFIGURATION 128 | %PARAMS.assembly_configuration = transpose( { uint16( [1,2,3,4,5,6,13,14,15,16,17,18,25,26,27,28,29,30,37,38,39,40,41,42,49,50,51,52,53,54,61,62,63,64,65,66] ) ; uint16( [7,8,9,10,11,12,19,20,21,22,23,24,31,32,33,34,35,36,43,44,45,46,47,48,55,56,57,58,59,60,67,68,69,70,71,72] ) ; uint16( [79,80,81,82,83,84,91,92,93,94,95,96,103,104,105,106,107,108,115,116,117,118,119,120,127,128,129,130,131,132,139,140,141,142,143,144] ) ; uint16( [73,74,75,76,77,78,85,86,87,88,89,90,97,98,99,100,101,102,109,110,111,112,113,114,121,122,123,124,125,126,133,134,135,136,137,138] ) } ); 129 | % \_ "4-square"-layout 130 | % 131 | 132 | PARAMS.rate_range = [ 1 6 ]; 133 | fprintf( 1 , [ '> neuronal firing rate between %.1f and %.1f Hz (s^-1)' '\n' ] , PARAMS.rate_range ); 134 | PARAMS.eventDuration = 0.5; 135 | fprintf( 1 , [ '> neuronal firing events of length %.0f ms' '\n' ] , 1000 * PARAMS.eventDuration ); 136 | %PARAMS.eventFreq = eventFreq; 137 | PARAMS.eventFreq = iif( numel( eventFreqRange ) == 1 , eventFreqRange , uniform_transform( rand() , num_range(eventFreqRange) ) ); 138 | fprintf( 1 , [ '> neuronal firing events at a frequency of %.1f mHz (1e-3 s^-1)' '\n' ] , 1000 * PARAMS.eventFreq ); 139 | PARAMS.eventMult = iif( numel( eventMultRange ) == 1 , eventMultRange , uniform_transform( rand() , num_range(eventMultRange) ) ); 140 | fprintf( 1 , [ '> neuronal firing rate elevation factor of %.1f at events' '\n' ] , PARAMS.eventMult ); 141 | 142 | % PARAMS.calcium_T1_2 = 1; 143 | % \_ GCaMP6s half-life: 1s (cf. Chen et al. 2013 Nature 499) 144 | PARAMS.calcium_T1_2 = iif( numel( calcium_T1_2Range ) == 1 , calcium_T1_2Range , uniform_transform( rand() , num_range(calcium_T1_2Range) ) ); 145 | fprintf( 1 , [ '> calcium indicator decay half-life of %.1f s' '\n' ] , PARAMS.calcium_T1_2 ); 146 | PARAMS.saturation_K = iif( numel( saturationKRange ) == 1 , saturationKRange , uniform_transform( rand() , num_range(saturationKRange) ) ); 147 | fprintf( 1 , [ '> calcium indicator fluorescence saturation constant of %.1f' '\n' ] , PARAMS.saturation_K ); 148 | 149 | PARAMS.noiseSTD = iif( numel( noiseSTDRange ) == 1 , noiseSTDRange , uniform_transform( rand() , num_range(noiseSTDRange) ) ); 150 | fprintf( 1 , [ '> fluorescence noise standard deviation of %.3f' '\n' ] , PARAMS.noiseSTD ); 151 | 152 | fprintf( 1 , [ '\n' ] ); 153 | 154 | %PARAMS 155 | %return; 156 | 157 | %% > CREATE TOPOLOGY 158 | % printConsoleSection( 'CREATE TOPOLOGY' ); 159 | % 160 | % a = 12; 161 | % topology = arrayfun( @(n) [ fix( ( n - 1 ) / a ) , mod( n - 1 , a ) ] , 1:PARAMS.units , 'UniformOutput' , false ); 162 | % clearvars a; 163 | 164 | %% > INITIALISE RANDOM-NUMBER-GENERATOR 165 | printConsoleSection( 'RE-INITIALISE RANDOM-NUMBER-GENERATOR' ); 166 | 167 | seed_devrandom(); 168 | %rng( 0 , 'twister' ); 169 | 170 | %% > GENERATE CALCIUM-FLUORESCENCE (dF/F) 171 | printConsoleSection( 'GENERATE CALCIUM-FLUORESCENCE (dF/F)' ); 172 | 173 | [ dF_F , F , F0 ] = generateArtificialCalciumFluorescence( PARAMS.units , PARAMS.time_steps , PARAMS.dT_step , PARAMS.assembly_configuration , PARAMS.calcium_T1_2 , PARAMS.rate_range , PARAMS.eventDuration , PARAMS.eventFreq , PARAMS.eventMult , PARAMS.noiseSTD , PARAMS.saturation_K ); 174 | 175 | %% > SAVE OUTPUT 176 | printConsoleSection( 'SAVE OUTPUT' ); 177 | 178 | output_args.calcium_fluorescence.F = F; 179 | output_args.calcium_fluorescence.F0 = F0; 180 | output_args.calcium_fluorescence.dF_F = dF_F; 181 | 182 | output_args.topology = topology; 183 | 184 | output_args.parameter = PARAMS; 185 | 186 | 187 | if( exist( [ output_directory '/' id ] , 'dir' ) ~= 7 ) 188 | mkdir( [ output_directory '/' id ] ); 189 | end 190 | fileattrib( [ output_directory '/' id ] , '+w' , 'g' ); 191 | 192 | OUTPUT_PATH = [ output_directory id '/' id '_CALCIUM-FLUORESCENCE' '.mat' ]; 193 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 194 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 195 | 196 | fprintf( 1 , [ 'Calcium fluorescence saved to %s.' '\n' ] , OUTPUT_PATH ); 197 | 198 | %% > END 199 | 200 | fprintf( 1 , [ '\n' '\n' ] ); 201 | 202 | beep on; beep; 203 | 204 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 205 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 206 | 207 | end -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/CALCIUM_FLUORESCENCE_CONVERSION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = CALCIUM_FLUORESCENCE_CONVERSION( output_directory , id , dF_F_field , dT_duration , calcium_T1_2 ) 2 | %CALCIUM_FLUORESCENCE_CONVERSION( output_directory , id , dF_F_field , dT_duration , calcium_T1_2 ) 3 | % Usage: CALCIUM_FLUORESCENCE_CONVERSION( '~/' , 'TEST_1' , dF_F , 0.5 , 1 ) 4 | 5 | if( exist( output_directory , 'dir' ) ~= 7 ) 6 | output_directory = '~/'; 7 | end 8 | 9 | fprintf( 1 , [ '\n' ] ); 10 | 11 | %% > PRINT FUNCTION-CALL 12 | if( isdeployed ) 13 | printConsoleSection( 'FUNCTION CALL' ); 14 | 15 | fprintf( 1 , [ 'CALCIUM_FLUORESCENCE_CONVERSION( %s , %s , %s , %s , %s )' '\n' ] , output_directory , id , NaN , dT_duration , calcium_T1_2 ); 16 | fprintf( 1 , [ '\n' ] ); 17 | end 18 | 19 | %% > SET PARAMETERS 20 | printConsoleSection( 'SET PARAMETERS' ); 21 | 22 | N_units = size( dF_F_field , 2 ); 23 | 24 | topology = transpose( arrayfun( @(n) NaN , 1:N_units , 'UniformOutput' , false ) ); 25 | 26 | PARAMS.units = N_units; 27 | PARAMS.dT_step = dT_duration; 28 | PARAMS.time_steps = size( dF_F_field , 1 ); 29 | fprintf( 1 , [ '> %u neuronal units over a time of %.1f s and %u time steps' '\n' ] , PARAMS.units , PARAMS.time_steps * PARAMS.dT_step , PARAMS.time_steps ); 30 | 31 | PARAMS.assembly_configuration = NaN; 32 | 33 | PARAMS.rate_range = NaN; 34 | PARAMS.eventDuration = NaN; 35 | PARAMS.eventFreq = NaN; 36 | PARAMS.eventMult = NaN; 37 | 38 | 39 | % PARAMS.calcium_T1_2 = 1; 40 | % \_ GCaMP6s half-life: 1s (cf. Chen et al. 2013 Nature 499) 41 | PARAMS.calcium_T1_2 = calcium_T1_2; 42 | fprintf( 1 , [ '> calcium indicator dF/F half-life of %.1f s' '\n' ] , PARAMS.calcium_T1_2 ); 43 | 44 | PARAMS.saturation_K = NaN; 45 | PARAMS.noiseSTD = NaN; 46 | 47 | fprintf( 1 , [ '\n' ] ); 48 | 49 | %PARAMS 50 | %return; 51 | 52 | %% > SAVE OUTPUT 53 | printConsoleSection( 'SAVE OUTPUT' ); 54 | 55 | output_args.calcium_fluorescence.F = NaN; 56 | output_args.calcium_fluorescence.F0 = NaN; 57 | output_args.calcium_fluorescence.dF_F = dF_F_field; 58 | 59 | output_args.topology = topology; 60 | 61 | output_args.parameter = PARAMS; 62 | 63 | output_args.meta_information = []; 64 | 65 | 66 | if( exist( [ output_directory '/' id ] , 'dir' ) ~= 7 ) 67 | mkdir( [ output_directory '/' id ] ); 68 | end 69 | fileattrib( [ output_directory '/' id ] , '+w' , 'g' ); 70 | 71 | OUTPUT_PATH = [ output_directory id '/' id '_CALCIUM-FLUORESCENCE' '.mat' ]; 72 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 73 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 74 | 75 | fprintf( 1 , [ 'Calcium fluorescence saved to %s.' '\n' ] , OUTPUT_PATH ); 76 | 77 | %% > END 78 | 79 | fprintf( 1 , [ '\n' '\n' ] ); 80 | 81 | beep on; beep; 82 | 83 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 84 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 85 | 86 | end -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/assembly-configurations/HEXv_K0.m: -------------------------------------------------------------------------------- 1 | %% 400 EXAMPLES OF ASSEMBLY CONFIGURATIONS WITH 0 ASSEMBLIES IN A HONEYCOMB STRUCTURED TECTUM 2 | % THERE ARE 40 CONFIGURATIONS WHICH ARE EMBEDDED IN TECTA OF INCREASING 3 | % DEGREE v = 8 , ... 17 4 | % 5 | % THE ASSEMBLY CONFIGURATION IS LEFT EMPTY AS NULL-CONTROL 6 | 7 | % 8 | % 9 | % === Jan Moelter, The University of Queensland, 2017 =================== 10 | % 11 | 12 | function [ X ] = HEXv_K0() 13 | 14 | for t = 0:9 15 | for j = 1:40 16 | 17 | % THE UNDERLYING TOPOLOGY 18 | T = hexagonal_tiling( 8 + t ); 19 | 20 | % THE SET OF ASSEMBLY-CONFIGURATION 21 | X{ 40 * t + j } = struct( 'T' , { T } , 'A' , { { } } ); 22 | 23 | end 24 | end 25 | 26 | end -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/generateArtificialCalciumFluorescence.m: -------------------------------------------------------------------------------- 1 | function [ dF_F , F , F0 ] = generateArtificialCalciumFluorescence( units , time_steps , dT_step , assembly_configuration , calcium_T1_2 , rate_range , eventDuration_t , eventFreq_f , eventMult , noiseSTD , saturation_K ) 2 | %GENERATEARTIFICIALCALCIUMFLUORESCENCE( units , time_steps , dT_step , assembly_configuration , calcium_T1_2 , rate_range , eventDuration_t , eventFreq_f , eventMult , noiseSTD , saturation_K ) 3 | % 4 | % PARAMETERS: 5 | % \_ units: number of neuronal units to be simulated 6 | % \_ time_steps: number of time steps 7 | % \_ dT_step: width of a time step in units of seconds 8 | % \_ assembly_configuration [1 x ? cell array]: list of collections of 9 | % units to be combined to assemblies 10 | % \_ calcium_T1_2: calcium-indicator fluorescence half-life in units of 11 | % seconds 12 | % \_ rateRange: range of base firing rate in units of inverse seconds 13 | % (Hertz) 14 | % \_ eventDuration_t: duration of active events in units of seconds 15 | % \_ eventFreq_f: frequency at which a unit is particularly active in units 16 | % of inverse seconds 17 | % \_ eventMult: firing rate multiplier at active events 18 | % \_ noiseSTD: standard deviation of the Gaussian noise on the fluorescence 19 | % \_ saturation_K: saturation constant 20 | % 21 | % EXAMPLE: 22 | % [ dF_F , F , F0 ] = generateArtificialCalciumFluorescence( 40 , 10 * 60 * 2 , 0.5 , transpose( num2cell( transpose( reshape( 1:40 , 10 , 4 ) ) , 2 ) ) , 1 , [ 1 6 ] , 0.5 , 0.01 , 6 , 0 , Inf ) 23 | % 24 | % 25 | % === Jan Moelter, The University of Queensland, 2018 =================== 26 | % 27 | 28 | 29 | N = units; 30 | T = time_steps; 31 | 32 | dT = dT_step; 33 | 34 | dt = 0.001; 35 | 36 | T_offset = ceil( 2 * calcium_T1_2 / dT_step ); 37 | % \_ T_offset: number of time steps as a initial offset 38 | 39 | if( mod( dT , dt ) ~= 0 ) 40 | error( 'mod( dT , dt ) ~= 0' ); 41 | end 42 | dT_n = round( dT / dt ); 43 | 44 | spikecount_field = generateSpikeCountField( N , ( T + T_offset ) , dT , assembly_configuration , rate_range , max( 1 , eventDuration_t / dT ) , eventFreq_f * dT , eventMult ); 45 | % \_ spikecount_field [T+T_offset x N matrix]: 46 | 47 | calcium_activity = zeros( T , N ); 48 | % \_ calcium_activity [T x N matrix]: 49 | 50 | calcium_convolution_kernel = calcium_kernel( calcium_T1_2 , dt ); 51 | % \_ calcium_convolution_kernel [? x 1 matrix]: 52 | 53 | spike_train = zeros( ( T + T_offset ) * dT_n , 1 ); 54 | %calcium_convolved_spike_train = zeros( T * dT_n + numel( calcium_convolution_kernel ) - 1 , 1 ); 55 | 56 | print_progress( 0 , 'initialise' ); 57 | 58 | for n = 1:N 59 | spike_train = 0 * spike_train; 60 | %calcium_convolved_spike_train = 0 * calcium_convolved_spike_train; 61 | 62 | i_spikes = cell_union( arrayfun( @( t ) dT_n * ( t - 1 ) + randi( [ 1 , dT_n ] , 1 , spikecount_field( t , n ) ) , transpose( 1:( T + T_offset ) ) , 'UniformOutput' , false ) ); 63 | spike_train( i_spikes ) = 1; 64 | 65 | calcium_convolved_spike_train = conv( spike_train , calcium_convolution_kernel ); 66 | 67 | calcium_activity( : , n ) = calcium_convolved_spike_train( dT_n * [ ( T_offset + 1 ):( T + T_offset ) ] ); 68 | if( saturation_K < Inf ) 69 | calcium_activity( : , n ) = arrayfun( @(c) saturation_K * c / ( c + saturation_K ) , calcium_activity( : , n ) , 'UniformOutput' , true ); 70 | end 71 | 72 | % >> plot calcium signal 73 | 74 | if( ~isdeployed && false ) 75 | 76 | ca_signal = calcium_convolved_spike_train( ( T_offset * dT_n + 1 ):( ( T + T_offset ) * dT_n ) ); 77 | 78 | subplot( 3 , 1 , [ 1:2 ] ); 79 | plot( 1:(T * dT_n) , ca_signal , 'Color' , HTML2RGB( '5100C0' ) ); 80 | hold on; 81 | plot( dT_n * [ 1:T ] , calcium_activity( : , n ) ); 82 | hold off; 83 | xlim( [ 1 (T * dT_n) ] ); 84 | ylim( [ 0 1.1*max( ca_signal ) ] ); 85 | 86 | set( gca , 'XTick' , [ 0:( 10^floor( log10( T * dT ) ) ):( T * dT ) ] / dt , 'XTickLabel' , arrayfun( @(t) sprintf( '%u s' , t ) , [ 0:( 10^floor( log10( T * dT ) ) ):( T * dT ) ] , 'UniformOutput' , false ) ); 87 | set( gca , 'YTick' , [] ); 88 | 89 | subplot( 3 , 1 , 3 ); 90 | bar( 1:(T * dT_n) , spike_train( ( T_offset * dT_n + 1 ):( ( T + T_offset ) * dT_n ) )' , 'k' ); 91 | hold off; 92 | xlim( [ 1 (T * dT_n) ] ); 93 | 94 | set( gca , 'XTick' , [] , 'YTick' , [] ); 95 | 96 | end 97 | 98 | print_progress( n / N , 'update' ); 99 | end 100 | 101 | print_progress( 1 , 'finalise' ); 102 | 103 | clearvars spike_train calcium_convolution_kernel calcium_convolved_spike_train; 104 | 105 | if( noiseSTD > 0 ) 106 | fprintf( 1 , [ 'Add Gaussian Noise ...' '\n' ] ); 107 | calcium_activity = calcium_activity + random( 'Normal' , 0 , noiseSTD * ones( size( calcium_activity ) ) ); 108 | calcium_activity = calcium_activity .* ( calcium_activity > 0 ); 109 | end 110 | 111 | calcium_fluorescence.rawF = transpose( calcium_activity ); 112 | calcium_fluorescence = fitF0smoother( calcium_fluorescence , ceil( 15 / dT ) ); 113 | 114 | dF_F = transpose( calcium_fluorescence.Fnorm ); 115 | F = transpose( calcium_fluorescence.rawF ); 116 | F0 = transpose( calcium_fluorescence.F0 ); 117 | 118 | end 119 | 120 | function [ spikecount_field ] = generateSpikeCountField( N , T , dT , assemblies , rateRange , eventDur , eventProb , eventMult ) 121 | % \_ N: number of neuronal units to be simulated 122 | % \_ T: number of time steps 123 | % \_ dT: width of a time step in units of seconds 124 | % \_ assemblies [1 x ? cell array]: list of collections of units to be 125 | % combined to assemblies 126 | % \_ rateRange: range of base firing rate in units of inverse seconds 127 | % (Hertz) 128 | % \_ eventDur: length of an active event as a number of timesteps 129 | % \_ eventProb: probability with which a unit is particularly active in a 130 | % single timestep 131 | % \_ eventMult: firing rate multiplier at active events 132 | 133 | uniform_transform = @( x , X ) ( max( X ) - min( X ) ) .* x + min( X ); 134 | % \_ uniform_transform( x , X ): maps a uniform random variable x on [0 1] 135 | % to the range X, so that uniform_transform( x , X ) is uniformly 136 | % distributed on X 137 | 138 | activation_field = false( [ T , N ] ); 139 | % \_ activation_field [T x N matrix]: field of activation event indicators 140 | 141 | for a = assemblies 142 | activation_field( : , a{:} ) = activation_field( : , a{:} ) | repmat( rand( T , 1 ) < eventProb , 1 , numel( a{:} ) ); 143 | end 144 | a = { setdiff( 1:N , cell_union( assemblies ) ) }; 145 | activation_field( : , a{:} ) = activation_field( : , a{:} ) | ( rand( T , numel( a{:} ) ) < eventProb ); 146 | 147 | if( eventDur > 1 ) 148 | activation_field_mask = activation_field; 149 | frac_activation_field_mask = activation_field_mask & ( random( 'Binomial' , 1 , frac( eventDur ) * ones( size(activation_field_mask) ) ) == 1 ); 150 | 151 | for m = 1:(floor(eventDur) - 1) 152 | %activation_field = activation_field | circshift( activation_field , m , 1 ); 153 | activation_field = activation_field | padarray( activation_field_mask(1:(end - m),:) , [ m 0 ] , false , 'pre' ); 154 | end 155 | m = floor(eventDur); 156 | activation_field = activation_field | padarray( frac_activation_field_mask(1:(end - m),:) , [ m 0 ] , false , 'pre' ); 157 | end 158 | 159 | firingrate_field = repmat( uniform_transform( rand( 1 , N ) , rateRange ) , T , 1 ); 160 | %firingrate_field = repmat( randi( rateRange , 1 , N ) , T , 1 ); 161 | % \_ firingrate_field [T x N matrix]: field of firing rates 162 | 163 | firingrate_field( activation_field ) = eventMult * firingrate_field( activation_field ); 164 | 165 | spikecount_field = random( 'Poisson' , firingrate_field * dT ); 166 | % \_ spikecount_field [T x N matrix]: field of spike counts at every time 167 | % step 168 | 169 | end 170 | 171 | function [ output ] = calcium_kernel( T1_2 , dt ) 172 | % \_ T1_2: kernel half-life time in units of seconds 173 | % \_ dt: time-precision in units of seconds 174 | 175 | a = 1; 176 | k = @( t ) a * exp( - log( 2 ) * t / T1_2 ); 177 | 178 | cut_off_ratio = 0.01; 179 | 180 | output = k( transpose( 0:dt:ceil( - log2( cut_off_ratio * a ) * T1_2 ) ) ); 181 | end -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/inc_generateArtificialCalciumFluorescence/HaasLab_fitF0smoother/KalmanAll/KPMstats/gaussian_prob.m: -------------------------------------------------------------------------------- 1 | function p = gaussian_prob(x, m, C, use_log) 2 | % GAUSSIAN_PROB Evaluate a multivariate Gaussian density. 3 | % p = gaussian_prob(X, m, C) 4 | % p(i) = N(X(:,i), m, C) where C = covariance matrix and each COLUMN of x is a datavector 5 | 6 | % p = gaussian_prob(X, m, C, 1) returns log N(X(:,i), m, C) (to prevents underflow). 7 | % 8 | % If X has size dxN, then p has size Nx1, where N = number of examples 9 | 10 | if nargin < 4, use_log = 0; end 11 | 12 | if length(m)==1 % scalar 13 | x = x(:)'; 14 | end 15 | [d N] = size(x); 16 | %assert(length(m)==d); % slow 17 | m = m(:); 18 | M = m*ones(1,N); % replicate the mean across columns 19 | denom = (2*pi)^(d/2)*sqrt(abs(det(C))); 20 | mahal = sum(((x-M)'*inv(C)).*(x-M)',2); % Chris Bregler's trick 21 | if any(mahal<0) 22 | warning('mahal < 0 => C is not psd') 23 | end 24 | if use_log 25 | p = -0.5*mahal - log(denom); 26 | else 27 | p = exp(-0.5*mahal) / (denom+eps); 28 | end 29 | -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/inc_generateArtificialCalciumFluorescence/HaasLab_fitF0smoother/KalmanAll/Kalman/kalman_filter.m: -------------------------------------------------------------------------------- 1 | function [x, V, VV, loglik] = kalman_filter(y, A, C, Q, R, init_x, init_V, varargin) 2 | % Kalman filter. 3 | % [x, V, VV, loglik] = kalman_filter(y, A, C, Q, R, init_x, init_V, ...) 4 | % 5 | % INPUTS: 6 | % y(:,t) - the observation at time t 7 | % A - the system matrix 8 | % C - the observation matrix 9 | % Q - the system covariance 10 | % R - the observation covariance 11 | % init_x - the initial state (column) vector 12 | % init_V - the initial state covariance 13 | % 14 | % OPTIONAL INPUTS (string/value pairs [default in brackets]) 15 | % 'model' - model(t)=m means use params from model m at time t [ones(1,T) ] 16 | % In this case, all the above matrices take an additional final dimension, 17 | % i.e., A(:,:,m), C(:,:,m), Q(:,:,m), R(:,:,m). 18 | % However, init_x and init_V are independent of model(1). 19 | % 'u' - u(:,t) the control signal at time t [ [] ] 20 | % 'B' - B(:,:,m) the input regression matrix for model m 21 | % 22 | % OUTPUTS (where X is the hidden state being estimated) 23 | % x(:,t) = E[X(:,t) | y(:,1:t)] 24 | % V(:,:,t) = Cov[X(:,t) | y(:,1:t)] 25 | % VV(:,:,t) = Cov[X(:,t), X(:,t-1) | y(:,1:t)] t >= 2 26 | % loglik = sum{t=1}^T log P(y(:,t)) 27 | % 28 | % If an input signal is specified, we also condition on it: 29 | % e.g., x(:,t) = E[X(:,t) | y(:,1:t), u(:, 1:t)] 30 | % If a model sequence is specified, we also condition on it: 31 | % e.g., x(:,t) = E[X(:,t) | y(:,1:t), u(:, 1:t), m(1:t)] 32 | 33 | [os T] = size(y); 34 | ss = size(A,1); % size of state space 35 | 36 | % set default params 37 | model = ones(1,T); 38 | u = []; 39 | B = []; 40 | ndx = []; 41 | upper = inf(size(y)); 42 | 43 | args = varargin; 44 | nargs = length(args); 45 | for i=1:2:nargs 46 | switch args{i} 47 | case 'model', model = args{i+1}; 48 | case 'u', u = args{i+1}; 49 | case 'B', B = args{i+1}; 50 | case 'ndx', ndx = args{i+1}; 51 | case 'upper', upper = args{i+1}; 52 | otherwise, error(['unrecognized argument ' args{i}]) 53 | end 54 | end 55 | 56 | x = zeros(ss, T); 57 | V = zeros(ss, ss, T); 58 | VV = zeros(ss, ss, T); 59 | 60 | loglik = 0; 61 | for t=1:T 62 | m = model(t); 63 | if t==1 64 | %prevx = init_x(:,m); 65 | %prevV = init_V(:,:,m); 66 | prevx = init_x; 67 | prevV = init_V; 68 | initial = 1; 69 | else 70 | prevx = x(:,t-1); 71 | prevV = V(:,:,t-1); 72 | initial = 0; 73 | end 74 | if isempty(u) 75 | [x(:,t), V(:,:,t), LL, VV(:,:,t)] = ... 76 | kalman_update(A(:,:,m), C(:,:,m), Q(:,:,m), R(:,:,m), y(:,t), prevx, prevV, 'initial', initial); 77 | if upper(:,t)< x(:,t) 78 | x(:,t) = upper(:,t); 79 | V(:,:,t) = V(:,:,t)*0.9; 80 | end 81 | else 82 | if isempty(ndx) 83 | [x(:,t), V(:,:,t), LL, VV(:,:,t)] = ... 84 | kalman_update(A(:,:,m), C(:,:,m), Q(:,:,m), R(:,:,m), y(:,t), prevx, prevV, ... 85 | 'initial', initial, 'u', u(:,t), 'B', B(:,:,m)); 86 | else 87 | i = ndx{t}; 88 | % copy over all elements; only some will get updated 89 | x(:,t) = prevx; 90 | prevP = inv(prevV); 91 | prevPsmall = prevP(i,i); 92 | prevVsmall = inv(prevPsmall); 93 | [x(i,t), smallV, LL, VV(i,i,t)] = ... 94 | kalman_update(A(i,i,m), C(:,i,m), Q(i,i,m), R(:,:,m), y(:,t), prevx(i), prevVsmall, ... 95 | 'initial', initial, 'u', u(:,t), 'B', B(i,:,m)); 96 | smallP = inv(smallV); 97 | prevP(i,i) = smallP; 98 | V(:,:,t) = inv(prevP); 99 | end 100 | end 101 | loglik = loglik + LL; 102 | end 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/inc_generateArtificialCalciumFluorescence/HaasLab_fitF0smoother/KalmanAll/Kalman/kalman_smoother.m: -------------------------------------------------------------------------------- 1 | function [xsmooth, Vsmooth, VVsmooth, loglik] = kalman_smoother(y, A, C, Q, R, init_x, init_V, varargin) 2 | % Kalman/RTS smoother. 3 | % [xsmooth, Vsmooth, VVsmooth, loglik] = kalman_smoother(y, A, C, Q, R, init_x, init_V, ...) 4 | % 5 | % The inputs are the same as for kalman_filter. 6 | % The outputs are almost the same, except we condition on y(:, 1:T) (and u(:, 1:T) if specified), 7 | % instead of on y(:, 1:t). 8 | 9 | [os T] = size(y); 10 | ss = size(A,1); 11 | 12 | % set default params 13 | model = ones(1,T); 14 | u = []; 15 | B = []; 16 | upper = inf(size(y)); 17 | 18 | args = varargin; 19 | nargs = length(args); 20 | for i=1:2:nargs 21 | switch args{i} 22 | case 'model', model = args{i+1}; 23 | case 'u', u = args{i+1}; 24 | case 'B', B = args{i+1}; 25 | case 'upper', upper = args{i+1}; 26 | otherwise, error(['unrecognized argument ' args{i}]) 27 | end 28 | end 29 | 30 | xsmooth = zeros(ss, T); 31 | Vsmooth = zeros(ss, ss, T); 32 | VVsmooth = zeros(ss, ss, T); 33 | 34 | % Forward pass 35 | [xfilt, Vfilt, VVfilt, loglik] = kalman_filter(y, A, C, Q, R, init_x, init_V, ... 36 | 'model', model, 'u', u, 'B', B, 'upper', upper); 37 | 38 | %if we have an upper bound for the estimated value 39 | xfilt = min(xfilt, upper); 40 | 41 | % Backward pass 42 | xsmooth(:,T) = xfilt(:,T); 43 | Vsmooth(:,:,T) = Vfilt(:,:,T); 44 | %VVsmooth(:,:,T) = VVfilt(:,:,T); 45 | 46 | for t=T-1:-1:1 47 | m = model(t+1); 48 | if isempty(B) 49 | [xsmooth(:,t), Vsmooth(:,:,t), VVsmooth(:,:,t+1)] = ... 50 | smooth_update(xsmooth(:,t+1), Vsmooth(:,:,t+1), xfilt(:,t), Vfilt(:,:,t), ... 51 | Vfilt(:,:,t+1), VVfilt(:,:,t+1), A(:,:,m), Q(:,:,m), [], []); 52 | else 53 | [xsmooth(:,t), Vsmooth(:,:,t), VVsmooth(:,:,t+1)] = ... 54 | smooth_update(xsmooth(:,t+1), Vsmooth(:,:,t+1), xfilt(:,t), Vfilt(:,:,t), ... 55 | Vfilt(:,:,t+1), VVfilt(:,:,t+1), A(:,:,m), Q(:,:,m), B(:,:,m), u(:,t+1)); 56 | end 57 | end 58 | 59 | VVsmooth(:,:,1) = zeros(ss,ss); 60 | 61 | -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/inc_generateArtificialCalciumFluorescence/HaasLab_fitF0smoother/KalmanAll/Kalman/kalman_update.m: -------------------------------------------------------------------------------- 1 | function [xnew, Vnew, loglik, VVnew] = kalman_update(A, C, Q, R, y, x, V, varargin) 2 | % KALMAN_UPDATE Do a one step update of the Kalman filter 3 | % [xnew, Vnew, loglik] = kalman_update(A, C, Q, R, y, x, V, ...) 4 | % 5 | % INPUTS: 6 | % A - the system matrix 7 | % C - the observation matrix 8 | % Q - the system covariance 9 | % R - the observation covariance 10 | % y(:) - the observation at time t 11 | % x(:) - E[X | y(:, 1:t-1)] prior mean 12 | % V(:,:) - Cov[X | y(:, 1:t-1)] prior covariance 13 | % 14 | % OPTIONAL INPUTS (string/value pairs [default in brackets]) 15 | % 'initial' - 1 means x and V are taken as initial conditions (so A and Q are ignored) [0] 16 | % 'u' - u(:) the control signal at time t [ [] ] 17 | % 'B' - the input regression matrix 18 | % 19 | % OUTPUTS (where X is the hidden state being estimated) 20 | % xnew(:) = E[ X | y(:, 1:t) ] 21 | % Vnew(:,:) = Var[ X(t) | y(:, 1:t) ] 22 | % VVnew(:,:) = Cov[ X(t), X(t-1) | y(:, 1:t) ] 23 | % loglik = log P(y(:,t) | y(:,1:t-1)) log-likelihood of innovatio 24 | 25 | % set default params 26 | u = []; 27 | B = []; 28 | initial = 0; 29 | 30 | args = varargin; 31 | for i=1:2:length(args) 32 | switch args{i} 33 | case 'u', u = args{i+1}; 34 | case 'B', B = args{i+1}; 35 | case 'initial', initial = args{i+1}; 36 | otherwise, error(['unrecognized argument ' args{i}]) 37 | end 38 | end 39 | 40 | % xpred(:) = E[X_t+1 | y(:, 1:t)] 41 | % Vpred(:,:) = Cov[X_t+1 | y(:, 1:t)] 42 | 43 | if initial 44 | if isempty(u) 45 | xpred = x; 46 | else 47 | xpred = x + B*u; 48 | end 49 | Vpred = V; 50 | else 51 | if isempty(u) 52 | xpred = A*x; 53 | else 54 | xpred = A*x + B*u; 55 | end 56 | Vpred = A*V*A' + Q; 57 | end 58 | 59 | e = y - C*xpred; % error (innovation) 60 | n = length(e); 61 | ss = length(A); 62 | S = C*Vpred*C' + R; 63 | Sinv = inv(S); 64 | ss = length(V); 65 | loglik = gaussian_prob(e, zeros(1,length(e)), S, 1); 66 | K = Vpred*C'*Sinv; % Kalman gain matrix 67 | % If there is no observation vector, set K = zeros(ss). 68 | xnew = xpred + K*e; 69 | Vnew = (eye(ss) - K*C)*Vpred; 70 | VVnew = (eye(ss) - K*C)*A*V; 71 | 72 | -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/inc_generateArtificialCalciumFluorescence/HaasLab_fitF0smoother/KalmanAll/Kalman/smooth_update.m: -------------------------------------------------------------------------------- 1 | function [xsmooth, Vsmooth, VVsmooth_future] = smooth_update(xsmooth_future, Vsmooth_future, ... 2 | xfilt, Vfilt, Vfilt_future, VVfilt_future, A, Q, B, u) 3 | % One step of the backwards RTS smoothing equations. 4 | % function [xsmooth, Vsmooth, VVsmooth_future] = smooth_update(xsmooth_future, Vsmooth_future, ... 5 | % xfilt, Vfilt, Vfilt_future, VVfilt_future, A, B, u) 6 | % 7 | % INPUTS: 8 | % xsmooth_future = E[X_t+1|T] 9 | % Vsmooth_future = Cov[X_t+1|T] 10 | % xfilt = E[X_t|t] 11 | % Vfilt = Cov[X_t|t] 12 | % Vfilt_future = Cov[X_t+1|t+1] 13 | % VVfilt_future = Cov[X_t+1,X_t|t+1] 14 | % A = system matrix for time t+1 15 | % Q = system covariance for time t+1 16 | % B = input matrix for time t+1 (or [] if none) 17 | % u = input vector for time t+1 (or [] if none) 18 | % 19 | % OUTPUTS: 20 | % xsmooth = E[X_t|T] 21 | % Vsmooth = Cov[X_t|T] 22 | % VVsmooth_future = Cov[X_t+1,X_t|T] 23 | 24 | %xpred = E[X(t+1) | t] 25 | if isempty(B) 26 | xpred = A*xfilt; 27 | else 28 | xpred = A*xfilt + B*u; 29 | end 30 | Vpred = A*Vfilt*A' + Q; % Vpred = Cov[X(t+1) | t] 31 | J = Vfilt * A' * inv(Vpred); % smoother gain matrix 32 | xsmooth = xfilt + J*(xsmooth_future - xpred); 33 | Vsmooth = Vfilt + J*(Vsmooth_future - Vpred)*J'; 34 | VVsmooth_future = VVfilt_future + (Vsmooth_future - Vfilt_future)*inv(Vfilt_future)*VVfilt_future; 35 | 36 | 37 | -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/inc_generateArtificialCalciumFluorescence/HaasLab_fitF0smoother/README__KalmanAll: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'KALMAN FILTER TOOLBOX' 2 | PACKAGE (https://www.cs.ubc.ca/~murphyk/Software/index.html / https://www.cs.ubc.ca/~murphyk/Software/Kalman/kalman.html) 3 | BY KEVIN MURPHY. 4 | 5 | THE FOLLOWING FUNCTIONS WERE MODIFIED FROM THEIR ORIGINAL STATE BY KASPAR PODGORSKI: 6 | 7 | _ kalman_filter.m 8 | _ kalman_smoother.m 9 | 10 | THE OTHER FUNCTIONS REMAINED UN-MODIFIED. -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/inc_generateArtificialCalciumFluorescence/HaasLab_fitF0smoother/README__fitF0smoother: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'HAASLAB_FITF0SMOOTHER' 2 | PACKAGE BY KASPAR PODGORSKI. 3 | 4 | THE FUNCTIONS REMAINED UN-MODIFIED. -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/inc_generateArtificialCalciumFluorescence/HaasLab_fitF0smoother/fitF0smoother/fitF0smoother.m: -------------------------------------------------------------------------------- 1 | function datastruct = fitF0smoother (datastruct, widthfactor) 2 | if nargin<2 3 | %Timescale over which to look for a local minimum 4 | widthfactor = 20; 5 | end 6 | for j = 1:numel(datastruct) 7 | %extize 8 | numframes = size(datastruct(j).rawF, 2); 9 | numcells = size(datastruct(j).rawF,1); 10 | uncertainty = 99999999*ones(numcells,1); 11 | bg = zeros(size(datastruct(j).rawF)); 12 | noise = estimatenoise(datastruct(j).rawF, 2); 13 | 14 | %initial smoothing, optional 15 | for n = 1: numcells 16 | bg(n,:) = smooth(datastruct(j).rawF(n,:), 0.012, 'rloess'); 17 | end 18 | 19 | drift = 0.001*mean(bg, 2)./noise; 20 | obs = zeros(numcells, numframes); 21 | R = zeros(numcells, numframes); 22 | AC = zeros(numcells, numframes); 23 | Q = zeros(numcells, numframes); 24 | 25 | for i = 1:numframes 26 | data = bg(:, max(i-widthfactor,3):min(i+widthfactor,numframes-2)); 27 | obs(:,i) = min(data,[],2); 28 | R(:,i) = max((var(data, 0, 2)./noise), eps); 29 | AC(:,i) = 1; 30 | Q(:,i) = drift; 31 | end 32 | 33 | prior = min(bg(:,3:widthfactor), [], 2); 34 | bg2 = fliplr(bg); 35 | prior2 = min(bg2(:,3:widthfactor), [], 2); 36 | 37 | for cellnum = 1:numcells 38 | %because all our methods are symmetrical in time, smooth going both forwards and backwards and take the minimum 39 | x_smooth = kalman_smoother(obs(cellnum,:), shiftdim(AC(cellnum,:), -1), shiftdim(AC(cellnum,:), -1), shiftdim(Q(cellnum,:),-1), shiftdim(R(cellnum,:),-1), prior(cellnum), uncertainty(cellnum), 'model', 1:numframes, 'upper', obs(cellnum,:)); 40 | x_smooth2 = kalman_smoother(fliplr(obs(cellnum,:)), shiftdim(fliplr(AC(cellnum,:)), -1), shiftdim(fliplr(AC(cellnum,:)), -1), shiftdim(fliplr(Q(cellnum,:)),-1), shiftdim(fliplr(R(cellnum,:)),-1), prior2(cellnum), uncertainty(cellnum), 'model', 1:numframes, 'upper', fliplr(obs(cellnum,:))); 41 | datastruct(j).F0(cellnum, :) = smooth(min(x_smooth,fliplr(x_smooth2)), 0.1, 'lowess'); 42 | end 43 | datastruct(j).Fnorm = (datastruct(j).rawF - datastruct(j).F0) ./ datastruct(j).F0; 44 | end 45 | -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/make-assembly-configurations/hexagonal_tiling.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = hexagonal_tiling( v ) 2 | %HEXAGONAL_TILING( v ) Returns a hexagonal tiling of degree v 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2017 =================== 6 | % 7 | 8 | %z = @( N ) ceil( 0.5 * ( sqrt(4 * N - 1) / sqrt(3) - 1 ) ); 9 | 10 | narginchk(1,1); 11 | 12 | rot = @( a ) [ cos(a) , -sin(a) ; sin(a) , cos(a) ]; 13 | 14 | w = [ 0 0 ]; 15 | output_args = { w }; 16 | 17 | for n = 1:v 18 | w = [ 0 n ]; 19 | u = - [ sqrt(3) 1 ] / 2; 20 | 21 | for e = 1:6 22 | for e_ = 1:n 23 | output_args{ numel( output_args ) + 1 } = w; 24 | w = w + u; 25 | end 26 | 27 | u = u * transpose( rot( pi / 3 ) ); 28 | end 29 | end 30 | 31 | output_args = transpose( output_args ); 32 | 33 | end 34 | 35 | -------------------------------------------------------------------------------- /artificial-calcium-fluorescence/make-assembly-configurations/random_assembly.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = random_assembly( v , S , n , N ) 2 | %RANDOM_ASSEMBLY( v , S , n , N ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2017 =================== 6 | % 7 | 8 | T = hexagonal_tiling( v ); 9 | m = @( x ) sqrt( x(1) ) * [ cos( 2 * pi * x(2) ) sin( 2 * pi * x(2) ) ]; 10 | 11 | uniform_transform = @( x , X ) ( max( X ) - min( X ) ) .* x + min( X ); 12 | 13 | for r = 1:N 14 | 15 | X = mvnrnd( ( sqrt(3) * v / 2 ) * m( rand(1,2) ) , uniform_transform( rand() , S )^2 * eye(2) , n ); 16 | D = pdist2( X , cell2mat( T ) , 'euclidean' ); 17 | 18 | output_args{r} = cell_union( cellfun( @( d ) find( d < 0.5 ) , num2cell( D , 2 ) , 'UniformOutput' , false ) ); 19 | 20 | end 21 | 22 | end -------------------------------------------------------------------------------- /assembly-detection/ASSEMBLIES_COLLECTION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = ASSEMBLIES_COLLECTION( CALCIUM_FLUORESCENCE_file ) 2 | %ASSEMBLIES_COLLECTION( CALCIUM_FLUORESCENCE_file ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,1); 9 | 10 | fprintf( 1 , [ '\n' ] ); 11 | 12 | timerVal = tic; 13 | 14 | %% > PRINT FUNCTION-CALL 15 | if( isdeployed ) 16 | printConsoleSection( 'FUNCTION CALL' ); 17 | 18 | fprintf( 1 , [ 'ASSEMBLIES_COLLECTION( %s )' '\n' ] , CALCIUM_FLUORESCENCE_file ); 19 | fprintf( 1 , [ '\n' ] ); 20 | end 21 | 22 | if( exist( CALCIUM_FLUORESCENCE_file , 'file' ) == 2 ) 23 | 24 | CALCIUM_FLUORESCENCE_mat = load( CALCIUM_FLUORESCENCE_file ); 25 | 26 | if( false ) 27 | 28 | % printConsoleSection( 'UPDATE PARAMETERS' ); 29 | % 30 | % if( ~isfield( CALCIUM_FLUORESCENCE_mat.parameter , 'eventDuration' ) ) 31 | % CALCIUM_FLUORESCENCE_mat.parameter.eventDuration = 0.5; 32 | % end 33 | % 34 | % CALCIUM_FLUORESCENCE_mat.parameter = orderfields( CALCIUM_FLUORESCENCE_mat.parameter , { 'units' , 'dT_step' , 'time_steps' , 'assembly_configuration' , 'rate_range' , 'eventDuration' , 'eventFreq' , 'eventMult' , 'calcium_T1_2' } ); 35 | % 36 | % save( CALCIUM_FLUORESCENCE_file , '-v7' , '-struct' , 'CALCIUM_FLUORESCENCE_mat' ); 37 | % fileattrib( CALCIUM_FLUORESCENCE_file , '+w' , 'g' ); 38 | 39 | end 40 | 41 | printConsoleSection( 'ASSEMBLIES COLLECTION' ); 42 | 43 | output_args.parameter = CALCIUM_FLUORESCENCE_mat.parameter; 44 | if( isfield( CALCIUM_FLUORESCENCE_mat , 'meta_information' ) ) 45 | output_args.meta_information = CALCIUM_FLUORESCENCE_mat.meta_information; 46 | end 47 | output_args.topology = CALCIUM_FLUORESCENCE_mat.topology; 48 | 49 | for SUFFIX = { '_ICA-ASSEMBLIES' , '_PROMAX-MP-ASSEMBLIES' , '_PROMAX-CS-ASSEMBLIES' , '_CORE-ASSEMBLIES' , '_SVD-ASSEMBLIES' , '_SGC-ASSEMBLIES' } 50 | 51 | clearvars 'SUFFIX_mat'; 52 | 53 | if( exist( strrep( CALCIUM_FLUORESCENCE_file , '_CALCIUM-FLUORESCENCE' , SUFFIX{:} ) , 'file' ) == 2 ) 54 | SUFFIX_mat = load( strrep( CALCIUM_FLUORESCENCE_file , '_CALCIUM-FLUORESCENCE' , SUFFIX{:} ) ); 55 | end 56 | 57 | switch SUFFIX{:} 58 | case '_SGC-ASSEMBLIES' 59 | if( exist( 'SUFFIX_mat' , 'var' ) == 1 ) 60 | fprintf( 1 , [ '> SGC assemblies' '\n' ] ); 61 | output_args.SGC_assemblies = transpose( SUFFIX_mat.assemblies ); 62 | else 63 | output_args.SGC_assemblies = NaN; 64 | end 65 | 66 | case '_PROMAX-MP-ASSEMBLIES' 67 | if( exist( 'SUFFIX_mat' , 'var' ) == 1 ) 68 | fprintf( 1 , [ '> Promax-MP assemblies' '\n' ] ); 69 | output_args.PROMAX_MP_assemblies = SUFFIX_mat.assembliesCells; 70 | else 71 | output_args.PROMAX_MP_assemblies = NaN; 72 | end 73 | 74 | case '_PROMAX-CS-ASSEMBLIES' 75 | if( exist( 'SUFFIX_mat' , 'var' ) == 1 ) 76 | fprintf( 1 , [ '> Promax-CS assemblies' '\n' ] ); 77 | output_args.PROMAX_CS_assemblies = SUFFIX_mat.assembliesCells; 78 | else 79 | output_args.PROMAX_CS_assemblies = NaN; 80 | end 81 | 82 | case '_ICA-ASSEMBLIES' 83 | if( exist( 'SUFFIX_mat' , 'var' ) == 1 ) 84 | fprintf( 1 , [ '> ICA-CS & ICA-MP assemblies' '\n' ] ); 85 | output_args.ICA_CS_assemblies = transpose( cellfun( @transpose , SUFFIX_mat.cs_assemblies , 'UniformOutput' , false ) ); 86 | output_args.ICA_MP_assemblies = transpose( cellfun( @transpose , SUFFIX_mat.mp_assemblies , 'UniformOutput' , false ) ); 87 | else 88 | output_args.ICA_CS_assemblies = NaN; 89 | output_args.ICA_MP_assemblies = NaN; 90 | end 91 | 92 | case '_CORE-ASSEMBLIES' 93 | if( exist( 'SUFFIX_mat' , 'var' ) == 1 ) 94 | fprintf( 1 , [ '> CORE assemblies' '\n' ] ); 95 | output_args.CORE_assemblies = SUFFIX_mat.assemblies; 96 | else 97 | output_args.CORE_assemblies = NaN; 98 | end 99 | 100 | case '_SVD-ASSEMBLIES' 101 | if( exist( 'SUFFIX_mat' , 'var' ) == 1 ) 102 | fprintf( 1 , [ '> SVD assemblies' '\n' ] ); 103 | output_args.SVD_assemblies = SUFFIX_mat.assemblies; 104 | else 105 | output_args.SVD_assemblies = NaN; 106 | end 107 | end 108 | end 109 | 110 | for SUFFIX = { '_FIM-PSF-PSR-ASSEMBLIES' } 111 | 112 | clearvars 'SUFFIX_dat'; 113 | 114 | if( exist( strrep( CALCIUM_FLUORESCENCE_file , '_CALCIUM-FLUORESCENCE.mat' , [ SUFFIX{:} '.dat' ] ) , 'file' ) == 2 ) 115 | SUFFIX_dat = read( strrep( CALCIUM_FLUORESCENCE_file , '_CALCIUM-FLUORESCENCE.mat' , [ SUFFIX{:} '.dat' ] ) ); 116 | end 117 | 118 | 119 | switch SUFFIX{:} 120 | case '_FIM-PSF-PSR-ASSEMBLIES' 121 | if( exist( 'SUFFIX_dat' , 'var' ) == 1 ) 122 | fprintf( 1 , [ '> FIM+PSF+PSR assemblies' '\n' ] ); 123 | output_args.FIM_PSF_PSR_assemblies = parse_FIM_PSF_PSR_ASSEMBLIES( SUFFIX_dat ); 124 | else 125 | output_args.FIM_PSF_PSR_assemblies = NaN; 126 | end 127 | 128 | end 129 | end 130 | 131 | 132 | printConsoleSection( 'SAVE RESULTS' ); 133 | 134 | [ directory , name , ~ ] = fileparts( CALCIUM_FLUORESCENCE_file ); 135 | 136 | OUTPUT_PATH = [ directory '/' strrep( name , '_CALCIUM-FLUORESCENCE' , '_ASSEMBLIES-COLLECTION' ) '.mat' ]; 137 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 138 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 139 | 140 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 141 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 142 | else 143 | output_args = NaN; 144 | 145 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 146 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 147 | end 148 | 149 | %% > PRINT TIMING 150 | if( isdeployed ) 151 | printConsoleSection( 'TIMING' ); 152 | 153 | fprintf( 1 , [ 'Elapsed time (walltime): %.3fs\n' ] , toc(timerVal) ); 154 | 155 | end 156 | 157 | end 158 | -------------------------------------------------------------------------------- /assembly-detection/CORE_ASSEMBLY_DETECTION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = CORE_ASSEMBLY_DETECTION( SPIKE_PROBABILITY_RASTER_file ) 2 | %CORE_ASSEMBLY_DETECTION( SPIKE_PROBABILITY_RASTER_file ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,1); 9 | 10 | fprintf( 1 , [ '\n' ] ); 11 | 12 | timerVal = tic; 13 | 14 | %% > PRINT FUNCTION-CALL 15 | if( isdeployed ) 16 | printConsoleSection( 'FUNCTION CALL' ); 17 | 18 | fprintf( 1 , [ 'CORE_ASSEMBLY_DETECTION( %s )' '\n' ] , SPIKE_PROBABILITY_RASTER_file ); 19 | fprintf( 1 , [ '\n' ] ); 20 | end 21 | 22 | %% > 23 | 24 | if( exist( SPIKE_PROBABILITY_RASTER_file , 'file' ) == 2 ) 25 | 26 | SPIKE_PROBABILITY_RASTER_mat = load( SPIKE_PROBABILITY_RASTER_file ); 27 | 28 | output_args = findCOREassemblies( SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster , SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster_thresholds( [ SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster_thresholds.p ] == 0.05 ).coactivity ); 29 | 30 | printConsoleSection( 'SAVE RESULTS' ); 31 | 32 | [ directory , name , ~ ] = fileparts( SPIKE_PROBABILITY_RASTER_file ); 33 | 34 | OUTPUT_PATH = [ directory '/' strrep( name , '_SPIKE-PROBABILITY-RASTER' , '_CORE-ASSEMBLIES' ) '.mat' ]; 35 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 36 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 37 | 38 | 39 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 40 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 41 | else 42 | output_args = NaN; 43 | 44 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 45 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 46 | end 47 | 48 | %% > PRINT TIMING 49 | if( isdeployed ) 50 | printConsoleSection( 'TIMING' ); 51 | 52 | fprintf( 1 , [ 'Elapsed time (walltime): %.3fs\n' ] , toc(timerVal) ); 53 | 54 | end 55 | 56 | end 57 | -------------------------------------------------------------------------------- /assembly-detection/FIM_PSF_PSR_ASSEMBLY_DETECTION/README__psf+psr: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'PSF+PSR' PACKAGE 2 | (http://www.borgelt.net/pycoco.html / http://www.borgelt.net/python/psf+psr.tar.gz) 3 | BY CHRISTIAN BORGELT. 4 | 5 | THE FUNCTIONS REMAINED UN-MODIFIED. 6 | 7 | 8 | 9 | FOR THE FUNCTIONS TO BE USED THE PYFIM MODULE BY CHRISTIAN BORGELT HAS TO 10 | BE INSTALLED. 11 | 12 | INSTRUCTIONS: 13 | 1. DOWNLOAD PYFIM PACKAGE: curl -O http://www.borgelt.net/src/pyfim.tar.gz 14 | 2. EXTRACT PACKAGE: tar -xzvf pyfim.tar.gz 15 | 3. INSTALL PYFIM MODULE: python setup_fim.py install --user -------------------------------------------------------------------------------- /assembly-detection/FIM_PSF_PSR_ASSEMBLY_DETECTION/parse_FIM_PSF_PSR_ASSEMBLIES.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = parse_FIM_PSF_PSR_ASSEMBLIES( input_args ) 2 | 3 | output_args = cell(0,0); 4 | 5 | for a = input_args 6 | R_ = regexp( a{:} , '([\d\s]+) \[supp=\d+\]' , 'tokens' ); 7 | 8 | if( ~isempty( R_ ) ) 9 | output_args{ numel( output_args ) + 1 } = sort( cellfun( @str2double , strsplit( char( R_{1} ) ) , 'UniformOutput' , true ) ); 10 | end 11 | end 12 | 13 | end 14 | 15 | -------------------------------------------------------------------------------- /assembly-detection/FIM_PSF_PSR_ASSEMBLY_DETECTION/psf+psr/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, 7 | publish, distribute, sublicense, and/or sell copies of the Software, 8 | and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 16 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assembly-detection/FIM_PSF_PSR_ASSEMBLY_DETECTION/py__FIM_PSF_PSR_ASSEMBLY_DETECTION.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset 3 | 4 | #py__FIM_PSF_PSR_ASSEMBLY_DETECTION ACTIVITY_FIM_RASTER_file 5 | # 6 | # 7 | # === Jan Moelter, The University of Queensland, 2018 =================== 8 | # 9 | 10 | SCRIPT=$( readlink --canonicalize $0 ) 11 | ROOT=$( dirname $SCRIPT ) 12 | 13 | 14 | ACTIVITY_FIM_RASTER_DAT=$1 15 | FIM_PSF_PSR_ASSEMBLIES_DAT=${ACTIVITY_FIM_RASTER_DAT/_ACTIVITY-FIM-RASTER.dat/_FIM-PSF-PSR-ASSEMBLIES.dat} 16 | 17 | if [[ -e "${ACTIVITY_FIM_RASTER_DAT}" ]]; then 18 | if ! [[ -e "${FIM_PSF_PSR_ASSEMBLIES_DAT}" ]]; then 19 | python ${ROOT}/psf+psr/psf+psr/fim+psf+psr.py -tc -uc -s-6 -gp -c1000 -Z2 -RS -S0 -v" [supp=%d]" "${ACTIVITY_FIM_RASTER_DAT}" "${FIM_PSF_PSR_ASSEMBLIES_DAT}" 20 | fi 21 | 22 | ( >&1 echo ">> END PROGRAM" ) 23 | ( >&2 echo ">> END PROGRAM" ) 24 | fi 25 | -------------------------------------------------------------------------------- /assembly-detection/FIM_PSF_PSR_ASSEMBLY_DETECTION/pyfim.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoodhillLab/neural-assembly-detection/f5415317aec2cf141e8f48ef816cddac0547cac3/assembly-detection/FIM_PSF_PSR_ASSEMBLY_DETECTION/pyfim.tar.gz -------------------------------------------------------------------------------- /assembly-detection/ICA_ASSEMBLY_DETECTION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = ICA_ASSEMBLY_DETECTION( CALCIUM_FLUORESCENCE_file ) 2 | %ICA_ASSEMBLY_DETECTION( CALCIUM_FLUORESCENCE_file ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,1); 9 | 10 | fprintf( 1 , [ '\n' ] ); 11 | 12 | timerVal = tic; 13 | 14 | %% > PRINT FUNCTION-CALL 15 | if( isdeployed ) 16 | printConsoleSection( 'FUNCTION CALL' ); 17 | 18 | fprintf( 1 , [ 'ICA_ASSEMBLY_DETECTION( %s )' '\n' ] , CALCIUM_FLUORESCENCE_file ); 19 | fprintf( 1 , [ '\n' ] ); 20 | end 21 | 22 | if( exist( CALCIUM_FLUORESCENCE_file , 'file' ) == 2 ) 23 | 24 | CALCIUM_FLUORESCENCE_mat = load( CALCIUM_FLUORESCENCE_file ); 25 | 26 | printConsoleSection( 'RUN ICA ASSEMBLY DETECTION' ); 27 | 28 | output_args = findICAAssemblies( CALCIUM_FLUORESCENCE_mat.calcium_fluorescence.dF_F , 1e-10 ); 29 | 30 | printConsoleSection( 'SAVE RESULTS' ); 31 | 32 | [ directory , name , ~ ] = fileparts( CALCIUM_FLUORESCENCE_file ); 33 | 34 | OUTPUT_PATH = [ directory '/' strrep( name , '_CALCIUM-FLUORESCENCE' , '_ICA-ASSEMBLIES' ) '.mat' ]; 35 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 36 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 37 | 38 | 39 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 40 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 41 | else 42 | output_args = NaN; 43 | 44 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 45 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 46 | end 47 | 48 | %% > PRINT TIMING 49 | if( isdeployed ) 50 | printConsoleSection( 'TIMING' ); 51 | 52 | fprintf( 1 , [ 'Elapsed time (walltime): %.3fs\n' ] , toc(timerVal) ); 53 | 54 | end 55 | 56 | end 57 | -------------------------------------------------------------------------------- /assembly-detection/PROMAX_CS_ASSEMBLY_DETECTION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = PROMAX_CS_ASSEMBLY_DETECTION( RASTER_file ) 2 | %PROMAX_CS_ASSEMBLY_DETECTION( RASTER_file ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,1); 9 | 10 | fprintf( 1 , [ '\n' ] ); 11 | 12 | timerVal = tic; 13 | 14 | %% > PRINT FUNCTION-CALL 15 | if( isdeployed ) 16 | printConsoleSection( 'FUNCTION CALL' ); 17 | 18 | fprintf( 1 , [ 'PROMAX_CS_ASSEMBLY_DETECTION( %s )' '\n' ] , RASTER_file ); 19 | fprintf( 1 , [ '\n' ] ); 20 | end 21 | 22 | if( exist( RASTER_file , 'file' ) == 2 ) 23 | 24 | printConsoleSection( 'RUN ASSEMBLY DETECTION' ); 25 | 26 | % if( isdeployed ) 27 | opts.threshold_method = 'circularshift'; 28 | opts.zMax = Inf; 29 | FindAssemblies( RASTER_file , opts ); 30 | % else 31 | % opts.threshold_method = 'circularshift'; 32 | % FindAssemblies( RASTER_file , opts ); 33 | % end 34 | AssembliesActivations( strrep( RASTER_file , '_RASTER' , '_PROMAX-CS-ASSEMBLIES' ) ); 35 | 36 | output_args = load( strrep( RASTER_file , '_RASTER' , '_PROMAX-CS-ASSEMBLIES' ) ); 37 | 38 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 39 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 40 | else 41 | output_args = NaN; 42 | 43 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 44 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 45 | end 46 | 47 | %% > PRINT TIMING 48 | if( isdeployed ) 49 | printConsoleSection( 'TIMING' ); 50 | 51 | fprintf( 1 , [ 'Elapsed time (walltime): %.3fs\n' ] , toc(timerVal) ); 52 | 53 | end 54 | 55 | end 56 | -------------------------------------------------------------------------------- /assembly-detection/PROMAX_MP_ASSEMBLY_DETECTION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = PROMAX_MP_ASSEMBLY_DETECTION( RASTER_file ) 2 | %PROMAX_MP_ASSEMBLY_DETECTION( RASTER_file ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,1); 9 | 10 | fprintf( 1 , [ '\n' ] ); 11 | 12 | timerVal = tic; 13 | 14 | %% > PRINT FUNCTION-CALL 15 | if( isdeployed ) 16 | printConsoleSection( 'FUNCTION CALL' ); 17 | 18 | fprintf( 1 , [ 'PROMAX_MP_ASSEMBLY_DETECTION( %s )' '\n' ] , RASTER_file ); 19 | fprintf( 1 , [ '\n' ] ); 20 | end 21 | 22 | if( exist( RASTER_file , 'file' ) == 2 ) 23 | 24 | printConsoleSection( 'RUN ASSEMBLY DETECTION' ); 25 | 26 | % if( isdeployed ) 27 | opts.zMax = Inf; 28 | FindAssemblies( RASTER_file , opts ); 29 | % else 30 | % FindAssemblies( RASTER_file ); 31 | % end 32 | AssembliesActivations( strrep( RASTER_file , '_RASTER' , '_PROMAX-MP-ASSEMBLIES' ) ); 33 | 34 | output_args = load( strrep( RASTER_file , '_RASTER' , '_PROMAX-MP-ASSEMBLIES' ) ); 35 | 36 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 37 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 38 | else 39 | output_args = NaN; 40 | 41 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 42 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 43 | end 44 | 45 | %% > PRINT TIMING 46 | if( isdeployed ) 47 | printConsoleSection( 'TIMING' ); 48 | 49 | fprintf( 1 , [ 'Elapsed time (walltime): %.3fs\n' ] , toc(timerVal) ); 50 | 51 | end 52 | 53 | end 54 | -------------------------------------------------------------------------------- /assembly-detection/SGC_ASSEMBLY_DETECTION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = SGC_ASSEMBLY_DETECTION( ACTIVITY_RASTER_file ) 2 | %SGC_ASSEMBLY_DETECTION( ACTIVITY_RASTER_file ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,1); 9 | 10 | fprintf( 1 , [ '\n' ] ); 11 | 12 | timerVal = tic; 13 | 14 | %% > PRINT FUNCTION-CALL 15 | if( isdeployed ) 16 | printConsoleSection( 'FUNCTION CALL' ); 17 | 18 | fprintf( 1 , [ 'SGC_ASSEMBLY_DETECTION( %s )' '\n' ] , ACTIVITY_RASTER_file ); 19 | fprintf( 1 , [ '\n' ] ); 20 | end 21 | 22 | %% > 23 | 24 | if( exist( ACTIVITY_RASTER_file , 'file' ) == 2 ) 25 | 26 | if( exist( strrep( ACTIVITY_RASTER_file , '_ACTIVITY-RASTER' , '_SGC-ASSEMBLIES' ) , 'file' ) ~= 2 ) 27 | 28 | printConsoleSection( 'INITIALISE ASSEMBLY PATTERN DETECTION' ); 29 | 30 | ACTIVITY_RASTER_mat = load( ACTIVITY_RASTER_file ); 31 | 32 | activity_patterns = num2cell( ACTIVITY_RASTER_mat.activity_raster( ACTIVITY_RASTER_mat.activity_raster_peaks , : ) , 2 ); 33 | 34 | printConsoleSection( 'RUN ASSEMBLY PATTERN DETECTION' ); 35 | 36 | output_args.assembly_pattern_detection = findAssemblyPatterns( activity_patterns ); 37 | 38 | output_args.assemblies = cellfun( @(a) uint16( find( a ~= 0 ) ) , output_args.assembly_pattern_detection.assemblyActivityPatterns , 'UniformOutput' , false ); 39 | 40 | else 41 | 42 | printConsoleSection( 'INITIALISE ASSEMBLY PATTERN DETECTION' ); 43 | 44 | output_args = load( strrep( ACTIVITY_RASTER_file , '_ACTIVITY-RASTER' , '_SGC-ASSEMBLIES' ) ); 45 | 46 | printConsoleSection( 'REDO ASSEMBLY PATTERN DETECTION' ); 47 | 48 | output_args.assembly_pattern_detection = refreshAssemblyPatterns( output_args.assembly_pattern_detection ); 49 | 50 | output_args.assemblies = cellfun( @(a) uint16( find( a ~= 0 ) ) , output_args.assembly_pattern_detection.assemblyActivityPatterns , 'UniformOutput' , false ); 51 | 52 | end 53 | 54 | printConsoleSection( 'SAVE RESULTS' ); 55 | 56 | [ directory , name , ~ ] = fileparts( ACTIVITY_RASTER_file ); 57 | 58 | OUTPUT_PATH = [ directory '/' strrep( name , '_ACTIVITY-RASTER' , '_SGC-ASSEMBLIES' ) '.mat' ]; 59 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 60 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 61 | 62 | 63 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 64 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 65 | else 66 | output_args = NaN; 67 | 68 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 69 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 70 | end 71 | 72 | %% > PRINT TIMING 73 | if( isdeployed ) 74 | printConsoleSection( 'TIMING' ); 75 | 76 | fprintf( 1 , [ 'Elapsed time (walltime): %.3fs\n' ] , toc(timerVal) ); 77 | 78 | end 79 | 80 | end 81 | -------------------------------------------------------------------------------- /assembly-detection/SVD_ASSEMBLY_DETECTION.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = SVD_ASSEMBLY_DETECTION( SPIKE_PROBABILITY_RASTER_file ) 2 | %SVD_ASSEMBLY_DETECTION( SPIKE_PROBABILITY_RASTER_file ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,1); 9 | 10 | fprintf( 1 , [ '\n' ] ); 11 | 12 | timerVal = tic; 13 | 14 | %% > PRINT FUNCTION-CALL 15 | if( isdeployed ) 16 | printConsoleSection( 'FUNCTION CALL' ); 17 | 18 | fprintf( 1 , [ 'SVD_ASSEMBLY_DETECTION( %s )' '\n' ] , SPIKE_PROBABILITY_RASTER_file ); 19 | fprintf( 1 , [ '\n' ] ); 20 | end 21 | 22 | %% > 23 | 24 | if( exist( SPIKE_PROBABILITY_RASTER_file , 'file' ) == 2 ) 25 | 26 | SPIKE_PROBABILITY_RASTER_mat = load( SPIKE_PROBABILITY_RASTER_file ); 27 | 28 | %disp( SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster_threshold ); 29 | %I = sum( SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster , 2 ) > SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster_threshold; 30 | [ core_svd , state_pks_full , ~ ] = findSVDensemble( transpose( SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster ) , NaN , struct( 'pks' , SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster_thresholds( [ SPIKE_PROBABILITY_RASTER_mat.spike_probability_raster_thresholds.p ] == 0.01 ).coactivity , 'ticut' , [] , 'jcut' , [] , 'state_cut' , [] ) ); 31 | 32 | output_args.assemblies = cellfun( @(a) uint16( transpose( a ) ) , transpose( core_svd ) , 'UniformOutput' , false ); 33 | output_args.assemblies_activation = transpose( state_pks_full ); 34 | 35 | 36 | 37 | printConsoleSection( 'SAVE RESULTS' ); 38 | 39 | [ directory , name , ~ ] = fileparts( SPIKE_PROBABILITY_RASTER_file ); 40 | 41 | OUTPUT_PATH = [ directory '/' strrep( name , '_SPIKE-PROBABILITY-RASTER' , '_SVD-ASSEMBLIES' ) '.mat' ]; 42 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 43 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 44 | 45 | 46 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 47 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 48 | else 49 | output_args = NaN; 50 | 51 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 52 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 53 | end 54 | 55 | %% > PRINT TIMING 56 | if( isdeployed ) 57 | printConsoleSection( 'TIMING' ); 58 | 59 | fprintf( 1 , [ 'Elapsed time (walltime): %.3fs\n' ] , toc(timerVal) ); 60 | 61 | end 62 | 63 | end 64 | -------------------------------------------------------------------------------- /assembly-detection/findCOREassemblies.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = findCOREassemblies( spike_probability_raster , spike_probability_coactivity_threshold ) 2 | %FINDCOREASSEMBLIES( spike_probability_raster , spike_probability_coactivity_threshold ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | %% > EXTRACT ENSEMBLES 9 | printConsoleSection( 'EXTRACT ENSEMBLES' ); 10 | 11 | i_ensemble = ( sum( spike_probability_raster , 2 ) > spike_probability_coactivity_threshold ); 12 | 13 | ensembles = num2cell( spike_probability_raster( i_ensemble , : ) , 2 ); 14 | ensembles_raster = cell2mat( ensembles ); 15 | 16 | pearson_R = corr( ensembles_raster' , 'type' , 'Pearson' ); 17 | z_pearson_R = 0.5 * log( ( 1 + pearson_R ) ./ ( 1 - pearson_R ) ); 18 | 19 | %% > DETERMINE SIGNIFICANT ENSEMBLE SIMILARITY THRESHOLD 20 | printConsoleSection( 'DETERMINE SIGNIFICANT ENSEMBLE SIMILARITY THRESHOLD' ); 21 | 22 | FULLY_VECTORISED = false; 23 | 24 | if( FULLY_VECTORISED ) 25 | 26 | % ! MEMORY INTESIVE 27 | 28 | shuff_pearson_R = zeros( [ 50000 , size( pearson_R ) ] ); 29 | 30 | timer_ = tic; 31 | print_progress( 0 , 'initialise' , timer_ ); 32 | for s = 1:size( shuff_pearson_R , 1 ) 33 | 34 | iN_shuffle = randperm( size( ensembles_raster , 2 ) ); 35 | shuff_pearson_R(s,:,:) = corr( ensembles_raster' , ensembles_raster(:,iN_shuffle)' , 'type' , 'Pearson' ); 36 | 37 | print_progress( s / size( shuff_pearson_R , 1 ) , 'update' , timer_ ); 38 | end 39 | print_progress( 1 , 'finalise' , timer_ ); 40 | 41 | sig_pearson_R = squeeze( prctile( shuff_pearson_R , 95 ) ); 42 | 43 | else 44 | 45 | sig_pearson_R = NaN * ones( size( pearson_R ) ); 46 | 47 | 48 | if( ~FULLY_VECTORISED ) 49 | 50 | M = size( sig_pearson_R , 1 ); 51 | n_C = 150; 52 | 53 | n_I_clusters = floor( M / ceil( M / n_C ) ) * ones( 1 , ceil( M / n_C ) ) + [ ones( 1 , mod( M , ceil( M / n_C ) ) ) , zeros( 1 , ceil( M / n_C ) - mod( M , ceil( M / n_C ) ) ) ]; 54 | n_I_clusters = n_I_clusters( randperm( numel( n_I_clusters ) ) ); 55 | 56 | I_values = randperm( M ); 57 | I_clusters = cell( 1 , numel( n_I_clusters ) ); 58 | for t = 1:numel( I_clusters ) 59 | I_clusters{t} = I_values( 1:n_I_clusters(t) ); 60 | I_values = I_values( (n_I_clusters(t)+1):end ); 61 | end 62 | 63 | else 64 | 65 | I_clusters = { 1:size( sig_pearson_R , 1 ) }; 66 | end 67 | 68 | 69 | for C_i = I_clusters 70 | for C_j = I_clusters 71 | 72 | shuff_pearson_R = zeros( [ 50000 , numel(C_i{:}) , numel(C_j{:}) ] ); 73 | 74 | for s = 1:size( shuff_pearson_R , 1 ) 75 | 76 | iN_shuffle = randperm( size( ensembles_raster , 2 ) ); 77 | shuff_pearson_R(s,:,:) = corr( ensembles_raster(C_i{:},:)' , ensembles_raster(C_j{:},iN_shuffle)' , 'type' , 'Pearson' ); 78 | end 79 | 80 | sig_pearson_R(C_i{:},C_j{:}) = prctile( shuff_pearson_R , 95 ); 81 | end 82 | end 83 | 84 | end 85 | 86 | I_sig_pearson_R = ( pearson_R > sig_pearson_R ); 87 | 88 | output_args.ensemble_detection.ensembles = ensembles; 89 | output_args.ensemble_detection.ensembleSimilarity = pearson_R; 90 | output_args.ensemble_detection.ensembleSimilaritySignificanceThreshold = sig_pearson_R; 91 | 92 | 93 | %% > FIND CORE ENSEMBLES 94 | printConsoleSection( 'FIND CORE ENSEMBLES' ); 95 | 96 | CONST.CORE_AFFINITY = 0.5; 97 | 98 | cores_ensembles = cellfun( @(I) mean( cell2mat( ensembles( I ) ) , 1 ) >= CONST.CORE_AFFINITY , num2cell( I_sig_pearson_R , 2 ) , 'UniformOutput' , false ); 99 | cores_ensembles = cores_ensembles( cellfun( @(C) any( C ) , cores_ensembles ) ); 100 | cores_ensembles = num2cell( unique( cell2mat( cores_ensembles ) , 'rows' ) , 2 ); 101 | 102 | unit_prob = mean( spike_probability_raster ); 103 | cores_ensembles_prob = cellfun( @(C) mean( all( spike_probability_raster( : , C ) , 2 ) ) , cores_ensembles ); 104 | cores_ensembles_0prob = cellfun( @(C) prod( unit_prob( C ) ) , cores_ensembles ); 105 | 106 | 107 | cores_ensembles = cores_ensembles( cores_ensembles_prob > cores_ensembles_0prob ); 108 | cores_ensembles = cellfun( @double , cores_ensembles , 'UniformOutput' , false ); 109 | cores_ensembles_raster = cell2mat( cores_ensembles ); 110 | 111 | 112 | output_args.ensemble_detection.coreEnsembles = cores_ensembles; 113 | 114 | %% > CLUSTER CORE ENSEMBLES 115 | printConsoleSection( 'CLUSTER CORE ENSEMBLES' ); 116 | 117 | switch numel( cores_ensembles ) 118 | case 0 119 | core_ensembles_IClusters = NaN; 120 | assemblies = {}; 121 | case 1 122 | core_ensembles_IClusters = { [1] }; 123 | assemblies = { uint16( find( cores_ensembles_raster( 1 , : ) >= 0.5 ) ) }; 124 | 125 | otherwise 126 | CONST.SILHOUETTE_ROUNDS = 100; 127 | 128 | silhouettes_S = cell( CONST.SILHOUETTE_ROUNDS , 1 ); 129 | 130 | dist = 'hamming'; 131 | 132 | timer_ = tic; 133 | print_progress( 0 , 'initialise' , timer_ ); 134 | for r = 1:numel( silhouettes_S ) 135 | silhouettes_S{r} = arrayfun( @(k) mean( silhouette( cores_ensembles_raster , kmeans( cores_ensembles_raster , k , 'Distance' , dist ) , dist ) ) , 1:ceil( size( cores_ensembles_raster , 1 ) / 4 ) , 'UniformOutput' , true ); 136 | 137 | print_progress( r / CONST.SILHOUETTE_ROUNDS , 'update' , timer_ ); 138 | end 139 | print_progress( 1 , 'finalise' , timer_ ); 140 | 141 | 142 | % [ silhouettes_S_k , k ] = max( mean( cell2mat( silhouettes_S ) , 1 ) ); 143 | [ ~ , k ] = max( max( cell2mat( silhouettes_S ) , [] , 1 ) ); 144 | 145 | fprintf( 1 , [ '> optimal number of clusters of core ensembles: %u' '\n' ] , k ); 146 | 147 | g = ones( 1 , size( cores_ensembles_raster , 1 ) ); 148 | g_S = 0; 149 | 150 | for r = 1:CONST.SILHOUETTE_ROUNDS 151 | g_ = kmeans( cores_ensembles_raster , k , 'Distance' , dist )'; 152 | g_S_ = mean( silhouette( cores_ensembles_raster , g_' , dist ) ); 153 | if( g_S_ > g_S ) 154 | g_S = g_S_; 155 | g = g_; 156 | end 157 | end 158 | 159 | 160 | core_ensembles_IClusters = arrayfun( @(r) find( g == r ) , unique( g ) , 'UniformOutput' , false ); 161 | 162 | assemblies = cellfun( @(I) uint16( find( mean( cores_ensembles_raster( I , : ) ) >= 0.5 ) ) , core_ensembles_IClusters , 'UniformOutput' , false ); 163 | assemblies = assemblies( ~cellfun( @isempty , assemblies ) ); 164 | 165 | end 166 | 167 | output_args.ensemble_detection.coreEnsemblesIClusters = core_ensembles_IClusters; 168 | output_args.assemblies = assemblies; 169 | 170 | end -------------------------------------------------------------------------------- /assembly-detection/findICAAssemblies.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = findICAAssemblies( deltaFoF , KS_significance ) 2 | %FINDICAASSEMBLIES( deltaFoF , KS_significance ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,2); 9 | if( nargin == 1 ) 10 | KS_significance = 0.1; 11 | end 12 | 13 | if( size( deltaFoF , 1 ) >= size( deltaFoF , 2 ) ) 14 | 15 | X = transpose( deltaFoF ); 16 | 17 | 18 | opts.threshold.method = 'MarcenkoPastur'; 19 | opts.Patterns.method = 'ICA'; 20 | opts.Patterns.number_of_iterations = 500; 21 | 22 | ica_assembly_patterns = assembly_patterns( X , opts ); 23 | 24 | mp_assembly_vectors = cellfun( @(a) largest_positive( a ) , num2cell( ica_assembly_patterns , 1 ) , 'UniformOutput' , false ); 25 | 26 | 27 | opts.threshold.method = 'circularshift'; 28 | opts.threshold.permutations_percentile = 95; 29 | opts.threshold.number_of_permutations = 500; 30 | opts.Patterns.method = 'ICA'; 31 | opts.Patterns.number_of_iterations = 500; 32 | 33 | ica_assembly_patterns = assembly_patterns( X , opts ); 34 | 35 | cs_assembly_vectors = cellfun( @(a) largest_positive( a ) , num2cell( ica_assembly_patterns , 1 ) , 'UniformOutput' , false ); 36 | 37 | 38 | 39 | for i = 1:numel( KS_significance ) 40 | 41 | output_args(i).cs_assembly_vectors = cs_assembly_vectors; 42 | 43 | output_args(i).cs_assemblies = transpose( cellfun( @(v) find( abs(v) > mean(abs(v)) + 2 * std(abs(v)) ) , output_args(i).cs_assembly_vectors , 'UniformOutput' , false ) ); 44 | output_args(i).cs_assemblies = output_args(i).cs_assemblies( ~cellfun( @isempty , output_args(i).cs_assemblies , 'UniformOutput' , true ) ); 45 | 46 | 47 | 48 | output_args(i).ks_alpha = KS_significance(i); 49 | 50 | output_args(i).mp_assembly_vectors = mp_assembly_vectors; 51 | output_args(i).mp_assembly_vectors = output_args(i).mp_assembly_vectors( cellfun( @(x) kstest( zscore( x ) , 'Alpha' , output_args(i).ks_alpha ) , output_args(i).mp_assembly_vectors , 'UniformOutput' , true ) ); 52 | % \_ select only those assembly vectors whose components seem to not come from a standard normal distribution 53 | 54 | output_args(i).mp_assemblies = transpose( cellfun( @(v) find( abs(v) > mean(abs(v)) + 2 * std(abs(v)) ) , output_args(i).mp_assembly_vectors , 'UniformOutput' , false ) ); 55 | output_args(i).mp_assemblies = output_args(i).mp_assemblies( ~cellfun( @isempty , output_args(i).mp_assemblies , 'UniformOutput' , true ) ); 56 | 57 | 58 | end 59 | 60 | else 61 | 62 | error( [ 'Error :: N > T' ] ); 63 | end 64 | 65 | end 66 | -------------------------------------------------------------------------------- /assembly-detection/helper/interactive_PROMAX_ASSEMBLY_DETECTION.m: -------------------------------------------------------------------------------- 1 | 2 | clc; 3 | 4 | ROOT = input( 'ROOT = ' , 's' ); 5 | 6 | items = dir( [ ROOT ] ); 7 | items = transpose( items ); 8 | items = items( [ items.isdir ] & [ ~strcmp( { items.name } , '.' ) ] & [ ~strcmp( { items.name } , '..' ) ] ); 9 | 10 | items = items( shuffle_vector( 1:numel( items ) ) ); 11 | 12 | 13 | for I = items 14 | 15 | if( exist( [ ROOT '/' I.name '/' I.name '_RASTER.mat' ] , 'file' ) == 2 ) 16 | 17 | if( exist( [ ROOT '/' I.name '/' I.name '_CLUSTERS.mat' ] , 'file' ) ~= 2 ) 18 | 19 | PROMAX_ASSEMBLY_DETECTION( [ ROOT '/' I.name '/' I.name '_RASTER.mat' ] ); 20 | 21 | end 22 | end 23 | end -------------------------------------------------------------------------------- /assembly-detection/helper/interactive_PROMAX_ASSEMBLY_DETECTION_VALIDATION.m: -------------------------------------------------------------------------------- 1 | function interactive_PROMAX_ASSEMBLY_DETECTION_VALIDATION() 2 | 3 | clc; 4 | 5 | ROOT = input( 'ROOT = ' , 's' ); 6 | 7 | items = dir( [ ROOT ] ); 8 | items = transpose( items ); 9 | items = items( [ items.isdir ] & [ ~strcmp( { items.name } , '.' ) ] & [ ~strcmp( { items.name } , '..' ) ] ); 10 | 11 | items = items( shuffle_vector( 1:numel( items ) ) ); 12 | 13 | for I = items 14 | 15 | if( exist( [ ROOT '/' I.name '/' I.name '_CLUSTERS.mat' ] , 'file' ) == 2 ) 16 | 17 | CheckAssemblies( [ ROOT '/' I.name '/' I.name '_CLUSTERS.mat' ] ) 18 | 19 | end 20 | end 21 | 22 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findICAAssemblies/README__toolbox: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'ICA-ASSEMBLY-DETECTION-TOOLBOX' 2 | AS DESCRIBED IN { Lopes-dos-Santos V., Ribeiro S., Tort A.B.L. (2013) J. Neurosci. Meth. } 3 | KINDLY PROVIDED BY VITOR LOPES-DOS-SANTOS. 4 | 5 | THE FOLLOWING FUNCTIONS WERE MODIFIED FROM THEIR ORIGINAL STATE (indicated with '% # '): 6 | 7 | _ assembly_patterns.m 8 | 9 | THE OTHER FUNCTIONS REMAINED UN-MODIFIED. -------------------------------------------------------------------------------- /assembly-detection/inc_findICAAssemblies/toolbox/assembly_activity.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoodhillLab/neural-assembly-detection/f5415317aec2cf141e8f48ef816cddac0547cac3/assembly-detection/inc_findICAAssemblies/toolbox/assembly_activity.m -------------------------------------------------------------------------------- /assembly-detection/inc_findICAAssemblies/toolbox/assembly_patterns.m: -------------------------------------------------------------------------------- 1 | % # (JM) MODIFIED FROM ORIGINAL FUNCTION 'assembly_patterns' 2 | 3 | function AssemblyTemplates = assembly_patterns(SpikeCount,opts) 4 | 5 | % Patterns = assembly_patterns(Activitymatrix,opts): extracts assembly patterns from the spike matrix. 6 | % 7 | % Description of inputs: 8 | % Activitymatrix: spike matrix. Rows represent neurons, columns represent time bins. Thus, each element of the matrix carries the spike count of a given neuron at a given bin. 9 | % opts: set parameters. All fields described below. 10 | % opts.threshold.method: defines the method to compute the threshold for assembly detection. Options are: 11 | % 'MarcenkoPastur': uses the analytical bound. 12 | % 'binshuffling': estimate eigenvalue distribution for independent activity from surrogate matrices generated by shuffling time bins. 13 | % 'circularshift': estimate eigenvalue distribution for independent activity from surrogate matrices generated by random circular shifts of original spike matrix. 14 | % opts.threshold.permutations_percentile: defines which percentile of the surrogate distribution of maximal eigenvalues is used as statistical threshold. It must be a number between 0 and 100 (95 or larger recommended). Not used when 'MarcenkoPastur' is chosen. 15 | % opts.threshold.number_of_permutations: defines how many surrogate matrices are generated (100 or more recommended). Not used when 'MarcenkoPastur' is chosen. 16 | % opts.Patterns.method: defines which method is used to extract assembly patterns. Options are: 'PCA' or 'ICA' (recommended). 17 | % opts.Patterns.number_of_iterations: number of iterations for fastICA algorithm (100 or more recommended). Not used when 'PCA' is chosen. 18 | % 19 | % Description of outputs: 20 | % Patterns: assembly patterns. Columns denote assembly # and rows neuron #. 21 | % 22 | % By simply running Patterns = assembly_patterns(Activitymatrix); The following default options will be used: 23 | % opts.Patterns.method: 'ICA' 24 | % opts.threshold.method: 'MarcenkoPastur' 25 | % opts.Patterns.number_of_iterations: 500. 26 | % 27 | % This framework is described in: 28 | % Lopes-dos-Santos V, Ribeiro S, Tort ABL 29 | % (2013) Detecting cell assemblies in large neuronal populations, 30 | % Journal of Neuroscience Methods. 31 | % 32 | % Please send bug reports to vitor@neuro.ufrn.br (V???tor) 33 | 34 | if nargin<2 35 | opts.threshold.method = 'MarcenkoPastur'; 36 | opts.Patterns.method = 'ICA'; 37 | opts.Patterns.number_of_iterations = 500; 38 | end 39 | zSpikeCount = zscore(SpikeCount'); 40 | 41 | CorrMatrix = corr(zSpikeCount); 42 | CorrMatrix(isnan(CorrMatrix))=0; 43 | [eigenvectors,d] = eig(CorrMatrix); 44 | eigenvalues=diag(d); 45 | 46 | q = size(zSpikeCount,1)/size(zSpikeCount,2); 47 | 48 | if q<1 49 | fprintf('Error: Number of time bins must be larger than number of neurons \n') 50 | return 51 | end 52 | 53 | %% Finding number of assemblies 54 | 55 | switch opts.threshold.method 56 | case 'MarcenkoPastur' 57 | % # fprintf('Using Marcenko-Pastur distribution for estimating number of assemblies \n') 58 | lambda_max = ((1+sqrt(1/q))^2); 59 | case 'binshuffling' 60 | % # fprintf('Generating control spike count matrix for estimating number of assemblies \n') 61 | if ~isfield(opts.threshold,'number_of_permutations') 62 | auxmsdg = 'Please enter a number of surrogates larger than zero: '; 63 | opts.threshold.number_of_permutations = input(auxmsdg); 64 | end 65 | if ~isfield(opts.threshold,'permutations_percentile') 66 | auxmsdg = 'Please enter percentile for statistical threshold: '; 67 | opts.threshold.permutations_percentile = input(auxmsdg); 68 | end 69 | while opts.threshold.number_of_permutations<=0 70 | auxmsdg = 'Please enter a number of surrogates larger than zero: '; 71 | opts.threshold.number_of_permutations = input(auxmsdg); 72 | end 73 | % # fprintf(['Number of permutations: ' num2str(opts.threshold.number_of_permutations) '\n']) 74 | control_max_eig = bin_shuffling(SpikeCount,opts.threshold.number_of_permutations); 75 | lambda_max = prctile(control_max_eig,opts.threshold.permutations_percentile); 76 | case 'circularshift' 77 | % # fprintf('Generating control spike count matrix for estimating number of assemblies \n') 78 | if ~isfield(opts.threshold,'number_of_permutations') 79 | auxmsdg = 'Please enter a number of surrogates larger than zero: '; 80 | opts.threshold.number_of_permutations = input(auxmsdg); 81 | end 82 | while opts.threshold.number_of_permutations<=0 83 | auxmsdg = 'Please enter a number of surrogates larger than zero: '; 84 | opts.threshold.number_of_permutations = input(auxmsdg); 85 | end 86 | if ~isfield(opts.threshold,'permutations_percentile') 87 | auxmsdg = 'Please enter percentile for statistical threshold: '; 88 | opts.threshold.permutations_percentile = input(auxmsdg); 89 | end 90 | % # fprintf(['Number of permutations: ' num2str(opts.threshold.number_of_permutations) '\n']) 91 | control_max_eig = circular_shift(SpikeCount,opts.threshold.number_of_permutations); 92 | lambda_max = prctile(control_max_eig,opts.threshold.permutations_percentile); 93 | end 94 | NumberOfAssemblies = sum(eigenvalues>lambda_max); 95 | % # fprintf(['Number of assemblies detected: ' num2str(NumberOfAssemblies) '\n']) 96 | if NumberOfAssemblies<1 97 | AssemblyTemplates=[]; 98 | return 99 | end 100 | %% Finding co-activation patterns 101 | 102 | switch opts.Patterns.method 103 | case 'PCA' 104 | [garbage,PC_position] = sort(-eigenvalues); 105 | AssemblyTemplates = eigenvectors(:,PC_position(1:NumberOfAssemblies)); 106 | 107 | case 'ICA' 108 | AssemblyTemplates=... 109 | fast_ica(zSpikeCount,NumberOfAssemblies,opts.Patterns.number_of_iterations); 110 | 111 | case 'ICA2' 112 | AssemblyTemplates=... 113 | fast_ica(zSpikeCount,length(eigenvalues),opts.Patterns.number_of_iterations); 114 | prjs = AssemblyTemplates'*zSpikeCount'; 115 | sigassemblies = var(prjs,[],2)>lambda_max; 116 | AssemblyTemplates = AssemblyTemplates(:,sigassemblies); 117 | end 118 | 119 | -------------------------------------------------------------------------------- /assembly-detection/inc_findICAAssemblies/toolbox/bin_shuffling.m: -------------------------------------------------------------------------------- 1 | function control_max_eig = bin_shuffling(SpikeCount,number_of_surrogates) 2 | 3 | control_max_eig=zeros(1,number_of_surrogates); 4 | for surr_idx = 1:number_of_surrogates 5 | ControlSpikeCount=zeros(size(SpikeCount)); 6 | for neuron_idx = 1:size(SpikeCount,1) 7 | ControlSpikeCount(neuron_idx,:) = SpikeCount(neuron_idx,randperm(length(SpikeCount))); 8 | end 9 | CorrelationMatrix = corr(ControlSpikeCount'); 10 | [garbage,eigenvalues]=eig(CorrelationMatrix); 11 | control_max_eig(surr_idx)=max(reshape(eigenvalues,1,[])); 12 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findICAAssemblies/toolbox/caller_1.m: -------------------------------------------------------------------------------- 1 | clear all % just clearing workspace 2 | 3 | % define mean firing rate 4 | Network_opts.meanspikebin = 1; 5 | 6 | % define number of neurons 7 | Network_opts.nneurons = 20 ; 8 | 9 | % define number of bins 10 | Network_opts.nbins = 10000; 11 | 12 | % above define assembly membership 13 | 14 | % line below sets neurons 1,2,3 and 4 to be in assembly 1 15 | Assembly_opts.assembly_neurons{1} = [1 2 3 4]; 16 | % line below sets neurons 5,6 and 7 to be in assembly 2 17 | Assembly_opts.assembly_neurons{2} = [5 6 7]; 18 | 19 | % defines number of activation bins 20 | Assembly_opts.number_of_activations = 300; 21 | 22 | % defines mean rate in activation bins 23 | Assembly_opts.meanspikerate_activations = 3; 24 | 25 | % running the function 26 | Activitymatrix = toy_simulation(Network_opts,Assembly_opts); 27 | 28 | %% 29 | 30 | correlationmat = corr(Activitymatrix'); 31 | figure(1),clf 32 | imagesc(correlationmat) 33 | 34 | %% 35 | 36 | opts.threshold.permutations_percentile = 95; 37 | opts.threshold.number_of_permutations = 20; 38 | opts.threshold.method = 'circularshift'; 39 | opts.AssemblyTemplate.method = 'PCA'; 40 | AssemblyTemplates = assembly_patterns(Activitymatrix,opts); 41 | 42 | %% 43 | figure(3),clf 44 | subplot(211) 45 | stem(AssemblyTemplates(:,1)) 46 | subplot(212) 47 | stem(AssemblyTemplates(:,2)) 48 | 49 | %% 50 | 51 | clear all % just clearing workspace 52 | 53 | Network_opts.meanspikebin = 1; 54 | Network_opts.nneurons = 20; 55 | Network_opts.nbins = 10000; 56 | 57 | Assembly_opts.assembly_neurons{1} = [1 2 3 4 5]; 58 | Assembly_opts.assembly_neurons{2} = [4 5 6 7 8]; 59 | Assembly_opts.number_of_activations = 300; 60 | Assembly_opts.meanspikerate_activations = 3; 61 | Activitymatrix = toy_simulation(Network_opts,Assembly_opts); 62 | 63 | opts.threshold.method = 'MarcenkoPastur'; 64 | opts.AssemblyTemplate.method = 'PCA'; 65 | AssemblyTemplates = assembly_patterns(Activitymatrix,opts); 66 | 67 | figure(2),clf 68 | subplot(211) 69 | stem(AssemblyTemplates(:,1)) 70 | subplot(212) 71 | stem(AssemblyTemplates(:,2)) 72 | 73 | 74 | %% 75 | opts.threshold.method = 'MarcenkoPastur'; 76 | opts.AssemblyTemplate.method = 'ICA'; 77 | opts.AssemblyTemplate.number_of_iterations = 200; 78 | AssemblyTemplates = assembly_patterns(Activitymatrix,opts); 79 | 80 | 81 | figure(3),clf 82 | subplot(211) 83 | stem(AssemblyTemplates(:,1)) 84 | subplot(212) 85 | stem(AssemblyTemplates(:,2)) 86 | 87 | %% 88 | 89 | Activities = assembly_activity(AssemblyTemplates,Activitymatrix); 90 | 91 | figure(4),clf 92 | subplot(211) 93 | imagesc(Activitymatrix) 94 | xlim([0 100]) 95 | subplot(212) 96 | plot(Activities') 97 | xlim([0 100]) 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /assembly-detection/inc_findICAAssemblies/toolbox/circular_shift.m: -------------------------------------------------------------------------------- 1 | function control_max_eig = circular_shift(SpikeCount,number_of_surrogates) 2 | 3 | control_max_eig=zeros(1,number_of_surrogates); 4 | for surr_idx = 1:number_of_surrogates 5 | ControlSpikeCount=zeros(size(SpikeCount)); 6 | for neuron_idx = 1:size(SpikeCount,1) 7 | drawnbin = randi(length(SpikeCount),1); 8 | auxbin = [drawnbin:length(SpikeCount) 1:drawnbin-1]; 9 | ControlSpikeCount(neuron_idx,:) = SpikeCount(neuron_idx,auxbin); 10 | end 11 | CorrelationMatrix = corr(ControlSpikeCount'); 12 | [garbage,eigenvalues]=eig(CorrelationMatrix); 13 | control_max_eig(surr_idx)=max(reshape(eigenvalues,1,[])); 14 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findICAAssemblies/toolbox/fast_ica.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoodhillLab/neural-assembly-detection/f5415317aec2cf141e8f48ef816cddac0547cac3/assembly-detection/inc_findICAAssemblies/toolbox/fast_ica.m -------------------------------------------------------------------------------- /assembly-detection/inc_findICAAssemblies/toolbox/toy_simulation.m: -------------------------------------------------------------------------------- 1 | function binnedmatrix = toy_simulation(Network_opts,Assembly_opts) 2 | 3 | % creating matrix 4 | binnedmatrix=poissrnd(Network_opts.meanspikebin,[Network_opts.nneurons Network_opts.nbins]); 5 | 6 | allassemblyneurons = unique([Assembly_opts.assembly_neurons{:}]); 7 | nonassemblyneurons = setdiff(1:Network_opts.nneurons,allassemblyneurons); 8 | nassemblies = length(Assembly_opts.assembly_neurons); 9 | 10 | % add activations of all assemblies in random bins 11 | for assemblyindex=1:nassemblies 12 | 13 | assemblysize = length(Assembly_opts.assembly_neurons{assemblyindex}); 14 | 15 | % drawing activations 16 | activation_bins = randi([1,Network_opts.nbins],1,Assembly_opts.number_of_activations); 17 | 18 | % introducting activations 19 | binnedmatrix(Assembly_opts.assembly_neurons{assemblyindex},activation_bins) = ... 20 | poissrnd(Assembly_opts.meanspikerate_activations,... 21 | assemblysize,Assembly_opts.number_of_activations); 22 | 23 | end 24 | -------------------------------------------------------------------------------- /assembly-detection/inc_findPROMAXAssemblies/CheckAssemblies.m: -------------------------------------------------------------------------------- 1 | function CheckAssemblies( filenameCLUSTERS ) 2 | %CHECKASSEMBLIES( filenameCLUSTERS ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2017 =================== 6 | % 7 | 8 | if( exist( filenameCLUSTERS , 'file' ) == 2 ) 9 | CLUSTERS_mat = load( filenameCLUSTERS ); 10 | 11 | 12 | [ ~ , filenameCLUSTERS_name , ~ ] = fileparts( filenameCLUSTERS ); 13 | 14 | hf = figure( 'Name' , 'zMax cut-off for including cells in assemblies' , ... 15 | 'MenuBar' , 'none' , ... 16 | 'Position' , get( 0 , 'ScreenSize' ) , ... 17 | 'KeyPressFcn' , @KeyPressFcn ); 18 | 19 | plot( CLUSTERS_mat.zMaxDensity.x , CLUSTERS_mat.zMaxDensity.densityNorm , 'LineWidth' , 2 , 'Color' , 'black' ); 20 | hold on; 21 | plot( CLUSTERS_mat.zMaxDensity.normCutOff * [ 1 1 ] , get( gca , 'ylim' ) , 'LineWidth' , 2 , 'LineStyle' , '--' , 'Color' , 'red' ); 22 | 23 | title([ 'zMax cut-off' ' : ' filenameCLUSTERS_name ],'FontWeight','Bold','Interpreter','none'); 24 | xlabel('zMax'); ylabel('Density'); 25 | 26 | try 27 | while( waitforbuttonpress ~= 1 ) 28 | 29 | end 30 | catch 31 | 32 | end 33 | end 34 | 35 | function KeyPressFcn(h, eventArgs) 36 | 37 | switch eventArgs.Key 38 | case 'delete' 39 | fprintf( 2 , 'DELETE *_CLUSTERS.mat :: %s \n\n' , filenameCLUSTERS ); 40 | end 41 | 42 | close( h ); 43 | end 44 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findPROMAXAssemblies/README__Toolbox-Romano-et-al: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'TOOLBOX-ROMANO-ET-AL' 2 | REPOSITORY (https://github.com/zebrain-lab/Toolbox-Romano-et-al). 3 | 4 | THE FOLLOWING FUNCTIONS WERE MODIFIED FROM THEIR ORIGINAL STATE ('% # '): 5 | 6 | _ FindAssemblies.m 7 | _ AssembliesActivations.m 8 | 9 | THE FOLLOWING FUNCTIONS REMAIN UN-MODIFIED: 10 | 11 | _ pValueSynch.m 12 | -------------------------------------------------------------------------------- /assembly-detection/inc_findPROMAXAssemblies/Toolbox-Romano-et-al/AssembliesActivations.m: -------------------------------------------------------------------------------- 1 | % # (JM) MODIFIED FROM ORIGINAL FUNCTION 'AssembliesActivations' 2 | 3 | function AssembliesActivations( filenameCLUSTER ) 4 | 5 | % # [filename,pathname] = uigetfile({'*_CLUSTERS.mat';'*_CLUSTERS.MAT'},'Open file with assemblies data', 'MultiSelect', 'off'); 6 | % # filenameCLUSTER=fullfile(pathname,filename); 7 | 8 | load(filenameCLUSTER); 9 | 10 | % # prompt = {'Select the threshold p-value for the significance of an assembly activation'}; 11 | % # dlg_title = 'User input'; 12 | % # num_lines = 1; 13 | % # def = {'0.01'}; 14 | % # answer = inputdlg(prompt,dlg_title,num_lines,def); 15 | threshSignifMatchIndex = 0.01; % # threshSignifMatchIndex= str2num(answer{1}); 16 | 17 | 18 | numFrames=size(matchIndexTimeSeries,2); 19 | totalClust=length(assembliesCells); 20 | 21 | % This is to keep the complete transient around the peak 22 | matchIndexTimeSeriesSignificant=zeros(totalClust,numFrames); 23 | matchIndexTimeSeriesSignificantPeaks=zeros(totalClust,numFrames); 24 | 25 | for indClust=1:totalClust 26 | tempSignif=(matchIndexTimeSeriesSignificance(indClust,:)<=threshSignifMatchIndex); 27 | matchIndexTimeSeriesSignificant(indClust,:)=zeros(size(matchIndexTimeSeries(indClust,:))); 28 | matchIndexTimeSeriesSignificantPeaks(indClust,tempSignif)=matchIndexTimeSeries(indClust,tempSignif); 29 | indsSignif=find(tempSignif); 30 | zerosMatch=find(matchIndexTimeSeries(indClust,:)==0); 31 | for i=1:length(indsSignif) 32 | temp=zerosMatch-indsSignif(i); 33 | indEnd=zerosMatch(find(temp>0,1,'first')); 34 | indStart=zerosMatch(find(temp<0,1,'last')); 35 | 36 | if isempty(indEnd) 37 | indEnd=numFrames; 38 | end 39 | if isempty(indStart) 40 | indStart=1; 41 | end 42 | 43 | matchIndexTimeSeriesSignificant(indClust,indStart:indEnd)=matchIndexTimeSeries(indClust,indStart:indEnd); 44 | end 45 | end 46 | if strcmp(clustering.method,'PCA-promax') 47 | save(filenameCLUSTER,'clustering','assembliesCells', 'assembliesVectors', 'PCsRot', 'confSynchBinary', 'matchIndexTimeSeries', 'matchIndexTimeSeriesSignificance','matchIndexTimeSeriesSignificant','matchIndexTimeSeriesSignificantPeaks','threshSignifMatchIndex','zMaxDensity') 48 | else 49 | save(filenameCLUSTER,'clustering','assembliesCells', 'confSynchBinary', 'matchIndexTimeSeries', 'matchIndexTimeSeriesSignificance','matchIndexTimeSeriesSignificant','matchIndexTimeSeriesSignificantPeaks','threshSignifMatchIndex') 50 | end 51 | 52 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findPROMAXAssemblies/Toolbox-Romano-et-al/pValueSynch.m: -------------------------------------------------------------------------------- 1 | function pValue=pValueSynch(raster,repetitions) 2 | 3 | rasterShuffle=raster; 4 | x=0:1:size(raster,2); 5 | histTotal=zeros(1,size(x,2)); 6 | for j=1:repetitions 7 | for i=1:size(raster,2) 8 | % This is for permutations of spike times, preserving only spike count 9 | % threshShuffle(:,i)=datos(randperm(size(datos,1)),i); 10 | 11 | % This is for shuffling ISIs, preserving therefore both single cell spike count 12 | % and ISI 13 | spikeTrain=raster(:,i); 14 | indSpike=find(spikeTrain); 15 | ISIs=diff(indSpike); 16 | 17 | spikeTrainShuffled=zeros(size(spikeTrain)); 18 | spikeTrainShuffled(1)=spikeTrain(1); 19 | spikeTrainShuffled(cumsum(ISIs(randperm(size(ISIs,1))))+1)=1; 20 | rasterShuffle(:,i)=spikeTrainShuffled; 21 | end 22 | 23 | rate=sum(rasterShuffle(2:end,:),2); 24 | [histRate, x]=hist(rate,x); 25 | histRate=histRate./sum(histRate); 26 | 27 | histTotal=histTotal + histRate./repetitions; 28 | 29 | end 30 | 31 | pValue=1-cumsum(histTotal); 32 | pValue(find(pValue<0))=pValue(find(pValue<0,1,'First')-1); 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/analyseGraphCommunityStructure/analyseGraphCommunityStructure.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = analyseGraphCommunityStructure( graph , opts ) 2 | %ANALYSEGRAPHCOMMUNITYSTRUCTURE( graph , opts ) Obtains an estimate for the 3 | %community structure of a given graph. 4 | % 5 | % These functions implement the approach described in 6 | % M. E. J. Newman and G. Reinert. "Estimating the number of communities 7 | % in a network". Phys. Rev. Lett. 117 (2016). 8 | % 9 | % INPUT: 10 | % graph [graph]: undirected, unweigted graph 11 | % opts [struct]: (optional) parameters of the algorithm 12 | % .Iterations [scalar]: number of independent MCMC runs (default: 1) 13 | % .MonteCarloSteps [scalar]: number of steps in every MCMC run (default: 10000) 14 | % .RNGSeed [scalar]: seed for the random number generator (default: NaN) 15 | % .initialK [scalar]: initial guess for the number of communities (default: NaN) 16 | % 17 | % OUTPUT: 18 | % output_args [struct]: results 19 | % .graph [graph]: undirected, unweigted graph (same as 20 | % input) 21 | % .communityStructure.count [scalar]: most likely number of 22 | % communities 23 | % .communityStructure.countDistribution [?x2 matrix]: probability 24 | % distribution for the number of communities 25 | % .communityStructure.assignment [1xk cell]: proposed community 26 | % structure given the most likely number of communities 27 | % .communityStructure.markovChainMonteCarloSamples [?x1 cell]: MCMC 28 | % samples 29 | % 30 | % EXAMPLES: 31 | % analyseGraphCommunityStructure( ZacharyKarateClub , struct( 'Iterations' , 1 , 'MonteCarloSteps' , 10000 , 'initialK' , 3 ) ) 32 | % 33 | % 34 | % === Jan Moelter, The University of Queensland, 2017 =================== 35 | % 36 | 37 | narginchk(1,2); 38 | if( nargin == 1 ) 39 | opts = struct(); 40 | end 41 | 42 | if( ~isa( graph , 'graph' ) ) 43 | error( 'Invalid input.' ); 44 | end 45 | 46 | opts_ = struct(); 47 | for opt = transpose( fieldnames( opts ) ) 48 | switch opt{:} 49 | case 'MonteCarloSteps' 50 | opts_.MonteCarloSteps = opts.MonteCarloSteps; 51 | case 'RNGSeed' 52 | opts_.RNGSeed = opts.RNGSeed; 53 | case 'initialK' 54 | opts_.initialK = opts.initialK; 55 | end 56 | end 57 | 58 | if( ~isfield( opts , 'Iterations' ) ) 59 | opts.Iterations = 1; 60 | end 61 | 62 | STD_OPTS = struct( 'MonteCarloSteps' , 10000 , 'RNGSeed' , NaN , 'maximalK' , ceil( numnodes( graph ) / 3 ) , 'initialK' , NaN , 'showBanner' , false ); 63 | for opt = transpose( fieldnames( STD_OPTS ) ) 64 | if( ~isfield( opts_ , opt{:} ) ) 65 | opts_.( opt{:} ) = STD_OPTS.( opt{:} ); 66 | end 67 | end 68 | 69 | 70 | output_args = NaN; 71 | 72 | if( numnodes( graph ) > 0 ) 73 | fprintf( 1 , [ 'Initialising graph community structure estimation ...' '\n' ] ); 74 | 75 | fprintf( 1 , [ ' Number of vertices: %i\n' ] , numnodes( graph ) ); 76 | fprintf( 1 , [ ' Number of edges: %i\n' ] , numedges( graph ) ); 77 | 78 | fprintf( 1 , [ '\n' ] ); 79 | 80 | if( isnan( opts_.RNGSeed ) ) 81 | opts_.RNGSeed = seed_devrandom(); 82 | end 83 | 84 | if( opts.Iterations > 1 ) 85 | fprintf( 1 , [ 'Running graph community structure estimation (' num2str( opts.Iterations ) ' iterations) ...' '\n' ] ); 86 | else 87 | fprintf( 1 , [ 'Running graph community structure estimation ...' '\n' ] ); 88 | end 89 | 90 | fprintf( 1 , [ '\n' ] ); 91 | 92 | % estimation_samples = estimateGraphCommunityStructure( graph , opts_ ); 93 | try 94 | estimation_samples = cell( opts.Iterations , 1 ); 95 | for i = 1:opts.Iterations 96 | timer = tic; 97 | estimation_samples{i} = estimateGraphCommunityStructure( graph , opts_ ); 98 | 99 | if( opts.Iterations > 1 ) 100 | fprintf( 1 , [ ' Iteration %i completed: %s' '\n' ] , i , print_timeinterval( toc( timer ) ) ); 101 | end 102 | end 103 | 104 | fprintf( 1 , [ '\n' ] ); 105 | fprintf( 1 , [ 'Graph community structure estimation completed.' '\n' ] ); 106 | fprintf( 1 , [ '\n' ] ); 107 | catch 108 | fprintf( 1 , [ '\n' ] ); 109 | fprintf( 1 , [ 'Graph community structure estimation failed.' '\n' ] ); 110 | fprintf( 1 , [ '\n' ] ); 111 | 112 | return; 113 | end 114 | 115 | [ k , k_distribution , g ] = computeGraphCommunityStructureMarginals( estimation_samples ); 116 | 117 | output.('graph') = graph; 118 | output.('communityStructure').('count') = k; 119 | output.('communityStructure').('countDistribution') = k_distribution; 120 | output.('communityStructure').('assignment') = cellfun( @(r) find( g == r ) , num2cell( unique( g ) ) , 'UniformOutput' , false ); 121 | 122 | output.('communityStructure').('markovChainMonteCarloSamples') = estimation_samples; 123 | 124 | output_args = output; 125 | end 126 | 127 | end 128 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/analyseGraphCommunityStructure/computeGraphCommunityStructureMarginals.m: -------------------------------------------------------------------------------- 1 | function [ k_ , k_distibution , g_ ] = computeGraphCommunityStructureMarginals( estimate_output ) 2 | %COMPUTEGRAPHCOMMUNITYSTRUCTUREMARGINALS( estimate_output ) Computes the 3 | %marginal distributions to estimate community structure of a graph given 4 | %the results of (several rounds) of Markov-Chain-Monte-Carlo sampling to 5 | %from the function ESTIMATEGRAPHCOMMUNITYSTRUCTURE. 6 | % 7 | % INPUT: 8 | % estimate_output [1x? cell]: estimate-MCMC samples from 9 | % ESTIMATEGRAPHCOMMUNITYSTRUCTURE. 10 | % 11 | % OUTPUT: 12 | % k_ [scalar]: most likely number of communities 13 | % k_distibution [?x2 matrix]: probability distribution for the number of 14 | % communities 15 | % g_ [1x? matrix]: proposed community structure given the most likely 16 | % number of communities 17 | % 18 | % 19 | % === Jan Moelter, The University of Queensland, 2017 =================== 20 | % 21 | 22 | K = []; G = []; 23 | 24 | for i = 1:numel( estimate_output ) 25 | 26 | estimate_output_E = [ estimate_output{i}.E ]; 27 | EQ_sample = estimate_output_E( ceil( numel( estimate_output_E ) / 2 ):end ); 28 | 29 | i_EQ = estimate_output_E > mean( EQ_sample ) - 2 * max( abs( EQ_sample - mean( EQ_sample ) ) ); 30 | i_EQ( 1:find( ~i_EQ , 1 , 'last' ) ) = false; 31 | 32 | K_ = [ estimate_output{i}.k ]; 33 | K = [ K , K_( i_EQ ) ]; 34 | G_ = cell2mat( transpose( { estimate_output{i}.g } ) ); 35 | G = [ G ; G_( i_EQ , : ) ]; 36 | end 37 | 38 | % 39 | 40 | H = double( min( unique(K) ):max( unique(K) ) ); 41 | k_distibution = transpose( [ H ; histc( K , H ) / length( K ) ] ); 42 | 43 | [ ~ , j ] = max( k_distibution( : , 2 ) ); 44 | k_ = k_distibution( j , 1 ); 45 | k_ = uint8( k_ ); 46 | 47 | % 48 | 49 | N = size( G , 2 ); 50 | 51 | g_distribution = zeros( N , k_ ); 52 | g_ = ones( 1 , N ); 53 | 54 | iK = transpose( K == k_ ); 55 | for n=1:N 56 | for r=1:k_ 57 | g_distribution( n , r ) = sum( iK & ( G( : , n ) == r ) ); 58 | end 59 | end 60 | g_distribution = g_distribution / sum( iK ); 61 | 62 | for n=1:N 63 | [ ~ , g_(n) ] = max( g_distribution( n , : ) ); 64 | end 65 | g_ = uint8( g_ ); 66 | 67 | end 68 | 69 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/analyseGraphCommunityStructure/estimate.m: -------------------------------------------------------------------------------- 1 | function output_args = estimate( graph , opts ) 2 | %ESTIMATE( graph , opts ) Program to calculate the number of communities in 3 | % a network using the method of Newman and Reinert, which calculates a 4 | % posterior probability by Monte Carlo simulation of the integrated 5 | % likelihood of a degree-corrected stochastic block model. 6 | % 7 | % This function implements the approach described in M. E. J. Newman and 8 | % G. Reinert. "Estimating the number of communities in a network". Phys. 9 | % Rev. Lett. 117 (2016). 10 | % Apart from slight modifications with regard to the I/O this is a 1:1 11 | % translation of the original programm 'estimate' written in C code and 12 | % published by Mark Newman on 6. April 2016. 13 | % 14 | % To use this function refer to the wrapper functions. 15 | % 16 | 17 | 18 | 19 | %/* Program to calculate the number of communities in a network using the 20 | % * method of Newman and Reinert, which calculates a posterior probability 21 | % * by Monte Carlo simulation of the integrated likelihood of a 22 | % * degree-corrected stochastic block model 23 | % * 24 | % * Written by Mark Newman 6 APR 2016 25 | % */ 26 | 27 | %/* Function control /* 28 | 29 | narginchk(2,2); 30 | 31 | if( ~isa( graph , 'graph' ) || isequal( sort( fieldnames( opts ) ) , sort( { 'K' , 'K0' , 'seed' , 'MCsweeps' , 'verbose' } ) ) ) 32 | error( 'Invalid input.' ); 33 | end 34 | 35 | output_args = struct( 'k' , num2cell( NaN * ones( 1 , opts.MCsweeps ) ) , 'g' , NaN , 'E' , NaN ); 36 | 37 | %/* Program control */ 38 | 39 | VERBOSE = opts.verbose; 40 | 41 | %/* Constants */ 42 | 43 | K = opts.K; % Maximum number of groups 44 | K0 = opts.K0; %* Initial number of groups 45 | MCSWEEPS = opts.MCsweeps; % Number of Monte Carlo sweeps 46 | SAMPLE = 10; % Interval at which to print out results, in sweeps 47 | 48 | %/* Globals */ 49 | 50 | G = NaN; % Struct storing the network 51 | twom = 0; % Twice the number of edges 52 | p = 0; % Average edge probability 53 | 54 | k = 0; % Current value of k 55 | g = NaN; % Group assignments 56 | n = NaN; % Group sizes 57 | m = NaN; % Edge counts 58 | 59 | lnfact = NaN; % Look-up table of log-gamma-values 60 | E = 0; % Log probability 61 | 62 | %/* main() */ 63 | 64 | if( ~isnan( opts.seed ) && isnumeric( opts.seed ) ) 65 | 66 | rng(opts.seed,'twister') 67 | 68 | else 69 | 70 | %// Initialize the random number generator from the system clock 71 | 72 | rng('shuffle','twister') 73 | end 74 | 75 | %// Read the network from stdin 76 | 77 | if( VERBOSE == 2 ) 78 | fprintf( 2 , 'Reading network...\n' ); 79 | end 80 | 81 | G = graph2NETWORK( graph ); 82 | twom = 0; 83 | for u_ = 0:( G.nvertices - 1 ) 84 | twom = twom + G.vertex(1+(u_)).degree; 85 | end 86 | p = twom / ( G.nvertices * G.nvertices ); 87 | 88 | if( VERBOSE == 2 ) 89 | fprintf( 2 , 'Read network with %i nodes and %i edges\n' , G.nvertices , twom/2 ); 90 | end 91 | 92 | %// Make the lookup table 93 | 94 | maketable() 95 | 96 | %// Initialize the group assignment 97 | 98 | initgroups() 99 | 100 | %// Perform the Monte Carlo 101 | 102 | if( VERBOSE == 1 ) 103 | MCTIMER = tic; 104 | print_progress( 0 , 'initialise' ); 105 | end 106 | 107 | for s_ = 0:( MCSWEEPS - 1 ) 108 | if( VERBOSE == 2 ) 109 | fprintf( 2 , 'Sweep %i...\r' , s_ ); 110 | end 111 | sweep(); 112 | 113 | output_args(1+(s_)).k = k; 114 | output_args(1+(s_)).g = g; 115 | output_args(1+(s_)).E = E; 116 | if( mod( s_ , SAMPLE ) == 0 ) 117 | switch( VERBOSE ) 118 | case 1 119 | print_progress( ( s_ + 1 ) / MCSWEEPS , 'update' , MCTIMER ); 120 | case 2 121 | fprintf( 1 , [ 'Sweep %i: k = %i , E = %g' , '\n' ] , s_ , k , E ); 122 | end 123 | end 124 | end 125 | 126 | if( VERBOSE == 1 ) 127 | print_progress( 1 , 'finalise' ); 128 | end 129 | 130 | if( VERBOSE == 2 ) 131 | fprintf( 2 , '\n' ); 132 | end 133 | 134 | 135 | %% Make a lookup table of log-factorial values 136 | 137 | function maketable() 138 | % t = 0; 139 | % length = 0; 140 | 141 | length = twom + G.nvertices + 1; 142 | lnfact = zeros( 1 , length ); 143 | for t = 0:( length - 1 ) 144 | lnfact(1+(t)) = gammaln( t + 1 ); 145 | end 146 | end 147 | 148 | %% Log-probability function 149 | 150 | function output_args = logp( n , m ) 151 | % r = 0; s = 0; 152 | % kappa = 0; 153 | res = 0; 154 | 155 | for r = 0:( k - 1 ) 156 | res = res + lnfact(1+(n(1+(r)))); 157 | 158 | if( n(1+(r)) > 0 ) 159 | kappa = 0; 160 | for s = 0:( k - 1 ) 161 | kappa = kappa + m(1+(r),1+(s)); 162 | end 163 | res = res + ( kappa * log( n(1+(r)) ) + lnfact(1+(n(1+(r)) - 1)) - lnfact(1+(kappa + n(1+(r)) - 1)) ); 164 | res = res + ( lnfact(1+(m(1+(r),1+(r)) / 2)) - ( ( m(1+(r),1+(r)) / 2 ) + 1 ) * log( 0.5 * p * n(1+(r)) * n(1+(r)) + 1 ) ); 165 | 166 | for s = (r+1):(k - 1) 167 | res = res + ( lnfact(1+(m(1+(r),1+(s)))) - ( m(1+(r),1+(s)) + 1 ) * log( p * n(1+(r)) * n(1+(s)) + 1 ) ); 168 | end 169 | end 170 | end 171 | 172 | output_args = res; 173 | end 174 | 175 | %% Initial group assignment 176 | 177 | function initgroups() 178 | % i = 0; u = 0; v = 0; 179 | % r = 0; 180 | 181 | %// Make the initial group assignments at random 182 | 183 | g = zeros(1,G.nvertices); 184 | for u = 0:( G.nvertices - 1 ) 185 | %* g(1+(u)) = randi( K ) - 1; 186 | g(1+(u)) = randi( K0 ) - 1; 187 | end 188 | 189 | %// Calculate the values of the n's 190 | 191 | n = zeros(1,K); 192 | for u = 0:( G.nvertices - 1 ) 193 | n(1+(g(1+(u)))) = n(1+(g(1+(u)))) + 1; 194 | end 195 | 196 | %// Calcalate the values of the m's 197 | 198 | m = zeros(K,K); 199 | for u = 0:( G.nvertices - 1 ) 200 | for i = 0:( G.vertex(1+(u)).degree - 1 ) 201 | v = G.vertex(1+(u)).edge(1+(i)).target; 202 | m(1+(g(1+(u))),1+(g(1+(v)))) = m(1+(g(1+(u))),1+(g(1+(v)))) + 1; 203 | end 204 | end 205 | 206 | %// Initialize k and the log-probability 207 | 208 | %* k = K; 209 | k = K0; 210 | E = logp(n,m); 211 | 212 | end 213 | 214 | %% Function to update value of k 215 | 216 | function changek() 217 | % r = 0; s = 0; u = 0; 218 | % kp = 0; 219 | empty = 0; 220 | % map = zeros(1,K); 221 | % sum = 0; 222 | 223 | %// With probability 0.5, decrease k, otherwise increase it 224 | 225 | if( rand() < 0.5 ) 226 | 227 | %// Count the number of empty groups 228 | 229 | for r = 0:( k - 1 ) 230 | if( n(1+(r)) == 0 ) 231 | empty = empty + 1; 232 | end 233 | end 234 | 235 | %// If there are any empty groups, remove one of them, or otherwise do nothing 236 | 237 | if( empty > 0 ) 238 | 239 | %// If there is more than one empty group, choose at random which one to remove 240 | 241 | bool_ = true; 242 | while( bool_ ) 243 | r = randi( k ) - 1; 244 | bool_ = ( n(1+(r)) > 0 ); 245 | end 246 | 247 | %DEBUG: fprintf( 1, 'changek(): X__ = %lu\n' , X__ ); 248 | 249 | %// Decrease k by 1 250 | 251 | k = k - 1; 252 | 253 | %// Update the group labels 254 | 255 | for u = 0:( G.nvertices - 1 ) 256 | if( g(1+(u)) == k ) 257 | g(1+(u)) = r; 258 | end 259 | end 260 | 261 | %// Update n_r 262 | 263 | n(1+(r)) = n(1+(k)); 264 | 265 | %// Update m_rs 266 | 267 | for s = 0:( k - 1 ) 268 | if( r == s ) 269 | m(1+(r),1+(r)) = m(1+(k),1+(k)); 270 | else 271 | m(1+(r),1+(s)) = m(1+(k),1+(s)); 272 | m(1+(s),1+(r)) = m(1+(s),1+(k)); 273 | end 274 | end 275 | end 276 | else 277 | %// With probability k/(n+k) increase k by 1, adding an empty group 278 | 279 | if((G.nvertices + k) * rand() < k) 280 | if( k < K ) 281 | n(1+(k)) = 0; 282 | for r = 0:k 283 | m(1+(k),1+(r)) = 0; 284 | m(1+(r),1+(k)) = 0; 285 | end 286 | k = k + 1; 287 | end 288 | end 289 | end 290 | 291 | end 292 | 293 | %% Function to update n and m for a proposed move 294 | 295 | function nmupdate( r , s , d ) 296 | % t = 0; 297 | 298 | n(1+(r)) = n(1+(r)) - 1; 299 | n(1+(s)) = n(1+(s)) + 1; 300 | 301 | for t = 0:( k - 1 ) 302 | m(1+(r),1+(t)) = m(1+(r),1+(t)) - d(1+(t)); 303 | m(1+(t),1+(r)) = m(1+(t),1+(r)) - d(1+(t)); 304 | m(1+(s),1+(t)) = m(1+(s),1+(t)) + d(1+(t)); 305 | m(1+(t),1+(s)) = m(1+(t),1+(s)) + d(1+(t)); 306 | end 307 | end 308 | 309 | %% Function that does one MCMC sweep (i.e., n individual moves) using the heatbath algorithm 310 | 311 | function output_args = sweep() 312 | % i = 0; j = 0; u = 0; v = 0; 313 | % r = 0; s = 0; 314 | % temp = 0; 315 | accept = 0; 316 | d = zeros(1,K); 317 | % x = 0; Z = 0; sum = 0; 318 | newE = zeros(1,K); 319 | boltzmann = zeros(1,K); 320 | 321 | for i = 0:( G.nvertices - 1 ) 322 | 323 | %// Optionally, perform a k-changing move 324 | 325 | if((G.nvertices + 1) * rand() < 1) 326 | changek(); 327 | end 328 | 329 | 330 | %// Choose a random node 331 | 332 | u = randi( G.nvertices ) - 1; 333 | r = g(1+(u)); 334 | 335 | %// Find the number of edges this node has to each group 336 | 337 | for s = 0:( k - 1 ) 338 | d(1+(s)) = 0; 339 | end 340 | 341 | for j = 0:( G.vertex(1+(u)).degree - 1 ) 342 | v = G.vertex(1+(u)).edge(1+(j)).target; 343 | d(1+(g(1+(v)))) = d(1+(g(1+(v)))) + 1; 344 | end 345 | 346 | 347 | %// Calculate the probabilities of moving it to each group in turn 348 | 349 | Z = 0; 350 | for s = 0:( k - 1 ) 351 | if(s == r) 352 | newE(1+(s)) = E; 353 | else 354 | nmupdate(r,s,d); 355 | newE(1+(s)) = logp(n,m); 356 | nmupdate(s,r,d); 357 | end 358 | boltzmann(1+(s)) = exp(newE(1+(s)) - E); 359 | Z = Z + boltzmann(1+(s)); 360 | end 361 | 362 | %// Choose which move to make based on these probabilities 363 | 364 | x = Z * rand(); 365 | sum = 0; 366 | for s = 0:( k - 1 ) 367 | sum = sum + boltzmann(1+(s)); 368 | if(sum > x) 369 | break; 370 | end 371 | end 372 | 373 | %// Make the move 374 | 375 | if( s ~= r ) 376 | g(1+(u)) = s; 377 | nmupdate(r,s,d); 378 | E = newE(1+(s)); 379 | accept = accept + 1; 380 | end 381 | end 382 | 383 | output_args = accept / G.nvertices; 384 | end 385 | 386 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/analyseGraphCommunityStructure/estimateGraphCommunityStructure.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = estimateGraphCommunityStructure( graph , opts ) 2 | %ESTIMATEGRAPHCOMMUNITYSTRUCTURE( graph , opts ) Wrapper function for the 3 | %'estimate' function to run the Marko-Chain-Monte-Carlo procedure for 4 | %estimating community structure. 5 | % 6 | % INPUT: 7 | % graph [graph]: undirected, unweigted graph 8 | % opts [struct]: (optional) parameters of the algorithm 9 | % .MonteCarloSteps [scalar]: number of steps in every MCMC run (default: 10000) 10 | % .RNGSeed [scalar]: seed for the random number generator (default: NaN) 11 | % .maximalK [scalar]: maximal number of communities (default: 40) 12 | % .initialK [scalar]: initial guess for the number of communities (default: NaN) 13 | % .showBanner [boolean]: show banner (default: false) 14 | % 15 | % OUTPUT: 16 | % output_args [1x? struct]: results 17 | % .k [scalar]: number of communities 18 | % .g [1x? matrix]: community assignment 19 | % .E [scalar]: log-likelihood 20 | % 21 | % EXAMPLES: 22 | % estimateGraphCommunityStructure( ZacharyKarateClub , struct() ) 23 | % 24 | % 25 | % === Jan Moelter, The University of Queensland, 2017 =================== 26 | % 27 | 28 | narginchk(2,2); 29 | 30 | if( ~isa( graph , 'graph' ) ) 31 | error( 'Invalid input.' ); 32 | end 33 | 34 | opts_ = struct(); 35 | for opt = transpose( fieldnames( opts ) ) 36 | switch opt{:} 37 | case 'MonteCarloSteps' 38 | opts_.MCsweeps = opts.MonteCarloSteps; 39 | case 'RNGSeed' 40 | opts_.seed = opts.RNGSeed; 41 | case 'maximalK' 42 | opts_.K = opts.maximalK; 43 | case 'initialK' 44 | opts_.K0 = opts.initialK; 45 | end 46 | end 47 | 48 | STD_OPTS = struct( 'K' , 40 , 'K0' , NaN , 'seed' , NaN , 'MCsweeps' , 10000 ,'verbose' , 1 ); 49 | for opt = { 'K' , 'K0' , 'seed' , 'MCsweeps' , 'verbose' } 50 | if( ~isfield( opts_ , opt{:} ) ) 51 | opts_.( opt{:} ) = STD_OPTS.( opt{:} ); 52 | end 53 | end 54 | 55 | if( isnan( opts_.K0 ) ) 56 | opts_.K0 = randi( opts_.K ); 57 | else 58 | opts_.K0 = min( opts_.K , opts_.K0 ); 59 | end 60 | 61 | if( isfield( opts , 'showBanner' ) ) 62 | if( opts.showBanner == true ) 63 | 64 | fprintf( 1 , [ '\n' ] ); 65 | 66 | fprintf( 1 , [ '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++' '\n' ] ); 67 | fprintf( 1 , [ '+ +' '\n' ] ); 68 | fprintf( 1 , [ '+ estimate || Newman, Reinert 2016 ; Phys.Rev.Lett 117 +' '\n' ] ); 69 | fprintf( 1 , [ '+ +' '\n' ] ); 70 | fprintf( 1 , [ '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++' '\n' ] ); 71 | 72 | fprintf( 1 , [ '\n' ] ); 73 | 74 | end 75 | end 76 | 77 | output_args = estimate( graph , opts_ ); 78 | 79 | 80 | switch( 2 ^ ( 2 + find( log2( opts_.K ) < 2 .^ ( 2 + [ 1:4 ] ) , 1, 'first' ) ) ) 81 | case 8 82 | uint = @(u) uint8( u ); 83 | case 16 84 | uint = @(u) uint16( u ); 85 | case 32 86 | uint = @(u) uint32( u ); 87 | case 64 88 | uint = @(u) uint64( u ); 89 | end 90 | 91 | for s = 1:numel( output_args ) 92 | output_args(s).k = uint( output_args(s).k ); 93 | output_args(s).g = uint( normalisePatternEnumeration( output_args(s).g ) ); 94 | end 95 | 96 | end 97 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/analyseGraphCommunityStructure/graph2NETWORK.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = graph2NETWORK( graph ) 2 | %GRAPH2NETWORK( graph ) Builds a NETWORK structure from a graph object. 3 | % 4 | % INPUT: 5 | % graph [graph]: undirected, unweigted graph 6 | % 7 | % OUTPUT: 8 | % output_args [struct]: NETWORK structure 9 | % 10 | % EXAMPLES: 11 | % analyseGraphCommunityStructure( ZacharyKarateClub , struct( 'Iterations' , 1 , 'MonteCarloSteps' , 10000 , 'initialK' , 3 ) ) 12 | % 13 | % 14 | % === Jan Moelter, The University of Queensland, 2017 =================== 15 | % 16 | 17 | 18 | if( isa( graph , 'graph' ) ) 19 | 20 | NETWORK.nvertices = graph.numnodes; 21 | 22 | for v = 1:graph.numnodes 23 | NETWORK.vertex(v).id = v - 1; 24 | NETWORK.vertex(v).degree = graph.degree(v); 25 | NETWORK.vertex(v).label = ''; 26 | 27 | n_ = graph.neighbors(v); 28 | for n = 1:numel( n_ ) 29 | NETWORK.vertex(v).edge(n).target = n_(n) - 1; 30 | NETWORK.vertex(v).edge(n).weight = 1; 31 | end 32 | end 33 | 34 | output_args = NETWORK; 35 | else 36 | error( 'Invalid input.' ); 37 | output_args = NaN; 38 | end 39 | 40 | end 41 | 42 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/analyseGraphCommunityStructure/normalisePatternEnumeration.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = normalisePatternEnumeration( input_args ) 2 | %NORMALISEPATTERNENUMERATION( input_args ) Normalised the enumeration of 3 | %the input pattern while keeping the overall pattern unchanged. In the 4 | %enumeration new indices will be added as required. 5 | % 6 | % INPUT: 7 | % input_args [1x? matrix]: input pattern 8 | % 9 | % OUTPUT: 10 | % output_args [1x? matrix]: normalised enumeration of the input pattern 11 | % 12 | % EXAMPLE: 13 | % normalisePatternEnumeration( [ 2 5 3 8 8 3 5 2 ] ) 14 | % 15 | % 16 | % === Jan Moelter, The University of Queensland, 2017 =================== 17 | % 18 | 19 | output_args = zeros( 1 , numel(input_args) ); 20 | 21 | G = unique( input_args , 'stable' ); 22 | for r=1:numel( G ) 23 | output_args( input_args == G(r) ) = r; 24 | end 25 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/buildPatternSimilarityGraph.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = buildPatternSimilarityGraph( X ) 2 | %BUILDPATTERNSIMILARITYGRAPH( X ) Returns a k-nearest-neighbour graph 3 | %according to the consine distance from the pattern data in X. 4 | % 5 | % INPUT: 6 | % X [1x? cell]: cell array of binary activity patterns 7 | % 8 | % 9 | % === Jan Moelter, The University of Queensland, 2018 =================== 10 | % 11 | 12 | % k = ceil(log( size( X , 1 ) )); 13 | cosineDistance = @( x , y ) ( 1 - ( ctranspose( x ) * y ) / ( norm( x ) * norm( y ) ) ); 14 | % miDistance = @( x , y ) ( 1 - 2 * ( ctranspose( x ) * y ) / ( sum( x ) + sum( y ) ) ); 15 | 16 | for k = ceil(log( size( X , 1 ) )):size( X , 1 ) 17 | 18 | knn = k_nearestneighbours( X , k , cosineDistance ); 19 | 20 | % We select the k nearest neighbours, however in case of a tie, when there 21 | % are multiple data point with the same distance from a single node, we 22 | % include all of them: 23 | 24 | A = zeros( size( knn , 1 ) ); 25 | for x = 1:size( knn , 1 ) 26 | n = knn{x}( knn{x} ~= x ); 27 | 28 | A( x , n ) = 1; 29 | A( n , x ) = 1; 30 | end 31 | 32 | output_args = graph( A ); 33 | 34 | if( numel( unique( conncomp( output_args ) ) ) == 1 ) 35 | break; 36 | end 37 | end 38 | 39 | end 40 | 41 | function [ output_args ] = k_nearestneighbours( X , k , d ) 42 | 43 | output_args = cell( size( X , 1 ) ); 44 | 45 | dist = cross_evaluation( d , cellfun( @(x) ctranspose( x ) , X , 'UniformOutput' , false ) ) + diag( NaN * ones( 1 , numel( X ) ) ); 46 | 47 | for i = 1:size( X , 1 ) 48 | s = sort( dist(i,:) ); 49 | 50 | output_args{i} = find( dist(i,:) <= s( k ) ); 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/findAssemblyPatterns.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = findAssemblyPatterns( activityPatterns ) 2 | %FINDASSEMBLYPATTERNS( activityPatterns ) 3 | % 4 | % INPUT: 5 | % activityPatterns [1x? cell]: cell array of binary activity patterns 6 | % 7 | % EXAMPLE: 8 | % findAssemblyPatterns( num2cell( [ sort( randi( [0,1] , 20 , 40 ) , 2 , 'ascend' ) ; sort( randi( [0,1] , 20 , 40 ) , 2 , 'descend' ) ] , 2 ) ) 9 | % 10 | % 11 | % === Jan Moelter, The University of Queensland, 2018 =================== 12 | % 13 | 14 | output_args.activityPatterns = activityPatterns; 15 | 16 | %% > BUILD SIMILARITY GRAPH 17 | printConsoleSection( 'BUILD SIMILARITY GRAPH' ); 18 | 19 | fprintf( 1 , [ '%i activity patterns' '\n' ] , numel( activityPatterns ) ); 20 | fprintf( 1 , [ '\n' ] ); 21 | 22 | if( numel( activityPatterns ) == 0 ) 23 | return; 24 | end 25 | 26 | patternSimilarityGraph = buildPatternSimilarityGraph( activityPatterns ); 27 | %output_args.patternSimilarityGraph = patternSimilarityGraph; 28 | 29 | %% > ANALYSE COMMUNITY STRUCTURE IN SIMILARITY GRAPH 30 | printConsoleSection( 'ANALYSE COMMUNITY STRUCTURE IN SIMILARITY GRAPH' ); 31 | 32 | N_ITERATIONS = 5; 33 | N_MONTECARLOSTEPS = 50000; 34 | 35 | patternSimilarityAnalysis = analyseGraphCommunityStructure( patternSimilarityGraph , struct( 'Iterations' , N_ITERATIONS , 'MonteCarloSteps' , N_MONTECARLOSTEPS , 'initialK' , NaN ) ); 36 | output_args.patternSimilarityAnalysis = patternSimilarityAnalysis; 37 | 38 | 39 | %% > INFER ASSEMBLY PATTERNS 40 | printConsoleSection( 'INFER ASSEMBLY PATTERNS' ); 41 | 42 | [ assemblyPatterns , iAssemblyPatterns ] = inferAssemblyPatterns( activityPatterns , patternSimilarityAnalysis ); 43 | 44 | output_args.assemblyActivityPatterns = assemblyPatterns; 45 | output_args.assemblyIActivityPatterns = iAssemblyPatterns; 46 | 47 | fprintf( 1 , [ ' %i assembly patterns' '\n' ] , numel( assemblyPatterns ) ); 48 | fprintf( 1 , [ '\n' ] ); 49 | 50 | end 51 | 52 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/inferAssemblyPatterns.m: -------------------------------------------------------------------------------- 1 | function [ assemblyPatterns , iAssemblyPatterns ] = inferAssemblyPatterns( activityPatterns , patternSimilarityAnalysis ) 2 | %INFERASSEMBLYPATTERNS( activityPatterns , patternSimilarityAnalysis ) 3 | % 4 | % INPUT: 5 | % activityPatterns [1x? cell]: cell array of binary activity patterns 6 | % patternSimilarityAnalysis [struct]: pattern similarity analysis results 7 | % 8 | % 9 | % === Jan Moelter, The University of Queensland, 2018 =================== 10 | % 11 | 12 | MINIMUM_SIZE = 5; 13 | STD_DEVIATIONS = 1.5; 14 | 15 | ACTIVTY_THRESHOLD = 0.2; 16 | 17 | 18 | cosineDistance = @( x_1 , x_2 ) ( 1 - ( ctranspose( x_1 ) * x_2 ) / ( norm( x_1 ) * norm( x_2 ) ) ); 19 | 20 | %% PERFORM SPECTRAL CLUSTERING ON THE SIMILARITY GRAPH 21 | 22 | gAssignment = spectralclustering( patternSimilarityAnalysis.graph , patternSimilarityAnalysis.communityStructure.count , 'normalised' ); 23 | 24 | %% DISREGARD COMMUNITIES CONSISTING OF TOO FEW ACTIVITY PATTERNS 25 | 26 | discriminateSize() 27 | 28 | %% DEFINE PRELIMINARY CORE ASSEMBLY PATTERNS 29 | 30 | prelimAssemblyPatterns = cell( max( gAssignment ) , 1 ); 31 | 32 | for r = 1:numel( prelimAssemblyPatterns ) 33 | if( any( gAssignment == r ) ) 34 | prelimAssemblyPatterns{ r } = meanActivityPattern( activityPatterns( gAssignment == r ) , ACTIVTY_THRESHOLD ); 35 | prelimAssemblyPatterns{ r } = double( prelimAssemblyPatterns{ r } ~= 0 ); 36 | else 37 | prelimAssemblyPatterns{ r } = zeros( size( activityPatterns{ 1 } ) ); 38 | end 39 | end 40 | 41 | %% COMBINE SIMILAR PRELIMINARY CORE ASSEMBLY PATTERNS 42 | 43 | p = ( 2 / 3 ); 44 | 45 | prelimAssemblyPatternsSimilarity = cross_evaluation( @(x,y) ( min( ( x * ctranspose( y ) ) / norm( y )^2 , ( y * ctranspose( x ) ) / norm( x )^2 ) > p ) , prelimAssemblyPatterns ); 46 | 47 | [ R , S ] = ind2sub( size( prelimAssemblyPatternsSimilarity ) , find( triu( prelimAssemblyPatternsSimilarity , 1 ) ) ); 48 | for i = 1:sum( sum( triu( prelimAssemblyPatternsSimilarity , 1 ) ) ) 49 | gAssignment( gAssignment == S(i) ) = R(i); 50 | 51 | % CHANGE THE REASSIGNMENT RECURSIVELY 52 | R( i + find( R( i+1:end ) == S(i) ) ) = R(i); 53 | end 54 | 55 | % RE-DEFINE PRELIMINARY CORE ASSEMBLY PATTERNS FROM THE CHANGED GROUP ASSIGNMENT 56 | 57 | for r = 1:numel( prelimAssemblyPatterns ) 58 | if( any( gAssignment == r ) ) 59 | prelimAssemblyPatterns{ r } = meanActivityPattern( activityPatterns( gAssignment == r ) , ACTIVTY_THRESHOLD ); 60 | prelimAssemblyPatterns{ r } = double( prelimAssemblyPatterns{ r } ~= 0 ); 61 | else 62 | prelimAssemblyPatterns{ r } = zeros( size( activityPatterns{ 1 } ) ); 63 | end 64 | end 65 | 66 | %% ASSIGN EVERY ACTIVITY TO A GROUP DEFINED BY A PRELIMINARY CORE ASSEMBLY PATTERN 67 | % IF THE PATTERNS DO NOT EXCEED A CERTAIN LEVEL OF SIMILARITY THEY WILL BE DISREGARDED 68 | 69 | p = ( 1 / 2 ); 70 | 71 | % H = figure(); 72 | for j = 1:numel( gAssignment ) 73 | x = activityPatterns{j}; 74 | [ ~ , r ] = min( cellfun( @(a) cosineDistance( transpose( a ) , transpose( x ) ) , prelimAssemblyPatterns , 'UniformOutput' , true ) ); 75 | 76 | if( ~isempty( r ) ) 77 | 78 | % REQUIRE F TO OVERLAP WITH AN CORE_ASSEMBLY TO AT LEAST p IN ORDER TO ASSOCIATE IT WITH IT 79 | % vvvvv DOES NOT WORK WITH MANY UNITS vvvv 80 | % gAssignment(j) = iif( ( prelimAssemblyPatterns{ r } * transpose( x ) > p * norm( x )^2 ) && ( norm( x )^2 > p * norm( prelimAssemblyPatterns{ r } )^2 ) , r , uint8( NaN ) ); 81 | % vvvvv IMPROVEMENT vvvv 82 | gAssignment(j) = iif( ( prelimAssemblyPatterns{ r } * transpose( x ) > p * norm( prelimAssemblyPatterns{ r } )^2 ) && ( norm( x )^2 > p * norm( prelimAssemblyPatterns{ r } )^2 ) , r , uint8( NaN ) ); 83 | 84 | else 85 | gAssignment(j) = 0; 86 | end 87 | 88 | if( gAssignment(j) ~= 0 ) 89 | % H.Name = [ num2str( j ) ' : ' iif( gAssignment(j) ~= 0 , 'accepted' , 'REJECTED' ) ]; 90 | % subplot( 1 , 2 , 1 ); 91 | % tikz_tectaltopologyplot( 12 * cell2mat( hexagonal_tiling( 16 ) ) , NaN , prelimAssemblyPatterns{r} , struct( 'reference_plot' , true , 'centre_of_mass' , false , 'assembly_boundary' , false ) , true ); 92 | % subplot( 1 , 2 , 2 ); 93 | % tikz_tectaltopologyplot( 12 * cell2mat( hexagonal_tiling( 16 ) ) , NaN , x , struct( 'reference_plot' , false , 'centre_of_mass' , false , 'assembly_boundary' , false ) , true ); 94 | % disp( j ); 95 | end 96 | end 97 | 98 | 99 | %% DISREGARD COMMUNITIES CONSISTING OF TOO FEW ACTIVITY PATTERNS 100 | 101 | discriminateSize() 102 | 103 | %% DEFINE CORE ASSEMBLY PATTERNS 104 | 105 | assemblyPatterns = cell( max( gAssignment ) , 1 ); 106 | iAssemblyPatterns = cell( max( gAssignment ) , 1 ); 107 | 108 | for r = 1:numel( assemblyPatterns ) 109 | if( any( gAssignment == r ) ) 110 | iAssemblyPatterns{ r } = find( gAssignment == r ); 111 | assemblyPatterns{ r } = meanActivityPattern( activityPatterns( iAssemblyPatterns{ r } ) , ACTIVTY_THRESHOLD ); 112 | end 113 | end 114 | 115 | I = ~cellfun( @isempty , assemblyPatterns ); 116 | 117 | iAssemblyPatterns = iAssemblyPatterns( I ); 118 | assemblyPatterns = assemblyPatterns( I ); 119 | 120 | 121 | 122 | function discriminateSize() 123 | 124 | minSize = max( 0, cellfun( @(h) mean( h ) - STD_DEVIATIONS * std( h ) , { histc( gAssignment , setdiff( unique( gAssignment ) , uint8( NaN ) ) ) } ) ); 125 | minSize = max( MINIMUM_SIZE , minSize ); 126 | 127 | for r_ = setdiff( unique( gAssignment ) , uint8( NaN ) ) 128 | if( sum( gAssignment == r_ ) < minSize ) 129 | gAssignment( gAssignment == r_ ) = uint8( NaN ); 130 | end 131 | end 132 | end 133 | 134 | end 135 | 136 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/meanActivityPattern.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = meanActivityPattern( activityPatterns , activityThreshold ) 2 | %MEANACTIVITYPATTERN ( activityPatterns , activityThreshold ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | %% AVERAGE ACTIVITY PATTERNS 9 | output_args = mean( cell2mat( activityPatterns ) , 1 ); 10 | 11 | %% THRESHOLD THE AVERAGE PATTERN 12 | output_args = output_args .* ( output_args > activityThreshold ); 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/normalisePatternEnumeration.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = normalisePatternEnumeration( input_args ) 2 | %NORMALISEPATTERNENUMERATION( input_args ) Returns a enumeration of the 3 | %input pattern Given the input pattern [ 2 4 3 1 1 3 4 2 ] this function 4 | %turns is into [ 1 2 3 4 4 3 2 1 ] keeping the overall pattern unchanged 5 | %but imposing a normalised enumeration. 6 | % 7 | % EXAMPLE: 8 | % normalisePatternEnumeration( [ 2 4 3 1 1 3 4 2 ] ) 9 | % 10 | % 11 | % === Jan Moelter, The University of Queensland, 2018 =================== 12 | % 13 | 14 | output_args = zeros( 1 , numel(input_args) ); 15 | 16 | G = unique( input_args , 'stable' ); 17 | for r=1:numel( G ) 18 | output_args( input_args == G(r) ) = r; 19 | end 20 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/refreshAssemblyPatterns.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = refreshAssemblyPatterns( input_args ) 2 | %REFRESHASSEMBLYPATTERNS( input_args ) 3 | % 4 | % INPUT: 5 | % input_args [struct]: findAssemblyPattern output 6 | % 7 | % 8 | % === Jan Moelter, The University of Queensland, 2018 =================== 9 | % 10 | 11 | output_args = input_args; 12 | 13 | %% > RE-ANALYSE COMMUNITY STRUCTURE IN SIMILARITY GRAPH 14 | printConsoleSection( 'RE-ANALYSE COMMUNITY STRUCTURE IN SIMILARITY GRAPH' ); 15 | 16 | [ k , k_distribution , g ] = computeGraphCommunityStructureMarginals( output_args.patternSimilarityAnalysis.communityStructure.markovChainMonteCarloSamples ); 17 | 18 | output_args.patternSimilarityAnalysis.('communityStructure').('count') = k; 19 | output_args.patternSimilarityAnalysis.('communityStructure').('countDistribution') = k_distribution; 20 | output_args.patternSimilarityAnalysis.('communityStructure').('assignment') = cellfun( @(r) find( g == r ) , num2cell( unique( g ) ) , 'UniformOutput' , false ); 21 | 22 | 23 | %% > INFER ASSEMBLY PATTERNS 24 | printConsoleSection( 'INFER ASSEMBLY PATTERNS' ); 25 | 26 | [ assemblyPatterns , iAssemblyPatterns ] = inferAssemblyPatterns( output_args.activityPatterns , output_args.patternSimilarityAnalysis ); 27 | 28 | output_args.assemblyActivityPatterns = assemblyPatterns; 29 | output_args.assemblyIActivityPatterns = iAssemblyPatterns; 30 | 31 | fprintf( 1 , [ ' %i assembly patterns' '\n' ] , numel( assemblyPatterns ) ); 32 | fprintf( 1 , [ '\n' ] ); 33 | 34 | end 35 | 36 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSGCAssemblies/spectralclustering.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = spectralclustering( G , K , normalisation ) 2 | %SPECTRALCLUSTERING( G , K , normalisation ) Performs spectral clustering 3 | %on the graph G into k clusters. 4 | % 5 | % INPUT: 6 | % G [graph]: input graph 7 | % K [1x? matrix]: number of clusters 8 | % h [Nx1 matrix]: external field 9 | % n [scalar]: number of states 10 | % normalisation [string]: (optional) spectral clustering normalisation 11 | % ('unnormalised','symmetric','randomwalk'/'normalised') 12 | % 13 | % 14 | % === Jan Moelter, The University of Queensland, 2018 =================== 15 | % 16 | 17 | if( nargin < 3 ) 18 | normalisation = ''; 19 | end 20 | 21 | optimisation = false; 22 | 23 | % ========================================================================= 24 | 25 | z = 1; 26 | H = graphlaplacian( G , normalisation ) + z * eye( numnodes( G ) ); 27 | % In H the spectrum was shifted by an amount z away from 0 in order for the 28 | % matrix to be non-singular so that the computation of eigenvectors tends 29 | % to be more stable. 30 | 31 | [ U_ , e_ ] = eig( H , 'vector' ); 32 | [ e_ , iex ] = sort( e_ , 'ascend' ); 33 | 34 | output_args = NaN * ones( numel( K ) , numnodes( G ) ); 35 | 36 | for j = 1:numel( K ) 37 | k = K(j); 38 | 39 | e = e_( 1:k ); 40 | U = U_( : , iex( 1:k ) ); 41 | 42 | % ========================================================================= 43 | 44 | if( isreal( U ) && max( max( abs( H * U - U * diag( e ) ) ) ) < 1e-10 ) 45 | 46 | switch( normalisation ) 47 | case { '' , 'unnormalised' } 48 | 49 | case 'symmetric' 50 | U = normr( U ); 51 | case { 'randomwalk' , 'normalised' } 52 | 53 | end 54 | 55 | V = uint16( 1:numnodes( G ) ); 56 | 57 | idx = transpose( kmeans( U , k , 'Distance' , 'sqeuclidean' , 'Replicates' , 100 ) ); 58 | idx = normalisePatternEnumeration( idx ); 59 | 60 | output_args_k = cell( k , 1 ); 61 | for r = 1:k 62 | output_args_k{r} = V( idx == r ); 63 | end 64 | 65 | 66 | if( optimisation && any( strcmp( normalisation , { 'randomwalk' , 'normalised' } ) ) ) 67 | output_args_k = ncutoptimisation( G , output_args_k ); 68 | end 69 | 70 | [ ~ , iO ] = sort( cellfun( 'size' , output_args_k , 2 ) , 'descend' ); 71 | output_args_k = output_args_k( iO ); 72 | 73 | output_args(j,:) = uint8( assignmentvector( G , output_args_k ) ); 74 | 75 | else 76 | fprintf( 1 , [ ' ! Spectral clustering failed.' '\n' ] ); 77 | fprintf( 2 , [ '! Spectral clustering failed.' '\n' ] ); 78 | output_args(j,:) = uint8( zeros( 1, numnodes( G ) ) ); 79 | end 80 | 81 | end 82 | 83 | end 84 | 85 | function [ output_args ] = graphlaplacian( G , normalisation ) 86 | 87 | if( nargin < 2 ) 88 | normalisation = ''; 89 | end 90 | 91 | A = full( adjacency( G ) ); 92 | D = degree( G ); 93 | 94 | J = eye( numnodes( G ) ); 95 | 96 | switch( normalisation ) 97 | case { '' , 'unnormalised' } 98 | d = D; 99 | output_args = diag( d ) - A; 100 | case 'symmetric' 101 | d = 1 ./ sqrt( D ); 102 | output_args = J - diag( d ) * A * diag( d ); 103 | case { 'randomwalk' , 'normalised' } 104 | d = 1 ./ D; 105 | output_args = J - diag( d ) * A; 106 | end 107 | end 108 | 109 | function [ output_args ] = ncutoptimisation( G , c ) 110 | 111 | A = full( adjacency( G ) ); 112 | D = degree( G ); 113 | 114 | n = numnodes( G ); 115 | K = 1:numel( c ); 116 | 117 | output_args = c; 118 | t_output_args = c; 119 | 120 | change = true; 121 | t = 0; 122 | 123 | while( change ) 124 | change = false; 125 | 126 | for x=uint16( randperm( n ) ) 127 | 128 | R = setdiff( K , K( cellfun(@(C) any( C == x ) , output_args ) ) ); 129 | R = R( randperm( numel( R ) ) ); 130 | 131 | for r=R 132 | t_output_args = move( output_args , x , r ); 133 | if( ncut( t_output_args ) < ncut( output_args ) ) 134 | output_args = t_output_args; 135 | 136 | % disp( x ); 137 | 138 | change = true; 139 | end 140 | end 141 | end 142 | 143 | t = t + 1; 144 | 145 | if( t >= 100 ) 146 | fprintf( 2 , [ 'break out of loop' '\n' ] ); 147 | break; 148 | end 149 | end 150 | 151 | 152 | 153 | function [ output_args ] = ncut( c ) 154 | 155 | output_args = zeros( 1 , numel( c ) ); 156 | for j = 1:numel( c ) 157 | output_args(j) = W( c{j} , setdiff( 1:n , c{j} ) ) / vol( c{j} ); 158 | end 159 | 160 | output_args = sum( output_args ); 161 | 162 | function [ output_args ] = vol( ic ) 163 | output_args = sum( D( ic ) ); 164 | end 165 | 166 | function [ output_args ] = W( ic1 , ic2 ) 167 | output_args = sum( sum( A( ic1 , ic2 ) ) ); 168 | end 169 | 170 | end 171 | 172 | function [ output_args ] = move( c , x , r ) 173 | if( r < numel( c ) ) 174 | for s=1:numel( c ) 175 | c{s} = setdiff( c{s} , [ x ] ); 176 | if( s == r ) 177 | c{s} = sort( [ c{s} x ] ); 178 | end 179 | end 180 | end 181 | 182 | output_args = c; 183 | end 184 | 185 | end 186 | 187 | function [ output_args ] = assignmentvector( G , c ) 188 | 189 | output_args = zeros( 1, numnodes( G ) ); 190 | 191 | for j = 1:numel( c ) 192 | output_args( c{j} ) = j; 193 | end 194 | 195 | output_args = normalisePatternEnumeration ( output_args ); 196 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/README__SVDEnsemble: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'SVDEnsemble' 2 | REPOSITORY (https://github.com/hanshuting/SVDEnsemble) BY SHUTING HAN. 3 | 4 | THE FOLLOWING FUNCTIONS WERE MODIFIED FROM THEIR ORIGINAL STATE ('% # '): 5 | 6 | _ findSVDensemble.m 7 | _ shuffle.m 8 | _ SVDStateBinary.m 9 | 10 | THE OTHER FUNCTIONS REMAINED UN-MODIFIED. 11 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/SVDEnsemble/README.md: -------------------------------------------------------------------------------- 1 | # SVDEnsemble 2 | ============== 3 | 4 | by Shuting Han, Feb. 2018 5 | 6 | Overview 7 | -------- 8 | This is the code for defining neuronal ensembles using singular value decomposition (SVD). Conceptually, we view neuronal ensembles as representative population vectors in N-dimensional space, where N is the number of neurons. SVD is used to find such representative states, and the member neurons therein. 9 | 10 | The SVD method consists of the following steps: 11 | 1. Defining high activity frames; 12 | 2. TF-IDF normalization; 13 | 3. Generating binarized similarity matrix; 14 | 4. SVD; 15 | 5. Defining important neurons in each significant SVD state. 16 | 17 | This repo is based on Luis Carrillo-Reid's Stoixeion package (forked under https://github.com/hanshuting/Stoixeion), but is made much more efficient and easier to understand. 18 | 19 | Usage 20 | -------- 21 | Call function `[core_svd,state_pks,param] = findSVDensemble(data,coords,param)`, and see the function for more explanations. 22 | 23 | Reference 24 | -------- 25 | * Carrillo-Reid, L., Miller, J. E. K., Hamm, J. P., Jackson, J., & Yuste, R. (2015). Endogenous sequential cortical activity evoked by visual stimuli. Journal of Neuroscience, 35(23), 8813-8828. 26 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/SVDEnsemble/SVDStateBinary.m: -------------------------------------------------------------------------------- 1 | % # (JM) MODIFIED FROM ORIGINAL FUNCTION 'SVDStateBinary' 2 | 3 | function [state_raster,state_pks,fac_cut] = SVDStateBinary(S,state_cut) 4 | % Find SVD states. 5 | % Shuting Han, 2018 6 | 7 | p = 0.025; %significant states need to appear at least 5% of the time to be considered LCR 8 | 9 | % do SVD on binarized similarity matrix 10 | sz = size(S,1); 11 | [~,S_svd,V_svd] = svd(S); 12 | 13 | % binary search factor cut 14 | fac_cut = 0.4; 15 | dlt = 1; 16 | while dlt > 0 17 | 18 | % restore factors 19 | fac_count = zeros(state_cut,1); 20 | for n = 1:min(state_cut,size(V_svd,2)) % # for n = 1:state_cut 21 | fac_count(n) = sum(sum((V_svd(:,n)*V_svd(:,n)'*S_svd(n,n))>fac_cut)); 22 | end 23 | 24 | state_count = floor(sqrt(fac_count)); 25 | state_count = find(state_count/sum(state_count)>=p); 26 | num_state = length(state_count); 27 | 28 | % find cells for each state 29 | svd_sig = zeros(sz,sz,num_state); 30 | for n = 1:num_state 31 | svd_sig(:,:,n) = (V_svd(:,state_count(n))*V_svd(:,state_count(n))'... 32 | *S_svd(state_count(n),state_count(n)))>fac_cut; 33 | end 34 | 35 | state_pks_num = zeros(num_state,sz); 36 | for n = 1:num_state 37 | state_pks_num(n,sum(svd_sig(:,:,n))>0) = 1; 38 | end 39 | 40 | % if there's no overlapping state, stop searching 41 | if max(sum(state_pks_num))>1 42 | fac_cut = fac_cut+0.01; 43 | dlt = 1; 44 | else 45 | dlt = 0; 46 | end 47 | 48 | end 49 | 50 | state_raster = rot90(sortrows(state_pks_num)')'; 51 | state_pks_sort = state_raster.*repmat(1:num_state,sz,1); 52 | state_pks = sum(state_pks_sort,2)'; 53 | 54 | % plot identified states 55 | % figure(3); 56 | % imagesc(edos_pks_num_sort_n==0);colormap(gray) 57 | % xlabel('frame'); ylabel('ensemble index'); title('ensemble activity') 58 | 59 | 60 | 61 | end 62 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/SVDEnsemble/calcTFIDF.m: -------------------------------------------------------------------------------- 1 | function [data_tfidf] = calcTFIDF(data) 2 | % TF-IDF normalization of raster data 3 | % INPUT: 4 | % data: N-by-T raster matrix 5 | % OUTPUT: 6 | % data_tfidf: N-by-T normalized matrix 7 | % Shuting Han, 2018 8 | 9 | dims = size(data); 10 | 11 | tf = data./(ones(dims(1),1)*sum(data,1)); 12 | idf = dims(2)./(sum(data,2)*ones(1,dims(2))); 13 | idf(isnan(idf)) = 0; 14 | idf = log(idf); 15 | data_tfidf = tf.*idf; 16 | 17 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/SVDEnsemble/calc_jcut.m: -------------------------------------------------------------------------------- 1 | function [jcut] = calc_jcut(data) 2 | % calculate threshold of similarity values from shuffled data 3 | 4 | num_shuff = 20; 5 | p = 0.99; 6 | dims = size(data); 7 | 8 | % calculate similarity matrix 9 | warning('off') 10 | S = zeros(dims(2),dims(2),num_shuff); 11 | for n = 1:num_shuff 12 | data_shuff = shuffle(data,'time'); 13 | S(:,:,n) = 1-pdist2(data_shuff',data_shuff','jaccard'); 14 | end 15 | warning('on') 16 | 17 | % determine threshold 18 | bins = 0:0.01:1; 19 | cd = histc(S(:),bins); 20 | cd = cumsum(cd/sum(cd)); 21 | jcut = bins(find(cd>p,1)); 22 | 23 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/SVDEnsemble/calc_scut.m: -------------------------------------------------------------------------------- 1 | function [scut] = calc_scut(data) 2 | % calculate threshold of similarity values from shuffled data 3 | 4 | num_shuff = 20; 5 | p = 0.98; 6 | dims = size(data); 7 | 8 | % calculate similarity matrix 9 | warning('off') 10 | S = zeros(dims(2),dims(2),num_shuff); 11 | for n = 1:num_shuff 12 | data_shuff = shuffle(data,'time'); 13 | S(:,:,n) = 1-pdist2(data_shuff',data_shuff','cosine'); 14 | end 15 | warning('on') 16 | 17 | % determine threshold 18 | bins = 0:0.01:1; 19 | cd = histc(S(:),bins); 20 | cd = cumsum(cd/sum(cd)); 21 | scut = bins(find(cd>p,1)); 22 | 23 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/SVDEnsemble/findActiveFrames.m: -------------------------------------------------------------------------------- 1 | function [data_high,pks_frame,pks] = findActiveFrames(data,pks) 2 | % find high activity frame using a threshold determined from shuffled data 3 | % INPUT: 4 | % data: N-by-T spike matrix 5 | % pks: significant level of frame activity; if left empty ([]), this 6 | % function will determine its value using shuffled data 7 | % OUTPUT: 8 | % data_high: N-by-T' data matrix with only significant frames 9 | % pks_frame: 1-by-T' vector containing indices of significant frames 10 | % pks: value of the final threshold 11 | % 12 | % Shuting Han, 2017 13 | % LCR Changed to S_index distributions to determine pks. The idea is that 14 | % after some pk value the similarity between vectors in real data will be 15 | % significantly higher than the similarity between vectors in random data 16 | 17 | % some parameters 18 | num_shuff = 100; 19 | p = 0.98; %LCR 20 | dims = size(data); 21 | S_out = zeros(num_shuff); 22 | 23 | % determine threshold from shuffled data 24 | if isempty(pks) 25 | 26 | % make shuffled data 27 | data_shuff = zeros(dims(1),dims(2),num_shuff); 28 | for ii = 1:num_shuff 29 | data_shuff(:,:,ii) = shuffle(data,'time'); 30 | end 31 | 32 | for n = 3:max(sum(data,1)) 33 | 34 | % find significant frames data 35 | data_high = data(:,sum(data,1)>=n); 36 | S = 1-pdist2(data_high',data_high','cosine'); 37 | 38 | % calculate similarity matrix shuffled 39 | warning('off') 40 | for ii = 1:num_shuff 41 | data_high_rnd = data_shuff(:,sum(data_shuff(:,:,ii))>=n); 42 | S_rd = 1-pdist2(data_high_rnd',data_high_rnd','cosine'); 43 | S_out(ii) = nanmean(S_rd(:)); 44 | end 45 | warning('on') 46 | 47 | % determine threshold 48 | bins = 0:0.02:max(S_out); 49 | cd = histc(S_out,bins); 50 | cd = cumsum(cd/sum(cd)); 51 | scut = bins(find(cd>p,1)); 52 | if mean(S(:))>scut 53 | pks = n; 54 | break; 55 | end 56 | end 57 | 58 | end 59 | 60 | pks_frame = find(sum(data,1)>=pks); 61 | data_high = data(:,pks_frame); 62 | 63 | end 64 | -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/SVDEnsemble/findSVDensemble.m: -------------------------------------------------------------------------------- 1 | % # (JM) MODIFIED FROM ORIGINAL FUNCTION 'findSVDensemble' 2 | 3 | function [core_svd,state_pks_full,param] = findSVDensemble(data,coords,param) 4 | % Find ensembles using SVD method. 5 | % INPUT: 6 | % data: N-by-T binary spike matrix, where N is the number of neurons, 7 | % T is number of frames 8 | % coords: N-by-2 matrix, containing coordinates of corresponding 9 | % neurons (for visualization purpose only) 10 | % param: struct with the following fields: 11 | % - pks: significant level of spike count per frame, default 4, 12 | % leave it empty [] if you want an automated threshold 13 | % - ticut: percentage of cells in a state; default 0.22, leave it 14 | % empty [] if you want an automated threshold 15 | % - jcut: another threshold for coactivity: further removes noise; 16 | % default 0.06 17 | % - state_cut: maximum number of states allowed, leave it empty if 18 | % you want automated value 19 | % OUTPUT: 20 | % core_svd: K-by-1 cell array, where K is the number of identified 21 | % ensembles, with the indices of core neurons in each ensemble 22 | % state_pks_full: 1-by-T vector with the active ensemble identity for 23 | % each frame 24 | % param: updated parameter structure with the actual values this code 25 | % used 26 | % 27 | % For details about this method, see the following paper: 28 | % Carrillo-Reid, et al. "Endogenous sequential cortical activity evoked by 29 | % visual stimuli." Journal of Neuroscience 35.23 (2015): 8813-8828. 30 | % 31 | % This code is based on Luis Carrillo-Reid's Stoixeon package, but is made 32 | % more efficient and easier to understand. 33 | % Shuting Han, 2018 34 | % 35 | 36 | %% set parameters 37 | if ~isfield(param,'pks'); param.pks = 4; end 38 | if ~isfield(param,'ticut'); param.ticut = 0.22; end 39 | if ~isfield(param,'jcut'); param.jcut = 0.06; end 40 | if ~isfield(param,'state_cut'); param.state_cut = round(size(data,1)/4); end 41 | 42 | pks = param.pks; 43 | ticut = param.ticut; 44 | jcut = param.jcut; 45 | state_cut = param.state_cut; 46 | if isempty(state_cut); state_cut = round(size(data,1)/4); end 47 | 48 | %% find similarity structure 49 | % find high-activity frames 50 | [data_active,pk_indx,pks] = findActiveFrames(data,pks); 51 | 52 | % run tf-idf - make this into a function 53 | data_tfidf = calcTFIDF(data_active); 54 | data_tfidf( isnan( data_tfidf ) ) = 0; % # 55 | 56 | % calculate cosine similarity of tf-idf matrix 57 | S_ti = 1-pdist2(data_tfidf',data_tfidf','cosine'); 58 | 59 | % threshold of noise 60 | if isempty(ticut) 61 | ticut = calc_scut(data_tfidf); 62 | end 63 | S_tib = double(S_ti>ticut); 64 | 65 | % jaccard similarity, define structures better 66 | if isempty(jcut) 67 | jcut = calc_jcut(S_tib); 68 | end 69 | js = 1-pdist2(S_tib,S_tib,'jaccard'); 70 | 71 | 72 | %% do SVD, find states and cells 73 | % Find the peaks in the states and the cells in the states 74 | [state_raster,state_pks,fac_cut] = SVDStateBinary(double(js>jcut),state_cut); 75 | num_state = size(state_raster,2); 76 | 77 | % get state from full dataset 78 | state_pks_full = zeros(1,size(data,2)); 79 | state_pks_full(pk_indx) = state_pks; 80 | 81 | % plot 82 | % # figure; set(gcf,'color','w') 83 | % # imagesc(state_raster'==0); colormap(gray); 84 | 85 | %% find sequences 86 | % find most significant cells for each state 87 | ti_vec = 0.01:0.01:0.1; % cross-validate this threshold 88 | core_svd = cell(num_state,1); 89 | pool_svd = cell(num_state,1); 90 | state_member_raster = zeros(size(data,1),num_state); 91 | % # figure; clf; set(gcf,'color','w') 92 | N = ceil(sqrt(num_state)); 93 | M = ceil(num_state/N); 94 | cc = jet(length(ti_vec)); 95 | cc = max(cc-0.3,0); 96 | for ii = 1:num_state 97 | 98 | % pull out all activities in a state 99 | state_ti_hist = sum(data_tfidf(:,state_pks==ii),2)'; 100 | state_ti_hist = state_ti_hist/max(state_ti_hist); 101 | 102 | % cross-validate ti_cut with cosine similarity - the core needs to 103 | % predict its corresponding state 104 | % # subplot(M,N,ii); hold on 105 | auc = zeros(size(ti_vec)); 106 | for n = 1:length(ti_vec) 107 | core_vec = zeros(size(data_active,1),1); 108 | core_vec(state_ti_hist>ti_vec(n)) = 1; 109 | sim_core = 1-pdist2(data_active',core_vec','cosine')'; 110 | [xx,yy,~,auc(n)] = perfcurve(double(state_pks==ii),sim_core,1); 111 | % # plot(xx,yy,'color',cc(n,:),'linewidth',1); 112 | end 113 | % # plot([0 1],[0 1],'k--') 114 | % # xlim([0 1]); ylim([0 1]) 115 | % # xlabel('FPR'); ylabel('TPR'); title(['state ' num2str(ii)]) 116 | [~,best_indx] = max(auc); 117 | ti_cut = ti_vec(best_indx); 118 | state_member_raster(:,ii) = state_ti_hist>ti_cut; 119 | core_svd{ii} = find(state_member_raster(:,ii)); 120 | pool_svd{ii} = find(state_ti_hist>0); 121 | 122 | end 123 | 124 | %% plot core neurons 125 | % plot ensemble component cells 126 | % # cc_lr = [1 0.8 0.8]; % light red 127 | % # cc_r = [1 0.2 0.2]; % red 128 | % # mksz = 30; 129 | % # figure; clf; set(gcf,'color','w') 130 | % # for ii = 1:num_state 131 | % # subplot(M,N,ii); hold on 132 | % # scatter(coords(:,1),-coords(:,2),mksz,'k'); 133 | % # scatter(coords(pool_svd{ii},1),-coords(pool_svd{ii},2),mksz,cc_lr,'filled'); 134 | % # scatter(coords(core_svd{ii},1),-coords(core_svd{ii},2),mksz,cc_r,'filled'); 135 | % # title(['ensemble #' num2str(ii)]); 136 | % # axis off equal 137 | % # end 138 | 139 | %% update parameters for output 140 | param.pks = pks; 141 | param.ticut = ticut; 142 | param.jcut = jcut; 143 | param.state_cut = state_cut; 144 | 145 | end -------------------------------------------------------------------------------- /assembly-detection/inc_findSVDAssemblies/SVDEnsemble/shuffle.m: -------------------------------------------------------------------------------- 1 | % # (JM) MODIFIED FROM ORIGINAL FUNCTION 'shuffle' 2 | 3 | function shuffled = shuffle(x,method) 4 | 5 | %shuffle Shuffles raster data using various different methods 6 | % Shuffles spike data (0 or 1) using three differnt methods 7 | % assumes rows are individual cells and columns are time frames 8 | % 9 | % 'frames' - shuffles the frames in time, maintains activity pattern of 10 | % each frame 11 | % 12 | % 'time' - shuffles the activity of each individual cell in time 13 | % each cell maintains its total level of activity 14 | % 15 | % 'time_shift' - shifts the time trace of each cell by a random ammount 16 | % each cell maintains its pattern of activity 17 | % 18 | % Methods fom synfire chains paper 19 | % 20 | % 'isi' - Inter-Spike Interval shuffling within cells 21 | % each cell maintains in level of activity 22 | % 23 | % 'cell' - shuffles the activity at a given time between cells 24 | % each frame maintains the number of active cells 25 | % 26 | % 'exchange' - exchange pairs of spikes across cells 27 | % slow, but each cell and frame maintains level of activity 28 | % 29 | % jzaremba 01/2012 30 | 31 | if nargin < 2 32 | method = 'frames'; 33 | end 34 | 35 | if ~any(strcmp(method, {'frames','time','time_shift','isi','cell','exchange'})) 36 | method = 'frames'; 37 | end 38 | 39 | shuffled=x; 40 | 41 | switch method 42 | case 'frames' 43 | randp = randperm(length(x)); 44 | shuffled = sortrows([randp;x]')'; 45 | shuffled = shuffled(2:end,:); 46 | 47 | case 'time' 48 | n = size(x,2); % # n = length(x); 49 | for i = 1:size(x,1) 50 | randp = randperm(n); 51 | temp = sortrows([randp; x(i,:)]')'; 52 | shuffled(i,:) = temp(2,:); 53 | end 54 | 55 | case 'time_shift' 56 | n = size(x,2); % # n = length(x); 57 | for i = 1:size(x,1) 58 | randp = randi(n); 59 | shuffled(i,:) = [ x(i,n-randp+1:n) x(i,1:n-randp) ]; 60 | end 61 | 62 | case 'isi' 63 | n = length(x); 64 | shuffled = zeros(size(x,1),n); 65 | 66 | for i = 1:size(x,1) 67 | % Pull out indices of spikes, get ISIs, buffer at start and end 68 | isi = diff(find([1 x(i,:) 1])); 69 | isi = isi(randperm(length(isi))); % Randomize ISIs 70 | 71 | temp = cumsum(isi); 72 | temp = temp(1:end-1); % Removes the end spikes that were added 73 | % Put the spikes back 74 | shuffled(i,temp) = true; 75 | end 76 | 77 | 78 | case 'cell' 79 | [n,len] = size(x); 80 | for i = 1:len 81 | randp = randperm(n); 82 | temp = sortrows([randp' x(:,i)]); 83 | shuffled(:,i) = temp(:,2); 84 | end 85 | 86 | case 'exchange' 87 | n = sum(x(:)); 88 | for i = 1:2*n 89 | randp = randi(n,1,2); 90 | [r,c] = find(shuffled); 91 | 92 | % Make sure that the swap will actually do something 93 | while randp(1)==randp(2) || r(randp(1))==r(randp(2)) || c(randp(1))==c(randp(2)) || shuffled(r(randp(2)),c(randp(1)))==true || shuffled(r(randp(1)),c(randp(2)))==true 94 | randp = randi(n,1,2); 95 | end 96 | 97 | % Swap 98 | shuffled(r(randp(2)),c(randp(1))) = true; 99 | shuffled(r(randp(1)),c(randp(1))) = false; 100 | 101 | shuffled(r(randp(1)),c(randp(2))) = true; 102 | shuffled(r(randp(2)),c(randp(2))) = false; 103 | 104 | end 105 | 106 | end 107 | 108 | -------------------------------------------------------------------------------- /assembly-detection/test__printAssemblies.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | bestmatch_d = @(c1,c2) 1 - numel( intersect( c1 , c2 ) ) / numel( union( c1 , c2 ) ); 5 | bestmatch_score = @(A,B) 1 - bestmatch( bestmatch_d , A , B ) / ( 1 * ( numel( A ) + numel( B ) ) ); 6 | 7 | 8 | printConsoleSection( 'EMBEDDED ASSEMBLY CONFIGURATION' ); 9 | A_ = CALCIUM_FLUORESCENCE_mat.parameter.assembly_configuration; 10 | A_ = cellfun( @(a) sort( a ) , A_ , 'UniformOutput' , false ); 11 | A_ = A_( ~cellfun( @isempty , A_ ) ); 12 | for r = 1:numel( A_ ) 13 | 14 | fprintf( 1 , [ '%4u: { ' strjoin( repmat( {'%5u'} , 1 , numel( A_{r} ) ) , '' ) ' }' '\n' ] , r , A_{r} ); 15 | 16 | end 17 | 18 | printConsoleSection( 'INFERRED ASSEMBLY CONFIGURATION' ); 19 | for r = 1:numel( A ) 20 | 21 | fprintf( 1 , [ '%4u: { ' strjoin( repmat( {'%5u'} , 1 , numel( A{r} ) ) , '' ) ' }' '\n' ] , r , A{r} ); 22 | 23 | end 24 | 25 | fprintf( 1 , '\n' ); 26 | fprintf( 1 , [ '> BestMatch score: %.5f' '\n' ] , bestmatch_score( A , A_ ) ); 27 | 28 | 29 | 30 | figure; 31 | 32 | imagesc( cross_evaluation( @(c1,c2) bestmatch_d(c1,c2) , A , A_ ) , [ 0 1 ] ) 33 | 34 | xticks( 1:numel( A_ ) ); 35 | yticks( 1:numel( A ) ); 36 | 37 | axis equal; 38 | axis tight; 39 | 40 | -------------------------------------------------------------------------------- /calcium-fluorescence-processing/CALCIUM_FLUORESCENCE_PROCESSING.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = CALCIUM_FLUORESCENCE_PROCESSING( CALCIUM_FLUORESCENCE_file , varargin ) 2 | %CALCIUM_FLUORESCENCE_PROCESSING( CALCIUM_FLUORESCENCE_file , varargin ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | narginchk(1,Inf); 9 | 10 | fprintf( 1 , [ '\n' ] ); 11 | 12 | %% > PRINT FUNCTION-CALL 13 | if( isdeployed ) 14 | printConsoleSection( 'FUNCTION CALL' ); 15 | 16 | fprintf( 1 , [ 'CALCIUM_FLUORESCENCE_PROCESSING( %s )' '\n' ] , CALCIUM_FLUORESCENCE_file ); 17 | fprintf( 1 , [ '\n' ] ); 18 | end 19 | 20 | if( exist( [ CALCIUM_FLUORESCENCE_file ] , 'file' ) == 2 ) 21 | 22 | printConsoleSection( 'PROCESS CALCIUM FLUORESCENCE' ); 23 | 24 | CALCIUM_FLUORESCENCE_mat = load( [ CALCIUM_FLUORESCENCE_file ] ); 25 | 26 | 27 | PRESETS = varargin; 28 | if( numel( PRESETS ) == 0 ) 29 | PRESETS = { 'ALL' }; 30 | end 31 | Q_presets = @( S ) any( strcmp( PRESETS , S ) ); 32 | 33 | 34 | %% > MAKE *_ACTIVITY-RASTER.MAT ( => similarity-graph-clustering ) 35 | if( Q_presets( 'ALL' ) || Q_presets( 'ACTIVITY-RASTER' ) || Q_presets( 'ACTIVITY-FIM-RASTER' ) || Q_presets( 'ACTIVITY-ISING-FREQUENCIES' ) ) 36 | 37 | fprintf( 1 , [ 'Prepare *_ACTIVITY-RASTER.MAT file for similarity-graph-clustering ...' '\n' ] ); 38 | 39 | [ directory , name , ~ ] = fileparts( CALCIUM_FLUORESCENCE_file ); 40 | OUTPUT_PATH = [ directory '/' strrep( name , '_CALCIUM-FLUORESCENCE' , '_ACTIVITY-RASTER' ) '.mat' ]; 41 | 42 | if( exist( OUTPUT_PATH , 'file' ) ~= 2 ) 43 | tic; 44 | [ sig_dF_F_activity , sig_dF_F_coactivity_threshold , sig_dF_F_coactivity_peaks ] = findSignificantDF_FCoactivity( CALCIUM_FLUORESCENCE_mat.calcium_fluorescence.dF_F ); 45 | 46 | output_args.activity_raster = sig_dF_F_activity; 47 | output_args.activity_raster_threshold = sig_dF_F_coactivity_threshold; 48 | output_args.activity_raster_peaks = sig_dF_F_coactivity_peaks; 49 | 50 | 51 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 52 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 53 | 54 | toc 55 | else 56 | output_args = load( OUTPUT_PATH ); 57 | sig_dF_F_activity = output_args.activity_raster; 58 | 59 | fprintf( 1 , [ '> ...' '\n' ] ); 60 | end 61 | 62 | fprintf( 1 , [ '' '\n' ] ); 63 | end 64 | 65 | %% > MAKE *_ACTIVITY-FIM-RASTER.DAT ( => frequent-item-set-mining ("fim+psf+psr" / "ccn+psf+psr") ) 66 | if( Q_presets( 'ALL' ) || Q_presets( 'ACTIVITY-FIM-RASTER' ) ) 67 | 68 | fprintf( 1 , [ 'Prepare *_ACTIVITY-FIM-RASTER.DAT file for frequent-item-set-mining ...' '\n' ] ); 69 | 70 | [ directory , name , ~ ] = fileparts( CALCIUM_FLUORESCENCE_file ); 71 | OUTPUT_PATH = [ directory '/' strrep( name , '_CALCIUM-FLUORESCENCE' , '_ACTIVITY-FIM-RASTER' ) '.dat' ]; 72 | 73 | if( exist( OUTPUT_PATH , 'file' ) ~= 2 ) 74 | tic; 75 | 76 | %------------------------------------------------------------------ 77 | 78 | output_args = cellfun( @(t) find( t == 1 ) , num2cell( sig_dF_F_activity , 2 ) , 'UniformOutput' , false ); 79 | 80 | i_ = fopen( OUTPUT_PATH , 'w' ); 81 | 82 | for k = 1:numel( output_args ) 83 | 84 | for n = output_args{k} 85 | fprintf( i_ , '%u ' , n ); 86 | end 87 | fprintf( i_ , '\n' ); 88 | end 89 | 90 | fclose( i_ ); 91 | 92 | %------------------------------------------------------------------ 93 | 94 | % i_ = fopen( '' , 'w' ); 95 | % 96 | % for t = 1:size( sig_dF_F_activity , 1 ) 97 | % 98 | % for n = 1:size( sig_dF_F_activity , 2 ) 99 | % if( sig_dF_F_activity(t,n) == 1 ) 100 | % fprintf( i_ , '%u %.3f\n' , n , ( t - 0.5 ) * CALCIUM_FLUORESCENCE_mat.parameter.dT_step ); 101 | % end 102 | % end 103 | % end 104 | % 105 | % fclose( i_ ); 106 | 107 | %------------------------------------------------------------------ 108 | 109 | % output_args = cellfun( @(s) ( find( s == 1 ) - 0.5 ) * CALCIUM_FLUORESCENCE_mat.parameter.dT_step , num2cell( sig_dF_F_activity , 1 ) , 'UniformOutput' , false ); 110 | % 111 | % i_ = fopen( '' , 'w' ); 112 | % 113 | % for n = 1:numel( output_args ) 114 | % 115 | % fprintf( i_ , '%u' , n ); 116 | % 117 | % for t = output_args{n} 118 | % fprintf( i_ , ' %.3f' , t ); 119 | % end 120 | % fprintf( i_ , '\n' ); 121 | % end 122 | % 123 | % fclose( i_ ); 124 | 125 | %------------------------------------------------------------------ 126 | 127 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 128 | 129 | toc 130 | else 131 | fprintf( 1 , [ '> ...' '\n' ] ); 132 | end 133 | 134 | fprintf( 1 , [ '' '\n' ] ); 135 | end 136 | 137 | %% > MAKE *_ACTIVITY-ISING-FREQUENCIES.p ( => ACE ) 138 | if( Q_presets( 'ALL' ) || Q_presets( 'ACTIVITY-ISING-FREQUENCIES' ) ) 139 | 140 | %fprintf( 1 , [ 'Prepare *_ACTIVITY-ISING-FREQUENCIES.p file for ACE ...' '\n' ] ); 141 | % 142 | % [ directory , name , ~ ] = fileparts( CALCIUM_FLUORESCENCE_file ); 143 | % OUTPUT_PATH = [ directory '/' strrep( name , '_CALCIUM-FLUORESCENCE' , '_ACTIVITY-ISING-FREQUENCIES' ) '.p' ]; 144 | % 145 | % if( exist( OUTPUT_PATH , 'file' ) ~= 2 ) 146 | % tic; 147 | % 148 | % i_ = fopen( OUTPUT_PATH , 'w' ); 149 | % print_p( i_ , sig_dF_F_activity ); 150 | % fclose( i_ ); 151 | % 152 | % fileattrib( OUTPUT_PATH , '+w' , 'g' ); 153 | % 154 | % toc 155 | % else 156 | % fprintf( 1 , [ '> ...' '\n' ] ); 157 | % end 158 | % 159 | % fprintf( 1 , [ '' '\n' ] ); 160 | end 161 | 162 | %% > MAKE *_SPIKE-PROBABILITY-RASTER.MAT ( => CORE algorithm ) 163 | if( Q_presets( 'ALL' ) || Q_presets( 'SPIKE-PROBABILITY-RASTER' ) ) 164 | 165 | fprintf( 1 , [ 'Prepare *_SPIKE-PROBABILITY-RASTER.MAT file ...' '\n' ] ); 166 | 167 | [ directory , name , ~ ] = fileparts( CALCIUM_FLUORESCENCE_file ); 168 | OUTPUT_PATH = [ directory '/' strrep( name , '_CALCIUM-FLUORESCENCE' , '_SPIKE-PROBABILITY-RASTER' ) '.mat' ]; 169 | 170 | if( exist( OUTPUT_PATH , 'file' ) ~= 2 ) 171 | tic; 172 | [ ~ , spike_probability_raster , spike_probability_raster_thresholds , oopsi_deconvolution ] = findDF_FSpikeProbability( CALCIUM_FLUORESCENCE_mat.calcium_fluorescence.dF_F , CALCIUM_FLUORESCENCE_mat.parameter.dT_step , CALCIUM_FLUORESCENCE_mat.parameter.calcium_T1_2 ); 173 | 174 | output_args = []; 175 | output_args.spike_probability_raster = spike_probability_raster; 176 | output_args.spike_probability_raster_thresholds = spike_probability_raster_thresholds; 177 | output_args.oopsi_deconvolution = oopsi_deconvolution; 178 | 179 | 180 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 181 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 182 | 183 | toc 184 | end 185 | 186 | fprintf( 1 , [ '' '\n' ] ); 187 | end 188 | 189 | %% > MAKE *_RASTER.MAT ( => PCA-promax ) 190 | if( Q_presets( 'ALL' ) || Q_presets( 'RASTER' ) ) 191 | 192 | fprintf( 1 , [ 'Prepare *_RASTER.MAT file for PCA-promax ...' '\n' ] ); 193 | 194 | [ directory , name , ~ ] = fileparts( CALCIUM_FLUORESCENCE_file ); 195 | OUTPUT_PATH = [ directory '/' strrep( name , '_CALCIUM-FLUORESCENCE' , '_RASTER' ) '.mat' ]; 196 | 197 | if( exist( OUTPUT_PATH , 'file' ) ~= 2 ) 198 | tic; 199 | [ ~ , output_args ] = findSignificantFluorescenceTraces( CALCIUM_FLUORESCENCE_mat.calcium_fluorescence.dF_F , CALCIUM_FLUORESCENCE_mat.parameter.calcium_T1_2 / log(2) , 1 / CALCIUM_FLUORESCENCE_mat.parameter.dT_step ); 200 | 201 | save( OUTPUT_PATH , '-v7' , '-struct' , 'output_args' ); 202 | fileattrib( OUTPUT_PATH , '+w' , 'g' ); 203 | 204 | toc 205 | else 206 | fprintf( 1 , [ '> ...' '\n' ] ); 207 | end 208 | 209 | fprintf( 1 , [ '' '\n' ] ); 210 | end 211 | 212 | %% > 213 | 214 | output_args = NaN; 215 | 216 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 217 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 218 | else 219 | 220 | output_args = NaN; 221 | 222 | fprintf( 1 , [ '>> END PROGRAM' '\n' ] ); 223 | fprintf( 2 , [ '>> END PROGRAM' '\n' ] ); 224 | end 225 | 226 | end 227 | 228 | -------------------------------------------------------------------------------- /calcium-fluorescence-processing/findDF_FSpikeProbability.m: -------------------------------------------------------------------------------- 1 | function [ spike_probability , spike_probability_raster , spike_probability_raster_thresholds , oopsi_deconvolution ] = findDF_FSpikeProbability( dF_F , dT , t1_2 ) 2 | %FINDDF_FSPIKEPROBABILITY( dF_F , dT , t1_2 ) 3 | % 4 | % PARAMETERS: 5 | % \_ dF_F [TxN matrix]: dF/F-signal for N units in T time steps 6 | % \_ dT: signal temporal resolution in units of seconds 7 | % \_ t1_2: calcium-indicator fluorescence half-life in units of seconds 8 | % 9 | % 10 | % === Jan Moelter, The University of Queensland, 2018 =================== 11 | % 12 | 13 | dF_F = dF_F( ~any( isnan( dF_F ) , 2 ) , : ); 14 | 15 | %% DECONVOLVE DF/F DATA 16 | 17 | V = struct( 'dt' , dT ); 18 | P = struct( 'gam' , 1 ./ 2^( dT / t1_2 ) ); % gam = F(t+dT)/F(t) 19 | 20 | n_best = NaN * ones( size( dF_F ) ); 21 | 22 | for n = 1:size( dF_F , 2 ) 23 | 24 | F = dF_F( : , n ); 25 | [ n_best(:,n) , P_best(n) , ~ , ~ ] = fast_oopsi( F , V , P ); 26 | 27 | end 28 | 29 | %% 30 | 31 | oopsi_deconvolution.n_best = n_best; 32 | oopsi_deconvolution.P_best = P_best; 33 | 34 | 35 | CONST.STD_SIG_THRESHOLD = 3; 36 | % \_ CONST.STD_THRESHOLD: spike probability standard deviation significance 37 | % level 38 | 39 | spike_probability = oopsi_deconvolution.n_best ./ max( oopsi_deconvolution.n_best ); 40 | spike_probability_raster = double( spike_probability > CONST.STD_SIG_THRESHOLD * std( spike_probability(:) ) ); 41 | 42 | 43 | CONST.SHUFFLE_ROUNDS = 1000; 44 | % \_ CONST.SHUFFLE_ROUNDS: rounds of shuffling for coactivity null model 45 | CONST.SIGNIFICANCE_P = [ 0.05 , 0.01 ]; 46 | % \_ CONST.SIGNIFICANCE_P: significance level for the spike probability 47 | % coactivity 48 | 49 | [ coactivity_thresholds , ~ ] = findSignificantCoactivity( spike_probability_raster , struct( 'shuffle_rounds' , CONST.SHUFFLE_ROUNDS , 'significance_p' , CONST.SIGNIFICANCE_P ) ); 50 | 51 | spike_probability_raster_thresholds = struct( 'p' , num2cell( CONST.SIGNIFICANCE_P ) , 'coactivity' , num2cell( coactivity_thresholds ) ); 52 | 53 | end -------------------------------------------------------------------------------- /calcium-fluorescence-processing/findSignificantDF_FCoactivity.m: -------------------------------------------------------------------------------- 1 | function [ sig_dF_F_activity , sig_dF_F_coactivity_threshold , sig_dF_F_coactivity_peaks ] = findSignificantDF_FCoactivity( dF_F ) 2 | %FINDSIGNIFICANTDF_FCOACTIVITY( dF_F ) 3 | % 4 | % PARAMETERS: 5 | % \_ dF_F [TxN matrix]: dF/F-signal for N units in T time steps 6 | % 7 | % 8 | % === Jan Moelter, The University of Queensland, 2018 =================== 9 | % 10 | 11 | dF_F = dF_F( ~any( isnan( dF_F ) , 2 ) , : ); 12 | 13 | %% PREPROCESS THE dF/F-signal 14 | 15 | CONST.STD_SIG_THRESHOLD = 2; 16 | % \_ CONST.STD_SIG_THRESHOLD: dF/F-signal significance level in standard 17 | % deviation from the mean 18 | 19 | fprintf( 1 , [ 'significance threshold: ' num2str( CONST.STD_SIG_THRESHOLD ) 'STD' '\n' ] ); 20 | 21 | [ T , N ] = size( dF_F ); 22 | 23 | mean_dF_F = mean( dF_F , 1 ); 24 | % \_ mean_dF_F [1 x N matrix]: mean dF/F-signal for N units 25 | std_dF_F = std( dF_F , 0 , 1 ); 26 | % \_ std_dF_F [1 x N matrix]: standard deviation in dF/F-signal for N units 27 | 28 | 29 | sig_dF_F_activity = double( dF_F > repmat( mean_dF_F + CONST.STD_SIG_THRESHOLD * std_dF_F , T , 1 ) ); 30 | % \_ sig_dF_F_mask [T x N matrix]: binary mask of significant dF/F-signal for N units in T time steps 31 | 32 | clearvars CONST; 33 | 34 | %% FIND SIGNIFICANT PEAKS IN THE THE COACTIVITY 35 | 36 | CONST.SHUFFLE_ROUNDS = 1000; 37 | % \_ CONST.SHUFFLE_ROUNDS: rounds of shuffling for coactivity null model 38 | CONST.SIGNIFICANCE_P = 0.05; 39 | % \_ CONST.SIGNIFICANCE_P: significance level for the dF/F-coactivity 40 | 41 | [ sig_dF_F_coactivity_threshold , ~ ] = findSignificantCoactivity( sig_dF_F_activity , struct( 'shuffle_rounds' , CONST.SHUFFLE_ROUNDS , 'significance_p' , CONST.SIGNIFICANCE_P ) ); 42 | % \_ sig_dF_F_coactivity_threshold: significance threshold for the 43 | % dF/F-coactivity 44 | 45 | normalised_sig_dF_F_coactivity = sum( sig_dF_F_activity , 2 ) ./ max( sum( sig_dF_F_activity , 2 ) ); 46 | normalised_sig_dF_F_coactivity_threshold = sig_dF_F_coactivity_threshold / max( sum( sig_dF_F_activity , 2 ) ); 47 | % \_ normalised_sig_dF_F_coactivity [T x 1 matrix]: normalised dF/F-coactivity 48 | % \_ normalised_sig_dF_F_coactivity_threshold: normalised significance 49 | % threshold for the normalised dF/F-coactivity 50 | 51 | [ sig_dF_F_coactivity_peaks , ~ ] = peakfinder( normalised_sig_dF_F_coactivity , 0.05 , normalised_sig_dF_F_coactivity_threshold , 1 , true , false ); 52 | % \_ sig_dF_F_coactivity_peaks [? x 1 matrix]: peak times of the 53 | % dF/F-coactivity 54 | 55 | clearvars CONST; 56 | 57 | %% END 58 | 59 | end -------------------------------------------------------------------------------- /calcium-fluorescence-processing/findSignificantFluorescenceTraces.m: -------------------------------------------------------------------------------- 1 | function [ raster , output_args ] = findSignificantFluorescenceTraces( deltaFoF , tauDecay , fps ) 2 | %FINDSIGNIFICANTFLUORESCENCETRACES( deltaFoF , tauDecay , fps ) 3 | % 4 | % PARAMETERS: 5 | % \_ deltaFoF: dF/F-signal 6 | % \_ tauDecay: calcium-indicator fluorescence decay constant in units of 7 | % seconds 8 | % \_ fps: frame rate in units of inverse seconds (Hertz) 9 | % 10 | % 11 | % === Jan Moelter, The University of Queensland, 2018 =================== 12 | % 13 | 14 | params.fps = fps; 15 | params.tauDecay = tauDecay; 16 | params.BaselineNoiseMethod = 'Gaussian model'; 17 | params.methodSignificatTransients = 'Dynamic threshold'; 18 | params.confCutOff = 95; 19 | 20 | movements = zeros( size( deltaFoF , 1 ) , 1 ); 21 | 22 | %% 'Step 2: Calculation of noise level in baseline fluorescence ROIs.' 23 | 24 | [deltaFoF, mu, sigma, params]=EstimateBaselineNoise(deltaFoF, params); 25 | 26 | deltaFoF(logical(movements),:)=NaN; 27 | 28 | %% 'Step 3: Detection of significant fluorescence transients.' 29 | 30 | %% 'Step 3.1: Estimating noise model.' 31 | [densityData, densityNoise, xev, yev] = NoiseModel( '' , deltaFoF, sigma, movements , false); 32 | [mapOfOdds] = SignificantOdds(deltaFoF, sigma, movements, densityData, densityNoise, xev, params, false); 33 | 34 | %% 'Step 3.2: Producing raster plot.' 35 | 36 | [raster, mapOfOddsJoint]=Rasterize(deltaFoF, sigma, movements, mapOfOdds, xev, yev, params); 37 | 38 | %% 'Step 3.3: Saving and quitting.' 39 | 40 | output_args.raster = raster; 41 | output_args.params = params; 42 | output_args.deltaFoF = deltaFoF; 43 | output_args.deletedCells = []; 44 | output_args.movements = movements; 45 | 46 | output_args.mu = mu; 47 | output_args.sigma = sigma; 48 | 49 | output_args.imageAvg = NaN; 50 | output_args.F0 = NaN; 51 | 52 | output_args.dataAllCells = NaN; 53 | 54 | end -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findDF_FSpikeProbability/README__oopsi: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'oopsi' 2 | REPOSITORY (https://github.com/jovo/oopsi) BY JOSHUA VOGELSTEIN. 3 | 4 | THE FUNCTIONS REMAINED UN-MODIFIED. 5 | -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findDF_FSpikeProbability/oopsi/CONTRIBUTING: -------------------------------------------------------------------------------- 1 | please do not :) 2 | this repo is defunkt. 3 | 4 | - https://github.com/j-friedrich/OASIS 5 | - https://github.com/zhoupc/OASIS_matlab 6 | 7 | have faster, debugged, and better algorithms. 8 | feel free to mention @jovo in any issues that you create and want my feedback on. 9 | -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findDF_FSpikeProbability/oopsi/Hill_v1.m: -------------------------------------------------------------------------------- 1 | function F = Hill_v1(P,C) 2 | % generalized hill model 3 | C(C<0) = 0; 4 | F = C.^P.n./(C.^P.n+P.k_d); -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findDF_FSpikeProbability/oopsi/README.md: -------------------------------------------------------------------------------- 1 | ### better algorithm/implementation for fast-oopsi now available 2 | 3 | - the standard toolbox for calcium imaging and analysis is [CaImAn](https://github.com/flatironinstitute/CaImAn), which extends our work in several nice ways (they have Python and MATLAB) 4 | - a very nice R package: https://cran.r-project.org/web/packages/LZeroSpikeInference/index.html, based on the following two articles 5 | - https://arxiv.org/abs/1802.07380 6 | - https://arxiv.org/abs/1703.08644 7 | 8 | 9 | imho, there is no reason to use this repo anymore unless you really want to use the particle filter based approach, 10 | i recommend that you use the above codes for R, python, and matlab. 11 | 12 | ### oopsi algorithm info 13 | 14 | This is a repo containing the most current code for doing model-based spike train inference from calcium imaging. Manuscripts explaining the theory and providing some results on simulated and real data are available from the fast-oopsi, smc-oopsi, and pop-oopsi github repositories. Those repositories also contain code that you may run and data to download to play with things. Any question, ask them in the issues tab. Please let me know of any positive or negative experiences. Much Obliged, jovo 15 | 16 | A question we often get is: "how shall we interpret the output? probability of spiking? instantaneous firing rate?? 17 | 18 | the answer is: yes, maybe :) 19 | 20 | the "issue" is the lack of calibration data, 21 | which means we do not know the absolute size of a calcium transient evoked from a single spike. 22 | we estimate it from the data, but if the neuron happens to always spike twice, for example, 23 | our estimate will be off by a factor of 2. 24 | 25 | we can think of the above this way: is it likely that the neuron to spikes multiple times per time bin? 26 | 27 | if so, i don't normalize the output, and interpret it as the instantaneous firing rate. 28 | 29 | if not, i normalize the output so that its max is 1, and then i interpret it as the probability of a spike. 30 | 31 | i hope this helps! 32 | 33 | if not, please post issues [here](https://github.com/jovo/oopsi/issues) 34 | 35 | -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findDF_FSpikeProbability/oopsi/demo.m: -------------------------------------------------------------------------------- 1 | clear, clc, 2 | 3 | % set simulation metadata 4 | T = 1000; % # of time steps 5 | V.dt = 1/8; % time step size 6 | 7 | % initialize params 8 | P.a = 1; % observation scale 9 | P.b = 0; % observation bias 10 | tau = 1.5; % decay time constant 11 | P.gam = 1-V.dt/tau; % C(t) = gam*C(t-1) 12 | P.lam = 0.1; % firing rate = lam/dt 13 | P.sig = 0.1; % standard deviation of observation noise 14 | 15 | % simulate data 16 | N = poissrnd(P.lam*V.dt*ones(T,1)); % simulate spike train 17 | C = filter(1,[1 -P.gam],N); % calcium concentration 18 | F = P.a*C+P.b + P.sig*randn(T,1); % observations 19 | 20 | % fast oopsi 21 | [Nhat Phat] = fast_oopsi(F,V,P); 22 | 23 | % smc-oopsi 24 | V.smc_iter_max = 1; 25 | [M P V] = smc_oopsi(F,V,P); 26 | 27 | %% plot results 28 | figure(1), clf 29 | tvec=0:V.dt:(T-1)*V.dt; 30 | h(1)=subplot(411); plot(tvec,F); axis('tight'), ylabel('F (au)') 31 | h(2)=subplot(412); plot(tvec,C); axis('tight'), ylabel('C (au)') 32 | h(3)=subplot(413); stem(tvec,N); hold on, plot(tvec,Nhat,'r','linewidth',1), axis('tight'), ylabel('fast') 33 | Nsmc = M.nbar/max(M.nbar); 34 | Nsmc(Nsmc<0.1)=0; 35 | h(4)=subplot(414); stem(tvec,N); hold on, plot(tvec,Nsmc,'k','linewidth',2); axis('tight'), ylabel('smc') 36 | xlabel('time (sec)') 37 | linkaxes(h,'x') 38 | 39 | 40 | -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findDF_FSpikeProbability/oopsi/smc_oopsi.m: -------------------------------------------------------------------------------- 1 | function [M P V] = smc_oopsi(F,V,P) 2 | % this function runs the SMC-EM on a fluorescence time-series, and outputs the inferred 3 | % distributions and parameter estimates 4 | % 5 | % Inputs 6 | % F: fluorescence time series 7 | % V: structure of stuff necessary to run smc-em code 8 | % P: structure of initial parameter estimates 9 | % 10 | % Outputs 11 | % M: structure containing mean, variance, and percentiles of inferred distributions 12 | % P: structure containing the final parameter estimates 13 | % V: structure Variables for algorithm to run 14 | 15 | if nargin < 2, V = struct; end 16 | if ~isfield(V,'T'), V.T = length(F); end % # of observations 17 | if ~isfield(V,'freq'), V.freq = 1; end % # time steps between observations 18 | if ~isfield(V,'T_o'), V.T_o = V.T; end % # of observations 19 | if ~isfield(V,'x'), V.x = ones(1,V.T); end % stimulus 20 | if ~isfield(V,'scan'), V.scan = 0; end % epi or scan 21 | if ~isfield(V,'name'), V.name ='oopsi'; end % name for output and figure 22 | if ~isfield(V,'Nparticles'), V.Nparticles = 99; end % # particles 23 | if ~isfield(V,'Nspikehist'), V.Nspikehist = 0; end % # of spike history terms 24 | if ~isfield(V,'condsamp'), V.condsamp = 1; end % whether to use conditional sampler 25 | if ~isfield(V,'ignorelik'), V.ignorelik = 1; end % epi or scan 26 | if ~isfield(V,'true_n'), % if true spikes are not available 27 | V.use_true_n = 0; % don't use them for anything 28 | else 29 | V.use_true_n = 1; 30 | end 31 | if ~isfield(V,'smc_iter_max'), % max # of iterations before convergence 32 | reply = str2double(input('\nhow many EM iterations would you like to perform \nto estimate parameters (0 means use default parameters): ', 's')); 33 | V.smc_iter_max = reply; 34 | end 35 | if ~isfield(V,'dt'), 36 | fr = input('what was the frame rate for this movie (in Hz)? '); 37 | V.dt = 1/fr; 38 | end 39 | 40 | % set which parameters to estimate 41 | if ~isfield(V,'est_c'), V.est_c = 1; end % tau_c, A, C_0 42 | if ~isfield(V,'est_t'), V.est_t = 1; end % tau_c (useful when data is poor) 43 | if ~isfield(V,'est_n'), V.est_n = 1; end % b,k 44 | if ~isfield(V,'est_h'), V.est_h = 0; end % w 45 | if ~isfield(V,'est_F'), V.est_F = 1; end % alpha, beta 46 | if ~isfield(V,'smc_plot'), V.smc_plot = 1; end % plot results with each iteration 47 | 48 | %% initialize model Parameters 49 | 50 | if nargin < 3, P = struct; end 51 | if ~isfield(P,'tau_c'), P.tau_c = 1; end % calcium decay time constant (sec) 52 | if ~isfield(P,'A'), P.A = 50; end % change ins [Ca++] after a spike (\mu M) 53 | if ~isfield(P,'C_0'), P.C_0 = 0; end % baseline [Ca++] (\mu M) 54 | if ~isfield(P,'C_init'),P.C_init= 0; end % initial [Ca++] (\mu M) 55 | if ~isfield(P,'sigma_c'),P.sigma_c= 0.1; end % standard deviation of noise (\mu M) 56 | if ~isfield(P,'n'), P.n = 1; end % hill equation exponent 57 | if ~isfield(P,'k_d'), P.k_d = 200; end % hill coefficient 58 | if ~isfield(P,'k'), % linear filter 59 | k = str2double(input('approx. how many spikes underly this trace: ', 's')); 60 | P.k = log(-log(1-k/V.T)/V.dt); 61 | end 62 | if ~isfield(P,'alpha'), P.alpha = mean(F); end % scale of F 63 | if ~isfield(P,'beta'), P.beta = min(F); end % offset of F 64 | if ~isfield(P,'zeta'), P.zeta = P.alpha/5; end % constant variance 65 | if ~isfield(P,'gamma'), P.gamma = P.zeta/5; end % scaled variance 66 | if V.Nspikehist==1 % if there are spike history terms 67 | if ~isfield(P,'omega'), P.omega = -1; end % weight 68 | if ~isfield(P,'tau_h'), P.tau_h = 0.02; end % time constant 69 | if ~isfield(P,'sigma_h'), P.sigma_h = 0; end % stan dev of noise 70 | if ~isfield(P,'g'), P.g = V.dt/P.tau_h; end % for brevity 71 | if ~isfield(P,'sig2_h'), P.sig2_h = P.sigma_h^2*V.dt; end % for brevity 72 | end 73 | if ~isfield(P,'a'), P.a = V.dt/P.tau_c; end % for brevity 74 | if ~isfield(P,'sig2_c'),P.sig2_c= P.sigma_c^2*V.dt; end % for brevity 75 | 76 | %% initialize other stuff 77 | starttime = cputime; 78 | P.lik = -inf; % we are trying to maximize the likelihood here 79 | F = max(F,eps); % in case there are any zeros in the F time series 80 | 81 | S = smc_oopsi_forward(F,V,P); % forward step 82 | M = smc_oopsi_backward(S,V,P); % backward step 83 | if V.smc_iter_max>1, P.conv=false; else P.conv=true; end 84 | 85 | while P.conv==false; 86 | P = smc_oopsi_m_step(V,S,M,P,F); % m step 87 | S = smc_oopsi_forward(F,V,P); % forward step 88 | M = smc_oopsi_backward(S,V,P); % backward step 89 | end 90 | fprintf('\n') 91 | 92 | V.smc_iter_tot = length(P.lik); 93 | V.smc_time = cputime-starttime; 94 | V = orderfields(V); -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findDF_FSpikeProbability/oopsi/smc_oopsi_backward.m: -------------------------------------------------------------------------------- 1 | function M = smc_oopsi_backward(S,V,P) 2 | % this function iterates backward one step computing P[H_t | H_{t+1},O_{0:T}] 3 | % Input--- 4 | % Sim: simulation metadata 5 | % S: particle positions and weights 6 | % P: parameters 7 | % Z: a bunch of stuff initialized for speed 8 | % t: current time step 9 | % 10 | % Output is a single structure Z with the following fields 11 | % n1: vector of spikes or no spike for each particle at time t 12 | % C0: calcium positions at t-1 13 | % C1: calcium positions at t (technically, this need not be output) 14 | % C1mat:matrix from C1 15 | % C0mat:matrix from C0 16 | % w_b: backwards weights 17 | 18 | 19 | fprintf('\nbackward step: ') 20 | Z.oney = ones(V.Nparticles,1); % initialize stuff for speed 21 | Z.zeroy = zeros(V.Nparticles); 22 | Z.C0 = S.C(:,V.T); 23 | Z.C0mat = Z.C0(:,Z.oney)'; 24 | 25 | if V.est_c==false % if not maximizing the calcium parameters, then the backward step is simple 26 | if V.use_true_n % when spike train is provided, backwards is not necessary 27 | S.w_b=S.w_f; 28 | else 29 | for t=V.T-V.freq-1:-1:V.freq+1 % actually recurse backwards for each time step 30 | Z = step_backward(V,S,P,Z,t); 31 | S.w_b(:,t-1) = Z.w_b; % update forward-backward weights 32 | end 33 | end 34 | else % if maximizing calcium parameters, 35 | % need to compute some sufficient statistics 36 | M.Q = zeros(3); % the quadratic term for the calcium par 37 | M.L = zeros(3,1); % the linear term for the calcium par 38 | M.J = 0; % remaining terms for calcium par 39 | M.K = 0; 40 | for t=V.T-V.freq-1:-1:V.freq+1 41 | if V.use_true_n % force true spikes hack 42 | Z.C0 = S.C(t-1); 43 | Z.C0mat = Z.C0; 44 | Z.C1 = S.C(t); 45 | Z.C1mat = Z.C1; 46 | Z.PHH = 1; 47 | Z.w_b = 1; 48 | Z.n1 = S.n(t); 49 | else 50 | Z = step_backward(V,S,P,Z,t); 51 | end 52 | S.w_b(:,t-1) = Z.w_b; 53 | 54 | % below is code to quickly get sufficient statistics 55 | C0dt = Z.C0*V.dt; 56 | bmat = Z.C1mat-Z.C0mat'; 57 | bPHH = Z.PHH.*bmat; 58 | 59 | M.Q(1,1)= M.Q(1,1) + sum(Z.PHH*(C0dt.^2)); % Q-term in QP 60 | M.Q(1,2)= M.Q(1,2) - Z.n1'*Z.PHH*C0dt; 61 | M.Q(1,3)= M.Q(1,3) + sum(sum(-Z.PHH.*Z.C0mat'*V.dt^2)); 62 | M.Q(2,2)= M.Q(2,2) + sum(Z.PHH'*(Z.n1.^2)); 63 | M.Q(2,3)= M.Q(2,3) + sum(sum(Z.PHH(:).*repmat(Z.n1,V.Nparticles,1))*V.dt); 64 | M.Q(3,3)= M.Q(3,3) + sum(Z.PHH(:))*V.dt^2; 65 | 66 | M.L(1) = M.L(1) + sum(bPHH*C0dt); % L-term in QP 67 | M.L(2) = M.L(2) - sum(bPHH'*Z.n1); 68 | M.L(3) = M.L(3) - V.dt*sum(bPHH(:)); 69 | 70 | M.J = M.J + sum(Z.PHH(:)); % J-term in QP /sum J^(i,j)_{t,t-1}/ 71 | 72 | M.K = M.K + sum(Z.PHH(:).*bmat(:).^2); % K-term in QP /sum J^(i,j)_{t,t-1} (d^(i,j)_t)^2/ 73 | end 74 | M.Q(2,1) = M.Q(1,2); % symmetrize Q 75 | M.Q(3,1) = M.Q(1,3); 76 | M.Q(3,2) = M.Q(2,3); 77 | end 78 | fprintf('\n') 79 | 80 | % copy particle swarm for later 81 | M.w = S.w_b; 82 | M.n = S.n; 83 | M.C = S.C; 84 | if isfield(S,'h'), M.h=S.h; end 85 | 86 | % check failure mode caused by too high P.A (low P.sigma_c) 87 | % fact=1.55; 88 | % if(sum(S.n(:))==0 && cnt<10) % means no spikes anywhere 89 | % fprintf(['Failed to find any spikes, likely too high a P.A.\n',... 90 | % 'Attempting to lower by factor %g...\n'],fact); 91 | % P.A=P.A/fact; 92 | % P.C_0=P.C_0/fact; 93 | % P.sigma_c=P.sigma_c/fact; 94 | % cnt=cnt+1; 95 | % elseif(cnt>=10) 96 | % M_best=M; 97 | % E_best=P; 98 | % fprintf('Warning: there are no spikes in the data. Wrong initialization?'); 99 | % return; 100 | % end 101 | M.nbar = sum(S.w_b.*S.n,1); 102 | 103 | end 104 | 105 | function Z = step_backward(V,S,P,Z,t) 106 | 107 | % compute ln P[n_t^i | h_t^i] 108 | Z.n1 = S.n(:,t); % for prettiness sake 109 | ln_Pn = 0*Z.oney; % for fastiness sake 110 | ln_Pn(Z.n1==1) = log(S.p(Z.n1==1,t)); % P[n=1] for those that spiked 111 | ln_Pn(~Z.n1) = log(1-S.p(~Z.n1,t)); % P[n=0] for those that did not 112 | 113 | % compute ln P[C_t^i | C_{t-1}^j, n_t^i] 114 | Z.C0 = S.C(:,t-1); % for prettiness sake 115 | Z.C1 = S.C(:,t); 116 | Z.C1mat = Z.C1(:,Z.oney); % recall from previous time step 117 | Z.C0mat = Z.C0(:,Z.oney); % faster than repamt 118 | mu = (1-P.a)*S.C(:,t-1)+P.A*Z.n1+P.a*P.C_0;% mean 119 | mumat = mu(:,Z.oney)'; % faster than repmat 120 | ln_PC_Cn = -0.5*(Z.C1mat - mumat).^2/P.sig2_c; % P[C_t^i | C_{t-1}^j, n_t^i] 121 | 122 | % compute ln P[h_t^i | h_{t-1}^j, n_{t-1}^i] 123 | ln_Ph_hn = Z.zeroy; % reset transition prob for h terms 124 | for m=1:V.Nspikehist % for each h term 125 | h1 = S.h(:,t,m); % faster than repmat 126 | h1 = h1(:,Z.oney); 127 | h0 = P.g(m)*S.h(:,t-1,m)+S.n(:,t-1); 128 | h0 = h0(:,Z.oney)'; 129 | ln_Ph_hn = ln_Ph_hn - 0.5*(h0 - h1).^2/P.sig2_h(m); 130 | end 131 | 132 | % compute P[H_t^i | H_{t-1}^j] 133 | sum_lns = ln_Pn(:,Z.oney)+ln_PC_Cn + ln_Ph_hn; % in order to ensure this product doesn't have numerical errors 134 | mx = max(sum_lns,[],1); % find max in each of row 135 | mx = mx(Z.oney,:); % make a matrix of maxes 136 | T0 = exp(sum_lns-mx); % exponentiate subtracting maxes (so that in each row, the max entry is exp(0)=1 137 | Tn = sum(T0,1); % then normalize 138 | T = T0.*repmat(1./Tn(:)', V.Nparticles, 1); % such that each column sums to 1 139 | 140 | % compute P[H_t^i, H_{t-1}^j | O] 141 | PHHn = (T*S.w_f(:,t-1))'; % denominator 142 | PHHn(PHHn==0) = eps; 143 | PHHn2 = PHHn(Z.oney,:)'; % faster than repmat 144 | PHH = T .* (S.w_b(:,t)*S.w_f(:,t-1)')./PHHn2; % normalize such that sum(PHH)=1 145 | sumPHH = sum(PHH(:)); 146 | if sumPHH==0 147 | Z.PHH = ones(V.Nparticles)/(V.Nparticles); 148 | else 149 | Z.PHH = PHH/sum(PHH(:)); 150 | end 151 | Z.w_b = sum(Z.PHH,1); % marginalize to get P[H_t^i | O] 152 | 153 | if any(isnan(Z.w_b)) 154 | return 155 | end 156 | 157 | if mod(t,100)==0 && t>=9900 158 | fprintf('\b\b\b\b\b%d',t) 159 | elseif mod(t,100)==0 && t>=900 160 | fprintf('\b\b\b\b%d',t) 161 | elseif mod(t,100)==0 162 | fprintf('\b\b\b%d',t) 163 | end 164 | 165 | end -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findDF_FSpikeProbability/oopsi/z1.m: -------------------------------------------------------------------------------- 1 | function x = z1(y) 2 | % linear normalize between 0 and 1 3 | x = (y-min(y(:)))/(max(y(:))-min(y(:)))+eps; 4 | 5 | % for multidimensional stuff, this normalizes each column to between 0 and 6 | % 1 independent of other columns 7 | 8 | % T=length(y); 9 | % y=y'; 10 | % miny=min(y); 11 | % x = (y-repmat(miny,T,1))./repmat(max(y)-min(y),T,1); -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findSignificantDF_FCoactivity/README__peakfinder: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'peakfinder' FILE EXCHANGE 2 | REPOSITORY HOSTED BY MATHWORKS (https://au.mathworks.com/matlabcentral/fileexchange/25500) 3 | BY NATHANAEL YODER. 4 | 5 | EVERY FUNCTION REMAINED UN-MODIFIED. -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findSignificantDF_FCoactivity/findSignificantCoactivity.m: -------------------------------------------------------------------------------- 1 | function [ sig_coactivity , shuff_coactivity ] = findSignificantCoactivity( X , opts ) 2 | %FINDSIGNIFICANTCOACTIVITY( X , opts ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2018 =================== 6 | % 7 | 8 | [ T , ~ ] = size( X ); 9 | 10 | shuffle = @( X , d ) cell2mat( cellfun( @(x) x( reshape( randperm( numel( x ) ) , size( x ) ) ) , num2cell( X , d ) , 'UniformOutput' , false ) ); 11 | % \_ shuffle( X , d ): shuffle X along its d-th dimension, i.e. every slice 12 | % of X along its d-th dimension is shuffled independently 13 | % in particular, all( sum( shuffle( X , d ) , d ) == sum( X , d ) ) holds 14 | % true 15 | 16 | shuff_coactivity = zeros( opts.shuffle_rounds , T ); 17 | % \_ shuff_coactivity [opts.shuffle_rounds x T matrix]: 18 | 19 | for s = 1:opts.shuffle_rounds 20 | shuff_coactivity( s , : ) = sum( shuffle( X , 1 ) , 2 ); 21 | end 22 | 23 | sig_coactivity = prctile( shuff_coactivity(:) , ( 1 - opts.significance_p ) * 100 ); 24 | % \_ sig_coactivity: significant coactivity threshold estimated as the 25 | % (1-opts.significance_p)-percentile from shuffled coactiviy levels 26 | 27 | end -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findSignificantDF_FCoactivity/peakfinder/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Nathanael C. Yoder 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findSignificantDF_FCoactivity/peakfinder/README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoodhillLab/neural-assembly-detection/f5415317aec2cf141e8f48ef816cddac0547cac3/calcium-fluorescence-processing/inc_findSignificantDF_FCoactivity/peakfinder/README -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findSignificantFluorescenceTraces/README__Toolbox-Romano-et-al: -------------------------------------------------------------------------------- 1 | THE FUNCTIONS IN THIS DIRECTORY WERE TAKEN FROM THE 'TOOLBOX-ROMANO-ET-AL' 2 | REPOSITORY (https://github.com/zebrain-lab/Toolbox-Romano-et-al). 3 | 4 | THE FOLLOWING FUNCTIONS WERE MODIFIED FROM THEIR ORIGINAL STATE ('% # '): 5 | 6 | _ EstimateBaselineNoise.m 7 | 8 | THE FOLLOWING FUNCTIONS REMAIN UN-MODIFIED: 9 | 10 | _ mygaussfit.m 11 | _ NoiseModel.m 12 | _ SignificantOdds.m 13 | _ Rasterize.m -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findSignificantFluorescenceTraces/Toolbox-Romano-et-al/EstimateBaselineNoise.m: -------------------------------------------------------------------------------- 1 | % # (JM) MODIFIED FROM ORIGINAL FUNCTION 'EstimateBaselineNoise' 2 | 3 | function [deltaFoF, mu, sigma, params]=EstimateBaselineNoise(deltaFoF, params) 4 | 5 | % # ansMethod = questdlg('Choose method for estimation of noise in baseline fluorescence', 'Select method', 'Gaussian model', 'Standard deviation', 'Gaussian model'); 6 | ansMethod = params.BaselineNoiseMethod; % # params.BaselineNoiseMethod=ansMethod; 7 | 8 | % # data=load(filename); 9 | if strcmp(ansMethod,'Gaussian model') 10 | 11 | 12 | numCells=size(deltaFoF,2); 13 | numFrames=size(deltaFoF,1); 14 | 15 | 16 | % We calculate the ROI's baseline noise by fitting a 17 | % gaussian to the distribution (local density estimation) of negative values of deltaFoF 18 | 19 | for numcell=1:numCells 20 | 21 | dataCell=deltaFoF(:,numcell); 22 | 23 | [smoothDist,x] = ksdensity(dataCell); 24 | 25 | [valuePeak,indPeak]=max(smoothDist); 26 | 27 | xFit=x(1:indPeak); 28 | dataToFit=smoothDist(1:indPeak)/numFrames; 29 | [sigma(numcell),mu(numcell),A]=mygaussfit(xFit',dataToFit); 30 | 31 | if ~isreal(sigma(numcell)) 32 | dev=nanstd(dataCell); 33 | outliers=abs(deltaFoF)>2*dev; 34 | 35 | deltaF2=dataCell; 36 | deltaF2(outliers)=NaN; 37 | sigma(numcell)=nanstd(deltaF2); 38 | mu(numcell)=nanmean(deltaF2); 39 | 40 | end 41 | 42 | 43 | distFit=A*exp(-(x-mu(numcell)).^2./(2*sigma(numcell)^2)); 44 | 45 | end 46 | 47 | deltaFoF=bsxfun(@minus,deltaFoF, mu); 48 | 49 | elseif strcmp(ansMethod,'Standard deviation') 50 | 51 | dev=nanstd(deltaFoF); 52 | outliers=bsxfun(@gt,abs(deltaFoF),2*dev); 53 | % We calculate the standard deviation of each cell without outliers 54 | deltaF2=deltaFoF; 55 | deltaF2(outliers)=NaN; 56 | sigma=nanstd(deltaF2); 57 | mu=nanmean(deltaF2); 58 | deltaFoF=bsxfun(@minus,deltaFoF, mu); 59 | 60 | 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findSignificantFluorescenceTraces/Toolbox-Romano-et-al/NoiseModel.m: -------------------------------------------------------------------------------- 1 | function [densityData, densityNoise, xev, yev] = NoiseModel(filename, deltaFoF, sigma, movements, plotFlag) 2 | 3 | lambda=8; 4 | 5 | deltaFoF(logical(movements),:)=NaN; 6 | transfDataMatrix=bsxfun(@rdivide,deltaFoF,sigma); 7 | points(:,1)=reshape(transfDataMatrix(1:end-1,:),[],1); 8 | points(:,2)=reshape(transfDataMatrix(2:end,:),[],1); 9 | points(isnan(points(:,1)),:)=[]; 10 | points(isnan(points(:,2)),:)=[]; 11 | 12 | 13 | pointsNeg=points(points(:,1)<0 & points(:,2)<0,1:2); 14 | Sigma=cov(pointsNeg(:,1), pointsNeg(:,2)); 15 | Mu = [0 0]; 16 | Sigma=[1 Sigma(1,2); Sigma(2,1) 1]; 17 | dataGaussianCov = mvnrnd(Mu,Sigma,4*length(pointsNeg)); 18 | clear pointsNeg 19 | 20 | mn=floor(min(min(min(transfDataMatrix)),min(reshape(dataGaussianCov,[],1)))); 21 | mx=ceil(max(max(max(transfDataMatrix)),max(reshape(dataGaussianCov,[],1)))); 22 | nevs=1000; 23 | [xev yev]=meshgrid(linspace(mn,mx,nevs),linspace(mn,mx,nevs)); 24 | 25 | binColIdx=reshape(xev,[],1); 26 | binRowIdx=repmat(linspace(mn,mx,nevs),1,1000.)'; 27 | 28 | [idx,dist]=knnsearch([points(:,1) points(:,2)],[binColIdx binRowIdx],'K',100); 29 | binSpread=reshape(mean(dist,2),nevs,nevs); 30 | 31 | clear idx dist 32 | 33 | [idxNoise,distNoise]=knnsearch([dataGaussianCov(:,1) dataGaussianCov(:,2)],[binColIdx binRowIdx],'K',100); 34 | binSpreadNoise=reshape(mean(distNoise,2),nevs,nevs); 35 | 36 | clear binColIdx binRowIdx idxNoise distNoise 37 | 38 | sizeWinFilt=8; % in sigmas 39 | smoothParam= 1/(sizeWinFilt*min(min(binSpread))); 40 | smoothParamNoise= 1/(sizeWinFilt*min(min(binSpreadNoise))); 41 | 42 | 43 | pointCol=interp1(xev(1,:),1:nevs,points(:,1),'nearest'); 44 | pointRow=interp1(xev(1,:),1:nevs,points(:,2),'nearest'); 45 | 46 | hist2dim=accumarray([pointRow pointCol],1,[nevs nevs]); 47 | 48 | pointColNoise=interp1(xev(1,:),1:nevs,dataGaussianCov(:,1) ,'nearest'); 49 | pointRowNoise=interp1(xev(1,:),1:nevs,dataGaussianCov(:,2) ,'nearest'); 50 | 51 | hist2dimNoise=accumarray([pointRowNoise pointColNoise],1,[nevs nevs]); 52 | 53 | 54 | 55 | densityData=zeros(size(xev)); 56 | [binRows,binCols]=find(hist2dim); 57 | for i=1:length(binRows) 58 | sigmaFilt=smoothParam*binSpread(binRows(i),binCols(i)); 59 | if mod(ceil(sizeWinFilt*sigmaFilt),2) == 0 60 | binFilter=fspecial('gaussian',double([ceil(sizeWinFilt*sigmaFilt)+1 ceil(sizeWinFilt*sigmaFilt)+1]),double(sigmaFilt)); 61 | else 62 | binFilter=fspecial('gaussian',double([ceil(sizeWinFilt*sigmaFilt) ceil(sizeWinFilt*sigmaFilt)]),double(sigmaFilt)); 63 | end 64 | 65 | widthRect=(size(binFilter,1)-1)/2; 66 | centerRect=widthRect+1; 67 | 68 | rectRows=binRows(i)-min(binRows(i)-1,widthRect):binRows(i)+min(size(densityData,1)-binRows(i),widthRect); 69 | rectCols=binCols(i)-min(binCols(i)-1,widthRect):binCols(i)+min(size(densityData,2)-binCols(i),widthRect); 70 | rectFiltRows=centerRect-min(binRows(i)-1,widthRect):centerRect+min(size(densityData,1)-binRows(i),widthRect); 71 | rectFiltCols=centerRect-min(binCols(i)-1,widthRect):centerRect+min(size(densityData,2)-binCols(i),widthRect); 72 | 73 | densityData(rectRows,rectCols)=densityData(rectRows,rectCols) + hist2dim(binRows(i),binCols(i))*binFilter(rectFiltRows,rectFiltCols); 74 | 75 | end 76 | 77 | densityNoise=zeros(size(xev)); 78 | [binRowsNoise,binColsNoise]=find(hist2dimNoise); 79 | for i=1:length(binRowsNoise) 80 | sigmaFilt=smoothParamNoise*binSpreadNoise(binRowsNoise(i),binColsNoise(i)); 81 | if mod(ceil(sizeWinFilt*sigmaFilt),2) == 0 82 | binFilter=fspecial('gaussian',double([ceil(sizeWinFilt*sigmaFilt)+1 ceil(sizeWinFilt*sigmaFilt)+1]),double(sigmaFilt)); 83 | else 84 | binFilter=fspecial('gaussian',double([ceil(sizeWinFilt*sigmaFilt) ceil(sizeWinFilt*sigmaFilt)]),double(sigmaFilt)); 85 | end 86 | 87 | widthRect=(size(binFilter,1)-1)/2; 88 | centerRect=widthRect+1; 89 | 90 | rectRows=binRowsNoise(i)-min(binRowsNoise(i)-1,widthRect):binRowsNoise(i)+min(size(densityNoise,1)-binRowsNoise(i),widthRect); 91 | rectCols=binColsNoise(i)-min(binColsNoise(i)-1,widthRect):binColsNoise(i)+min(size(densityNoise,2)-binColsNoise(i),widthRect); 92 | rectFiltRows=centerRect-min(binRowsNoise(i)-1,widthRect):centerRect+min(size(densityNoise,1)-binRowsNoise(i),widthRect); 93 | rectFiltCols=centerRect-min(binColsNoise(i)-1,widthRect):centerRect+min(size(densityNoise,2)-binColsNoise(i),widthRect); 94 | 95 | densityNoise(rectRows,rectCols)=densityNoise(rectRows,rectCols) + hist2dimNoise(binRowsNoise(i),binColsNoise(i))*binFilter(rectFiltRows,rectFiltCols); 96 | 97 | end 98 | 99 | densityData = Smooth1D(densityData,lambda); 100 | densityData = Smooth1D(densityData',lambda)'; 101 | densityData = densityData./(sum(sum(densityData))); 102 | densityNoise = Smooth1D(densityNoise,lambda); 103 | densityNoise = Smooth1D(densityNoise',lambda)'; 104 | densityNoise = densityNoise./(sum(sum(densityNoise))); 105 | 106 | if plotFlag 107 | 108 | figure 109 | z = log10(densityData); 110 | contour(xev,yev,z,linspace(max(max(z))-4,max(max(z)),20)); 111 | hold on 112 | z = log10(densityNoise); 113 | contour(xev,yev,z,linspace(max(max(z))-4,max(max(z)),20)); 114 | axis tight 115 | axis square 116 | ext=get(gca,'XLim'); 117 | xlim([ext(1)-1 ext(2)+1]); ylim([ext(1)-1 ext(2)+1]) 118 | hC=colorbar; 119 | tcks=get(hC,'Ytick'); 120 | set(hC,'Ytick',unique(round(tcks)),'YTicklabel',10.^unique(round(tcks))); 121 | hxlab=xlabel('Baseline noise normalized dFoF @ sample i'); hylab=ylabel('Baseline noise normalized dFoF @ sample i+1'); set(gcf,'color','w'); 122 | set(gca,'FontSize',14); set([hxlab hylab],'FontSize',14) 123 | 124 | cut=strfind(filename,'_ALL_CELLS.mat'); 125 | outfile=[filename(1:cut-1) '_densities.png']; 126 | export_fig(outfile); 127 | end 128 | 129 | 130 | function Z = Smooth1D(Y,lambda) 131 | [m,n] = size(Y); 132 | E = eye(m); 133 | D1 = diff(E,1); 134 | D2 = diff(D1,1); 135 | P = lambda.^2 .* D2'*D2 + 2.*lambda .* D1'*D1; 136 | Z = (E + P) \ Y; 137 | -------------------------------------------------------------------------------- /calcium-fluorescence-processing/inc_findSignificantFluorescenceTraces/Toolbox-Romano-et-al/Rasterize.m: -------------------------------------------------------------------------------- 1 | function [raster, mapOfOddsJoint]=Rasterize(deltaFoF, sigma, movements, mapOfOdds, xev, yev, params) 2 | 3 | temp=deltaFoF; 4 | temp(logical(movements),:)=0; 5 | transfDataMatrix=bsxfun(@rdivide,temp,sigma); 6 | 7 | cc=bwconncomp(~mapOfOdds); 8 | stats=regionprops(cc,'PixelList'); 9 | indZero=find(xev(1,:)>0,1,'first');% 10 | 11 | 12 | for i=1:cc.NumObjects 13 | if ismember(indZero,stats(i).PixelList(:,1)) 14 | break 15 | end 16 | end 17 | mapOfOddsCorrected=ones(size(mapOfOdds)); 18 | mapOfOddsCorrected(cc.PixelIdxList{i})=0; 19 | 20 | %% 21 | noiseBias=1.5; 22 | factorDecay=exp(-1/(params.fps*params.tauDecay)); 23 | decayMap=ones(size(mapOfOdds)); 24 | rowsDecay=1:size(decayMap,1); 25 | for i=1:size(decayMap,2) 26 | decayMap(rowsDecay(yev(:,1)ymax*h; 31 | xnew=[xnew,x(n)]; 32 | ynew=[ynew,y(n)]; 33 | end 34 | end 35 | 36 | %% fitting 37 | ylog=log(ynew); 38 | xlog=xnew; 39 | 40 | if optionStab==1 41 | p=polyfit(xlog,ylog,2); 42 | A2=p(1); 43 | A1=p(2); 44 | A0=p(3); 45 | sigma=sqrt(-1/(2*A2)); 46 | mu=A1*sigma^2; 47 | A=exp(A0+mu^2/(2*sigma^2)); 48 | end 49 | 50 | if optionStab==2 51 | % option for numerical stability 52 | [p,s,s2]=polyfit(xlog,ylog,2); 53 | A2=p(1); 54 | A1=p(2); 55 | A0=p(3); 56 | A1=A1/s2(2)-2*A2*s2(1)/s2(2); 57 | A2=A2/s2(2)^2; 58 | sigma=sqrt(-1/(2*A2)); 59 | mu=A1*sigma^2; 60 | A=exp(A0+mu^2/(2*sigma^2)); 61 | end 62 | -------------------------------------------------------------------------------- /examples/HEX5_K5_medium__T1800s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoodhillLab/neural-assembly-detection/f5415317aec2cf141e8f48ef816cddac0547cac3/examples/HEX5_K5_medium__T1800s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0.zip -------------------------------------------------------------------------------- /examples/HEX5_K5_medium__T1800s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0.zip.sha256: -------------------------------------------------------------------------------- 1 | 5b7bc64726ab81007c086cd90cc31075b36bd19d339b71e56ecdd7c1d5235d6b HEX5_K5_medium__T1800s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0.zip 2 | -------------------------------------------------------------------------------- /examples/ZEBRAFISH-9DPF.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoodhillLab/neural-assembly-detection/f5415317aec2cf141e8f48ef816cddac0547cac3/examples/ZEBRAFISH-9DPF.zip -------------------------------------------------------------------------------- /examples/ZEBRAFISH-9DPF.zip.sha256: -------------------------------------------------------------------------------- 1 | 963795e4bda890a3490f30f6edb3fb83e1da142ac6aa906fbe373f40308052fa ZEBRAFISH-9DPF.zip 2 | -------------------------------------------------------------------------------- /include/bestmatch.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = bestmatch( d , C1 , C2 ) 2 | %BESTMATCH( d , C1 , C2 ) Returns the BestMatch index between two 3 | %clusterings C1 and C2 for given set distance d. 4 | % 5 | % INPUT: 6 | % d [function handle]: two-argument distance function 7 | % C1 [1x? cell]: clustering 8 | % C2 [1x? cell]: clustering 9 | % 10 | % 11 | % === Jan Moelter, The University of Queensland, 2017 =================== 12 | % 13 | 14 | narginchk(3,3) 15 | 16 | if( min( numel( C1 ) , numel( C2 ) ) > 0 ) 17 | output_args = sum( min( cross_evaluation( d , C1 , C2 ) , [] , 2 ) ) + sum( min( cross_evaluation( d , C2 , C1 ) , [] , 2 ) ); 18 | else 19 | output_args = NaN; 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /include/bestmatch_expectation.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = bestmatch_expectation( N , numelA , numelB , nA_dist , nB_dist ) 2 | %BESTMATCH_EXPECTATION( N , numelA , numelB , nA_dist , nB_dist ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2017 =================== 6 | % 7 | 8 | % N = 20; 9 | % numelA = 2; numelB = 3; 10 | % 11 | % mA = 10; wA = 6; 12 | % mB = 15; wB = 4; 13 | % 14 | % nA_dist = [ (mA-wA):(mA+wA) ; arrayfun( @(k) binopdf( k , 2 * wA , 0.5 ) , [ (mA-wA):(mA+wA) ] - ( mA - wA ) , 'UniformOutput' , true ) ]'; 15 | % nB_dist = [ (mB-wB):(mB+wB) ; arrayfun( @(k) binopdf( k , 2 * wB , 0.5 ) , [ (mB-wB):(mB+wB) ] - ( mB - wB ) , 'UniformOutput' , true ) ]'; 16 | 17 | X = []; 18 | for nA = nA_dist(:,1)' 19 | for nB = nB_dist(:,1)' 20 | for m = 0:min(nA,nB) 21 | X = [ X , 1 - m / ( nA + nB - m ) ]; 22 | end 23 | end 24 | end 25 | X = unique( X ); 26 | 27 | F_X = F( X ); 28 | 29 | pA = arrayfun( @(x) sum( F_X( X >= x ) )^(numelA) - sum( F_X( X > x ) )^(numelA) , X , 'UniformOutput' , true ); 30 | pB = arrayfun( @(x) sum( F_X( X >= x ) )^(numelB) - sum( F_X( X > x ) )^(numelB) , X , 'UniformOutput' , true ); 31 | 32 | output_args = 1 - ( numelA * sum( X .* pB ) + numelB * sum( X .* pA ) ) / ( numelA + numelB ); 33 | 34 | 35 | function f = F( r ) 36 | 37 | f = 0 * r; 38 | 39 | % for nA_j = 1:size( nA_dist , 1 ) 40 | % for nB_j = 1:size( nB_dist , 1 ) 41 | % for i = 1:numel(r) 42 | % 43 | % x = ( nA_dist(nA_j,1) + nB_dist(nB_j,1) ) * ( 1 - 1/( 2-r(i) ) ); 44 | % if( abs( x - round( x ) ) < 1e-14 ) 45 | % x = round( x ); 46 | % end 47 | % 48 | % f(i) = f(i) + nA_dist(nA_j,2) * nB_dist(nB_j,2) * hygepdf( x , N , nA_dist(nA_j,1) , nB_dist(nB_j,1) ); 49 | % 50 | % end 51 | % end 52 | % end 53 | 54 | 55 | nA_X = repmat( nA_dist(:,1) , 1 , size( nB_dist , 1 ) ); 56 | nB_X = transpose( repmat( nB_dist(:,1) , 1 , size( nA_dist , 1 ) ) ); 57 | 58 | for i = 1:numel(r) 59 | 60 | x = ( nA_X + nB_X ) * ( 1 - 1/( 2-r(i) ) ); 61 | 62 | I = abs( x - round( x ) ) < 1e-14; 63 | x( I ) = round( x( I ) ); 64 | 65 | H_X = hygepdf( x , N , nA_X , nB_X ); 66 | 67 | 68 | f(i) = transpose( nA_dist(:,2) ) * H_X * nB_dist(:,2); 69 | end 70 | 71 | end 72 | 73 | %function y = hypergeompdf( X , M , K , N ) 74 | % y = ( gamma( 1+K )*gamma( 1-K+M )*gamma( 1+M-N )*gamma( 1+N ) )/( gamma( 1+M )*gamma( 1+K-X )*gamma( 1+N-X )*gamma( 1+X )*gamma( 1-K+M-N+X ) ); 75 | %end 76 | end 77 | 78 | -------------------------------------------------------------------------------- /include/cell_union.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = cell_union( input_args , mode ) 2 | %CELL_UNION( input_args , mode ) Returns the union of all sets (vectors) in 3 | %the a cell array. 4 | % 5 | % INPUT: 6 | % input_args [1x? cell]: cell array of sets (vectors) 7 | % mode [string]: union mode ('','sorted','stable') 8 | % 9 | % 10 | % === Jan Moelter, The University of Queensland, 2017 =================== 11 | % 12 | 13 | narginchk(1,2); 14 | if( nargin < 2 ) 15 | mode = ''; 16 | end 17 | 18 | output_args = []; 19 | input_args = input_args(:); 20 | 21 | if( any( strcmp( mode , { 'sorted' , 'stable' } ) ) ) 22 | 23 | for j = 1:numel( input_args ); 24 | output_args = union( output_args , input_args{j} , mode ); 25 | end 26 | 27 | else 28 | 29 | for j = 1:numel( input_args ); 30 | output_args = union( output_args , input_args{j} ); 31 | end 32 | 33 | end 34 | 35 | end 36 | 37 | -------------------------------------------------------------------------------- /include/cross_evaluation.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = cross_evaluation( f , X , Y ) 2 | %CROSS_EVALUATION( f , X , Y ) Returns the matrix f(x,y) for x in X and y 3 | %in Y. 4 | % 5 | % INPUT: 6 | % f [function handle]: two-argument function 7 | % X [1x? cell]: data points 8 | % Y [1x? cell]: data points, =X if not explicitly given 9 | % 10 | % 11 | % === Jan Moelter, The University of Queensland, 2017 =================== 12 | % 13 | 14 | narginchk(2,3); 15 | if( nargin == 2 ) 16 | Y = X; 17 | end 18 | 19 | output_args = NaN * ones( numel( X ) , numel( Y ) ); 20 | 21 | for ix = 1:numel( X ) 22 | for iy = 1:numel( Y ) 23 | output_args( ix , iy ) = f( X{ix} , Y{iy} ); 24 | end 25 | end 26 | 27 | end -------------------------------------------------------------------------------- /include/iif.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = iif( input_args , true_output_args , false_output_args ) 2 | %IIF( input_args , true_output_args , false_output_args ) Inline 3 | %if-then-else function to use in anonymous functions. 4 | % 5 | % 6 | % === Jan Moelter, The University of Queensland, 2016 =================== 7 | % 8 | 9 | if( input_args ) 10 | output_args = true_output_args; 11 | else 12 | output_args = false_output_args; 13 | end 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /include/io/printConsoleSection.m: -------------------------------------------------------------------------------- 1 | function printConsoleSection( input_args ) 2 | %PRINTCONSOLESECTION( input_args ) 3 | % 4 | % INPUT: 5 | % input_args [string]: section title 6 | % 7 | % EXAMPLE: 8 | % printConsoleSection( 'Hello World!' ) 9 | % 10 | % === Jan Moelter, The University of Queensland, 2017 =================== 11 | % 12 | 13 | S_Z = 80; 14 | 15 | fprintf( 1 , [ repmat( '_' , 1 , S_Z ) '\n' ] ); 16 | fprintf( 1 , [ ':: %s' '\n' ] , upper( input_args ) ); 17 | fprintf( 1 , [ '\n' ] ); 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /include/io/print_progress.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = print_progress( p , type , timer ) 2 | %PRINT_PROGRESS( p , type , timer ) Prints an progress bar in the console. 3 | % While working within the console it might be desirable to monitor the 4 | % progress of certain calculation. However, the classic waitbar( ) is 5 | % not accessible here, so that print_progress( ) is a way to go. 6 | % 7 | % INPUT: 8 | % p [scalar]: percentage of completion 9 | % type [string]: 'initialise', 'update' to update the value of an 10 | % initialised progress bar, and 'finalise' 11 | % timer [scalar, uint64]: timer variable a returned from TIC 12 | % 13 | % 14 | % === Jan Moelter, The University of Queensland, 2017 =================== 15 | % 16 | 17 | S_Z = 80; 18 | 19 | CHAR_SPACE = char( 32 ); 20 | if( ~isdeployed ) 21 | %CHAR_BLOCK = char( 9608 ); 22 | CHAR_BLOCK = char( 61 ); 23 | else 24 | CHAR_BLOCK = char( 61 ); 25 | end 26 | CHAR_FRAME = char( 124 ); 27 | 28 | try 29 | if( nargin > 2 && ( p ~= 0 && p~= 1 ) ) 30 | dT = ceil( ( (1 - p) / p ) * toc( timer ) ); 31 | dTx = sprintf( ' ~%5s left' , print_timeinterval( dT ) ); 32 | else 33 | dT = NaN; 34 | end 35 | catch 36 | dT = NaN; 37 | end 38 | 39 | switch type 40 | case 'initialise' 41 | %fprintf( '\n' ); 42 | fprintf( [ CHAR_FRAME repmat( CHAR_SPACE , 1 , (S_Z - 2) ) CHAR_FRAME ] ); 43 | 44 | case 'update' 45 | fprintf( repmat( '\b' , 1 , S_Z ) ); 46 | if( ~isnan( dT ) ) 47 | fprintf( [ CHAR_FRAME repmat( CHAR_BLOCK , 1 , ceil( p * (S_Z - 2 - length( dTx )) ) ) repmat( CHAR_SPACE , 1 , floor( (1 - p) * (S_Z - 2 - length( dTx )) ) ) CHAR_FRAME dTx ] ); 48 | else 49 | fprintf( [ CHAR_FRAME repmat( CHAR_BLOCK , 1 , ceil( p * (S_Z - 2) ) ) repmat( CHAR_SPACE , 1 , floor( (1 - p) * (S_Z - 2) ) ) CHAR_FRAME ] ); 50 | end 51 | 52 | % S = [ char_frame repmat( char_block , 1 , ceil( p * (s_z - 2) ) ) repmat( char_space , 1 , floor( (1 - p) * (s_z - 2) ) ) char_frame ]; 53 | % S_p = sprintf( '%5.1f%%' , 100 * p ); S( (s_z / 2 - 2):(s_z / 2 + 3) ) = S_p; 54 | case 'finalise' 55 | fprintf( repmat( '\b' , 1 , S_Z ) ); 56 | 57 | fprintf( [ CHAR_FRAME repmat( CHAR_BLOCK , 1 , (S_Z - 2) ) CHAR_FRAME ] ); 58 | fprintf( '\n' ); 59 | end 60 | 61 | output_args = dT; 62 | 63 | end 64 | 65 | % function [ output_args ] = print_progress( p , type ) 66 | % %print_progress Prints an updatable progress bar to the console 67 | % % While working within the console it might be desirable to monitor the 68 | % % progress of certain calculation. However, the classic waitbar( ) is 69 | % % not accessible here, so that print_progress( ) is a way to go. 70 | % 71 | % 72 | % 73 | % s_z = 80; 74 | % 75 | % char_space = char( 32 ); 76 | % % char_block = char( 9608 ); 77 | % char_block = char( 61 ); 78 | % char_frame = char( 124 ); 79 | % 80 | % S = ''; 81 | % 82 | % switch type 83 | % case 'initialise' 84 | % fprintf( '\n' ); 85 | % fprintf( [ char_frame repmat( char_space , 1 , (s_z - 2) ) char_frame ] ); 86 | % fprintf( '\n' ); 87 | % case 'update' 88 | % fprintf( repmat( '\b' , 1 , s_z + 1 ) ); 89 | % fprintf( [ char_frame repmat( char_block , 1 , ceil( p * (s_z - 2) ) ) repmat( char_space , 1 , floor( (1 - p) * (s_z - 2) ) ) char_frame ] ); 90 | % fprintf( '\n' ); 91 | % 92 | % % S = [ char_frame repmat( char_block , 1 , ceil( p * (s_z - 2) ) ) repmat( char_space , 1 , floor( (1 - p) * (s_z - 2) ) ) char_frame ]; 93 | % % S_p = sprintf( '%5.1f%%' , 100 * p ); S( (s_z / 2 - 2):(s_z / 2 + 3) ) = S_p; 94 | % case 'finalise' 95 | % fprintf( repmat( '\b' , 1 , s_z + 1 ) ); 96 | % 97 | % fprintf( [ char_frame repmat( char_block , 1 , (s_z - 2) ) char_frame ] ); 98 | % fprintf( '\n' ); 99 | % end 100 | % 101 | % end -------------------------------------------------------------------------------- /include/io/print_timeinterval.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = print_timeinterval( dT ) 2 | %PRINT_TIMEINTERVAL( dT ) Prints time-interval in optimal units. 3 | % 4 | % INPUT: 5 | % dT [scalar]: time interval in seconds 6 | % 7 | % 8 | % === Jan Moelter, The University of Queensland, 2017 =================== 9 | % 10 | 11 | 12 | dTx = timevec( dT ); 13 | switch( find( dTx , 1 ) ) 14 | case 1 15 | output_args = sprintf( '%.1fd' , dot( dTx , [ 1 , 1/( 24 ) , 1/( 24 * 60 ) , 1/( 24 * 60 * 60 ) ] ) ); 16 | case 2 17 | output_args = sprintf( '%.1fh' , dot( dTx , [ 0 , 1 , 1/( 60 ) , 1/( 60 * 60 ) ] ) ); 18 | case 3 19 | output_args = sprintf( '%.1fm' , dot( dTx , [ 0 , 0 , 1 , 1/( 60 ) ] ) ); 20 | case 4 21 | output_args = sprintf( '%.1fs' , dot( dTx , [ 0 , 0 , 0 , 1 ] ) ); 22 | end 23 | 24 | end 25 | 26 | function [ output_args ] = timevec( t ) 27 | 28 | mult = [ 24 60 60 1 ]; 29 | output_args = zeros( 1 , numel( mult ) ); 30 | 31 | for j = 1:numel( mult ) 32 | output_args( j ) = fix( t / prod( mult(j:end) ) ); 33 | t = rem( t , prod( mult(j:end) ) ); 34 | end 35 | end -------------------------------------------------------------------------------- /include/io/read.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = read( filename ) 2 | %READ( filename ) Reads a text file and returns a cell array of the lines. 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2017 =================== 6 | % 7 | 8 | % Alternative implementation: 9 | % 10 | % i_ = fopen( filename , 'r' ); 11 | % while( ~boolean( feof(i_) ) ) 12 | % output_args{ numel( output_args ) + 1 } = fgetl( i_ ); 13 | % end 14 | % fclose(i_); 15 | 16 | if( exist( filename , 'file' ) == 2 ) 17 | i_ = fopen( filename , 'r' ); 18 | 19 | output_args = textscan( i_ , '%s' , 'Delimiter' , '\n' ); 20 | output_args = transpose( output_args{1} ); 21 | 22 | fclose( i_ ); 23 | 24 | else 25 | 26 | output_args = {}; 27 | end 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /include/math/largest_positive.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = largest_positive( input_args ) 2 | %LARGEST_POSITIVE( input_args ) 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2017 =================== 6 | % 7 | 8 | [ ~ , iM ] = max( abs( input_args ) ); 9 | output_args = input_args / sign( input_args( iM ) ); 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /include/math/num_range.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = num_range( X ) 2 | %NUM_RANGE( X ) Returns the numerical range of a collection of numbers X. 3 | % 4 | % 5 | % === Jan Moelter, The University of Queensland, 2017 =================== 6 | % 7 | 8 | output_args = [ min( X(:) ) max( X(:) ) ]; 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /include/random/seed_devrandom.m: -------------------------------------------------------------------------------- 1 | function [ output_args ] = seed_devrandom( verbose ) 2 | %SEED_DEVRANDOM( verbose ) Seeds the internal random number generator from 3 | %the /dev/urandom device (only on Unix systems). 4 | % 5 | % INPUT: 6 | % verbose [boolean] 7 | % 8 | % OUPUT: 9 | % output_args [scalar]: 4 byte random seed 10 | % 11 | % 12 | % === Jan Moelter, The University of Queensland, 2017 =================== 13 | % 14 | 15 | narginchk( 0 , 1 ); 16 | if( nargin == 0 ) 17 | verbose = true; 18 | end 19 | 20 | if( isunix ) 21 | try 22 | if( verbose ) 23 | fprintf( 1 , [ 'Opening /dev/urandom for reading 4 byte random seed ...' '\n' ] ); 24 | end 25 | 26 | dev_random_ = fopen( '/dev/urandom' , 'r' ); 27 | seed_ = typecast( uint8( fread( dev_random_ , 4 ) ), 'uint32' ); 28 | fclose( dev_random_ ); 29 | 30 | if( verbose ) 31 | fprintf( 1 , [ ' 4 byte random seed is 0x' dec2hex( seed_ , 8 ) '.' '\n' ] ); 32 | end 33 | rng( seed_ , 'twister' ); 34 | catch 35 | if( verbose ) 36 | fprintf( 1 , [ ' Reading 4 byte random seed from /dev/urandom failed.' '\n' ] ); 37 | end 38 | rng( 'shuffle' , 'twister' ); 39 | end 40 | else 41 | rng( 'shuffle' , 'twister' ); 42 | end 43 | 44 | RNG = rng; 45 | output_args = RNG.Seed; 46 | 47 | if( verbose ) 48 | fprintf( 1 , [ '\n' ] ); 49 | fprintf( 1 , [ 'Internal random number generator was initialised with seed 0x' dec2hex( RNG.Seed , 8 ) '.' '\n' ] ); 50 | fprintf( 1 , [ '\n' ] ); 51 | end 52 | 53 | end 54 | -------------------------------------------------------------------------------- /include/random/shuffle_vector.m: -------------------------------------------------------------------------------- 1 | function [ output_args i_shuffle ] = shuffle_vector( input_args ) 2 | %shuffle Shuffles the elements of a vector 3 | 4 | i_shuffle = randperm( numel( input_args ) ); 5 | output_args = input_args( i_shuffle ); 6 | 7 | end -------------------------------------------------------------------------------- /scripts/GENERATE_ALL_DATASETS.m: -------------------------------------------------------------------------------- 1 | %GENERATE_ALL_DATASETS 2 | % 3 | % Note: This script will generate 4800 datasets of surrogate calcium 4 | % fluorescence activity, which were analysed in the corresponding paper. 5 | % On a single desktop computer this may take several days or rather weeks 6 | % and will require about 350GB of disk space. 7 | % 8 | % 9 | % === Jan Moelter, The University of Queensland, 2018 =================== 10 | % 11 | 12 | OUTPUT_DIRECTORY = '~/Desktop/'; 13 | 14 | DEFAULT_PARAMETERS = struct( ... 15 | 'T_durationRange' , 3600 , ... 16 | 'dT_durationRange' , 0.5 , ... 17 | 'assembly_configuration_list' , 'HEX12_K10_medium' , ... 18 | 'calcium_T1_2Range' , 1 , ... 19 | 'eventFreqRange' , 0.01 , ... 20 | 'eventMultRange' , 6 , ... 21 | 'noiseSTDRange' , 0 , ... 22 | 'saturationKRange' , Inf ... 23 | ); 24 | 25 | 26 | 27 | for SERIES = { 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' , 'HEXv_K10_medium_N__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' , 'HEX12_varK_medium_N__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' , 'HEX12_K10_var__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' , 'HEX12_K10_medium_overlap__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' , 'HEX12_K10_medium__T0-7200s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' , 'HEX12_K10_medium__T3600s_dT100-500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' , 'HEX12_K10_medium__T3600s_dT500ms_cT0-2s_sKInf_eF10.0mHz_eM6_nS0' , 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sKInf_eF0.0-10.0mHz_eM6_nS0' , 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM1-26_nS0' , 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0-8' , 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sK0-1000_eF10.0mHz_eM6_nS0' } 28 | 29 | PARAMETERS = DEFAULT_PARAMETERS; 30 | 31 | switch( SERIES{:} ) 32 | 33 | case 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' 34 | 35 | case 'HEXv_K10_medium_N__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' 36 | PARAMETERS.( 'assembly_configuration_list' ) = 'HEXv_K10_medium_N'; 37 | 38 | case 'HEX12_varK_medium_N__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' 39 | PARAMETERS.( 'assembly_configuration_list' ) = 'HEX12_varK_medium_N'; 40 | 41 | case 'HEX12_K10_var__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' 42 | PARAMETERS.( 'assembly_configuration_list' ) = 'HEX12_K10_var'; 43 | 44 | case 'HEX12_K10_medium_overlap__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' 45 | PARAMETERS.( 'assembly_configuration_list' ) = 'HEX12_K10_medium_overlap'; 46 | 47 | case 'HEX12_K10_medium__T0-7200s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' 48 | PARAMETERS.( 'T_durationRange' ) = [0 7200]; 49 | 50 | case 'HEX12_K10_medium__T3600s_dT100-500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0' 51 | PARAMETERS.( 'dT_durationRange' ) = [0.1 0.5]; 52 | 53 | case 'HEX12_K10_medium__T3600s_dT500ms_cT0-2s_sKInf_eF10.0mHz_eM6_nS0' 54 | PARAMETERS.( 'calcium_T1_2Range' ) = [0 2]; 55 | 56 | case 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sKInf_eF0.0-10.0mHz_eM6_nS0' 57 | PARAMETERS.( 'eventFreqRange' ) = [0 0.01]; 58 | 59 | case 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM1-26_nS0' 60 | PARAMETERS.( 'eventMultRange' ) = [1 26]; 61 | 62 | case 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sKInf_eF10.0mHz_eM6_nS0-8' 63 | PARAMETERS.( 'noiseSTDRange' ) = [0 8]; 64 | 65 | case 'HEX12_K10_medium__T3600s_dT500ms_cT1s_sK0-1000_eF10.0mHz_eM6_nS0' 66 | PARAMETERS.( 'saturationKRange' ) = [0 1000]; 67 | 68 | end 69 | 70 | 71 | for i = 1:400 72 | 73 | ID = [ SERIES{:} '__' num2str( i ) ]; 74 | OUTPUT_DIRECTORY_ = [ OUTPUT_DIRECTORY '_' SERIES{:} '/' ]; 75 | 76 | ARTIFICIAL_CALCIUM_FLUORESCENCE_GENERATION( OUTPUT_DIRECTORY_ , ID , NaN , PARAMETERS.( 'T_durationRange' ) , PARAMETERS.( 'dT_durationRange' ) , PARAMETERS.( 'assembly_configuration_list' ) , i , PARAMETERS.( 'calcium_T1_2Range' ) , PARAMETERS.( 'eventFreqRange' ) , PARAMETERS.( 'eventMultRange' ) , PARAMETERS.( 'noiseSTDRange' ) , PARAMETERS.( 'saturationKRange' ) ); 77 | end 78 | end --------------------------------------------------------------------------------