Skip to content

Commit e7e7b36

Browse files
authored
Merge pull request #156 from ImperialCollegeLondon/task/graphics-improvements
task: Graphics improvements
2 parents ad8334a + e32d86f commit e7e7b36

File tree

6 files changed

+114
-8
lines changed

6 files changed

+114
-8
lines changed

resources/release-notes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@
44

55
## Software
66

7+
- (All) Add support for showing multiple lines in a stacked plot
8+
- (All) Allow specifying `LegendOrientation` for axes that support legends
79
- (HelioSwarm) Add support for `hs-mag` v2.0.0 artifacts
10+
- (IMAP) Fix issue in field view where events for a sensor with no data are still being shown

src/mission/imap/+mag/+imap/+view/Field.m

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,20 @@ function visualize(this)
122122
error("Unrecognized event ""%s"".", e);
123123
end
124124

125+
if ~primary.HasData
126+
ed(1:2) = [];
127+
end
128+
129+
if ~secondary.HasData
130+
ed(end-1:end) = [];
131+
end
132+
125133
eventData = [eventData, ed]; %#ok<AGROW>
126134
end
127135
end
128136

129137
function [numHK, hkData] = getHKData(this, pwrHK, primary, secondary, primarySensor, secondarySensor)
130-
138+
131139
numHK = 0;
132140
hkData = {};
133141

@@ -139,9 +147,9 @@ function visualize(this)
139147
hkData = [hkData, {pwrHK, ...
140148
mag.graphics.style.Default(Title = compose("%s & ICU Temperatures", primarySensor), YLabel = this.TLabel, Legend = [primarySensor, "ICU"], Charts = mag.graphics.chart.Plot(YVariables = [primarySensor, "ICU"] + "Temperature"))}];
141149
end
142-
150+
143151
if ~isempty(secondary) && secondary.HasData
144-
152+
145153
numHK = 1;
146154
hkData = [hkData, {pwrHK, ...
147155
mag.graphics.style.Default(Title = compose("%s & ICU Temperatures", secondarySensor), YLabel = this.TLabel, YAxisLocation = "right", Legend = [secondarySensor, "ICU"], Charts = mag.graphics.chart.Plot(YVariables = [secondarySensor, "ICU"] + "Temperature"))}];

src/visualize/+mag/+graphics/+chart/Stackedplot.m

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,25 @@
4242
error("Mismatch in number of colors for number of plots.");
4343
end
4444

45+
% Check if layout already has a stack layout.
46+
existingGraphics = layout.Children;
47+
48+
if isempty(existingGraphics) || ~isequal(existingGraphics(1).Type, "tiledlayout")
49+
stackLayout = tiledlayout(layout, Ny, 1, TileSpacing = "tight", Padding = "tight", Layout = axes.Layout);
50+
else
51+
stackLayout = existingGraphics(1);
52+
end
53+
4554
% Create custom stacked plot.
4655
graph = matlab.graphics.chart.primitive.Line.empty(0, Ny);
47-
stackLayout = tiledlayout(layout, Ny, 1, TileSpacing = "tight", Padding = "tight", Layout = axes.Layout);
4856

4957
for y = 1:Ny
5058

51-
ax = nexttile(stackLayout);
59+
ax = nexttile(stackLayout, y);
60+
61+
hold(ax, "on");
62+
resetAxesHold = onCleanup(@() hold(ax, "off"));
63+
5264
graph(y) = plot(ax, xData, yData(:, y), this.MarkerStyle{:}, this.LineCustomization{:}, Color = this.Colors(y, :));
5365

5466
if this.EventsVisible && ~isempty(data.Properties.Events)

src/visualize/+mag/+graphics/+mixin/LegendSupport.m

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
Legend (1, :) string = string.empty()
77
% LEGENDLOCATION Location of legend.
88
LegendLocation (1, 1) string = "best"
9+
% LEGENDORIENTATION Orientation of legend.
10+
LegendOrientation (1, 1) string = "vertical"
911
end
1012

1113
methods (Access = protected)
@@ -17,7 +19,7 @@
1719
if isempty(this.Legend)
1820
l = matlab.graphics.illustration.Legend.empty();
1921
else
20-
l = legend(axes, this.Legend, Location = this.LegendLocation);
22+
l = legend(axes, this.Legend, Location = this.LegendLocation, Orientation = this.LegendOrientation);
2123
end
2224
end
2325
end

src/visualize/+mag/+graphics/+style/Stackedplot.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
arguments
1919
options.?mag.graphics.style.Stackedplot
20-
options.Charts (1, 1) mag.graphics.chart.Stackedplot
20+
options.Charts (1, :) mag.graphics.chart.Stackedplot
2121
options.LegendLocation (1, 1) string {mustBeMember(options.LegendLocation, ["north", "south", "east", "west"])} = "south"
2222
end
2323

@@ -53,7 +53,7 @@
5353

5454
if ~isempty(this.YLabels)
5555

