Skip to content

Commit

Permalink
revised demo for Neuropixels that functionalizes the transformation s…
Browse files Browse the repository at this point in the history
…o it is easier to understand
  • Loading branch information
stevevanhooser committed Dec 20, 2024
1 parent 7a9f906 commit e98c3c5
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 13 deletions.
55 changes: 55 additions & 0 deletions +deepinterp/+internal/+test/neuropixelsPlay.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

% this script was made to explore the input/output requirements of the
% pretrained neuropixels network

E = [[1:192]' [1:192]'+0.5]; % number electrodes by Y (whole number) and X 2*(mod 1)

NP = repmat(E,1,1,500); % 500 frames of data
% now transpose to be the same as the expected neuropixels data
NP = permute(NP, [3 1 2]);

nb_probes = 384; % Number of probes

pre_post_omission = 3; % Number of frames omitted before and after the inferred frame

pre_frame = 30; % Number of frames provided before the inferred frame
post_frame = 30; % Number of frames provided after the inferred frame

batch_size = 100;

start_frame = 100;

end_frame = 200;


input_full = single(zeros(batch_size, nb_probes, 2, pre_frame + post_frame));


for frame_index = start_frame:end_frame

input_index = (frame_index - pre_frame - pre_post_omission) : (frame_index + post_frame + pre_post_omission );

input_index = input_index(input_index ~= frame_index); % drop the predicted frame

for index_padding = 1: pre_post_omission % drop pre_post_omission number of frames surrounding the predicted frame
input_index = input_index(input_index ~= frame_index - index_padding);
input_index = input_index(input_index ~= frame_index + index_padding);
end

data_img_input = ephys(input_index, :, :);

data_img_input = permute(data_img_input,[2,3,1]);

data_img_input = (single(data_img_input) - local_mean) / local_std;

% alternating filling with zeros padding
odd = 1: 2: nb_probes;
even = odd + 1;

input_full(frame_index-start_frame+1, odd, 1, :) = data_img_input(:, 1, :);
input_full(frame_index-start_frame+1, even, 2, :) = data_img_input(:, 2, :);


end


58 changes: 58 additions & 0 deletions +deepinterp/NPcheckerboard2frame.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
function frame = checkerboard2NPframe(cb)
% CHECKERBOARD2NPFRAME - convert geometrically realistic matrix to raw Neuropixels Phase 3 format
%
% FRAME = CHECKERBOARD2NPFRAME(CB)
%
% Convert geometrically-realistic matrix data CB (384 x 2 x NSAMPLES)
% into a format that matches the raw data output of Neuropixels Phase 3
% probes. CB is expected to reflect the checkerboard layout of electrodes,
% where every even linear index is 0.
%
% FRAME will be a 192 x 2 x NSAMPLES matrix.
%
% For example, the following single-frame example input where each data point has
% been set, for illustration purposes, to the electrode number (incremented by 0.25)
% would be transformed as follows:
%
% 1.0000 0
% 0 1.2500
% 2.0000 0
% 0 2.2500
% 3.0000 0
% 0 3.2500
% ...
% 190.0000 0
% 0 190.2500
% 191.0000 0
% 0 191.2500
% 192.0000 0
% 0 192.2500
%
% to
%
% 1.0000 1.2500
% 2.0000 2.2500
% 3.0000 3.2500
% ...
% 189.0000 189.2500
% 190.0000 190.2500
% 191.0000 191.2500
% 192.0000 192.2500

% Check input dimensions
if size(cb, 1) ~= 384 || size(cb, 2) ~= 2
error('Input matrix CB must be 384 x 2 x NSAMPLES.');
end

frame = zeros(size(cb,1)/2, size(cb,2), size(cb,3));
odd = 1:2:size(cb,1);
even = odd + 1;
frame(:,1,:) = cb(odd,1,:);
frame(:,2,:) = cb(even,2,:);







