1- function  [expRef , expSeq ] =  newExp(subject , expDate , expParams )
1+ function  [expRef , expSeq ,  url ] =  newExp(subject , expDate , expParams ,  AlyxInstance )
22% DAT.NEWEXP Create a new unique experiment in the database
3- %    [ref, seq] = DAT.NEWEXP(subject, expDate, expParams) TODO
3+ %    [ref, seq, url] = DAT.NEWEXP(subject, expDate, expParams[, AlyxInstance])
4+ %    Create a new experiment by creating the relevant folder tree in the
5+ %    local and main data repositories in the following format:
6+ % 
7+ %    subject/
8+ %           |_ YYYY-MM-DD/
9+ %                        |_ expSeq/
10+ % 
11+ %    If experiment parameters are passed into the function, they are saved
12+ %    here, as a mat and in JSON (if possible).  If an instance of Alyx is
13+ %    passed and a base session for the experiment date is not found, one is
14+ %    created in the Alyx database. A corresponding subsession is also
15+ %    created and the parameters file is registered with the sub-session.
16+ % 
17+ %    See also DAT.PATHS
418% 
519%  Part of Rigbox
620
1630  expParams =  [];
1731end 
1832
33+ if  (nargin  <  4  ||  isempty(AlyxInstance )) &&  ~strcmp(subject , ' default' 
34+   %  no instance of Alyx, don't create session on Alyx
35+   AlyxInstance =  alyx .loginWindow ;
36+ end 
37+ 
1938if  ischar(expDate )
2039  %  if the passed expDate is a string, parse it into a datenum
2140  expDate =  datenum(expDate , ' yyyy-mm-dd' 
2948[~ , dateList , seqList ] =  dat .listExps(subject );
3049
3150%  filter the list by expdate
32- expDate =  floor(expDate );
33- filterIdx =  dateList  ==  expDate ;
51+ filterIdx =  dateList  ==  floor(expDate );
3452
3553%  find the next sequence number
3654expSeq =  max(seqList(filterIdx )) +  1 ;
4058end 
4159
4260%  expInfo repository is the reference location for which experiments exist
43- [expPath , expRef ] =  dat .expPath(subject , expDate , expSeq , ' expInfo' 
61+ [expPath , expRef ] =  dat .expPath(subject , floor( expDate ) , expSeq , ' expInfo' 
4462%  ensure nothing went wrong in making a "unique" ref and path to hold
4563assert(~any(file .exists(expPath )), ...
4664  sprintf(' Something went wrong as experiment folders already exist for "%s ".' expRef ));
4765
4866%  now make the folder(s) to hold the new experiment
4967assert(all(cellfun(@(p ) mkdir(p ), expPath )), ' Creating experiment directories failed' 
5068
69+ if  ~strcmp(subject , ' default' %  Ignore fake subject
70+   %  if the Alyx Instance is set, find or create BASE session
71+   expDate =  alyx .datestr(expDate ); %  date in Alyx format
72+   %  Get list of base sessions
73+   sessions =  alyx .getData(AlyxInstance ,...
74+     [' sessions?type=Base&subject=' subject ]);
75+   
76+   % If the date of this latest base session is not the same date as
77+   % today, then create a new base session for today
78+   if  isempty(sessions ) ||  ~strcmp(sessions{end }.start_time(1 : 10 ), expDate(1 : 10 ))
79+     d =  struct ;
80+     d.subject =  subject ;
81+     d.procedures =  {' Behavior training/tasks' 
82+     d.narrative =  ' auto-generated session' 
83+     d.start_time =  expDate ;
84+     d.type =  ' Base' 
85+     %        d.users = {AlyxInstance.username};
86+     
87+     base_submit =  alyx .postData(AlyxInstance , ' sessions' d );
88+     assert(isfield(base_submit ,' subject' 
89+       ' Submitted base session did not return appropriate values' 
90+     
91+     % Now retrieve the sessions again
92+     sessions =  alyx .getData(AlyxInstance ,...
93+       [' sessions?type=Base&subject=' subject ]);
94+   end 
95+   latest_base =  sessions{end };
96+   
97+   % Now create a new SUBSESSION, using the same experiment number
98+   d =  struct ;
99+   d.subject =  subject ;
100+   d.procedures =  {' Behavior training/tasks' 
101+   d.narrative =  ' auto-generated session' 
102+   d.start_time =  expDate ;
103+   d.type =  ' Experiment' 
104+   d.parent_session =  latest_base .url ;
105+   d.number =  expSeq ;
106+   %    d.users = {AlyxInstance.username};
107+   
108+   subsession =  alyx .postData(AlyxInstance , ' sessions' d );
109+   assert(isfield(subsession ,' subject' 
110+     ' Failed to create new sub-session in Alyx for %s ' subject );
111+   url =  subsession .url ;
112+ else 
113+   url =  [];
114+ end 
115+ 
51116%  if the parameters had an experiment definition function, save a copy in
52117%  the experiment's folder
53118if  isfield(expParams , ' defFunction' 
61126%  now save the experiment parameters variable
62127superSave(dat .expFilePath(expRef , ' parameters' ' parameters' expParams ));
63128
64- 
129+ if  ~isempty(expParams )
130+   try   %  save a copy of parameters in json
131+     %  First, change all functions to strings
132+     f_idx =  structfun(@(s )isa(s , ' function_handle' expParams );
133+     fields =  fieldnames(expParams );
134+     paramCell =  struct2cell(expParams );
135+     paramCell(f_idx ) =  cellfun(@func2str , paramCell(f_idx ),' UniformOutput' false );
136+     expParams =  cell2struct(paramCell , fields );
137+     %  Generate JSON path and save
138+     jsonPath =  fullfile(fileparts(dat .expFilePath(expRef , ' parameters' ' master' 
139+       [expRef , ' _parameters.json' 
140+     savejson(' parameters' expParams , jsonPath );
141+     %  Register our JSON parameter set to Alyx
142+     if  ~strcmp(subject , ' default' 
143+       alyx .registerFile(jsonPath , ' json' url , ' Parameters' AlyxInstance );
144+     end 
145+   catch  ex 
146+     warning(ex .identifier , ' Failed to save paramters as JSON: %s .\n  Registering mat file instead' ex .message )
147+     %  Register our parameter set to Alyx
148+     if  ~strcmp(subject , ' default' 
149+       alyx .registerFile(dat .expFilePath(expRef , ' parameters' ' master' ' mat' 
150+         url , ' Parameters' AlyxInstance );
151+     end 
152+   end 
153+ end 
65154end 
0 commit comments