-
Notifications
You must be signed in to change notification settings - Fork 1
/
DesignSpace_exported.m
1212 lines (997 loc) · 60.5 KB
/
DesignSpace_exported.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
classdef DesignSpace_exported < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
DesignSpacePlotterUIFigure matlab.ui.Figure
DataPanel matlab.ui.container.Panel
ExperimentListBox matlab.ui.control.ListBox
ExperimentsLabel matlab.ui.control.Label
VariableListBox matlab.ui.control.ListBox
VariablesLabel matlab.ui.control.Label
LoadfileButton matlab.ui.control.Button
Label matlab.ui.control.Label
SettingsPanel matlab.ui.container.Panel
ColourpalletDropDownLabel matlab.ui.control.Label
ColourpalletDropDown matlab.ui.control.DropDown
DefaultcolorDropDownLabel matlab.ui.control.Label
DefaultcolorDropDown matlab.ui.control.DropDown
StemstyleDropDownLabel matlab.ui.control.Label
StemstyleDropDown matlab.ui.control.DropDown
SizeSliderLabel matlab.ui.control.Label
SizeSlider matlab.ui.control.Slider
ToggledebugCheckBox matlab.ui.control.CheckBox
InvertToggle matlab.ui.control.CheckBox
GridoffCheckBox matlab.ui.control.CheckBox
VideoButton matlab.ui.control.Button
FPSEditFieldLabel matlab.ui.control.Label
FPSEditField matlab.ui.control.NumericEditField
PlotPanel matlab.ui.container.Panel
PlotLabel matlab.ui.control.Label
GraphAxes matlab.ui.control.UIAxes
end
properties (Access = private)
filePath % File path
fileName % File name
variables = zeros(1) % The table where all the data gets stored
varNames % The variable names
experiments % The name of each experiment (numbered list)
colorScheme = parula; % Default colour map (parula)
defaultColor = "blue"; % Default normal colour
lineStyle = "-"; % Default line style
defaultSize = 40 % Default point Size
gridOff = false; % Defines if the grid is on or off (off default)
vid = false; % If true then starts to make the vido (false default)
vidImagesFile = 'VideoImages\'; % File location for the images that create the video
Blue2Red % Predefine the Blue2Red custom color map
ColourLinked % The array of variables that points to each colour map
fps = 2; % Default fps
end
methods (Access = private)
%--------------------------------------------------------------------------
% Resets the variables when a new file is loaded
function reset(app)
app.filePath = "";
app.fileName = "";
app.variables = zeros(1);
app.varNames = "";
app.experiments = "";
end
%--------------------------------------------------------------------------
% Loads the variables and experiments into the list boxes
function loadVariables(app)
% Extracts the variable names and adds them to the variables
% list box (var names in the header of the file submitted)
app.varNames = app.variables.Properties.VariableNames;
app.VariableListBox.Items = app.varNames;
% Labels each experiment detected (number of rows) from 1 to
% the total number of experiments
numbOfExp = size(app.variables,1);
app.experiments = string(1:numbOfExp);
app.ExperimentListBox.Items = app.experiments;
end
%--------------------------------------------------------------------------
%Updates the graph UI
function updateGraph(app)
% Gets the selected value that is contained in the list box
selectedGraphNames = app.ExperimentListBox.Value;
% If there are multiple selected, it turns
% them into a cell. Therefore this detects this and reverts it
% back to a strign array if multiple are selected. If only one
% is detected it is a char. Therefore convert it to a string.
if iscell(selectedGraphNames)
selectedGraphNames = cellfun(@string, selectedGraphNames);
else
selectedGraphNames = string(selectedGraphNames);
end
%Creates an intal empty logal array with all zero with all the
%possible selections it could be
logicArry = false(1,length(app.ExperimentListBox.Items));
%Loops through each experiment selectd and finds the
%location of it.
for resp = 1:length(selectedGraphNames)
% Finds the location of the experiment in the list
% of the allowed experiments and flips it so it adds
% correctly to the logic array.
temp = strcmp(string(1:length(app.experiments)),selectedGraphNames(resp));
% Adds on this location. If == 1 then that responce
% function is being used, if == 0 then it is not.
logicArry = logicArry + temp;
end
% Clear graph
cla(app.GraphAxes,'reset')
% Gets the selected value that is contained in the list box
selectedVars = app.VariableListBox.Value;
% If there are multiple selected, it turns
% them into a cell. Therefore this detects this and reverts it
% back to a strign array if multiple are selected. If only one
% is detected it is a char. Therefore convert it to a string.
if iscell(selectedVars)
varOrder = cellfun(@string, selectedVars);
else
varOrder = string(selectedVars);
end
% If more than 1 variable is selected (so a 2D or more plot
% can be done)
if length(varOrder) > 1 && length(selectedGraphNames) >= 1
% If too many variables are selected and are added to varOrder
% then only select the first 5 (plot will only go as
% high as the 5th dimension)
if length(varOrder) > 5
varOrder = varOrder(1:5);
end
% Logic array contains the true false data of each
% graph that is selected. Where 0 = not seleected and 1
% = selectd. This function converts this into a
% numbered array and removes any 0's so that it can be
% used to index the combined data table. For example if
% logicArry = [0 0 1 0 1 0] then it would be this .* [1
% 2 3 4 5 6] = [0 0 3 0 5 0] and then zeros removed to
% give [3 5] so the table is indexed at 3 and 5.
logicArry = logicArry.*(1:1:length(logicArry));
logicArry(logicArry==0) = [];
logicArry = logicArry'; % Makes sure it is in the right direction
% Uses this logical array to index the specfic data
extractedData = app.variables(logicArry, varOrder);
% Plots a 2D graph when the number of columns in
% extracted data = 2;
if size(extractedData,2) == 2
% 2D plot of the selected points
scatter(app.GraphAxes, extractedData{:,1},extractedData{:,2}, app.defaultSize , app.defaultColor, 'filled');
% As extractedData is a table it selects the VariableNames
% as the x and y label.
xlabel(app.GraphAxes, extractedData.Properties.VariableNames(1));
ylabel(app.GraphAxes, extractedData.Properties.VariableNames(2));
% If debug mode is on, display the text
if app.ToggledebugCheckBox.Value == 1
text(app.GraphAxes, extractedData{:,1},extractedData{:,2}, ' ' + string(logicArry))
end
% Turn grids on by defult (get switched off later if
% it has been toggled so, for a 2d graph the grids are
% off by default)
app.GraphAxes.XGrid = 'on';
app.GraphAxes.YGrid = 'on';
% If video option has been selected
if app.vid == true
clear F % Clears the Frames if it exists
% Make the direcotry for the images of the video to
% be stored (if it has not already)
mkdir(app.vidImagesFile)
% Creates a new figure to film with an axis in it
newFig = figure;
newGraph = axes(newFig);
% Gets the current size of the graph
xsize = app.GraphAxes.XLim;
ysize = app.GraphAxes.YLim;
% Clear graph in the new figure
cla(newGraph,'reset')
% Sets the sizes
newGraph.XLim = xsize;
newGraph.YLim = ysize;
% Sets the labels
xlabel(newGraph, extractedData.Properties.VariableNames(1));
ylabel(newGraph, extractedData.Properties.VariableNames(2));
% if grid off is not selected then activate these
% grids.
if app.gridOff == false
newGraph.XGrid = 'on';
newGraph.YGrid = 'on';
end
hold(newGraph, "on")
% Loops through each data point and plots it. Can do
% this all in one go but this allows it to work with
% video capture.
for point = 1:size(extractedData,1)
%Plot the point
scatter(newGraph, extractedData{point,1},extractedData{point,2}, app.defaultSize , app.defaultColor, 'filled')
% If debug mode is on, display the text
if app.ToggledebugCheckBox.Value == 1
text(newGraph, extractedData{point,1}, extractedData{point,2}, ' ' + string(logicArry(point)))
end
% Creates image name, saves it as a .jpeg with
% a good resolution, re-reads and then converts
% to a frame ready to be processed later.
fname = [app.vidImagesFile 'image' num2str(point)]; % full name of image
print(newFig,'-djpeg','-r200',fname) % save image with '-r200' resolution
I = imread([fname '.jpg']); % read saved image
F(point) = im2frame(I); % convert image to frame
end
hold(newGraph, "off")
end
% Plots a 3D graph when the number of columns in
% extracted data = 3;
elseif size(extractedData,2) == 3
% 3D scatter graph
scatter3(app.GraphAxes, extractedData{:,1}, extractedData{:,2}, extractedData{:,3}, app.defaultSize, app.defaultColor, 'filled')
% Add to the same axis the lines that go down to
% the xy plane
hold (app.GraphAxes, 'on')
% Set upper and lower bound of the z axis so that the
% lines drawn don't always go to z = 0 and show loads
% of blank space.
lowerBound = floor(min(extractedData{:,3})/5)*5;
% loop through each element and add the line that
% goes down to the xy plane
for x = 1:size(extractedData,1)
plot3(app.GraphAxes, [extractedData{x,1} extractedData{x,1}], [extractedData{x,2} extractedData{x,2}], [lowerBound, extractedData{x,3}], 'Color', app.defaultColor, 'LineStyle', app.lineStyle)
end
% Stop appending to the same axis
hold (app.GraphAxes, 'off')
% Add the graph labels based on the table col name
% values
xlabel(app.GraphAxes, extractedData.Properties.VariableNames(1));
ylabel(app.GraphAxes, extractedData.Properties.VariableNames(2));
zlabel(app.GraphAxes, extractedData.Properties.VariableNames(3));
% Get the current Z axis UB limit and then set the new
% Z axis limits to minimise whitespace.
zaxis = zlim(app.GraphAxes);
zlim(app.GraphAxes, [lowerBound, zaxis(2)])
% if debug mode is on, then plot the numbers next
% each point for easier identifcation
if app.ToggledebugCheckBox.Value == 1
text(app.GraphAxes, extractedData{:,1},extractedData{:,2}, extractedData{:,3}, ' ' + string(logicArry))
end
% If video option has been selected
if app.vid == true
clear F % Clears the Frames if it exists
% Make the direcotry for the images of the video to
% be stored (if it has not already)
mkdir(app.vidImagesFile)
% Creates a new figure to film with an axis in it
newFig = figure;
newGraph = axes(newFig);
% Gets the current size of the graph
xsize = app.GraphAxes.XLim;
ysize = app.GraphAxes.YLim;
zsize = app.GraphAxes.ZLim;
% Clear graph in the new figure
cla(newGraph,'reset')
% Sets the sizes
newGraph.XLim = xsize;
newGraph.YLim = ysize;
newGraph.ZLim = zsize;
% Sets the labels
xlabel(newGraph, extractedData.Properties.VariableNames(1));
ylabel(newGraph, extractedData.Properties.VariableNames(2));
zlabel(newGraph, extractedData.Properties.VariableNames(3));
%For some reason these actions set the graph state
%to 2D, so make sure it is 3D.
view(newGraph,3)
% Switch on by default to begin with
newGraph.Box = "on";
% if grid off is not selected then activate these
% grids.
if app.gridOff == false
newGraph.XGrid = 'on';
newGraph.YGrid = 'on';
newGraph.ZGrid = 'on';
newGraph.Box = "off";
end
hold(newGraph, "on")
% Loops through each data point and plots it. Can do
% this all in one go but this allows it to work with
% video capture.
for point = 1:size(extractedData,1)
% Plot the point
scatter3(newGraph, extractedData{point,1},extractedData{point,2}, extractedData{point,3}, app.defaultSize , app.defaultColor, 'filled')
% Plot the line
plot3(newGraph, [extractedData{point,1} extractedData{point,1}], [extractedData{point,2} extractedData{point,2}], [lowerBound, extractedData{point,3}], 'Color', app.defaultColor, 'LineStyle', app.lineStyle)
% If debug mode is on, display the text
if app.ToggledebugCheckBox.Value == 1
text(newGraph, extractedData{point,1},extractedData{point,2}, extractedData{point,3}, ' ' + string(logicArry(point)))
end
% Creates image name, saves it as a .jpeg with
% a good resolution, re-reads and then converts
% to a frame ready to be processed later.
fname = [app.vidImagesFile 'image' num2str(point)]; % full name of image
print(newFig,'-djpeg','-r200',fname) % save image with '-r200' resolution
I = imread([fname '.jpg']); % read saved image
F(point) = im2frame(I); % convert image to frame
end
hold(newGraph, "off")
end
% Plots a 4D graph when the number of columns in
% extracted data = 4, using color as the 4th dimension
elseif size(extractedData,2) == 4
% 4D scatter graph where the colour is the 4th
% dimenson
scatter3(app.GraphAxes, extractedData{:,1}, extractedData{:,2}, extractedData{:,3}, app.defaultSize, extractedData{:,4}, "filled")
% Set the colur scheme to app.colorScheme
cmap = colormap(app.GraphAxes,app.colorScheme);
% If the invert option is selected it inverts the
% colour scheme.
if app.InvertToggle.Value == 0
cmap = colormap(app.GraphAxes, flipud(cmap));
end
% Add the colour bar
cbar = colorbar(app.GraphAxes);
% This sets up the colours for the dotted lines so
% that they match the scattered point colours. If
% all the values in extracted method are the same,
% then set it to the first color. If if is a
% difference between the values, use the max and
% min values to generate c, which is a matrix that
% spaces out the colours uniformly and in realtion
% to the colours of the scatter points.
if nnz(diff(extractedData{:,4})) == 0
c = ones(size(cmap,1));
else
c = round(1+(size(cmap,1)-1)*(extractedData{:,4} - min(extractedData{:,4}))/(max(extractedData{:,4})-min(extractedData{:,4})));
end
% Add to the same axis the lines that go down to
% the xy plane
hold(app.GraphAxes, 'on');
% Set upper and lower bound of the z axis so that the
% lines drawn don't always go to z = 0 and show loads
% of blank space.
lowerBound = floor(min(extractedData{:,3})/5)*5;
% Based on the index/ color psotion (c) plots a
% dotted line that goes down from the point to the
% xy plane
for x = 1:size(extractedData,1)
plot3(app.GraphAxes, [extractedData{x,1} extractedData{x,1}], [extractedData{x,2} extractedData{x,2}], [lowerBound extractedData{x,3}], "Color",cmap(c(x),:), 'LineStyle', app.lineStyle)
end
% Stop appending to the same axis
hold (app.GraphAxes, 'off');
% Add the graph labels based on the table col name
% values
xlabel(app.GraphAxes, extractedData.Properties.VariableNames(1));
ylabel(app.GraphAxes, extractedData.Properties.VariableNames(2));
zlabel(app.GraphAxes, extractedData.Properties.VariableNames(3));
% Get the current Z axis UB limit and then set the new
% Z axis limits to minimise whitespace.
zaxis = zlim(app.GraphAxes);
zlim(app.GraphAxes, [lowerBound, zaxis(2)])
% Add title to colour bar
title(cbar, extractedData.Properties.VariableNames(4), "FontSize",10, "FontWeight","bold")
% Puts in a title so that the spacing at the top of
% the graph includes the title above the cbar
title(app.GraphAxes, " ", "FontSize",20, "FontWeight","bold")
cbar.FontSize = 10; %Makes font of cbar increments larger
% if debug mode is on, then plot the numbers next
% each point for easier identifcation
if app.ToggledebugCheckBox.Value == 1
% Loops through each point and adds text next
% to it that includes the number and var4 data
for graph = 1:size(extractedData,1)
text(app.GraphAxes, extractedData{graph,1},extractedData{graph,2}, extractedData{graph,3}, " " + string(logicArry(graph)) + ", " + string(extractedData{graph,4}))
end
end
% If video option has been selected
if app.vid == true
clear F % Clears the Frames if it exists
% Make the direcotry for the images of the video to
% be stored (if it has not already)
mkdir(app.vidImagesFile)
% Creates a new figure to film with an axis in it
newFig = figure;
newGraph = axes(newFig);
% Gets the current size of the graph
xsize = app.GraphAxes.XLim;
ysize = app.GraphAxes.YLim;
zsize = app.GraphAxes.ZLim;
% Clear graph in the new figure
cla(newGraph,'reset')
% Sets the sizes
newGraph.XLim = xsize;
newGraph.YLim = ysize;
newGraph.ZLim = zsize;
% Sets the labels
xlabel(newGraph, extractedData.Properties.VariableNames(1));
ylabel(newGraph, extractedData.Properties.VariableNames(2));
zlabel(newGraph, extractedData.Properties.VariableNames(3));
% Set the colur scheme to app.colorScheme
cmapVid = colormap(newGraph,app.colorScheme);
% If the invert option is selected it inverts the
% colour scheme.
if app.InvertToggle.Value == 0
cmapVid = colormap(newGraph, flipud(cmapVid));
end
% Add the colour bar
cbarVid = colorbar(newGraph);
% Add title to colour bar
title(cbarVid, extractedData.Properties.VariableNames(4), "FontSize",10, "FontWeight","bold")
% Puts in a title so that the spacing at the top of
% the graph includes the title above the cbar
title(newGraph, " ", "FontSize",20, "FontWeight","bold")
cbar.FontSize = 10; %Makes font of cbar increments larger
%For some reason these actions set the graph state
%to 2D, so make sure it is 3D.
view(newGraph,3)
% Switch on by default to begin with
newGraph.Box = "on";
% if grid off is not selected then activate these
% grids.
if app.gridOff == false
newGraph.XGrid = 'on';
newGraph.YGrid = 'on';
newGraph.ZGrid = 'on';
newGraph.Box = "off";
end
hold(newGraph, "on")
% Plot all the points initally really tiny to
% correctly configure the colour bar
for x = 1:size(extractedData,1)
scatter3(newGraph,extractedData{x,1},extractedData{x,2},extractedData{x,3},0.001, extractedData{x,4}, "filled");
end
% Loops through each data point and plots it. Can do
% this all in one go but this allows it to work with
% video capture.
for point = 1:size(extractedData,1)
%Plot the point
scatter3(newGraph, extractedData{point,1}, extractedData{point,2}, extractedData{point,3}, app.defaultSize, extractedData{point,4}, "filled")
%Plot the line
plot3(newGraph, [extractedData{point,1} extractedData{point,1}], [extractedData{point,2} extractedData{point,2}], [lowerBound extractedData{point,3}], "Color",cmapVid(c(point),:), 'LineStyle', app.lineStyle)
% If debug mode is on, display the text
if app.ToggledebugCheckBox.Value == 1
text(newGraph, extractedData{point,1},extractedData{point,2}, extractedData{point,3}, " " + string(logicArry(point)) + ", " + string(extractedData{point,4}))
end
% Creates image name, saves it as a .jpeg with
% a good resolution, re-reads and then converts
% to a frame ready to be processed later.
fname = [app.vidImagesFile 'image' num2str(point)]; % full name of image
print(newFig,'-djpeg','-r200',fname) % save image with '-r200' resolution
I = imread([fname '.jpg']); % read saved image
F(point) = im2frame(I); % convert image to frame
end
hold(newGraph, "off")
end
% Plots a 5D graph when the number of columns in
% extracted data = 5, using color as the 4th
% dimension and size of the dot as the 5th dimension.
elseif size(extractedData,2) == 5
% Change these to vary the maximum and minimim dot
% sizes
maxDotSize = 100;
minDotSize = 5;
% Scale the data so that the size is bewteen the
% max and min dot size, for when it is plotted on
% the graph.
scaledData = rescale(extractedData{:,5}, minDotSize, maxDotSize);
% Generates 5 uniformly spaced marker sizes between
% the min and max dot size specified
ledgMarkerSize = linspace(minDotSize, maxDotSize, 5);
markersActualNumb = rescale(ledgMarkerSize, min(extractedData{:,5}), max(extractedData{:,5}));
% Add to the same axis the lines that go down to
% the xy plane
hold (app.GraphAxes, 'on');
% The loop starts to create the figger that
% displays the dot size. It works by plotting 5
% points of varying marker size (plot3 has to be
% used instead of scatter3 as only this changes the
% dot size in the legend for some reason) and
% setting their visabilty to 0. Then each each
% number that corrisponds to the 5 uniformly
% distrubuted sizes is set to a cell which then
% later is used to called the legend function
% (which only shows these first 5 dots). This has
% to be done before the scatter function as it
% needs to be the FIRST 5 dots.
for ind = 1:numel(ledgMarkerSize)
% Generate the plots and save them in figplots
% array. Set them at (0,0,0) and set the marker
% size to the square root of the ledgMarkerSize
% (for some reason this works well for size
% comparson, not sure how acurate it is).
figplots(ind) = plot3(app.GraphAxes,0,0,0,'bo','markersize',round(sqrt(ledgMarkerSize(ind)),1),'MarkerFaceColor','blue', "MarkerEdgeColor","blue");
set(figplots(ind),'visible','off') % Make them invisable
% Adds each number (acutal number not the marker
% size number) so that it is displayed as the
% label when the legend function is called later
legentry{ind} = num2str(round(markersActualNumb(ind),1));
end
% 5D scatter graph where the colour is the 4th
% dimenson and size of the dot is the 5th dimension
scatter3(app.GraphAxes, extractedData{:,1}, extractedData{:,2}, extractedData{:,3}, scaledData, extractedData{:,4}, "filled")
% Stop appending to the same axis
hold (app.GraphAxes, 'off');
% Set the colur scheme to app.colorScheme
cmap = colormap(app.GraphAxes,app.colorScheme);
% If the invert option is selected it inverts the
% colour scheme.
if app.InvertToggle.Value == 0
cmap = colormap(app.GraphAxes, flipud(cmap));
end
% Add the colour bar
cbar = colorbar(app.GraphAxes);
% This sets up the colours for the dotted lines so
% that they match the scattered point colours. If
% all the values in extracted method are the same,
% then set it to the first color. If if is a
% difference between the values, use the max and
% min values to generate c, which is a matrix that
% spaces out the colours uniformly and in realtion
% to the colours of the scatter points.
if nnz(diff(extractedData{:,4})) == 0
c = ones(size(cmap,1));
else
c = round(1+(size(cmap,1)-1)*(extractedData{:,4} - min(extractedData{:,4}))/(max(extractedData{:,4})-min(extractedData{:,4})));
end
% Add to the same axis the lines that go down to
% the xy plane
hold (app.GraphAxes, 'on');
% Set upper and lower bound of the z axis so that the
% lines drawn don't always go to z = 0 and show loads
% of blank space.
lowerBound = floor(min(extractedData{:,3})/5)*5;
% Based on the index/ color psotion (c) plots a
% dotted line that goes down from the point to the
% xy plane
for x = 1:size(extractedData,1)
plot3(app.GraphAxes, [extractedData{x,1} extractedData{x,1}], [extractedData{x,2} extractedData{x,2}], [lowerBound extractedData{x,3}], "Color",cmap(c(x),:), 'LineStyle', app.lineStyle)
end
% Stop appending to the same axis
hold (app.GraphAxes, 'off');
% Add the graph labels based on the table col name
% values
xlabel(app.GraphAxes, extractedData.Properties.VariableNames(1));
ylabel(app.GraphAxes, extractedData.Properties.VariableNames(2));
zlabel(app.GraphAxes, extractedData.Properties.VariableNames(3));
% Add title to colour bar
title(cbar, extractedData.Properties.VariableNames(4), "FontSize",10, "FontWeight","bold")
% Puts in a title so that the spacing at the top of
% the graph includes the title above the cbar
title(app.GraphAxes, " ", "FontSize",20, "FontWeight","bold")
cbar.FontSize = 10; %Makes font of cbar increments larger
% Creat the legend at the end after all points have
% been added as we only want the first 5 points
% (the dummy invisable ones stored in figplots)
leg = legend(app.GraphAxes, legentry);
leg.Location = 'eastoutside'; %Display next to the colour bar
leg.FontSize = 10; % Make font the same size as the color bar
% Gives the legend a title
title(leg, extractedData.Properties.VariableNames(5),"FontSize",10, "FontWeight","bold");
% Get the current Z axis UB limit and then set the new
% Z axis limits to minimise whitespace.
zaxis = zlim(app.GraphAxes);
zlim(app.GraphAxes, [lowerBound, zaxis(2)])
%For some reason these actions set the graph state
%to 2D, so make sure it is 3D.
view(app.GraphAxes,3)
% if debug mode is on, then plot the numbers next
% each point for easier identifcation
if app.ToggledebugCheckBox.Value == 1
% Loops through each point and adds text next
% to it that includes the number, var4 and
% var5 data data
for graph = 1:size(extractedData,1)
text(app.GraphAxes, extractedData{graph,1},extractedData{graph,2}, extractedData{graph,3}, " " + string(logicArry(graph)) + ", " + string(extractedData{graph,4}) + ", " + string(extractedData{graph,5}))
end
end
% If video option has been selected
if app.vid == true
clear F % Clears the Frames if it exists
% Make the direcotry for the images of the video to
% be stored (if it has not already)
mkdir(app.vidImagesFile)
% Creates a new figure to film with an axis in it
newFig = figure;
newGraph = axes(newFig);
% Gets the current size of the graph
xsize = app.GraphAxes.XLim;
ysize = app.GraphAxes.YLim;
zsize = app.GraphAxes.ZLim;
% Clear graph in the new figure
cla(newGraph,'reset')
% Sets the sizes
newGraph.XLim = xsize;
newGraph.YLim = ysize;
newGraph.ZLim = zsize;
% Sets the labels
xlabel(newGraph, extractedData.Properties.VariableNames(1));
ylabel(newGraph, extractedData.Properties.VariableNames(2));
zlabel(newGraph, extractedData.Properties.VariableNames(3));
% Set the colur scheme to app.colorScheme
cmapVid = colormap(newGraph,app.colorScheme);
% If the invert option is selected it inverts the
% colour scheme.
if app.InvertToggle.Value == 0
cmapVid = colormap(newGraph, flipud(cmapVid));
end
% Add the colour bar
cbarVid = colorbar(newGraph);
% Add title to colour bar
title(cbarVid, extractedData.Properties.VariableNames(4), "FontSize",10, "FontWeight","bold")
% Puts in a title so that the spacing at the top of
% the graph includes the title above the cbar
title(newGraph, " ", "FontSize",20, "FontWeight","bold")
cbar.FontSize = 10; %Makes font of cbar increments larger
%For some reason these actions set the graph state
%to 2D, so make sure it is 3D.
view(newGraph,3)
% Switch on by default to begin with
newGraph.Box = "on";
% if grid off is not selected then activate these
% grids.
if app.gridOff == false
newGraph.XGrid = 'on';
newGraph.YGrid = 'on';
newGraph.ZGrid = 'on';
newGraph.Box = "off";
end
hold(newGraph, "on")
% Same code as before, creates the legend markers
% and makes the points invisable so they cant be
% seen
for ind = 1:numel(ledgMarkerSize)
% Generate the plots and save them in figplots
% array. Set them at (0,0,0) and set the marker
% size to the square root of the ledgMarkerSize
% (for some reason this works well for size
% comparson, not sure how acurate it is).
figplotsVid(ind) = plot3(newGraph,0,0,0,'bo','markersize',round(sqrt(ledgMarkerSize(ind)),1),'MarkerFaceColor','blue', "MarkerEdgeColor","blue");
set(figplotsVid(ind),'visible','off') % Make them invisable
end
% Create the legend at the end after all points have
% been added as we only want the first 5 points
% (the dummy invisable ones stored in figplots)
legVid = legend(newGraph, legentry);
legVid.Location = 'eastoutside'; %Display next to the colour bar
legVid.FontSize = 10; % Make font the same size as the color bar
% Gives the legend a title
title(legVid, extractedData.Properties.VariableNames(5),"FontSize",10, "FontWeight","bold");
% Stop legend from adding more things to it
% automatically
set(legVid,'AutoUpdate','off');
% Plot all the points initally really tiny to
% correctly configure the colour bar
for x = 1:size(extractedData,1)
scatter3(newGraph,extractedData{x,1},extractedData{x,2},extractedData{x,3},0.001, extractedData{x,4}, "filled");
end
% Loops through each data point and plots it. Can do
% this all in one go but this allows it to work with
% video capture.
for point = 1:size(extractedData,1)
%Plot the point
scatter3(newGraph, extractedData{point,1}, extractedData{point,2}, extractedData{point,3}, scaledData(point), extractedData{point,4}, "filled")
%Plot the line
plot3(newGraph, [extractedData{point,1} extractedData{point,1}], [extractedData{point,2} extractedData{point,2}], [lowerBound extractedData{point,3}], "Color",cmapVid(c(point),:), 'LineStyle', app.lineStyle)
% If debug mode is on, display the text
if app.ToggledebugCheckBox.Value == 1
text(newGraph, extractedData{point,1},extractedData{point,2}, extractedData{point,3}, " " + string(logicArry(point)) + ", " + string(extractedData{point,4}))
end
% Creates image name, saves it as a .jpeg with
% a good resolution, re-reads and then converts
% to a frame ready to be processed later.
fname = [app.vidImagesFile 'image' num2str(point)]; % full name of image
print(newFig,'-djpeg','-r200',fname) % save image with '-r200' resolution
I = imread([fname '.jpg']); % read saved image
F(point) = im2frame(I); % convert image to frame
end
hold(newGraph, "off")
end
end
% Removes the grid lines but keeps the box
if app.gridOff == 1
%Box only on if dimenson is > 2
if size(extractedData,2) > 2
app.GraphAxes.Box = "on";
end
app.GraphAxes.XGrid = 'off';
app.GraphAxes.YGrid = 'off';
app.GraphAxes.ZGrid = 'off';
else
app.GraphAxes.XGrid = 'on';
app.GraphAxes.YGrid = 'on';
app.GraphAxes.ZGrid = 'on';
end
if app.vid == true
% create the video writer with 2 fps, Uncompressed AVI
% prevents image quality from being lost
writerObj = VideoWriter('myVideo.avi', 'Uncompressed AVI');
writerObj.FrameRate = app.fps;
% set the seconds per image
% open the video writer
open(writerObj);
% write the frames to the video
for i=1:length(F)
% convert the image to a frame
frame = F(i) ;
writeVideo(writerObj, frame);
end
% close the writer object
close(writerObj);
app.vid = false;
end
end
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
% Load in custom made color map. First create property at the
% start with the desired name, load it in and make sure it is
% NOT a structure.
app.Blue2Red = load("Blue2Red.mat", "Blue2Red");
app.Blue2Red = app.Blue2Red.Blue2Red; %Convert from struct to array
% All avaiable types of colour maps. Can add more to end if
% adding more custom palletes
app.ColourpalletDropDown.Items = ["parula", "hsv", "hot", ...
"cool", "spring", "summer", "autumn", "winter", ...
"gray", "bone", "copper", "jet", "Blue2Red"];
% Each of the pallets points to the actual varaible containing
% the colours. Again add to the end if you want a custom one.
% Must be in same order as above.
app.ColourLinked = {parula, hsv, hot, ...
cool, spring, summer, autumn, winter, ...
gray, bone, copper, jet, app.Blue2Red};
% Predefined matlab colours
app.DefaultcolorDropDown.Items = ["yellow", "magenta", "cyan", "red", "green", "blue", "white", "black"];
% Predefined line types
app.StemstyleDropDown.Items = ["none","-","--",":","-."];
% Set defaults (defined when colorScheme etc were made)
app.ColourpalletDropDown.Value = "parula";
app.DefaultcolorDropDown.Value = app.defaultColor;
app.StemstyleDropDown.Value = app.lineStyle;
end
% Button pushed function: LoadfileButton
function LoadfileButtonPushed(app, event)
% Resets all the variables
app.reset();
% Opens the file explorer to allow the user to select an excel
% file - only files containing '.xls' will be shown.
[app.fileName, app.filePath] = uigetfile('*.xls*', 'Open Excel File');
% Predefine error check
errCheck = true;
% Start the error checking loop
while errCheck
% If no file is selected
if app.fileName == 0
app.Label.Text = "No file was selected";
break % End the error checking loop
end
% Gets the extension of the file
[~,~,extension] = fileparts(app.fileName);
% If the extension does not contain '.xls'
if ~contains(extension, '.xls')
app.Label.Text = "File type must be of the form *.xls*";
break % End the error checking loop
end
% Try loading the file into a table format, and display
% error if it cannot be loaded.
try
% Load file into table format
app.variables = readtable(app.filePath + "\" + app.fileName);
app.Label.Text = app.fileName + " loaded!";
errCheck = false; % Set error check to false
break
catch ME
app.Label.Text = "File failed to load";
break % End the error checking loop
end
end
% If the file was sucessfully loaded (and err check was set to
% false) then load the variables into the list boxes.
if errCheck == false
app.loadVariables()
end
end
% Value changed function: ExperimentListBox
function ExperimentListBoxValueChanged(app, event)
% Any different variable selected in list box will update the
% graph
app.updateGraph();
end
% Value changed function: VariableListBox
function VariableListBoxValueChanged(app, event)
% Any different variable selected in list box will update the
% graph
app.updateGraph();
end
% Value changed function: ToggledebugCheckBox
function ToggledebugCheckBoxValueChanged(app, event)
% If the debug box is toggled then update the graph
app.updateGraph();
end
% Value changed function: ColourpalletDropDown
function ColourpalletDropDownValueChanged(app, event)
% Converts the items to a string array
names = cellfun(@string, app.ColourpalletDropDown.Items);
% Finds the index of the item so that it can be used to point
% to the linked colourmap
index = find(strcmp(names, app.ColourpalletDropDown.Value));
% Use the index to select the correct color map
app.colorScheme = app.ColourLinked(index);
% Convert from cell to array
app.colorScheme = app.colorScheme{:,:};
app.updateGraph();
end
% Value changed function: DefaultcolorDropDown
function DefaultcolorDropDownValueChanged(app, event)
app.defaultColor = string(app.DefaultcolorDropDown.Value);
app.updateGraph();
end
% Value changed function: StemstyleDropDown
function StemstyleDropDownValueChanged(app, event)
app.lineStyle = string(app.StemstyleDropDown.Value);
app.updateGraph();
end
% Value changed function: InvertToggle
function InvertToggleValueChanged(app, event)
app.updateGraph();
end
% Value changed function: SizeSlider
function SizeSliderValueChanged(app, event)
app.defaultSize = app.SizeSlider.Value;
app.updateGraph();
end
% Value changed function: GridoffCheckBox
function GridoffCheckBoxValueChanged(app, event)
app.gridOff = app.GridoffCheckBox.Value;
app.updateGraph();
end
% Button pushed function: VideoButton