48 changes: 48 additions & 0 deletions +deepinterp/NPframe2checkerboard.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
function cb = NPframe2checkerboard(frame)
% NPFRAME2CHECKERBOARD - convert raw Neuropixels Phase 3 to geometrically realistic matrix
%
% CB = NPframe2checkerboard(FRAME)
%
% Convert Neuropixels data frame data FRAME (192 x 2 x NSAMPLES)
% into a geometrically-realistic matrix that reflects the checkerboad
% layout of electrodes such as the Phase 3 version.
%
% CB will be a 384 x 2 x NSAMPLES matrix where every even linear index
% will be 0.
%
% For example, the following single-frame example input where each data point has
% been set, for illustration purposes, to the electrode number (incremented by 0.5)
% would be transformed as follows:
%
% 1.0000 1.5000
% 2.0000 2.5000
% 3.0000 3.5000
% ...
% 189.0000 189.5000
% 190.0000 190.5000
% 191.0000 191.5000
%
% to
%
% 1.0000 0
% 0 1.5000
% 2.0000 0
% 0 2.5000
% 3.0000 0
% 0 3.5000
%...
% 190.0000 0
% 0 190.5000
% 191.0000 0
% 0 191.5000
% 192.0000 0
% 0 192.5000

cb = zeros(size(frame,1)*2,size(frame,2),size(frame,3));

odd = 1:2:size(frame,1)*2;
even = odd + 1;

cb(odd,1,:) = frame(:,1,:);
cb(even,2,:) = frame(:,2,:);

27 changes: 19 additions & 8 deletions +deepinterp/Net.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
options.Npost (1,1) double {mustBeInteger} = 30
options.Nomit (1,1) double {mustBeInteger} = 1
options.modelParameters (1,1) struct = struct('none',[])
options.varname (1,:) char = "net"
end

networkType = options.type;
Expand All @@ -77,13 +78,17 @@
obj.network=deepinterp.internal.importKerasMAE(options.file);
case 'tensorflowzip',
obj.network=deepinterp.internal.openTensorFlowNetwork(options.file,matlab.lang.makeValidName(options.model));
case 'matlab',
matdata = load(options.file);
obj.network = getfield(matdata,options.varname);
case 'pretrained',
[modelfilename, modelparams] = deepinterp.internal.getPretrainedModelFilename(options.model);
obj = deepinterp.Net(modelparams.format,'file',modelfilename,...
'N',modelparams.dim(1),'M',modelparams.dim(2),...
'Npre',modelparams.pre,'Npost',modelparams.post,'Nomit',modelparams.omit,...
'type',modelparams.type,...
'modelParameters',modelparams.parameters,'model',options.model);
'modelParameters',modelparams.parameters,'model',options.model,...
"varname",options.varname);
return;
otherwise,
error(['Unknown command: ' command]);
Expand Down Expand Up @@ -131,22 +136,26 @@
options.progbar (1,1) logical = true;
end

if obj.networkType=="fMRI",
error(['fMRI not yet supported by deepinterp.Net class.']);
end;

output = input;
Nomit_pre = (obj.Nomit+1)/2;
Nomit_post = (obj.Nomit+1)/2;
offsets = [ fliplr(-[Nomit_pre:obj.Npre+Nomit_pre-1]) Nomit_post:obj.Npost+Nomit_post-1];
if options.progbar,
deepinterp.internal.progressbar();
end;
totalWork = size(input,3)-(obj.Npost+obj.Npre);
for t = obj.Npre+1 : size(input,3) - obj.Npost,
totalWork = size(input,3)-(obj.Npost+obj.Npre+Nomit_pre-1+Nomit_post-1);
for t = obj.Npre+1+Nomit_pre-1 : size(input,3) - obj.Npost-Nomit_post+1,
if options.progbar,
deepinterp.internal.progressbar((t-(obj.Npre+1))/totalWork);
end;
output(:,:,t) = predict(obj.network,input(:,:,offsets+t));
end;
if options.progbar,
deepinterp.internal.progressbar(0.9999999999);
deepinterp.internal.progressbar(1);
end;
end; % interp()

