How to create a custom profile in matlab plots

1 view (last 30 days)
Sachin Hegde
Sachin Hegde on 24 Jul 2024
Edited: Umar on 25 Jul 2024
Hello Everyone,
I am trying to create a profile based on user defined inputs. The profile consists of different modes each having a certain duration and order as defined by the user.
I have uploaded a picture which shows how i want the profile to look like.
Additionally i have coded to some extent, but i am struggling to get it right.
Also i would like to break the number of cycles for dynamic elements and use '...' to show continuity. However, on th etime axis i would like to have the actual value instead of shortened periods by discontinuity.
I kindly request for support and i thank you in advance.
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);
t = current_time + (0:0.1:duration);
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;
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);
if n_cycles > 3
t_dynamic_1 = t_dynamic_full(1:nr_pts*2+2);
v_dynamic_1 = v_dynamic_full(1:nr_pts*2+2);
t_dynamic_2 = t_dynamic_full(nr_pts*3+3:nr_pts*4+4);
v_dynamic_2 = v_dynamic_full(nr_pts*3+3:nr_pts*4+4);
t_continuity = t_dynamic_full(nr_pts*2+4:nr_pts*3+2);
v_continuity = NaN * ones(size(t_continuity));
t = [t_dynamic_1, t_continuity, t_dynamic_2];
v = [v_dynamic_1, v_continuity, v_dynamic_2];
else
t = t_dynamic_full;
v = v_dynamic_full;
end
end
time = [time, t];
voltage = [voltage, v];
current_time = t(end);
if i>1
time_act(i) = time_act(i)+time_act(i-1);
else
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([])
  3 Comments
Sachin Hegde
Sachin Hegde on 25 Jul 2024
Hello Umar,
First of all thank you. But i think there was some misunderstanding. For the dynamic cycles i do not want to have all the cycles shown (attached figure in the original post shows how i want it). I want to only show 2 cycles followed by '...' and finally the last cycle (something like this ^^...^). I need time axis to just show the values at the end of each phase.
Umar
Umar on 25 Jul 2024
Edited: Umar on 25 Jul 2024

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);
        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([])

% 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.

Sign in to comment.

Answers (0)

Categories

Find more on Graphics Object Programming in Help Center and File Exchange

Products


Release

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!