Copy text from a string that meets a certain condition MATLAB - matlab

i have a strings from a text file:
20130806_083642832,!AIVDM,1,1,,B,13aFeA0P00PEqQNNC4Um7Ow`2#O2,0*5E
20130806_083643032,!AIVDM,2,1,4,B,E>jN6<0W6#1WPab3bPa2#LtP0000:uoH?9Ur,0*50
i need to go through the characters and extract the date at the start then the message that starts after B, (but could also be A,) up until ,0
Any thoughts?

Ok, there are much more elegant ways to solve this, but my following example will give you a feeling on how to manipulate strings in MatLab (Which might be the thing you are having problems with). Here you go:
String='20130806_083642832,!AIVDM,1,1,,B,13aFeA0P00PEqQNNC4Um7Ow`2#O2,0*5E'
for i=1:length(String)
if(strcmp(String(i),'B')) %or strcmp(String(i),'A')
for j=i:length(String) %or "for j=length(String):i" if you meant the last 0 ;)
if(strcmp(String(j),'0'))
String2=String(i:j)
break
end
end
break
end
end
Output
String =
20130806_083642832,!AIVDM,1,1,,B,13aFeA0P00PEqQNNC4Um7Ow`2#O2,0*5E
String2 =
B,13aFeA0
Just play around with string indexing and with strcmp or strcmpi and you'll get a feeling and will be able to write much nicer expressions.
Now try extracting the date by yourself!
Hope that helps!

Without loops you could do something like this:
startString = ['20130806_083642832,!AIVDM,1,1,,B,13aFeA0P00PEqQNNC4Um7Ow`2#O2,0*5E'];
startPosition = find(startString == 'B') + 1;
if ~startPosition
startPosition = find(startString == 'A') + 1;
end
tmpMessage = startString(startPosition:end);
endPosition = find(tmpMessage == '0') - 1;
outMessage = tmpMessage(1:endPosition(1))
dateString = startString(1:8)
This gives the output:
outMessage = ,13aFeA
dateString = 20130806

Related

Matlab: how to sum fields of two equivalent structures?

I am working in Matlab. I have defined:
a(1).x=1;
a(1).y=2;
a(1).z.w=3;
a(2).x=4;
a(2).y=5;
a(2).z.w=6;
I am now trying to add the fields in the two structures a(1) and a(2) such that I get:
c.x = 5;
c.y = 7;
c.z.w = 9;
Any idea how I can do this in an elegant way? Note that in the original problem the structures have many more fields (around 50).
Thank you very much in advance!
José
Here is a solution, for any depth of struct
The code of the script (or MATLAB command)
a(1).x=1;
a(1).y=2;
a(1).z.w=3;
a(2).x=4;
a(2).y=5;
a(2).z.w=6;
c=a(1);
c = returnStruct(c, a(2));
%{
you can also sum any amount of structs
for i=2:length(a)
c=returnStruct(c, a(i));
end
%}
with the recursive function
function rs = returnStruct(s,a)
fn = fieldnames(s);
for i=1:length(fn)
if isstruct(s.(fn{i}))
s.(fn{i}) = returnStruct(s.(fn{i}), a.(fn{i}));
else
s.(fn{i}) = s.(fn{i})+a.(fn{i});
end
end
rs = s;
end
I tested it for deeper levels of structs and it worked perfectly. Maybe, you have to adapt it slightly for your case, but this should be the way to go.
Unfortunately, any function like struct2cell only converts the first level, so you need something else.
If the deepest substructure level is 2 then this code will work:
fields=fieldnames(a);
for i=1:numel(fields)
if isstruct(a(1).(fields{i}))
fields2=fieldnames(a(1).(fields{i}));
for j=1:numel(fields2)
a(3).(fields{i}).(fields2{j})= a(1).(fields{i}).(fields2{j})+a(2).(fields{i}).(fields2{j});
end
else
a(3).(fields{i})=a(1).(fields{i})+a(2).(fields{i});
end
end
You can have a simple recursive solution
function r = sumfields(s)
if isstruct(s)
for f = fieldnames(s).'
r.(f{1}) = sumfields([s.(f{1})]);
end
else
r = sum(s);
end
end

If and elseif, only the first line work?

