Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
jaib1 committed Jul 19, 2019
2 parents 1d9f0a8 + 5556a3c commit 82d73de
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 71 deletions.
3 changes: 2 additions & 1 deletion @Alyx/Alyx.m
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@

function obj = set.BaseURL(obj, value)
% Drop trailing slash and ensure protocol defined
if isempty(value); obj.BaseURL = ''; return; end % return on empty
value = iff(value(1:4)~='http', ['https://' value], value);
obj.BaseURL = iff(value(end)=='/', value(1:end-1), value);
end
Expand All @@ -109,7 +110,7 @@
% Checks for and uploads queued data to Alyx
[data, statusCode] = flushQueue(obj)
% Recovers the full filepath of a file on the repository, given the datasetURL
fullPath = getFile(obj, datasetURL)
[fullPath, exists] = getFile(obj, eid, type)
% Query the database for a list of sessions
[sessions, eids] = getSessions(obj, varargin)
% Lists recorded subjects
Expand Down
70 changes: 46 additions & 24 deletions @Alyx/getFile.m
Original file line number Diff line number Diff line change
@@ -1,36 +1,58 @@
function fullPath = getFile(obj, datasetURL)
%GETFILE Recovers the full filepath of a file on the repository, given the datasetURL
% This function is SUPER inefficient because it has to load all
% filerecords from the database, and then search for the specific
% filerecord whose parent dataset matches the one supplied as input.
function [fullPath, exists] = getFile(obj, eid, type)
%GETFILE Returns the full filepath for a given eid.
% Returns the full path of associated data files given a dataset or file
% record URL or eid (experiment ID). Also returns a logical array
% indicating whether files exist for each element in the `eid` array.
%
% datasetURL: URL of a dataset on Alyx
% Inputs:
% `eid`: a string or char array containing the full URL(s) or eid(s) of
% dataset(s) / file record(s) on Alyx.
% `type`: a string indicating type of eid(s) ('dataset' (default) or
% 'file')
%
% See also ALYX, GETDATA
% Outputs:
% `fullPath`: a cellstring containing the full data file path(s) for
% each element in the `eid` array
% `exists`: a logical array indicating whether files exist for each eid
% in the `eid` array
%
% See also ALYX, GETDATA, GETSESSIONS
%
% Part of Alyx
% TODO: Create endpoint so this function is no longer inefficient?
% 2017 PZH created
% 2019 MW Rewrote

if nargin < 3; type = 'dataset'; end

% Get all file records
filerecords = obj.getData('files');

% Extract the datasets which are parent to the filerecords
datasets = cellfun(@(fr) fr.dataset, filerecords, 'uni', 0);

% Find whichever filerecord has input datasetURL as its parent
idx = contains(datasets, datasetURL);

if any(idx)
fr = filerecords{idx};
relPath = fr.relative_path; % Get relative path of file

repo = obj.getData('data-repository'); % Get absolute path of repository
fullPath = [repo{1}.path relPath]; % Recover the full path of the file on the repository
% Convert array of strings to cell string
if isstring(eid) && ~isscalar(eid)
eid = cellstr(eid);
else
error('No filerecords with inputted datasetURL as its parent');
eid = ensureCell(eid);
end

% Validate URL (UUIDs have 36 characters)
assert(all(cellfun(@(str)ischar(str) && length(str) >= 36, eid)), 'Invalid eid')
eid = mapToCell(@(str)str(end-35:end), eid);

% Get all file records
switch lower(type)
case 'file'
filerecords = mapToCell(@(url)obj.getData(['files/', url]), eid);
repos = obj.getData('data-repository');
repos = containers.Map({repos.name}, {repos.data_url});
fullPath = mapToCell(@(s)[repos(s.data_repository) s.relative_path], filerecords);
exists = cellfun(@(s)s.exists, filerecords);
% Return as char if user expects one output
if numel(eid) == 1; fullPath = fullPath{1}; end
case 'dataset'
filerecords = catStructs(mapToCell(@(url)getOr(obj.getData(['datasets/', url]), 'file_records'), eid));
exists = [filerecords.exists];
fullPath = {filerecords.data_url};
% Remove records with empty url field
exists = exists(emptyElems(fullPath));
fullPath = rmEmpty(fullPath);
otherwise
error('Alyx:GetFile:InvalidType', 'Invalid eid type: must be ''dataset'' or ''file''')
end

7 changes: 2 additions & 5 deletions @Alyx/listSubjects.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,8 @@
subjects = [{'default'}, subjNames]';
end
else
% The master 'main' repository is the reference for the existence of
% The remote 'main' repositories are the reference for the existence of
% experiments, as given by the folder structure
mainPath = dat.reposPath('main', 'master');

dirs = file.list(mainPath, 'dirs');
subjects = setdiff(dirs, {'@Recently-Snapshot', '@Recycle'}); %exclude the trash directories
subjects = dat.listSubjects;
end
end
3 changes: 1 addition & 2 deletions @Alyx/newExp.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@
try
% Generate JSON path and save
jsonParams = obj2json(expParams);
jsonPath = fullfile(fileparts(dat.expFilePath(expRef, 'parameters', 'master')),...
[expRef, '_parameters.json']);
jsonPath = dat.expFilePath(expRef, 'parameters', 'master', 'json');
fid = fopen(jsonPath, 'w'); fprintf(fid, '%s', jsonParams); fclose(fid);
% Register our JSON parameter set to Alyx
files = [files; {jsonPath}];
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Alyx-MATLAB
![Custom badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgladius.serveo.net%2Fcoverage%2Falyx-matlab%2Fdev)
![Custom badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgladius.serveo.net%2Fstatus%2Falyx-matlab%2Fdev)

This repository contains a MATLAB class called Alyx, that facilitates RESTful POST and GET requests to an instance of the [Alyx database](http://alyx.readthedocs.io/en/latest/).

## Getting started
Expand Down Expand Up @@ -153,4 +156,4 @@ For use with [Rigbox](https://github.com/cortex-lab/Rigbox), use the submodule t
* [MD5 in MATLAB](https://uk.mathworks.com/matlabcentral/fileexchange/7919-md5-in-matlab) - For checksums (no longer used)

## Authors
This code is maintained and developed by a number of people at [CortexLab](https://www.ucl.ac.uk/cortexlab). See [contributors](https://github.com/cortex-lab/alyx-matlab/graphs/contributors) list for more info.
This code is maintained and developed by a number of people at [CortexLab](https://www.ucl.ac.uk/cortexlab). See [contributors](https://github.com/cortex-lab/alyx-matlab/graphs/contributors) list for more info.
Loading

0 comments on commit 82d73de

Please sign in to comment.