Save information associated with a text entry type

3 views (last 30 days)
Dear all
I am attaching a file called "exchange.txt" to this post. From line 46, you can see that blocks of entries like the following appear:
Cr2 Cr4 ( 0, 0, 0) 0.2393 ( 0.000, 0.000, 6.549) 6.549
J_iso: 0.2393
[Testing!] Jprime: 0.825, B: -0.328
[Testing!] DMI: (-0.0000 -0.0000 -0.0732)
[Testing!]J_ani:
[[-0.07 -0. 0. ]
[-0. -0.07 0. ]
[ 0. 0. -0.656]]
which are separated by dashed lines. Interestingly, as it can be seen in the aforementioned file, the last element of the first line of these blocks is a number that is equal to or greater than the equivalent one of the previous block, if such a thing exists.
My goal is to save some information from every text blocks that meet:
  1. that the first element of these blocks is "Cr2", and
  2. that the second element of these blocks is "Cr3" or "Cr4".
So whenever these conditions are met, I would like to be able to store the following information in different columns on the same row:
  1. the last element of the first line,
  2. the number that appears on the second line, and
  3. the three numbers that appear on the third line,
so that each line of the created variable has as many lines as the number of times conditions 1. and 2. above are verified, and five columns. In the text block I put above as an example, the information that would be stored would be: 6.549, 0.2393, 0, 0, -0.0732.
I asked two similar questions which were kindly answered by user @Stephen23:

Accepted Answer

Aastha
Aastha on 20 Sep 2024
As I understand, you want to store the information from every text block that that meet the constraints specified by you in different columns of the same row.
You may refer to the steps mentioned below to do so:
1. First, you can read the exchange.txt into memory, split it into lines, and trim the lines to discard unnecessary content. This can be done using the following code snippet:
file_content = fileread('exchange.txt');
lines = transpose(strsplit(file_content, '\n'));
lines = lines(45:end);
block_seperator = '----------------------------------------------------------------------------------------';
lines(size(lines,1)+1) = {block_seperator};
block_size = 9;
blocks = {};
num_blocks = 0;
You may refer to MathWorks Documentation for more information on strsplit” function. Here is the link to it:
2. Next, from visual inspection of the file it can be observed that the blocks are nine lines long. You can use this to separate the lines into blocks and store them in a cell array. This can be done as follows:
line_idx = 1;
while(line_idx < size(lines,1))
    num_blocks = num_blocks+1;
    blocks{num_blocks} = lines(line_idx:line_idx+block_size);
    line_idx = line_idx + block_size;
end
blocks = transpose(blocks);
3.You can iterate through the blocks using a for loop, extract information corresponding to the parameters “i”, “j”, “R”, “J_iso(meV)”, “vector”, “distance”,” J_iso”, “J_prim”, “DMI” and “J_ani”, and store these parameters separately it in a MATLAB struct data structure. These can then be accessed using dot indexing.
blocks_struct = {};
for block_idx = 1:size(blocks,1)
    block = blocks{block_idx};
    % create the block struct
    block{2} = strrep(block{2}, '( ', '(');
    block{2} = strrep(block{2}, '( ', '(');
    block{2} = strrep(block{2}, ' )', ')');
    first_line_elements = strsplit(block{2}, ' ');
    block_struct.i = first_line_elements{2};
    block_struct.j = first_line_elements{3};
    block_struct.R = [first_line_elements{4}, first_line_elements{5}, first_line_elements{6}];
    block_struct.J_iso_meV = first_line_elements{7};
    block_struct.vector = [first_line_elements{8}, first_line_elements{9}, first_line_elements{10}];
    block_struct.distance = first_line_elements{11};
    second_line_elements = strsplit(block{3},':');
    block_struct.J_iso = second_line_elements{2};
    third_line_elements = strsplit(block{4},':');
    block_struct.J_prime = strsplit(third_line_elements{2},',');
    block_struct.J_prime = block_struct.J_prime{1};
    block_struct.B = third_line_elements{3};
    fourth_line_elements = strsplit(block{5},':');
    block_struct.DMI = fourth_line_elements{2};
    block_struct.J_ani = {block{7}(2:end),block{8},block{9}(1:end-2)};
    blocks_struct{block_idx} = block_struct;
end
blocks_struct = transpose(blocks_struct);
For more information on “strrep” function, refer to the link of MathWorks documentation mentioned below:
4. Subsequently, you can iterate through the individual blocks which satisfy the constraints of “i” is “Cr2” and “j” is either “Cr3” or “Cr4”, and then store the distance, J_iso, and DMI values in a cell array. This can be accomplished using the following code snippet:
stored_info = {};
cnt = 1;
for block_idx = 1:size(blocks_struct,1)
    block = blocks_struct{block_idx};
    if block.i == 'Cr2'
        if block.j == 'Cr3' | block.j == 'Cr4'
            stored_info{cnt}={block.distance, block.J_iso, block.DMI};
            disp(stored_info{cnt});
            cnt = cnt + 1;
        end
    end
