Skip to content

Commit

Permalink
Adapted code to accomodate pixel_distance in lieu of previous scaling…
Browse files Browse the repository at this point in the history
… functions
  • Loading branch information
lolaBerkowitz committed Dec 2, 2024
1 parent 4e9354e commit c59bb6a
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 136 deletions.
31 changes: 15 additions & 16 deletions preprocessing/behavior/general_behavior_file_SNlab.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@ function general_behavior_file_SNlab(varargin)
basename = basenameFromBasepath(basepath);
session = loadSession(basepath,basename);

% try
% load(fullfile(basepath,'digitalIn.events.mat'))
% catch
% disp('no digitalin.events found. Can''t run general behavior file for ephys')
% return
% end

% check if file was already made
if force_overwrite
disp('Overwriting previous runs')
Expand All @@ -39,7 +32,7 @@ function general_behavior_file_SNlab(varargin)

% run update_behavioralTracking to make sure dlc files and associated
% epochs are indicated in basename.session.behavioralTracking
update_behavioralTracking('basepath',basepath)
update_behavioralTracking('basepath',basepath,'force',force_overwrite)
session = loadSession(basepath,basename);


Expand All @@ -48,34 +41,39 @@ function general_behavior_file_SNlab(varargin)
tracking_files{i} = session.behavioralTracking{1, i}.filenames;
end

% extract tracking for godot tracking
if any(contains({tracking_files{:}},'godot'))
[t,x,y,v,a,angle,units,source,fs,notes,extra_points,vidnames] = ...
tracking.extract_godot_tracking(basepath);
end


% extract tracking for Deeplabcut
if any(contains({tracking_files{:}},'DLC'))
[t_dlc,x_dlc,y_dlc,v_dlc,a_dlc,angle_dlc,units_dlc,source_dlc,fs_dlc,notes_dlc,extra_points_dlc,vidnames_dlc] = ...
tracking.extract_tracking(basepath,primary_coords_dlc,likelihood_dlc,smooth_factor);

% deeplabcut will often have many tracking points, add them here
if ~isempty(extra_points_dlc)
for field = fieldnames(extra_points_dlc)'
field = field{1};
behavior.position.(field) = extra_points_dlc.(field)';
behavior.position.(field{1}) = extra_points_dlc.(field{1})';
end
end

end

if exist('t','var') & isrow(t)
% transpose timestamps
if exist('t','var') && isrow(t)
t = t';
end

if exist('t_dlc','var') & isrow(t_dlc)
% transpose timestamps from DLC
if exist('t_dlc','var') && isrow(t_dlc)
t_dlc = t_dlc';
end

% combine both
if exist('t','var') & exist('t_dlc','var')
if exist('t','var') && exist('t_dlc','var')

if min(t) < min(t_dlc)
% concatenate
Expand All @@ -91,6 +89,7 @@ function general_behavior_file_SNlab(varargin)
notes = {notes; notes_dlc};
vidnames = {vidnames; vidnames_dlc};
extra_points = {extra_points; extra_points_dlc};

else
% concatenate
t = [t_dlc; t];
Expand All @@ -107,8 +106,9 @@ function general_behavior_file_SNlab(varargin)
extra_points = {extra_points_dlc;extra_points};
end
end
% for dlc
if ~exist('t','var') & exist('t_dlc','var')

% for DLC only
if ~exist('t','var') && exist('t_dlc','var')
% rename
t = t_dlc;
x = x_dlc;
Expand Down Expand Up @@ -150,7 +150,6 @@ function general_behavior_file_SNlab(varargin)
behavior.processinginfo.function = 'general_behavioral_file_SNlab.mat';
behavior.processinginfo.source = source;


if save_mat
save([basepath,filesep,[basename,'.animal.behavior.mat']],'behavior');
end
Expand Down
82 changes: 77 additions & 5 deletions preprocessing/behavior/get_maze_XY.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function get_maze_XY(varargin)
p = inputParser;
p.addParameter('basepath',pwd,@isfolder);
p.addParameter('vid_type','.avi',@ischar);
p.addParameter('re-do_rescale',false,@islogical);
p.addParameter('overwrite',false,@islogical);
p.addParameter('vid_time',300,@isnumeric); % time of video to load in seconds
p.addParameter('config_path','C:\Users\schafferlab\github\SNLab_ephys\behavior\behavior_configs',@isfolder); % time of video to load in seconds
Expand All @@ -44,6 +45,7 @@ function get_maze_XY(varargin)
p.parse(varargin{:})
basepath = p.Results.basepath;
vid_type = p.Results.vid_type;
rescale = p.Results.re-do_rescale;
overwrite = p.Results.overwrite;
vid_time = p.Results.vid_time;
config_path = p.Results.config_path;
Expand All @@ -57,14 +59,23 @@ function get_maze_XY(varargin)
return
end


if ~isfield(session,'behavioralTracking')
warning('No tracking items found. No maze coords to return.')
return
end