Expand All @@ -168,10 +177,12 @@
inSz = obj.network.Layers(1).InputSize;
obj.N = inSz(1);
obj.M = inSz(2);
assert(inSz(3)==obj.Npre+obj.Npost,...
['Npre + Npost must add up to the total ' ...
'number of image inputs to ' ...
'deepinterp.net.ImageTimeSeries.']);
if numel(inSz)<4,
assert(inSz(end)==obj.Npre+obj.Npost,...
['Npre + Npost must add up to the total ' ...
'number of image inputs to ' ...
'deepinterp.net.ImageTimeSeries.']);
end;
end;
end; % SetInputSize
end;
Expand Down
Binary file modified examples/tiny_ephys_inference.mlx
Binary file not shown.
Binary file removed examples/tiny_ephys_inference2.mlx
Binary file not shown.
Binary file modified examples/tiny_ephys_training.mlx
Binary file not shown.
Binary file modified examples/tiny_ophys_inference.mlx
Binary file not shown.
31 changes: 26 additions & 5 deletions pretrainedModels/pretrained.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
"omit":1,
"type":"two-photon",
"format": "TensorFlowZip",
"variable": "none",
"license": "https://github.com/MATLAB-Community-Toolboxes-at-INCF/DeepInterpolation-MATLAB/blob/main/LICENSE",
"parameters":
{
"framerate":30,
"objective_power":16,
"objective_NA":0.8,
"indicator":"GCaMP6f",
"strain":"Ai93",
"strain":"Ai93 (https://pmc.ncbi.nlm.nih.gov/articles/PMC6086366)",
"training_data":"https://github.com/AllenInstitute/deepinterpolation/blob/cfb42bc2c5bd8cc08ee870a163230e8c89c676ba/examples/paper_generation_code/json_data/2019-09-05-train-very-large-single-plane-Ai93-norm.json",
"description":"Pre-processing: Individual movies were motion corrected. Each movie recording was mean-centered and normalized with a single pair of value for all pixels",
"field_of_view_um":[400,400],
Expand All @@ -34,16 +35,17 @@
"omit":1,
"type":"two-photon",
"format": "TensorFlowZip",
"variable": "none",
"license": "https://github.com/MATLAB-Community-Toolboxes-at-INCF/DeepInterpolation-MATLAB/blob/main/LICENSE",
"parameters":
{
"framerate":30,
"objective_power":16,
"objective_NA":0.8,
"indicator":"GCaMP6f",
"strain":"Ai148",
"strain":"Ai148 (https://pmc.ncbi.nlm.nih.gov/articles/PMC6086366)",
"training_data":"https://github.com/AllenInstitute/deepinterpolation/blob/cfb42bc2c5bd8cc08ee870a163230e8c89c676ba/examples/paper_generation_code/json_data/2019-09-05-train-very-large-single-plane-Ai148-norm.json",
"description":"Pre-processing: Individual movies were motion corrected. Each movie recording was mean-centered and normalized with a single pair of value for all pixels",
"description":"Pre-processing: Individual movies were motion corrected. Each movie recording was mean-centered and normalized with a single pair of value for all pixels. Trained on data from mouse strain Ai148.",
"field_of_view_um":[400,400],
"excitation_wavelength_nm":910
}
Expand All @@ -52,19 +54,38 @@
"name":"Ephys-Neuropixels_Phase_3a_1050",
"filename":"TensorFlowNetworks/2020_02_29_15_28_unet_single_ephys_1024_mean_squared_error-1050.zip",
"url":"",
"dim":[192,2],
"dim":[384,2],
"pre":30,
"post":30,
"omit":3,
"type":"ephys",
"format": "TensorFlowZip",
"variable": "none",
"license": "https://github.com/MATLAB-Community-Toolboxes-at-INCF/DeepInterpolation-MATLAB/blob/main/LICENSE",
"parameters":
{
"samplerate":30000,
"electrode": "Neuropixels Phase 3a",
"training_data":"(unknown)",
"description":"Pre-processing: Median subtraction was applied to individual probes to remove signals that were common across all recording sites. Each probe recording was mean-centered and normalized with a single pair of value for all nodes on the probe."
"description":"Pre-processing: Median subtraction was applied to individual probes to remove signals that were common across all recording sites. Each probe recording was mean-centered and normalized with a single pair of value for all nodes on the probe. The network was trained on data that were transformed to match the geometry of the Phase 3a probe and need to passed through deepinterp.NPframe2checkerboard() before inference can be performed."
}
},
{
"name": "fMRI-DeepInterpolation_3mm",
"filename": "fmri_pretrained_matlab_compatible.mat",
"url":"",
"dim":[7,7,7],
"pre": 2,
"post": 2,
"omit": 1,
"type": "fMRI",
"format": "Matlab",
"variable": "net",
"license": "https://github.com/MATLAB-Community-Toolboxes-at-INCF/DeepInterpolation-MATLAB/blob/main/LICENSE",
"parameters":
{
"description": "TR, 3000 ms; TE, 30 ms; flip angle, 80°; voxel size, 3 × 3 × 3 mm; FOV, 192 × 192 mm; number of slices, 50, slice gap, 0 mm",
"training_data": "(unknown)"
}
}
]

0 comments on commit e98c3c5

Please sign in to comment.