L=1; Nx=51; PeriodicFlag=1; T=15; Nt=51;
spacedef='Pade6FirstDeriv'; casedef='LinearAdvection';
if (spacedef == 'Pade6FirstDeriv')
D1 = sparse(Pade6(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Upwind3FirstDeriv')
D1 = sparse(Upwind3(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Central4FirstDeriv')
D1 = sparse(Central4(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Central2FirstDeriv')
D1 = sparse(Central2(Nx,dx,PeriodicFlag));
else
error(sprintf('Unknown spacedef = %s',spacedef));
end
In the above code, the if section is a small segment from a function I've constructed. I'm trying to get the function to know which methods to use based on my input (spacedef). Central2, Central4, Upwind3, and Pade6 are other functions I've written. The weird thing is that when spacedef =/= to 'Pade6FirstDeriv', I would get an error stating Error using ==, Matrix dimensions must agree. I've tried swapping the order of the if loop (by placing Central4, Central2, Pade6, and Upwind3 in the first line of the loop), and it seems like only the top line of the loop will work (the elseifs are not working). I'd greatly appreciate it if anybody can help me out. Thanks!
As has been noted in the comments, this is a common error when people first start comparing strings in MATLAB, and strcmp or strcmpi is generally the solution.
However, one solution the questions links in the comments don't present, and a solution I think looks much nicer, is the switch statement:
switch (spacedef)
case('Pade6FirstDeriv')
D1 = sparse(Pade6(Nx,dx,PeriodicFlag));
case('Upwind3FirstDeriv')
D1 = sparse(Upwind3(Nx,dx,PeriodicFlag));
case('Central4FirstDeriv')
D1 = sparse(Central4(Nx,dx,PeriodicFlag));
case('Central2FirstDeriv')
D1 = sparse(Central2(Nx,dx,PeriodicFlag));
otherwise
error(sprintf('Unknown spacedef = %s',spacedef));
end
Note: if I expect others to use my code with string comparisons, I usually lower the input such that the comparison is case-insensitive, although I have not done that here.

Iterate through a lot of Structs

my Problem is the following:
I have about 300 Struct files given.
They are set up like this:
DSC_0001 has about 250 other struct files in it:
-> like this: DSC_0001.marker_1
And this one has 10 Numbers in it.
Like that:
DSC_0001.marker_1.flow_angle = 90
and now I want to iterate through all the Struct files
Something like that:
for i = 1:300
for j = 1:250
flow_angle = DSC_**i**.marker_**j**
end
end
Is there a way to do this?
I have the feeling that it could be really easy but I just can't find the solution...
I hope my question is clear enough...
Thanks for your help!
If possible don't use eval.
It depends on how your data is stored, but one possiblity is that it is in a .mat file. In that case it can be loaded using
DSC_structs = load('My_DSC_struct_file.mat');
and then you can access the values like so:
for i = 1:300
for j = 1:250
flow_angle(i,j) = DSC_structs.(['DSC_' sprintf('%04d',i)]).(['marker_' sprintf('%d',j)]);
end
end
Why avoid the eval function
Edit: You say that each struct is in a different file. That's a bit messier. I would probably do something like this to load them:
DSC_structs = cell(1,300);
for i = 1:300
%Note: I'm guess at your file names here
DSC_structs{i} = load(['DSC_' sprintf('%04d',i) '.mat'];
end
and then access the values as
DSC_structs{i}.(['DSC_' sprintf('%04d',i)]).(['marker_' sprintf('%d',j)]);
I guess this is a use case for the dreaded eval function:
for i = 1:300
for j = 1:250
eval (['flow_angle = DSC_', sprintf('%04d',i), '.marker_', num2str(j)]);
end
end
BUT NB there are 2 problems with my code above
You haven't told us where you want to store your angle, so my code doesn't :/ but you'd want something like this if you just want to store them in a matrix: eval (['flow_angle(', num2str(i), ',', num2str(j), ') = DSC_', sprintf('%04d',i), '.marker_', num2str(j)])
eval is a horrible way of doing things but you're forced to because someone saved your data in a horrible. Sort yourself out now for the future by re-saving your data in a smarter way! so something like:
.
for i = 1:300
eval ( ['DSC(', num2str(i), ') = DSC_', sprintf('%04d',i)]);
end
%// then save DCS!
And now your can iterate through this matrix of structs rather than having a 300 structs polluting your workspace and forcing you to use eval

matlab code source

how to write a program in matlab that reads a certain number of images let's say 20 for example which are saved in a given directory (C:) such that later i can use them. suppose that the images are saved by numbers. later, i am gonna use them.
I'd have the code look something like this. Assuming cell array im holds your images.
Write out:
IMG_DIR = 'C:\';
filename_root = 'image';
IMG_EXT = '.jpg';
NUM_IMAGES = 20;
for i = 1:NUM_IMAGES
imwrite(im{i}, [IMG_DIR filename_root num2str(i) IMG_EXT]);
end
Read in:
for i = 1:NUM_IMAGES
im{i} = imread([IMG_DIR filename_root num2str(i) IMG_EXT]);
end
If you don't know how many there are, you can also use ls command (works differently in Windows vs. Linux).
If you don't know, in advance, which files will be in there, but you know that they have the string in them, 'rawImage' (like 'rawImage001.jpg' etc.) you can do something like
a = dir('c:\temp');
requiredBaseFileName = 'rawImage'; % you want them to contain the substring 'rawImage'
for i = 1:length(a),
fileName = a(i).name;
if(isempty(strfind(fileName,'.jpg')) & isempty(strfind(fileName,'.png')))
continue;
end
if(isempty(strfind(fileName,requiredBaseFileName)))
continue;
end
% do your processing here
end

Switching even- and odd-indexed characters in Matlab

Using Matlab, write a function called tripFlip that takes in one string and switches each even-indexed charactar with the odd-indexed character immediately preceding it. Use iteration. Example: tripFlip('orange') ->'ronaeg'
I assume this is homework, so I won't give a complete answer. You can use double to convert a string to an array, and char to go back, if working with arrays makes the problem any easier. Otherwise, strings seem to work just like arrays in terms of indexing: s(1) gets the first character, length(s) gets the length, etc.
I agree its a homework question, and posting it here will only bite you back in the long run. But here goes:
a = 'orange';
b = '';
b(2:2:length(a))= a(1:2:end);
b(1:2:length(a))= a(2:2:end);
disp(b)
In one line:
>> input = 'orange';
>> output = input(reshape([2:2:end;1:2:end],1,[]))
output =
ronaeg
It's not a function and doesn't use iteration, but it's how you'd solve this if you were to learn Matlab.
Something like this should do the trick, perhaps you want to make it a bit more robust.
function b = TripFlip(a)
a = 'orange';
b = '';
for i = 2:2:length(a)
b=[b a(i) a(i-1)]
end