Save information associated with a text entry type
4 views (last 30 days)
Show older comments
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:
- that the first element of these blocks is "Cr2", and
- 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:
- the last element of the first line,
- the number that appears on the second line, and
- 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:
0 Comments
Accepted Answer
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
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!
More Answers (0)
See Also
Categories
Find more on Whos 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!