106
106
cfg.filename = ft_getopt(cfg , ' filename' );
107
107
cfg.showinfo = ft_getopt(cfg , ' showinfo' , {' functionname' });
108
108
cfg.keepremoved = ft_getopt(cfg , ' keepremoved' , ' no' );
109
- cfg.feedback = ft_getopt(cfg , ' feedback' , ' yes ' );
109
+ cfg.feedback = ft_getopt(cfg , ' feedback' , ' text ' );
110
110
cfg.prune = ft_getopt(cfg , ' prune' , ' yes' );
111
111
cfg.filetype = ft_getopt(cfg , ' filetype' );
112
112
cfg.fontsize = ft_getopt(cfg , ' fontsize' , 10 );
254
254
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255
255
% SUBFUNCTION for recursive walking along the cfg.previous.previous info
256
256
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257
- function info = walktree(cfg , count )
258
-
259
- ft_progress(0.1 ); % FIXME no percentage complete known
257
+ function info = walktree(cfg )
260
258
261
259
if isempty(cfg ) || (isstruct(cfg ) && numel(fieldnames(cfg ))==0 )
262
260
info = [];
289
287
end
290
288
end
291
289
290
+ ft_progress(rand(1 ), ' parsing provenance for %s\n ' , this .name ); % FIXME no percentage complete known
291
+ drawnow
292
+
292
293
% the order of the output elements matters for the recursion
293
294
info = [{this } branch previous ];
294
295
300
301
node.cfg = cfg ;
301
302
node.name = f ;
302
303
node.id = getvalue(cfg , ' version.id' );
303
- node.this = struct2hash (cfg );
304
+ node.this = ft_hash (cfg );
304
305
if isfield(cfg , ' previous' ) && ~isempty(cfg .previous ) && iscell(cfg .previous )
305
306
% skip the entries that are empty
306
307
cfg.previous = cfg .previous(~cellfun(@isempty , cfg .previous ));
307
- node.parent = cellfun(@struct2hash , cfg .previous , ' UniformOutput' , false );
308
+ node.parent = cellfun(@ft_hash , cfg .previous , ' UniformOutput' , false );
308
309
elseif isfield(cfg , ' previous' ) && ~isempty(cfg .previous ) && isstruct(cfg .previous )
309
- node.parent = {struct2hash (cfg .previous )};
310
+ node.parent = {ft_hash (cfg .previous )};
310
311
elseif isfield(cfg , ' previous' ) && ~isempty(cfg .previous )
311
312
error(' unexpected content in cfg.previous' );
312
313
else
360
361
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361
362
function pipeline2matlabfigure(cfg , pipeline )
362
363
363
- if istrue(cfg .feedback )
364
- fprintf(' plotting pipeline as MATLAB figure\n ' );
365
- end
364
+ fprintf(' plotting pipeline as MATLAB figure\n ' );
366
365
367
366
layout = cell(numel(pipeline ));
368
367
for i= 1 : length(pipeline )
@@ -388,44 +387,44 @@ function pipeline2matlabfigure(cfg, pipeline)
388
387
axis tight ;
389
388
390
389
for i= 1 : numel(pipeline )
391
-
390
+
392
391
label = makelabel(pipeline(i ), cfg .showinfo );
393
-
392
+
394
393
% dublicate backslashes to escape tex interpreter (in case of windows filenames)
395
394
label = strrep(label , ' \' , ' \\ ' );
396
395
label = strrep(label , ' {\\ bf' , ' {\b f' ); % undo for bold formatting
397
-
396
+
398
397
% escape underscores
399
398
label = strrep(label , ' _' , ' \_' );
400
-
399
+
401
400
% strip blank line if present and not needed
402
401
if strcmp(label{end },' ' )
403
402
label(end ) = [];
404
403
end
405
-
404
+
406
405
% compute width and height of each box, note that axis Units are set to Normalized
407
406
boxsize = 1 ./[maxwidth + 1 maxheight + 3 ];
408
-
407
+
409
408
% create the 4 corners for our patch, close the patch by returning to the start point
410
409
x = ([0 1 1 0 0 ]-0.5 ) .* boxsize(1 );
411
410
y = ([0 0 1 1 0 ]-0.5 ) .* boxsize(2 );
412
-
411
+
413
412
% position the patch
414
413
location = pipeline(i ).position([2 1 ]);
415
414
location(1 ) = (location(1 )-0.5 )/maxwidth ;
416
415
location(2 ) = (location(2 )-0.5 )/maxheight ;
417
-
416
+
418
417
% the location specifies the center of the patch
419
418
x = x + location(1 );
420
419
y = y + location(2 );
421
-
420
+
422
421
p = patch(x ' , y ' , 0 );
423
422
set(p , ' Facecolor' , [1 1 0.6 ])
424
-
423
+
425
424
pipeline(i ).x = x ;
426
425
pipeline(i ).y = y ;
427
426
guidata(fig , pipeline );
428
-
427
+
429
428
if length(label )==1
430
429
textloc = location ;
431
430
l = text(textloc(1 ), textloc(2 ), label );
@@ -438,18 +437,18 @@ function pipeline2matlabfigure(cfg, pipeline)
438
437
textloc = location ;
439
438
textloc(1 ) = textloc(1 )-boxsize(1 )/2 ;
440
439
textloc(2 ) = textloc(2 )+boxsize(2 )/2 ;
441
-
440
+
442
441
l = text(textloc(1 ), textloc(2 ), label );
443
442
set(l , ' HorizontalAlignment' , ' left' );
444
443
set(l , ' VerticalAlignment' , ' top' );
445
444
set(l , ' fontUnits' , ' points' );
446
445
set(l , ' fontSize' , cfg .fontsize );
447
446
set(l , ' interpreter' , ' tex' );
448
447
end
449
-
448
+
450
449
% draw an arrow if appropriate
451
450
n = length(pipeline(i ).parent);
452
-
451
+
453
452
for j= 1 : n
454
453
[parentlocation(2 ), parentlocation(1 )] = ind2sub([maxheight , maxwidth ], find(strcmp(layout(: ), pipeline(i ).parent{j }), 1 , ' first' ));
455
454
% parentlocation = info(find(strcmp({pipeline.this}, analysis.parent{j}), 1, 'first')).position;
@@ -467,8 +466,8 @@ function pipeline2matlabfigure(cfg, pipeline)
467
466
end
468
467
arrow(base , tip , ' length' , 8 , ' lineWidth' , 1 );
469
468
end
470
-
471
-
469
+
470
+
472
471
end % for numel(info)
473
472
474
473
set(fig , ' WindowButtonUpFcn' , @button );
@@ -499,77 +498,77 @@ function pipeline2matlabfigure(cfg, pipeline)
499
498
label = {};
500
499
for k = 1 : numel(showinfo )
501
500
switch showinfo{k }
502
-
501
+
503
502
case ' functionname'
504
503
% label{end+1} = ['{\bf ' pipeline(i).name '}'];
505
504
label{end + 1 } = pipeline .name ;
506
505
if k == 1 % add blank line if function name is on top, looks nice
507
506
label{end + 1 } = ' ' ;
508
507
end
509
-
508
+
510
509
case ' revision'
511
510
if isfield(pipeline .cfg , ' version' ) && isfield(pipeline .cfg .version , ' id' )
512
511
label{end + 1 } = pipeline .cfg .version .id ;
513
512
else
514
513
label{end + 1 } = ' <revision unknown>' ;
515
514
end
516
-
515
+
517
516
case ' matlabversion'
518
517
if isfield(pipeline .cfg , ' callinfo' ) && isfield(pipeline .cfg .callinfo , ' matlab' )
519
518
label{end + 1 } = [' MATLAB ' pipeline .cfg .callinfo .matlab ];
520
519
else
521
520
label{end + 1 } = ' <MATLAB version unknown>' ;
522
521
end
523
-
522
+
524
523
case ' computername'
525
524
if isfield(pipeline .cfg , ' callinfo' ) && isfield(pipeline .cfg .callinfo , ' hostname' )
526
525
label{end + 1 } = [' Hostname: ' pipeline .cfg .callinfo .hostname ];
527
526
else
528
527
label{end + 1 } = ' <hostname unknown>' ;
529
528
end
530
-
529
+
531
530
case ' architecture'
532
531
if isfield(pipeline .cfg , ' callinfo' ) && isfield(pipeline .cfg .callinfo , ' hostname' )
533
532
label{end + 1 } = [' Architecture: ' pipeline .cfg .callinfo .computer ];
534
533
else
535
534
label{end + 1 } = ' <architecture unknown>' ;
536
535
end
537
-
536
+
538
537
case ' username'
539
538
if isfield(pipeline .cfg , ' callinfo' ) && isfield(pipeline .cfg .callinfo , ' user' )
540
539
label{end + 1 } = [' Username: ' pipeline .cfg .callinfo .user ];
541
540
else
542
541
label{end + 1 } = ' <username unknown>' ;
543
542
end
544
-
543
+
545
544
case ' calltime'
546
545
if isfield(pipeline .cfg , ' callinfo' ) && isfield(pipeline .cfg .callinfo , ' calltime' )
547
546
label{end + 1 } = [' Function called at ' datestr(pipeline .cfg .callinfo .calltime )];
548
547
else
549
548
label{end + 1 } = ' <function call time unknown>' ;
550
549
end
551
-
550
+
552
551
case ' timeused'
553
552
if isfield(pipeline .cfg , ' callinfo' ) && isfield(pipeline .cfg .callinfo , ' proctime' )
554
553
label{end + 1 } = sprintf(' Function call required %d seconds' , round(pipeline .cfg .callinfo .proctime ));
555
554
else
556
555
label{end + 1 } = ' <processing time unknown>' ;
557
556
end
558
-
557
+
559
558
case ' memused'
560
559
if isfield(pipeline .cfg , ' callinfo' ) && isfield(pipeline .cfg .callinfo , ' procmem' )
561
560
label{end + 1 } = sprintf(' Function call required %d MB' , round(pipeline .cfg .callinfo .procmem / 1024 / 1024 ));
562
561
else
563
562
label{end + 1 } = ' <memory requirement unknown>' ;
564
563
end
565
-
564
+
566
565
case ' workingdir'
567
566
if isfield(pipeline .cfg , ' callinfo' ) && isfield(pipeline .cfg .callinfo , ' pwd' )
568
567
label{end + 1 } = sprintf(' Working directory was %s ' , pipeline .cfg .callinfo .pwd );
569
568
else
570
569
label{end + 1 } = ' <working directory unknown>' ;
571
570
end
572
-
571
+
573
572
case ' scriptpath'
574
573
if isfield(pipeline .cfg , ' version' ) && isfield(pipeline .cfg .version , ' name' )
575
574
label{end + 1 } = sprintf(' Full path to script was %s ' , pipeline .cfg .version .name );
@@ -587,9 +586,7 @@ function pipeline2matlabscript(cfg, pipeline)
587
586
[p , f , x ] = fileparts(cfg .filename );
588
587
filename = fullfile(p , [f ' .m' ]);
589
588
590
- if istrue(cfg .feedback )
591
- fprintf(' exporting MATLAB script to file ''%s''\n ' , filename );
592
- end
589
+ fprintf(' exporting MATLAB script to file ''%s''\n ' , filename );
593
590
594
591
varname = {};
595
592
varhash = {};
@@ -637,9 +634,7 @@ function pipeline2dotfile(cfg, pipeline)
637
634
[p , f , x ] = fileparts(cfg .filename );
638
635
filename = fullfile(p , [f ' .dot' ]);
639
636
640
- if istrue(cfg .feedback )
641
- fprintf(' exporting DOT file to ''%s''\n ' , filename );
642
- end
637
+ fprintf(' exporting DOT file to ''%s''\n ' , filename );
643
638
644
639
% write the complete script to file
645
640
fid = fopen(filename , ' wb' );
@@ -680,46 +675,41 @@ function pipeline2htmlfile(cfg, pipeline)
680
675
[p , f , x ] = fileparts(cfg .filename );
681
676
filename = fullfile(p , [f ' .html' ]);
682
677
683
- if istrue(cfg .feedback )
684
- fprintf(' exporting HTML file to ''%s''\n ' , filename );
685
- end
678
+ % skip the data-like fields and the fields that probably were not added by the user himself
679
+ skipfields = {' previous' , ' grid' , ' headmodel' , ' event' , ' warning' , ' progress' , ' trackconfig' , ' checkconfig' , ' checksize' , ' showcallinfo' , ' debug' , ' outputfilepresent' , ' trackcallinfo' , ' trackdatainfo' };
680
+
681
+ fprintf(' exporting HTML file to ''%s''\n ' , filename );
686
682
687
683
html = ' ' ;
688
684
totalproctime = 0 ;
689
685
690
- if istrue(cfg .feedback )
691
- ft_progress(' init' , ' text' , ' serialising cfg-structures...' );
692
- else
693
- ft_progress(' init' , ' none' );
694
- end
686
+ ft_progress(' init' , cfg .feedback , ' serialising cfg-structures...' );
695
687
696
688
for k = 1 : numel(pipeline )
697
- ft_progress(k / numel(pipeline ));
698
-
689
+ ft_progress(k / numel(pipeline ), ' serialising cfg-structure %d from %d ' , k , numel( pipeline ) );
690
+
699
691
% strip away the cfg.previous fields, and all data-like fields
700
- tmpcfg = removefields(pipeline(k ).cfg,...
701
- {' previous' , ' grid' , ' headmodel' , ' event' , ' warning' });
702
-
692
+ tmpcfg = removefields(pipeline(k ).cfg, skipfields );
693
+
703
694
usercfg = [];
704
-
695
+
705
696
% record the usercfg and proctime if present
706
697
if isfield(tmpcfg , ' callinfo' )
707
698
if isfield(tmpcfg .callinfo , ' usercfg' )
708
- usercfg = removefields(tmpcfg .callinfo .usercfg ,...
709
- {' previous' , ' grid' , ' headmodel' , ' event' , ' warning' });
710
-
699
+ usercfg = removefields(tmpcfg .callinfo .usercfg , skipfields );
700
+
711
701
% avoid processing usercfg twice
712
702
tmpcfg.callinfo = rmfield(tmpcfg .callinfo , ' usercfg' );
713
703
end
714
-
704
+
715
705
if isfield(tmpcfg .callinfo , ' proctime' )
716
706
totalproctime = totalproctime + tmpcfg .callinfo .proctime ;
717
707
end
718
708
end
719
-
709
+
720
710
html = [html sprintf(' nodes["%s "] = {"id": "%s ", "name": "%s ", "cfg": "%s ", "usercfg": "%s ", "parentIds": [' ,...
721
711
pipeline(k ).this, pipeline(k ).this, pipeline(k ).name, escapestruct(tmpcfg ), escapestruct(usercfg ))];
722
-
712
+
723
713
if ~isempty(pipeline(k ).parent)
724
714
for j = 1 : numel(pipeline(k ).parent)
725
715
html = [html ' "' pipeline(k ).parent{j } ' "' ];
@@ -728,14 +718,14 @@ function pipeline2htmlfile(cfg, pipeline)
728
718
end
729
719
end
730
720
end
731
-
721
+
732
722
html = [html sprintf(' ]};\n ' )];
733
-
723
+
734
724
if k == numel(pipeline )
735
725
% we are at the single leaf node
736
726
html = [html sprintf(' var leafId = "%s ";\n ' , pipeline(k ).this)];
737
727
end
738
-
728
+
739
729
end
740
730
ft_progress(' close' );
741
731
@@ -780,24 +770,3 @@ function pipeline2htmlfile(cfg, pipeline)
780
770
cfghtml = strrep(cfghtml , sprintf(' \t ' ), ' \t ' );
781
771
cfghtml = strrep(cfghtml , ' "' , ' \"' );
782
772
783
-
784
- % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
785
- % SUBFUNCTION
786
- % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787
- function h = struct2hash(s )
788
- % both of these are from Mathworks file exchange
789
- try
790
- % this one uses a mex file
791
- h = CalcMD5(mxSerialize(s ));
792
- catch
793
- % this one uses Java
794
- h = DataHash(s );
795
- end
796
-
797
- % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798
- % SUBFUNCTION
799
- % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
800
- function b = istrue(s )
801
- false_list = {' no' ' false' ' off' ' n' ' none' };
802
- b = ~any(strcmp(s , false_list ));
803
-
0 commit comments