56-
for i = 1:numel(axes)
56+
for i = 1:numel(this.YLabels)
5757
l(i) = ylabel(axes(i), this.YLabels(i));
5858
end
5959
end

tests/unit/visualize/chart/tStackedplot.m

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,87 @@
88

99
methods (Test)
1010

11+
% Test that stackedplot charts can view more than one line per
12+
% axis.
13+
function stackedplotWithMultipleLines(testCase)
14+
15+
% Set up.
16+
data = testCase.createTestDataWithEvents(SetDuration = false, SetEndTime = false);
17+
18+
chart1 = mag.graphics.chart.Stackedplot(YVariables = ["A", "B", "C"]);
19+
chart2 = mag.graphics.chart.Stackedplot(YVariables = ["C", "A", "B"]);
20+
21+
% Exercise.
22+
f = mag.graphics.visualize(data, mag.graphics.style.Stackedplot(Charts = [chart1, chart2]));
23+
testCase.addTeardown(@() close(f));
24+
25+
% Verify.
26+
% The chart should only return the main objects, but the figure
27+
% should also show two vertical lines per plot.
28+
testCase.assertTrue(isvalid(f), "Figure should be valid.");
29+
30+
tl = f.Children.Children(1);
31+
testCase.assertClass(tl, "matlab.graphics.layout.TiledChartLayout", "Child should be a tiled layout.");
32+
33+
axes = mag.test.getAllAxes(tl);
34+
graph = [axes.Children];
35+
36+
testCase.assertSize(graph, [2, 3], "Number of graphs should match expectation.");
37+
testCase.assertClass(graph, "matlab.graphics.chart.primitive.Line", "Graphs should be lines.");
38+
39+
testCase.verifyEqual(graph(1, 1).YData, data.B', "Graph data should match.");
40+
testCase.verifyEqual(graph(1, 2).YData, data.A', "Graph data should match.");
41+
testCase.verifyEqual(graph(1, 3).YData, data.C', "Graph data should match.");
42+
testCase.verifyEqual(graph(2, 1).YData, data.C', "Graph data should match.");
43+
testCase.verifyEqual(graph(2, 2).YData, data.B', "Graph data should match.");
44+
testCase.verifyEqual(graph(2, 3).YData, data.A', "Graph data should match.");
45+
end
46+
47+
% Test that multiple stackedplot can be independent of each other.
48+
function multipleIndependentStackedplots(testCase)
49+
50+
% Set up.
51+
data = testCase.createTestDataWithEvents(SetDuration = false, SetEndTime = false);
52+
53+
chart1 = mag.graphics.chart.Stackedplot(YVariables = ["A", "B", "C"]);
54+
chart2 = mag.graphics.chart.Stackedplot(YVariables = ["C", "A", "B"]);
55+
56+
% Exercise.
57+
f = mag.graphics.visualize(data, [mag.graphics.style.Stackedplot(Charts = chart1), mag.graphics.style.Stackedplot(Charts = chart2)]);
58+
testCase.addTeardown(@() close(f));
59+
60+
% Verify.
61+
% The chart should only return the main objects, but the figure
62+
% should also show two vertical lines per plot.
63+
testCase.assertTrue(isvalid(f), "Figure should be valid.");
64+
65+
tl1 = f.Children.Children(1);
66+
testCase.assertClass(tl1, "matlab.graphics.layout.TiledChartLayout", "Child should be a tiled layout.");
67+
68+
axes1 = mag.test.getAllAxes(tl1);
69+
graph1 = [axes1.Children];
70+
71+
testCase.assertSize(graph1, [1, 3], "Number of graphs should match expectation.");
72+
testCase.assertClass(graph1, "matlab.graphics.chart.primitive.Line", "Graphs should be lines.");
73+
74+
testCase.verifyEqual(graph1(1).YData, data.B', "Graph data should match.");
75+
testCase.verifyEqual(graph1(2).YData, data.A', "Graph data should match.");
76+
testCase.verifyEqual(graph1(3).YData, data.C', "Graph data should match.");
77+
78+
tl2 = f.Children.Children(3);
79+
testCase.assertClass(tl2, "matlab.graphics.layout.TiledChartLayout", "Child should be a tiled layout.");
80+
81+
axes2 = mag.test.getAllAxes(tl2);
82+
graph2 = [axes2.Children];
83+
84+
testCase.assertSize(graph2, [1, 3], "Number of graphs should match expectation.");
85+
testCase.assertClass(graph2, "matlab.graphics.chart.primitive.Line", "Graphs should be lines.");
86+
87+
testCase.verifyEqual(graph2(1).YData, data.C', "Graph data should match.");
88+
testCase.verifyEqual(graph2(2).YData, data.B', "Graph data should match.");
89+
testCase.verifyEqual(graph2(3).YData, data.A', "Graph data should match.");
90+
end
91+
1192
% Test that instantaneous events are correctly displayed on the
1293
% stackedplot.
1394
function instantaneousEvents(testCase)

0 commit comments

Comments
 (0)