Skip to content

Commit

Permalink
first gui commit
Browse files Browse the repository at this point in the history
  • Loading branch information
nsteinme committed May 27, 2018
1 parent e9a7934 commit 9aeb57f
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 0 deletions.
Binary file added configFiles/defaultOps.mat
Binary file not shown.
17 changes: 17 additions & 0 deletions kilosort.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
function k = kilosort
% Call this to open the kilosort gui.

f = figure('Name', 'Kilosort',...
'MenuBar', 'none',...
'Toolbar', 'none',...
'NumberTitle', 'off',...
'Units', 'normalized',...
'OuterPosition', [0.1 0.1 0.8 0.8]);
h = ksGUI(f);

if nargout > 0
k = h;
end

end

243 changes: 243 additions & 0 deletions ksGUI.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@


classdef ksGUI < handle
% GUI for kilosort
%
% Purpose is to display some basic data and diagnostics, to make it easy to
% run kilosort
%
% Kilosort by M. Pachitariu
% This GUI by N. Steinmetz

properties
figHandle % handle to the figure

guiHandles % struct of handles to useful parts of the gui

ops % struct for kilosort to run

rez % struct of results of running

end

methods
function obj = ksGUI(parent)

obj.init();

obj.build(parent);

end

function init(obj)

% check that required functions are present
if ~exist('uiextras.HBox')
error('ksGUI:init:uix', 'You must have the "uiextras" toolbox to use this GUI. Choose Environment->Get Add-ons and search for "GUI Layout Toolbox" by David Sampson.\n')
end

% add paths
fprintf(1, '%s\n', mfilename);
if ~exist('preprocessDataSub')
addpath(genpath(fileparts(mfilename)));
end
if ~exist('readNPY')
githubDir = fileparts(fileparts(mfilename)); % taking a guess that they have a directory with all github repos
if exist(fullfile(githubDir, 'npy-matlab'))
addpath(genpath(fullfile(githubDir, 'npy-matlab')));
end
end
if ~exist('readNPY')
warning('ksGUI:init:npy', 'In order to save data for phy, you must have the npy-matlab repository from https://github.com/kwikteam/npy-matlab in your matlab path\n');
end

% compile if necessary
if ~exist('mexWtW2')

fprintf(1, 'Compiled Kilosort files not found. Attempting to compile now.\n');
try
oldDir = pwd;
cd(fullfile(fileparts(mfilename), 'CUDA'));
mexGPUall;
fprintf(1, 'Success!\n');
cd(oldDir);
catch ex
fprintf(1, 'Compilation failed. Check installation instructions at https://github.com/cortex-lab/Kilosort\n');
rethrow(ex);
end
end

obj.ops = ksGUI.defaultOps();

end


function build(obj, f)
% construct the GUI with appropriate panels
obj.figHandle = f;

obj.guiHandles.root = uiextras.VBox('Parent', f,...
'DeleteFcn', @(~,~)obj.cleanup(), 'Visible', 'on', ...
'Padding', 5);

% - Root sections

obj.guiHandles.titleBar = uicontrol(...
'Parent', obj.guiHandles.root,...
'Style', 'text', 'HorizontalAlignment', 'left', ...
'String', 'Kilosort', 'FontSize', 36,...
'FontName', 'Myriad Pro', 'FontWeight', 'bold');

obj.guiHandles.mainSection = uiextras.HBox(...
'Parent', obj.guiHandles.root);

obj.guiHandles.logPanel = uiextras.Panel(...
'Parent', obj.guiHandles.root, ...
'Title', 'Message Log', 'FontSize', 18,...
'FontName', 'Myriad Pro');

obj.guiHandles.root.Sizes = [-1 -8 -2];

% -- Main section
obj.guiHandles.settingsPanel = uiextras.Panel(...
'Parent', obj.guiHandles.mainSection, ...
'Title', 'Settings', 'FontSize', 18,...
'FontName', 'Myriad Pro');

obj.guiHandles.probePanel = uiextras.Panel(...
'Parent', obj.guiHandles.mainSection, ...
'Title', 'Probe view', 'FontSize', 18,...
'FontName', 'Myriad Pro');

obj.guiHandles.dataPanel = uiextras.Panel(...
'Parent', obj.guiHandles.mainSection, ...
'Title', 'Data view', 'FontSize', 18,...
'FontName', 'Myriad Pro');

obj.guiHandles.mainSection.Sizes = [-1 -1 -2];

% --- Settings panel

obj.guiHandles.settingsVBox = uiextras.VBox(...
'Parent', obj.guiHandles.settingsPanel);

obj.guiHandles.settingsGrid = uiextras.Grid(...
'Parent', obj.guiHandles.settingsVBox);

% choose file
obj.guiHandles.settings.ChooseFileTxt = uicontrol(...
'Parent', obj.guiHandles.settingsGrid,...
'Style', 'pushbutton', 'HorizontalAlignment', 'left', ...
'String', 'Select data file');
obj.guiHandles.settings.ChooseFileEdt = uicontrol(...
'Parent', obj.guiHandles.settingsGrid,...
'Style', 'edit', 'HorizontalAlignment', 'left', ...
'String', '...');

% choose temporary directory

% choose output path

% set nChannels

% set Fs

% choose probe

% choose max number of clusters

set( obj.guiHandles.settingsGrid, ...
'ColumnSizes', [-1 -1], 'RowSizes', -1 );%-1*ones(1,7)


% button for advanced options

% button for run

% button for write script

% button for save defaults

% -- Message log
obj.guiHandles.logBox = uicontrol(...
'Parent', obj.guiHandles.logPanel,...
'Style', 'listbox', 'Enable', 'inactive', 'String', {}, ...
'Tag', 'Logging Display', 'FontSize', 14);

obj.log('Initialization success.');

end

function run(obj)

% check that everything is set up correctly to run

% do preprocessing
obj.ops.gui = obj; % for kilosort to access, e.g. calling "log"
try
obj.rez = preprocessDataSub(obj.ops);
catch ex
log(sprintf('Error preprocessing! %s', ex.message));
end

% update gui with results of preprocessing
obj.updateDataView();

% fit templates
try
obj.rez = learnAndSolve8(obj.rez);
catch ex
log(sprintf('Error running kilosort! %s', ex.message));
end

% save results
try
rezToPhy(obj.rez, obj.ops.saveDir);
catch ex
log(sprintf('Error saving data for phy! %s', ex.message));
end

end

function writeScript(obj)
% write a .m file script that the user can use later to run
% directly, i.e. skipping the gui

end

function cleanup(obj)
fclose('all');
end

function log(obj, message)
% show a message to the user in the log box
timestamp = datestr(now, 'dd-mm-yyyy HH:MM:SS');
str = sprintf('[%s] %s', timestamp, message);
current = get(obj.guiHandles.logBox, 'String');
set(obj.guiHandles.logBox, 'String', [current; str], ...
'Value', numel(current) + 1);
end
end

methods(Static)
function ops = defaultOps()
% look for a default ops file and load it
if exist('defaultOps.mat')
load('defaultOps.mat', 'ops');
else
ops = [];
end
end

function docString = opDoc(opName)
switch opName
case 'NchanTOT'; docString = 'Total number of rows in the data file';
case 'Th'; docString = 'Threshold on projections (like in Kilosort1)';
end
end

end

end


0 comments on commit 9aeb57f

Please sign in to comment.