end
In this way, you can store the required information.
I hope this is helpful!
  2 Comments
Roderick
Roderick on 20 Sep 2024
Hi @Aastha, thank you very much! It just worked great for that single exchange file as long as I changed while(line_idx < size(lines,1)) to while(line_idx < size(lines,1)-1). I do not know if it is the same for you. Now, I am trying to use this approach for different exchange files in different folders, as follows, according to your approach:
clc;
clear all;
close all force;
Initial_Directory=pwd;
%% Let's define the necessary folders
Sliding_Text={'0.0' '0.1' '0.2' '0.3' '0.4' '0.5' '0.6' '0.7' '0.8' '0.9' '1.0'};
%% Let's characterize the interlayer exchange data centered at Cr2
cnt=1;
for i=0:9
for j=1:length(Sliding_Text)
% Let's change the folder
cd(strcat(Initial_Directory,'\slide_a0.',num2str(i),'\0.',num2str(i),'_',Sliding_Text{j},'\TB2J\TB2J_results'));
% Let's upload the relevant file
file_content=fileread('exchange.out');
lines=transpose(strsplit(file_content,'\n'));
lines=lines(45:end);
block_seperator='----------------------------------------------------------------------------------------';
lines(size(lines,1)+1)={block_seperator};
block_size=9;
blocks={};
num_blocks=0;
line_idx=1;
while(line_idx<size(lines,1))
num_blocks=num_blocks+1;
blocks{num_blocks}=lines(line_idx:line_idx+block_size);
line_idx=line_idx+block_size;
end
blocks=transpose(blocks);
blocks_struct={};
for block_idx=1:size(blocks,1)
block=blocks{block_idx};
% Create the block struct
block{2}=strrep(block{2},'( ','(');
block{2}=strrep(block{2},'( ','(');
block{2}=strrep(block{2},' )',')');
first_line_elements=strsplit(block{2},' ');
block_struct.i=first_line_elements{2};
block_struct.j=first_line_elements{3};
block_struct.R=[first_line_elements{4},first_line_elements{5},first_line_elements{6}];
block_struct.J_iso_meV=first_line_elements{7};
block_struct.vector=[first_line_elements{8},first_line_elements{9},first_line_elements{10}];
block_struct.distance=first_line_elements{11};
second_line_elements=strsplit(block{3},':');
block_struct.J_iso=second_line_elements{2};
third_line_elements=strsplit(block{4},':');
block_struct.J_prime=strsplit(third_line_elements{2},',');
block_struct.J_prime=block_struct.J_prime{1};
block_struct.B=third_line_elements{3};
fourth_line_elements=strsplit(block{5},':');
block_struct.DMI=fourth_line_elements{2};
block_struct.J_ani={block{7}(2:end),block{8},block{9}(1:end-2)};
blocks_struct{block_idx}=block_struct;
end
blocks_struct=transpose(blocks_struct);
for block_idx=1:size(blocks_struct,1)
block=blocks_struct{block_idx};
if block.i=='Cr2'
if block.j=='Cr3' | block.j=='Cr4'
stored_info(cnt,1)=str2num(block.distance);
stored_info(cnt,2:4)=sscanf(block.vector,'(%f,%f,%f)');
stored_info(cnt,5)=str2num(block.J_iso);
stored_info(cnt,6:8)=sscanf(block.DMI,' ( %f %f %f) ');
cnt=cnt+1;
end
end
end
clear block block_idx block_seperator block_size block_struct blocks blocks_struct file_content first_line_elements line_idx lines num_blocks second_line_elements third_line_elements
end
end
but I received the following error message, in the same line that the comment that I forwarded you before:
Index exceeds the number of array elements. Index must not exceed 790.
Error in Interlayer_Exchange_Centered_at_Cr2 (line 25)
blocks{num_blocks}=lines(line_idx:line_idx+block_size);
Any ideas?
Aastha
Aastha on 23 Sep 2024
The error is saying that the lines variable is only 790 lines long but inside the while loop in the line
lines(line_idx:line_idx+block_size)
is accessing values of the lines array with indices more than 790.
Some possible things you can do to fix this is are as follows:
  • You can use a breakpoint at the line which is in error to see during the last few blocks why is the code accessing values out of bounds. Once you have confirmed the reason, you can stop the access by adding an if condition to stop the while loop.
  • This can also be done by changing the while loop condition to "while (line_idx<size(lines,1)-block_size)". This will ensure that the "line_idx+block_size" is always less than the "size(lines,1)".
Please note that my answer was tailored to the file you attached. If the file changes, you might need to do some minor tweaks.
I hope this helps!

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!