How to create a custom profile in matlab plots
3 Comments
Hi Sachin,
I took time out to resolve your addressed problems “would like to break the number of cycles for dynamic elements and use '...' to show continuity. However, on the time axis i would like to have the actual value instead of shortened periods by discontinuity” as mentioned in your post. From here on, you can tweak code based on your preferences. Please see my response to your mentioned comments below.
To display the actual time values on the x-axis, I had to modify the code where the time vectors are generated. Currently, the time vectors are created using the current_time variable and the duration of each phase. I had to replace this with a cumulative time approach, where you can keep track of the total time elapsed.In the modified code, I added the current_time to the time vector t before appending it to the time vector which made sure that the time values are cumulative and represent the actual time elapsed.
To break the number of cycles for dynamic elements, I had to modify the section that handles dynamic phases. Currently, the code generates a full waveform for each dynamic phase based on the specified number of cycles. In the modified code, the variable n_breaks is calculated as the difference between the number of cycles (n_cycles) and 1. This represents the number of breaks needed between the dynamic phases. The number of points per break (nr_pts_per_break) is calculated by dividing the number of points per cycle (nr_pts) by the total number of breaks plus 1. Inside the loop that generates the breaks, a new time array (t_breaks) and voltage array (v_breaks) are initialized. For each break, a new set of time and voltage points is generated and appended to the respective arrays. The current time is updated accordingly.After generating the breaks, the dynamic phases and breaks are combined by concatenating the arrays. The resulting time array (t) and voltage array (v) include the dynamic phases with breaks in between. Here is the updated code with modifications,
Vconst.val = [1, 0.85, 0.6, 0.4];
Vconst.txt = {'OCV', 'Idle', 'Mid Load', 'High Load'};
Vdyn.val = [0.8, 0.7, 0.8, 0.5, 1.5, 1];
Vdyn.txt = {'Dynamic Low', 'Dyn low trough', 'Dynamic High', 'Dyn high trough', 'SUSD', 'SUSD trough'};
% Define the order of phases and durations
order = {'OCV', 'SUSD', 'OCV', 'Mid Load', 'High Load', 'Mid Load', 'Dynamic Low', 'Mid Load', 'Dynamic High', 'OCV'}; % duration in s for Vconst elements, nr. of cycles for Vdyn elements
durations = [100, 10, 200, 100, 50, 50, 4, 50, 4, 100]; % Corresponding durations in seconds or cycles
% Initialize time and voltage vectors
time = [];
voltage = [];
current_time = 0;
% Generate time and voltage vectors
for i = 1:length(order)
phase = order{i};duration = durations(i);
if ismember(phase, {'OCV', 'Idle', 'Mid Load', 'High Load'})% Constant phases
t = current_time + (0:0.1:duration);
V_idx = find(strcmp(Vconst.txt, phase));
v = Vconst.val(V_idx) * ones(size(t));
time_act(i) = t(end);
else
% Dynamic phases
n_cycles = duration; % Number of dynamic cycles
t_dynamic_full = [];
v_dynamic_full = [];
Vdyn_idx = find(strcmp(Vdyn.txt, phase));
peak_height = Vdyn.val(Vdyn_idx);
trough_height = Vdyn.val(Vdyn_idx + 1);
nr_pts = 50;
% Calculate the number of breaks needed based on the number of cycles
n_breaks = n_cycles - 1;
for j = 1:n_cycles
t_cycle = current_time + (0:1:nr_pts);
tri_wave = sawtooth(2 * pi * (1/nr_pts) * (t_cycle - current_time), 0.5);
tri_wave = (peak_height - trough_height) * tri_wave / 2 + (peak_height + trough_height) / 2;
tri_wave(tri_wave > peak_height) = peak_height;
tri_wave(tri_wave < trough_height) = trough_height;
t_dynamic_full = [t_dynamic_full, t_cycle];
v_dynamic_full = [v_dynamic_full, tri_wave];
current_time = t_cycle(end);
end
time_act(i) = t_dynamic_full(end);
% Check if breaks are needed
if n_breaks > 0
% Calculate the number of points per break
nr_pts_per_break = floor(nr_pts / (n_breaks + 1));
% Initialize arrays for breaks
t_breaks = [];
v_breaks = [];
% Generate breaks
for k = 1:n_breaks
t_break = current_time + (0:1:nr_pts_per_break);
v_break = NaN * ones(size(t_break));
t_breaks = [t_breaks, t_break];
v_breaks = [v_breaks, v_break];
current_time = t_break(end);
end
% Combine the dynamic phases and breaks
t = [t_dynamic_full(1:nr_pts_per_break+1), t_breaks, t_dynamic_full(nr_pts_per_break+2:end)];
v = [v_dynamic_full(1:nr_pts_per_break+1), v_breaks, v_dynamic_full(nr_pts_per_break+2:end)];
else
% No breaks needed, use the full dynamic waveform
t = t_dynamic_full;
v = v_dynamic_full;
end
end
time = [time, t + current_time];
voltage = [voltage, v];
current_time = current_time + duration;
if i > 1
time_act(i) = time_act(i) + time_act(i-1);
end
end
% Plot the voltage over time
figure;
plot(time, voltage, 'LineWidth', 1.5);
xlabel('Time (s)');
ylabel('Voltage (V)');
title('User Defined Plot with Flexible Phase Order and Durations');
grid on;
ylim([0 2])
yticklabels([])
Please see attached plot.