% check if behavior file exsists and if not make one
if ~exist([basepath,filesep,[basename,'.animal.behavior.mat']],'file')
general_behavior_file_SNlab(basepath)
error('Cannot update behavior file as one does not exist.')
end

% if maze_coords exist, but you want to correct the rescale
if length(dir(fullfile(basepath,'*maze_coords.csv'))) == length(session.behavioralTracking) && rescale
disp('Maze coords found for each behavioralTracking entry, rescaling coordinates')



end

% get coords
Expand All @@ -85,7 +96,63 @@ function main(session, config_path, vid_time, vid_type)
basename = basenameFromBasepath(basepath);

% load animal behavior file
load(fullfile(basepath,[basename,'.animal.behavior.mat']))
load(fullfile(basepath,[basename,'.animal.behavior.mat']),'beahvior')


% loop through video
for file = 1:length(session.behavioralTracking) %loop through folders containing subject videos


vid_path = fullfile(basepath,session.behavioralTracking{1,file}.notes);
vid_type = extractAfter(session.behavioralTracking{1,file}.notes,'.');
coords_table = readtable(fullfile(basepath,[extractBefore(session.behavioralTracking{1,file}.notes,vid_type),'_maze_coords.csv']))

% create image save to current directory
sys_cmd = ['ffmpeg -ss ', num2str(vid_time),' -i ',vid_path,' -vframes 1 ',img_path];
system(sys_cmd)

epoch = session.behavioralTracking{1,file}.epoch;
% choose config based on epoch
config = get_behavior_config(session,epoch,config_path);
crop_params = session.behavioralTracking{1, file}.crop_params;
% pulls up video frame and grabs coords
coords_table = grab_coords(img_path,session.behavioralTracking{1,file}.notes,config,crop_params);

% load pixel distance and pixel_reference
pixel_distance = session.behavioralTracking{1, file}.pixel_distance;
pixel_dist_reference = session.behavioralTracking{1, file}.pixel_dist_reference;

coords_table.x_scaled = coords_table.x * (pixel_dist_reference/pixel_distance);
coords_table.y_scaled = coords_table.y * (pixel_dist_reference/pixel_distance);
% save to session
session.behavioralTracking{1,file}.maze_coords = coords_table;

% save data to csv
save_file = fullfile(basepath,[extractBefore(session.behavioralTracking{1,file}.notes,vid_type),'_maze_coords.csv']);
writetable(coords_table,save_file);

% delete the image you created
delete(img_path)
end

% save session back to basepath
save(fullfile(basepath,[basename,'.session.mat']),'session');

end

function main(session, config_path, vid_time, vid_type)
% runs main process of looping through videos in basepath, pulling up
% image via local grab_coords function which allows user to collect coordinate data
% and outputs coords for object A center, object A edge, object B center,
% object B edge, corner center A-D (inner corner of maze).
%

% LB 2022
basepath = session.general.basePath;
basename = basenameFromBasepath(basepath);

% load animal behavior file
load(fullfile(basepath,[basename,'.animal.behavior.mat']),'beahvior')


% loop through video
Expand All @@ -98,19 +165,24 @@ function main(session, config_path, vid_time, vid_type)

vid_path = fullfile(basepath,session.behavioralTracking{1,file}.notes);
img_path = fullfile(basepath,'temp_img.png');

% create image save to current directory
sys_cmd = ['ffmpeg -ss ', num2str(vid_time),' -i ',vid_path,' -vframes 1 ',img_path];
system(sys_cmd)
%Pull up video
% videoObj = VideoReader(vid_path,'CurrentTime',vid_time); % load video starting at vid_time


epoch = session.behavioralTracking{1,file}.epoch;
% choose config based on epoch
config = get_behavior_config(session,epoch,config_path);
crop_params = session.behavioralTracking{1, file}.crop_params;
% pulls up video frame and grabs coords
coords_table = grab_coords(img_path,session.behavioralTracking{1,file}.notes,config,crop_params);

% load pixel distance and pixel_reference
pixel_distance = session.behavioralTracking{1, file}.pixel_distance;
pixel_dist_reference = session.behavioralTracking{1, file}.pixel_dist_reference;

coords_table.x_scaled = coords_table.x * (pixel_dist_reference/pixel_distance);
coords_table.y_scaled = coords_table.y * (pixel_dist_reference/pixel_distance);
% save to session
session.behavioralTracking{1,file}.maze_coords = coords_table;

Expand Down
2 changes: 0 additions & 2 deletions preprocessing/behavior/restrict_and_transform.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ function restrict_and_transform(basepath,varargin)
%
% Assumes general behavior file and *maze_coords.csv is in basepath.
p = inputParser;
p.addParameter('maze_size',[],@isnumeric)
p.addParameter('overwrite',false,@islogical)

p.parse(varargin{:});
maze_size = p.Results.maze_size;
overwrite = p.Results.overwrite;

