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

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?

 Respuesta aceptada

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 comentarios

Giuseppe
Giuseppe el 1 de Mzo. de 2022
Editada: Giuseppe el 1 de Mzo. de 2022
Thank you. I'm following your line of reasoning and I produced the following code, but I've a problem to create my data structure:
% Definition of directories 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\';
% Automatically detec .txt file names in the directories
files_Ly = dir([input_path_Fortran, '\*.txt'])
files_Ly_filtered = dir([output_path_Fortran, '\*.txt'])
% due esempi da eliminare
files_Ly.name
files_Ly_filtered.name
% Import original databases for L1 and L2 Ly. orb. respectively containing 4183 and 2171 orbits
% in a cell array
Ly_orb = cell(1,numel(files_Ly)) %pre-allocation
for i=1,numel(files_Ly)
Ly_orb = table2cell(import_Ly_orb_file(fullfile(input_path_Fortran,files_Ly(i).name),3,inf))
end
I would like to have two data structure array or cell array (one named Ly_orb and another one Ly_orb_filtered) and then access them by using for-loop with i from 1 to 2. in this way I can avoid to repeat the same code lines and I can acces my data with loops.
Any ideas?
Can you also show me an example of plot with for-loop?
I would want to get something like this:
I'm less familliar working with cell arrays, maybe something like this would work:
mytable = table(rand(4,1),rand(4,1))
mytable = 4×2 table
Var1 Var2 ________ _______ 0.13586 0.36123 0.9548 0.474 0.033967 0.21612 0.54405 0.72248
for i=1:2
Ly_orb{i} = table2array(mytable);
end
Ly_orb{1}
ans = 4×2
0.1359 0.3612 0.9548 0.4740 0.0340 0.2161 0.5440 0.7225
you can also achieve that using structure:
for i=1:2
% you can either use table2struct to keep your data organization
Ly_orb2(i).organized = table2struct(mytable);
% or table2array that could be easier to use afterward
Ly_orb2(i).arrayed = table2array(mytable);
end
Ly_orb2(1).organized
ans = 4×1 struct array with fields:
Var1 Var2
Ly_orb2(1).arrayed
ans = 4×2
0.1359 0.3612 0.9548 0.4740 0.0340 0.2161 0.5440 0.7225
Giuseppe
Giuseppe el 3 de Mzo. de 2022
Editada: Giuseppe el 3 de Mzo. de 2022
Thank you very much! I prefer the first choice (Ly_orb2(i).organized).
I have two questions:
1 - Can you tell me how to preallocate such structure?
2 - How to index the elements of a field? for example, I want to assign to a variable the 3rd element of field "period" of the second data struct (the one that has index 2 in the for-loop).
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)

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Reporting and Database Access en Centro de ayuda y File Exchange.

Productos

Versión

R2021a

Preguntada:

el 1 de Mzo. de 2022

Comentada:

el 3 de Mzo. de 2022

Community Treasure Hunt

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

Start Hunting!

Translated by