I hope this answers your question.
Hi Sachin,
I spent time by updating your code by showing values at end of each phase and to check if there are more than 2 cycles for the last dynamic phase. However, I left all cycles shown on purpose for you to figure out rest of the code snippet and figure out adding lines of code for 2 cycles followed by '...' and finally the last cycle (something like this ^^...^ because if I do all the work, you will not be able to learn a lot about your project. In my opinion, you were looking for clues and were struggling figuring it out. Hope, I did help you out figuring out most things. Here is the updated code along with attached plot.

Vconst.val = [1, 0.85, 0.6, 0.4];
Vconst.txt = {'OCV', 'Idle', 'Mid Load', 'High Load'};
Vdyn.val = [0.8, 0.7, 0.8, 0.5, 1.5, 1];
Vdyn.txt = {'Dynamic Low', 'Dyn low trough', 'Dynamic High', 'Dyn high trough', 'SUSD', 'SUSD trough'};
% Define the order of phases and durations
order = {'OCV', 'SUSD', 'OCV', 'Mid Load', 'High Load', 'Mid Load', 'Dynamic Low', 'Mid Load', 'Dynamic High', 'OCV'}; % duration in s for Vconst elements, nr. of cycles for Vdyn elements
durations = [100, 10, 200, 100, 50, 50, 4, 50, 4, 100]; % Corresponding durations in seconds or cycles
% Initialize time and voltage vectors
time = [];
voltage = [];
current_time = 0;
% Generate time and voltage vectors
for i = 1:length(order)
phase = order{i};duration = durations(i);
if ismember(phase, {'OCV', 'Idle', 'Mid Load', 'High Load'})% Constant phases
t = current_time + (0:0.1:duration);
V_idx = find(strcmp(Vconst.txt, phase));
v = Vconst.val(V_idx) * ones(size(t));
time_act(i) = t(end);
else
% Dynamic phases
n_cycles = duration; % Number of dynamic cycles
t_dynamic_full = [];
v_dynamic_full = [];
Vdyn_idx = find(strcmp(Vdyn.txt, phase));
peak_height = Vdyn.val(Vdyn_idx);
trough_height = Vdyn.val(Vdyn_idx + 1);
nr_pts = 50;
% Calculate the number of breaks needed based on the number of cycles
n_breaks = n_cycles - 1;
for j = 1:n_cycles
t_cycle = current_time + (0:1:nr_pts);
tri_wave = sawtooth(2 * pi * (1/nr_pts) * (t_cycle - current_time), 0.5);
tri_wave = (peak_height - trough_height) * tri_wave / 2 + (peak_height + trough_height) / 2;
tri_wave(tri_wave > peak_height) = peak_height;
tri_wave(tri_wave < trough_height) = trough_height;
t_dynamic_full = [t_dynamic_full, t_cycle];
v_dynamic_full = [v_dynamic_full, tri_wave];
current_time = t_cycle(end);
endtime_act(i) = t_dynamic_full(end);
% Check if breaks are needed
if n_breaks > 0
% Calculate the number of points per break
nr_pts_per_break = floor(nr_pts / (n_breaks + 1));
% Initialize arrays for breaks
t_breaks = [];
v_breaks = [];
% Generate breaks
for k = 1:n_breaks
t_break = current_time + (0:1:nr_pts_per_break);v_break = NaN * ones(size(t_break));
t_breaks = [t_breaks, t_break];
v_breaks = [v_breaks, v_break];
current_time = t_break(end);
end
% Combine the dynamic phases and breakst = [t_dynamic_full(1:nr_pts_per_break+1), t_breaks, t_dynamic_full(nr_pts_per_break+2:end)];
v = [v_dynamic_full(1:nr_pts_per_break+1), v_breaks, v_dynamic_full(nr_pts_per_break+2:end)];
else
% No breaks needed, use the full dynamic waveform
t = t_dynamic_full;
v = v_dynamic_full;
end
end
time = [time, t + current_time];
voltage = [voltage, v];
current_time = current_time + duration;
if i > 1
time_act(i) = time_act(i) + time_act(i-1);
end
end
% Plot the voltage over time
figure;
plot(time, voltage, 'LineWidth', 1.5);
xlabel('Time (s)');
ylabel('Voltage (V)');
title('User Defined Plot with Flexible Phase Order and Durations');
grid on;
ylim([0 2])
yticklabels([])
% Modify time axis to show values at the end of each phase
xticks(time_act);
xticklabels(order);
xtickangle(45);
% Check if there are more than 2 cycles for the last dynamic phase
last_cycle_idx = find(strcmp(order, 'OCV'), 1, 'last');
if last_cycle_idx < length(time_act)
last_cycle_start = time_act(last_cycle_idx);
last_cycle_end = time_act(last_cycle_idx + 1);
last_cycle_duration = last_cycle_end - last_cycle_start;
last_cycle_ticks = linspace(last_cycle_start, last_cycle_end, last_cycle_duration * 10 + 1);
last_cycle_labels = repmat('^', 1, last_cycle_duration * 10 + 1);
xticks([xticks(1:2), last_cycle_ticks]);xticklabels([xticklabels(1:2), '...', last_cycle_labels]);
end
Please let me know if you have any further questions. I really enjoyed working on this project and learned something about ticklabels how useful they can be especially for this project. Hope, no hard feelings.
Answers (0)
Categories
Find more on Programming in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!