The assignment is
You are testing a functional near infrared (fNIR) device and
measuring how well each subject is able to control the computer mouse using
it. Write a function getcogdata that returns the requested category for
the requested user id. If the requested user does not exist, return an empty
matrix. If no user is requested, return a
cell array of values for all users.
My code is as follows
function output=getcogdata(cat,id)
info=struct('id',{'33','10','48','41'},'name',{'Joe','Sally','Harry','Ann'},...
'age',{'27','25','23','19'},...
'height',{'5.9','6.1','5.8','6.0'},'score',{'9,5','9.3','9.7','9.4'});
if id=='33'
id=1;
elseif id=='10'
id=2;
elseif id=='48'
id=3;
else id=='41'
id=4;
end
output=info(id).(cat)
end
My code works for when measurement and user are specified but I can't figure out how to code for if the user doesn't exist or if no user is requested. I tried not exist(id) I get an error. Is there a way I can use not exist?
Matlab's exist function will tell you if something is known to the current Matlab instance. It won't tell you if a particular value is present.
Your task is probably a little bit more complex than you originally thought but you can accomplish it with a mixture of strcmp, and any.
First, we convert the ids in info to a cell array with
{info.id}
now we can use strcmp to compare them against id
strcmp(id, {info.id})
Finally, we can use any to tell us if any of the values in {info.id} are equal to id. So putting this all together we get
>> info = struct('id',{'33','10','48','41'});
>> id = '33';
>> any(strcmp(id, {info.id}))
ans =
1
We can also this to find the index of id in {info.id} and do away with the if statements in your question by using find instead of any
>> id = '10'; % Present in index 2 - Output should be 2
>> find(strcmp(id, {info.id}))
ans =
2
To answer your final question about not passing the id to getcogdata you can do this using nargin
function output = getcogdata(cat,id)
if (nargin < 2)
fprintf(1, 'No id passed to getcogdata()\n');
end
end
nargin will tell you how many arguments were passed to the function getcogdata.
Thanks to #AndrasDeak for teaching me Matlab's strcmp is much better than the C version I had been assuming it was similar to!
Note: Always read the manual!
Related
The related problem comes from the power Grid in Germany. I have a network of substations, which are connected according to the Lines. The shortest way from point A to B was calculated using the graphshortestpath function. The result is a path with the used substation ID's. I am interested in the Line ID's though, so I have written a sequential code to figure out the used Line_ID's for each path.
This algorithm uses two for loops. The first for-loop to access the path from a cell array, the second for-loop looks at each connection and searches the Line_ID from the array.
Question: Is there a better way of coding this? I am looking for the Line_ID's, graphshortestpath only returns the node ID's.
Here is the main code:
for i = i_entries
path_i = LKzuLK_path{i_entries};
if length(path_i) > 3 %If length <=3 no lines are used.
id_vb = 2:length(path_i) - 2;
for id = id_vb
node_start = path_i(id);
node_end = path_i(id+1);
idx_line = find_line_idx(newlinks_vertices, node_start, ...
node_end);
Zuordnung_LKzuLK_pathLines(ind2sub(size_path,i),idx_line) = true;
end
end
end
Note: The first and last enrty of path_i are area ID's, so they are not looked upon for the search for the Line_ID's
function idx_line = find_line_idx(newlinks_vertices, v_id_1, v_id_2)
% newlinks_vertices includes the Line_ID, and then the two connecting substations
% Mirror v_id's in newlinks_vertices:
check_links = [newlinks_vertices; newlinks_vertices(:,1), newlinks_vertices(:,3), newlinks_vertices(:,2)];
tmp_dist1 = find(check_links(:,2) == v_id_1);
tmp_dist2 = find(check_links(tmp_dist1,3) == v_id_2,1);
tmp_dist3 = tmp_dist1(tmp_dist2);
idx_line = check_links(tmp_dist3,1);
end
Note: I have already tried to shorten the first find-search routine, by indexing the links list. This step will return a short list with only relevant entries of the links looked upon. That way the algorithm is reduced of the first and most time consuming find function. The result wasn't much better, the calculation time was still at approximately 7 hours for 401*401 connections, so too long to implement.
I would look into Dijkstra's algorithm to get a faster implementation. This is what Matlab's graphshortestpath uses by default. The linked wiki page probably explains it better than I ever could and even lays it out in pseudocode!
Round 2: Picking out leaders in an email
Alrighty, so my next problem is trying to figure out who the leader is in a project. In order to determine this, we are given an email and have to find who says "Do you want..." (capitalization may vary). I feel like my code should work for the most part, but I really have an issue figuring out how to correctly populate my cell array. I can get it to create the cell array, but it just puts the email in it over over again. So each cell is basically the name.
function[Leader_Name] = teamPowerHolder(email)
email = fopen(email, 'r'); %// Opens my file
lines = fgets(email); %// Reads the first line
conversations = {lines}; %// Creates my cell array
while ischar(lines) %// Populates my cell array, just not correct
Convo = fgets(email);
if Convo == -1 %// Prevents it from just logging -1 into my cell array like a jerk
break; %// Returns to function
end
conversations = [conversations {lines}]; %// Populates my list
end
Sentences = strfind(conversations,'Do you want'); %// Locates the leader position
Leader_Name = Sentences{1}; %// Indexes that position
fclose(email);
end
What I ideally need it to do is find the '/n' character (hence why I used fgets) but I'm not sure how to make it do that. I tried to have my while loop be like:
while lines == '/n'
but that's incorrect. I feel like I know how to do the '/n' bit, I just can't think of it. So I'd appreciate some hints or tips to do that. I could always try to strsplit or strtok the function, but I need to then populate my cell array so that might get messy.
Please and thanks for help :)
Test Case:
Anna: Hey guys, so I know that he just assigned this project, but I want to go ahead and get started on it.
Can you guys please respond and let me know a weekly meeting time that will work for you?
Wiley: Ummmmm no because ain't nobody got time for that.
John: Wiley? What kind of a name is that? .-.
Wiley: It's better than john. >.>
Anna: Hey boys, let's grow up and talk about a meeting time.
Do you want to have a weekly meeting, or not?
Wiley: I'll just skip all of them and not end up doing anything for the project anyway.
So I really don't care so much.
John: Yes, Anna, I'd like to have a weekly meeting.
Thank you for actually being a good teammate and doing this. :)
out2 = teamPowerHolder('teamPowerHolder_convo2.txt')
=> 'Anna'
The main reason why it isn't working is because you're supposed to update the lines variable in your loop, but you're creating a new variable called Convo that is updating instead. This is why every time you put lines in your cell array, it just puts in the first line repeatedly and never quits the loop.
However, what I would suggest you do is read in each line, then look for the : character, then extract the string up until the first time you encounter this character minus 1 because you don't want to include the actual : character itself. This will most likely correspond to the name of the person that is speaking. If we are missing this occurrence, then that person is still talking. As such, you would have to keep a variable that keeps track of who is still currently talking, until you find the "do you want" string. Whoever says this, we return the person who is currently talking, breaking out of the loop of course! To ensure that the line is case insensitive, you'll want to convert the string to lower.
There may be a case where no leader is found. In that case, you'll probably want to return the empty string. As such, initialize Leader_Name to the empty string. In this case, that would be []. That way, should we go through the e-mail and find no leader, MATLAB will return [].
The logic that you have is pretty much correct, but I wouldn't even bother storing stuff into a cell array. Just examine each line in your text file, and keep track of who is currently speaking until we encounter a sentence that has another : character. We can use strfind to facilitate this. However, one small caveat I'll mention is that if the person speaking includes a : in their conversation, then this method will break.
Judging from the conversation that I'm seeing your test case, this probably won't be the case so we're OK. As such, borrowing from your current code, simply do this:
function[Leader_Name] = teamPowerHolder(email)
Leader_Name = []; %// Initialize leader name to empty
name = [];
email = fopen(email, 'r'); %// Opens my file
lines = fgets(email); %// Reads the first line
while ischar(lines)
% // Get a line in your e-mail
lines = fgets(email);
% // Quit like a boss if you see a -1
if lines == -1
break;
end
% // Check if this line has a ':' character.
% // If we do, then another person is talking.
% // Extract the characters just before the first ':' character
% // as we don't want the ':' character in the name
% // If we don't encounter a ':' character, then the same person is
% // talking so don't change the current name
idxs = strfind(lines, ':');
if ~isempty(idxs)
name = lines(1:idxs(1)-1);
end
% // If we find "do you want" in this sentence, then the leader
% // is found, so quit.
if ~isempty(strfind(lower(lines), 'do you want'))
Leader_Name = name;
break;
end
end
By running the above code with your test case, this is what I get:
out2 = teamPowerHolder('teamPowerHolder_convo2.txt')
out2 =
Anna
I'm trying to filter noise out of an image in matlab and I've hit an issue. I need to be able ask some function whether or not if the index -1,-3 or -1,4 or 5,-1 exists, and I need it to return some integer or a false so that I can put it in an if statement. so far, with islogical() exist() and just ARRAYNAME(-1,4) I've gotten an error saying that index position doesn't exist (duh, but that's not what I want) is there a function that can return 1 if there's an error? I really just need this one thing. let me know if the question is too vague.
You can use try-catch statement as follows.
function element=neverReturnIndexingError(array1)
%array1=[1 2 3 4];
try
element=array1(-1,2);
catch
fprintf('Index is invalid\n');
element=1; %returning 1 as you said
end
I want to create a structure with a variable name in a matlab script. The idea is to extract a part of an input string filled by the user and to create a structure with this name. For example:
CompleteCaseName = input('s');
USER WRITES '2013-06-12_test001_blabla';
CompleteCaseName = '2013-06-12_test001_blabla'
casename(12:18) = struct('x','y','z');
In this example, casename(12:18) gives me the result test001.
I would like to do this to allow me to compare easily two cases by importing the results of each case successively. So I could write, for instance :
plot(test001.x,test001.y,test002.x,test002.y);
The problem is that the line casename(12:18) = struct('x','y','z'); is invalid for Matlab because it makes me change a string to a struct. All the examples I find with struct are based on a definition like
S = struct('x','y','z');
And I can't find a way to make a dynamical name for S based on a string.
I hope someone understood what I write :) I checked on the FAQ and with Google but I wasn't able to find the same problem.
Use a structure with a dynamic field name.
For example,
mydata.(casename(12:18)) = struct;
will give you a struct mydata with a field test001.
You can then later add your x, y, z fields to this.
You can use the fields later either by mydata.test001.x, or by mydata.(casename(12:18)).x.
If at all possible, try to stay away from using eval, as another answer suggests. It makes things very difficult to debug, and the example given there, which directly evals user input:
eval('%s = struct(''x'',''y'',''z'');',casename(12:18));
is even a security risk - what happens if the user types in a string where the selected characters are system(''rm -r /''); a? Something bad, that's what.
As I already commented, the best case scenario is when all your x and y vectors have same length. In this case you can store all data from the different files into 2 matrices and call plot(x,y) to plot each column as a series.
Alternatively, you can use a cell array such that:
c = cell(2,nufiles);
for ii = 1:numfiles
c{1,ii} = import x data from file ii
c{2,ii} = import y data from file ii
end
plot(c{:})
A structure, on the other hand
s.('test001').x = ...
s.('test001').y = ...
Use eval:
eval(sprintf('%s = struct(''x'',''y'',''z'');',casename(12:18)));
Edit: apologies, forgot the sprintf.
Actually I am coding a Matlab simulation where the AnchorID and SourceID will report to eachother. For example if I take an anchor 30 and source 50 it will collect all the agc values between these anchor and source and calculate rssi_dB and display them.Below mentioned is an example of anchor 30 and source id 50
Note: list of anchors ID's and source ID's are same. for e.g. 30 50 55 58 . These ID are both same for anchor and source.
function A30(BlinkSet)
for i=1:length(BlinkSet)
xAnchorID=30;
xSourceID=50;
a=BlinkSet{i}.AnchorID;
b=BlinkSet{i}.SourceID;
if xAnchorID==a && xSourceID==b
xagc=BlinkSet{i}.agc;
rssi_dB(i)=-(33+xagc*(89-33)/(29-1));
end
end
rssi_dB(rssi_dB==0)=[];
rssi_dBm=sum(rssi_dB(:))/length(rssi_dB);
disp([sprintf('The rssi value is %0.0f',rssi_dBm)]);
When I call the function in Matlab command window I get the rssi value of the above function.
Also my task is when I reciprocate the Anchor ID and source ID say Anchor as 50 and source as 30 like the function I have mentioned below I get an error which is mentioned after the function below.
function A50(BlinkSet)
for i=1:length(BlinkSet)
xAnchorID=50;
xSourceID=30;
a=BlinkSet{i}.AnchorID;
b=BlinkSet{i}.SourceID;
if xAnchorID==a && xSourceID==b
xagc=BlinkSet{i}.agc;
rssi_dB(i)=-(33+xagc*(89-33)/(29-1));
end
end
rssi_dB(rssi_dB==0)=[];
rssi_dBm=sum(rssi_dB(:))/length(rssi_dB);
disp([sprintf('The rssi value is %0.0f',rssi_dBm)]);
When I call this function I get an error as
??? Undefined function or variable "rssi_dB".
Error in ==> A50 at 14
rssi_dB(rssi_dB==0)=[];
Error in ==> main_reduced at 26
A50(BlinkSet);
In main function I have coded like this,
%A30(BlinkSet);
A50(BlinkSet);
Any help is highly appreciated.
In both of these functions, you only create the variable rssi_dB if execution enters the if statement within the loop (i.e., if xAnchorID==a && xSourceID==b is at some point true). Clearly, this code is never executed in your A50 function. Without knowing what is in BlinkSet it's a bit difficult to diagnose the exact problem, but this is the cause at least.
As a side note: it's not a good idea to create two separate functions to do this job when their code is almost identical. You should add an input argument to your function that allows it to do the job of both. In this particular case, all that changes is the value of xAnchorID and xSourceID, so you could just pass these in:
function srcToAnchorRssi(BlinkSet, xSourceID, xAnchorID)
% The rest of the function stays the same!
If you want to provide some defaults for these arguments, you can do, e.g.:
if nargin < 3 || isempty(xAnchorID), xAnchorID = 50; end
if nargin < 2 || isempty(xSourceID), xSourceID = 30; end
It's always a good idea to include an isempty in statements of this sort, so that your function supports syntax like myFunction(myArg1, [], myArg3). Also note that the order of the operands to || is crucial; if you did if isempty(theArgument) || nargin < theArgumentNumber and the user did not pass theArgument, then it would error in the isempty because theArgument would not exist as a local variable. We can get around this by swapping the operands' order because MATLAB is smart enough to know it doesn't have to evaluate the right operand if the left operand is true (note that this is also the case in many other programming languages).