% session basename to load animal behavior file and sessions file
Expand Down
83 changes: 17 additions & 66 deletions preprocessing/behavior/update_behavior_from_metadata.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@ function update_behavior_from_metadata(metadata_path,varargin)
% input parser
p = inputParser;
addParameter(p,'basepath',pwd);
addParameter(p,'batch',false); % flag for batch processing
addParameter(p,'data_folder',[]); % directory for batch

parse(p,varargin{:});
basepath = p.Results.basepath;
batch = p.Results.batch;
data_folder = p.Results.data_folder; % for batch in progress

% read in metadata csv
df = readtable(metadata_path);
Expand All @@ -22,75 +18,19 @@ function update_behavior_from_metadata(metadata_path,varargin)
return
end

if batch
disp('batch processing option a work in progress')
return

end

% update trials
% update trials in behavior file
update_trials(basepath,df)

% update maze size
% update maze size in session and in behavior file
update_maze_size(basepath,df)

% update behavior.epochs.scale_measurement from maze_size column
% update pixel in session and in behavior file
update_pixel_distance(basepath,df)


end



% Batch function in progress
function main_batch(data_folder,df)
% loop through and update animal behavior file for all subfolders in
% data_folder
%
basenames = unique(df.basename);
% loop through unique basenamesl
for i = 1:length(basenames)
% obtain subject dir from basename
basename = basenames{i};

sub = split(basename,'_');
sub = sub{1};

% create basepath
basepath = [data_folder,filesep,sub,filesep,basename];
session = loadSession(basepath,basename);

% load animal behavior file
if exist(fullfile(basepath,[basename,'.animal.behavior.mat']),'file')
load(fullfile(basepath,[basename,'.animal.behavior.mat']),'behavior')
else
try
general_behavior_file_SNlab('basepath',basepath)
load(fullfile(basepath,[basename,'.animal.behavior.mat']),'behavior')
catch e
disp(e)
continue
end

end

if ~isempty(behavior.trials)
continue
else
% update behavior.trials from trial_start/stop columns
update_trials(basepath,df)
end

% update behavior.epochs.maze_size from maze_size column
update_maze_size(basepath,df)

% update behavior.epochs.scale_measurement from maze_size column
update_pixel_distance(basepath,df)


end
end

function update_pixel_distance(basepath,df)
% updates behavior.trials from frames in df

Expand All @@ -106,7 +46,7 @@ function update_pixel_distance(basepath,df)

% setup
vars = fieldnames(temp_df);
col_idx = contains(vars,{'pixel_distance'});
col_idx = contains(vars,{'pixel_distance','pixel_dist_reference'});

% loop through videos indicated in session.behavioralTracking
for ii = 1:length(session.behavioralTracking)
Expand All @@ -117,11 +57,19 @@ function update_pixel_distance(basepath,df)
vidname = session.behavioralTracking{1,ii}.notes;
row_idx = contains(temp_df.vidname,extractBefore(vidname,'.avi'));

behavior.epochs{1, epoch}.pixel_distance = table2array(temp_df(row_idx,col_idx));
values = table2array(temp_df(row_idx,col_idx));
behavior.epochs{1, epoch}.pixel_distance = values(1);
behavior.epochs{1, epoch}.pixel_dist_reference = values(2);

session.behavioralTracking{1,ii}.pixel_distance = values(1);
session.behavioralTracking{1,ii}.pixel_dist_reference = values(2);


end
% save behavior file
save(fullfile(basepath,[basename,'.animal.behavior.mat']),'behavior')
save(fullfile(basepath,[basename,'.session.mat']),'session')

end

function update_maze_size(basepath,df)
Expand Down Expand Up @@ -150,11 +98,14 @@ function update_maze_size(basepath,df)
vidname = session.behavioralTracking{1,ii}.notes;
row_idx = contains(temp_df.vidname,extractBefore(vidname,'.avi'));

session.behavioralTracking{1,ii}.maze_size = table2array(temp_df(row_idx,col_idx));

behavior.epochs{1, epoch}.maze_size = table2array(temp_df(row_idx,col_idx));

end
% save behavior file
% save behavior and session file
save(fullfile(basepath,[basename,'.animal.behavior.mat']),'behavior')
save(fullfile(basepath,[basename,'.session.mat']),'session')
end

function update_trials(basepath,df)
Expand Down
5 changes: 2 additions & 3 deletions preprocessing/functions/update_epochs.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@ function update_epochs(varargin)
else
% loop through the other epochs
for i = start_idx:1:size(digitalIn.timestampsOn{1, 2},1) % by default 2nd column is events
session.epochs{i}.name = char(i);
session.epochs{i}.startTime = digitalIn.timestampsOn{1, 2}(i)
session.epochs{i}.stopTime = digitalIn.timestampsOff{1, 2}(i)
session.epochs{i}.startTime = digitalIn.timestampsOn{1, 2}(i);
session.epochs{i}.stopTime = digitalIn.timestampsOff{1, 2}(i);
end
end

Expand Down
Loading

0 comments on commit c59bb6a

Please sign in to comment.