How to reduce code lines for data post-processing by using for-loops?

2 views (last 30 days)
Giuseppe
Giuseppe on 1 Mar 2022
Commented: Johan on 3 Mar 2022
Hi to everyone,
I've a livescript where I import two pairs of .txt files that only differ for a number (1 and 2):
  • Planar_Lyapunov_SE_L1.txt;
  • Planar_Lyapunov_SE_L2.txt;
  • Planar_Lyapunov_SE_L1_evenly_spaced.txt;
  • Planar_Lyapunov_SE_L2_evenly_spaced.txt.
Then I perform some operations and make two plots. My script contains duplicate variables that only differs for number mentioned above, as you can see here:
%Planar Lyapunov Orbits (SE system, L1 - L2 points)
clear all; close all; clc;
%Data import
% Definition of path names and file names
Input_path_Fortran = 'D:\OneDrive\MSc_Thesis\Projects\Planar_Lyapunov_orbits\InputFiles\';
Output_path_Fortran = 'D:\OneDrive\MSc_Thesis\Projects\Planar_Lyapunov_orbits\OutputFiles\';
filename_L1_Ly_orb = 'Planar_Lyapunov_SE_L1.txt';
filename_L1_Ly_orb_selected = 'Planar_Lyapunov_SE_L1_evenly_spaced.txt';
filename_L2_Ly_orb = 'Planar_Lyapunov_SE_L2.txt';
filename_L2_Ly_orb_selected = 'Planar_Lyapunov_SE_L2_evenly_spaced.txt';
%Import original databases for L1 and L2 Ly. orb. respectively containing 4182 and 2171 orbits
L1_Ly_orb = import_Ly_orb_file(filename_L1_Ly_orb,3,inf);
L2_Ly_orb = import_Ly_orb_file(filename_L2_Ly_orb,3,inf);
%Import filtered data containing 50 orbits quasi-evenly spaced according Jacobi constant
L1_Ly_orb_sel = import_Ly_orb_file(filename_L1_Ly_orb_selected,4,inf);
L2_Ly_orb_sel = import_Ly_orb_file(filename_L2_Ly_orb_selected,4,inf);
diff_L1 = diff(L1_Ly_orb_sel.Jacobi_constant);
diff_L2 = diff(L2_Ly_orb_sel.Jacobi_constant);
%%Plots
%L1
load("Customized_colors.mat");
% Trova un modo per trasferire le opzioni di grafica di una figura a
% un'altra senza ripetere i comandi all'interno del plot (color, marker, et..)
fig_name = figure;
plot(L1_Ly_orb.x0,L1_Ly_orb.Jacobi_constant,'.','color',my_cyan,'MarkerFaceColor'...
,my_cyan,'MarkerSize',2); hold on
plot(L1_Ly_orb_sel.x0,L1_Ly_orb_sel.Jacobi_constant,'.','color',my_red,'MarkerFaceColor'...
,my_red,'MarkerSize',8); hold on
yline(L1_Ly_orb_sel.Jacobi_constant,'color',my_red,'LineStyle',":");
grid off;
xlabel('$x_0$','interpreter','latex','fontsize',12);
ylabel('$Jacobi\ Constant$','interpreter','latex','FontSize',12);
lgd = legend('$Original\ database$','$Filtered\ database$',...
'Orientation',"vertical",'Location',"northwest");
lgd.Interpreter = 'latex';
lgd.FontSize = 10;
%Zoom on a casual portion of figure to show the equally spaced Jacobi constant values
x_min_L1 = L1_Ly_orb_sel.x0(30,1)-0.00001;
x_max_L1 = L1_Ly_orb_sel.x0(22,1)+0.00001;
indexOfInterest = (L1_Ly_orb.x0 < x_max_L1) & (L1_Ly_orb.x0 > x_min_L1);
indexOfInterest_sel = (L1_Ly_orb_sel.x0 < x_max_L1) & (L1_Ly_orb_sel.x0 > x_min_L1);
% Rectangle of area to zoom
y_min_L1 = min(L1_Ly_orb.Jacobi_constant(indexOfInterest)); % need indexofInterest for this
y_max_L1 = max(L1_Ly_orb.Jacobi_constant(indexOfInterest));
width_L1 = x_max_L1-x_min_L1;
height_L1 = y_max_L1-y_min_L1;
ROI_Position_L1 = [x_min_L1 y_min_L1 width_L1 height_L1];
rectangle('Position',ROI_Position_L1,'EdgeColor','k','LineWidth',0.5); hold on
% Mini-plot inside figure
axes('position',[.63 .16 .25 .25])
box on % put box around new pair of axes
plot(L1_Ly_orb.x0(indexOfInterest),L1_Ly_orb.Jacobi_constant(indexOfInterest),...
'.','color',my_cyan,'MarkerFaceColor',my_cyan,'MarkerSize',2); hold on
plot(L1_Ly_orb_sel.x0(indexOfInterest_sel),L1_Ly_orb_sel.Jacobi_constant(indexOfInterest_sel),...
'.','color',my_red,'MarkerFaceColor',my_orange,'MarkerSize',8); hold on
yline(L1_Ly_orb_sel.Jacobi_constant(indexOfInterest_sel),'color',my_red,'LineStyle',":");
axis tight
% Option to center better the curves inside the plot window
% x_lim = xlim;
% y_lim = ylim;
% xlim([x_lim(1)-0.00*norm(x_lim) x_lim(2)+0.0*norm(x_lim)]);
% ylim([y_lim(1)-0.00*norm(y_lim) y_lim(2)+0.12*norm(y_lim)]);
set(gcf,'position',[278.6, 0.2, 600, 400]); %aspect ratio 3/2
exportgraphics(fig_name,'data.pdf'); %salva in pdf
%% L2
fig_name2 = figure;
plot(L2_Ly_orb.x0,L2_Ly_orb.Jacobi_constant,'.','color',my_cyan,'MarkerFaceColor'...
,my_cyan,'MarkerSize',2); hold on
plot(L2_Ly_orb_sel.x0,L2_Ly_orb_sel.Jacobi_constant,'.','color',my_red,'MarkerFaceColor'...
,my_red,'MarkerSize',8); hold on
yline(L2_Ly_orb_sel.Jacobi_constant,'color',my_red,'LineStyle',":");
grid off;
xlabel('$x_0$','interpreter','latex','fontsize',12);
ylabel('$Jacobi\ Constant$','interpreter','latex','FontSize',12);
lgd = legend('$Original\ database$','$Filtered\ database$',...
'Orientation',"vertical",'Location',"northwest");
lgd.Interpreter = 'latex';
lgd.FontSize = 10;
%Zoom on a casual portion of figure to show the equally spaced Jacobi constant values
x_min_L2 = L2_Ly_orb_sel.x0(30,1)-0.00001;
x_max_L2 = L2_Ly_orb_sel.x0(22,1)+0.00001;
indexOfInterest = (L2_Ly_orb.x0 < x_max_L2) & (L2_Ly_orb.x0 > x_min_L2);
indexOfInterest_sel = (L2_Ly_orb_sel.x0 < x_max_L2) & (L2_Ly_orb_sel.x0 > x_min_L2);
% Rectangle of area to zoom
y_min_L2 = min(L2_Ly_orb.Jacobi_constant(indexOfInterest)); % need indexofInterest for this
y_max_L2 = max(L2_Ly_orb.Jacobi_constant(indexOfInterest));
width_L2 = x_max_L2-x_min_L2;
height_L2 = y_max_L2-y_min_L2;
ROI_Position_L2 = [x_min_L2 y_min_L2 width_L2 height_L2];
rectangle('Position',ROI_Position_L2,'EdgeColor','k','LineWidth',0.5); hold on
% Mini-plot inside figure
axes('position',[.63 .16 .25 .25])
box on % put box around new pair of axes
plot(L2_Ly_orb.x0(indexOfInterest),L2_Ly_orb.Jacobi_constant(indexOfInterest),...
'.','color',my_cyan,'MarkerFaceColor',my_cyan,'MarkerSize',2); hold on
plot(L2_Ly_orb_sel.x0(indexOfInterest_sel),L2_Ly_orb_sel.Jacobi_constant(indexOfInterest_sel),...
'.','color',my_red,'MarkerFaceColor',my_orange,'MarkerSize',8); hold on
yline(L2_Ly_orb_sel.Jacobi_constant(indexOfInterest_sel),'color',my_red,'LineStyle',":");
axis tight
% Option to center better the curves inside the plot window
% x_lim = xlim;
% y_lim = ylim;
% xlim([x_lim(1)-0.00*norm(x_lim) x_lim(2)+0.0*norm(x_lim)]);
% ylim([y_lim(1)-0.00*norm(y_lim) y_lim(2)+0.12*norm(y_lim)]);
set(gcf,'position',[278.6, 0.2, 600, 400]); %aspect ratio 3/2
exportgraphics(fig_name2,'data2.pdf'); %salva in pdf
All files necessary to run this code are attached to this question.
My question is: can you show me a way to avoid using duplicate variables whose names only differ for a number?
So I would want to get a shorter script. The idea is to use loop-cycles and so use once the variables indexed for 1 and 2 and so to halve the length of my script.
Can you help me, please?

Accepted Answer

Johan
Johan on 1 Mar 2022
You can use structure to organize your data and simplify your analysis. For example you can define the path of the file you want to import in a cell array and loop over the cell array to import your data in a structure that you can reference using string variable:
names = {'data1','data2','data3','data4'};
for i = 1:length(names)
mydata.(names{i}) = rand(1);
end
mydata
mydata = struct with fields:
data1: 0.1582 data2: 0.6473 data3: 0.6244 data4: 0.6384
  4 Comments
Johan
Johan on 3 Mar 2022
You can find a lot of helpful example in the help page for structure.
Assuming you know the name of your data structure beforhand you can try the code below. Note that it does not appear to change anything in term of computation speed.... Maybe there is a better way to do it but I don't know it
n = 1000;
mytable = table(rand(250),rand(250));
timer = zeros(n,2);
for indexloop = 1:n
%timing with prealocation
tic
substruct = struct('Var1',[],'Var2',[]);
mystruct(1:2) = struct('data',substruct);
for index=1:2
mystruct(index).data = table2struct(mytable)';
end
timer(indexloop,1) = toc;
%timing wihtout prealocation
tic
for index=1:2
mystruct2(index).data = table2struct(mytable)';
end
timer(indexloop,2) = toc;
end
mean(timer)
ans = 1×2
0.0035 0.0036
plot(timer)

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!