I need help. I am having an table like this:
local dict = {}
dict[1] = {achan = '7f', aseq='02'} --ACK
dict[2] = {dchan = '7f', dseq='03'} --DATA
dict[3] = {achan = '7f', aseq='03'} --ACK
dict[4] = {dchan = '7f', dseq='04'} --DATA
dict[5] = {achan = '7f', aseq='04'} --ACK
dict[6] = {dchan = '7f', dseq='02'} --DATA
Basically I am using this in an Dissector so I don't know the Index except the one I am actually "standing" at the moment.
So what I want to have is:
if the "achan" and the "dchan" is the same and the "aseq" i am standing at the moment is the same as an "dseq" value on positions from the past which are already saved into the table then it should give me back the index from the same "dseq" value from the past.
if (dict[position at the moment].achan == dict[?].dchan) and (dict[position at the moment].aseq == dict[?].dseq) then
return index
end
for example: dchan from position 6 is the same es achan from position 1 and dseq from position 6 is the same as aseq from position 1. So I want to get the position 1 back
You can use a numeric for loop with a negative step size to go back in your table, starting from the previous element. Check wether the achan and aseq fields exist, then compare them vs the dchan and dseq fields of your current entry.
function getPreviousIndex(dict, currentIndex)
for i = currentIndex - 1, 1, -1 do
if dict[i].achan and dict[currentIndex].dchan
and dict[i].achan == dict[currentIndex].dchan
and dict[i].aseq and dict[currentIndex].dseq
and dict[i].aseq == dict[currentIndex].dseq then
return i
end
end
end
This code assumes you have no gaps in your table. You should also add some error handling that makes sure you actually are at a dchan entry and that your index is in range and so on...
Related
I'm working in PsychoPy to design an experiment. It's almost complete, but I'm trying to output a few variables that I created in a code component into my data file for the experiment, and I haven't been able to figure out how to do that. Here is some relevant code:
if branch == 1:
if money.keys == 'left':
feedback = 'You chose $10 immediately'
TotalNow = TotalNow + 10
add = (amount - 10)/2
amount = add + amount
elif money.keys == 'right':
feedback = 'You chose $%.2f in two weeks' %(amount)
TotalLater = TotalLater + amount
TLtext = '%.2f' %(TotalLater)
amount = (amount + 10)/2
elif money.keys in ['', [], None]:
feedback = 'You did not make a choice. No reward given.'
amount = amount
if branch == 2:
if money.keys == 'right':
feedback = 'You chose $10 immediately'
TotalNow = TotalNow + 10
add = (amount - 10)/2
amount = add + amount
elif money.keys == 'left':
feedback = 'You chose $%.2f in two weeks' %(amount)
TotalLater = TotalLater + amount
TLtext = '%.2f' %(TotalLater)
amount = (amount + 10)/2
elif money.keys in ['', [], None]:
feedback = 'You did not make a choice. No reward given.'
amount = amount
I would like to output the following variables into the data file: 'TotalLater', 'TotalNow', and 'amount'. I've tried a few things, but it doesn't seem that I'm close. Any help would be appreciated.
Use the addData() method of the current experiment handler (which by default is named thisExp in Builder:
# specify each column name and its associated variable:
thisExp.addData('TotalLater', TotalLater)
thisExp.addData('TotalNow', TotalNow)
thisExp.addData('amount', amount)
Do this at the end of the relevant routine to save the current values for that trial.
If you like writing your own code, and want to learn a bit more Python, look into dictionaries which store things as "key" and "value" pairs. You start somewhere are the beginning of your program to create the dictionary with all the keys you want, and then as the program runs you store the values in the dictionary. Before the first trial you can use a function to write the keys as the column headings of a spreadsheet, and then each trial add lines with the values. For instance:
import csv ; #to use the spreadsheet export
def createDataFile(fh,d):
#fh is the handle for a file you created
#d is the name of the dictionary you have created
cdw = csv.DictWriter(fh,fieldnames = d.keys(),quoting = csv.QUOTE_MINIMAL)
cdw.writeheader()
return(cdw)
Here are some example lines from a dictionary where I am setting the values for the conditions of an expriments, note that some of these lines have keys where the value is another dictionary - the dictionaries are nested.
dty['tstX'] = dty['xoffset']['r']
dty['cbCon'] = dict(r = dty['tstCon'], l = dty['stdCon'])
dty['cbOri'] = dict(r = dty['tstStrOri'], l = dty['stdStrOri'])
dty['stdX'] = dty['xoffset']['l']
In your case you would have values for dty['amt'] = amount and at the end of a trial, you would use the function writerow() to put the latest values in their right place in the spreadsheet.
I know this is a lot more detailed, and less intuitive then the above, but you can use dictionaries in lots of places, and they are pretty darn handy.
As I have been cutting and pasting from a file of ours, the above code will likely not work out of the box for you, but will hopefully provide some useful guide posts for your own explorations.
Is there any way to get every index value of a table?
Example:
local mytbl = {
["Hello"] = 123,
["world"] = 321
}
I want to get this:
{"Hello", "world"}
local t = {}
for k, v in pairs(mytbl) do
table.insert(t, k) -- or t[#t + 1] = k
end
Note that the order of how pairs iterates a table is not specified. If you want to make sure the elements in the result are in a certain order, use:
table.sort(t)
I need to build an array of objects of class ID using arrayfun:
% ID.m
classdef ID < handle
properties
id
end
methods
function obj = ID(id)
obj.id = id;
end
end
end
But get an error:
>> ids = 1:5;
>> s = arrayfun(#(id) ID(id), ids)
??? Error using ==> arrayfun
ID output type is not currently implemented.
I can build it alternatively in a loop:
s = [];
for k = 1 : length(ids)
s = cat(1, s, ID(ids(k)));
end
but what is wrong with this usage of arrayfun?
Edit (clarification of the question): The question is not how to workaround the problem (there are several solutions), but why the simple syntax s = arrayfun(#(id) ID(id), ids); doesn't work. Thanks.
Perhaps the easiest is to use cellfun, or force arrayfun to return a cell array by setting the 'UniformOutput' option. Then you can convert this cell array to an array of obects (same as using cat above).
s = arrayfun(#(x) ID(x), ids, 'UniformOutput', false);
s = [s{:}];
You are asking arrayfun to do something it isn't built to do.
The output from arrayfun must be:
scalar values (numeric, logical, character, or structure) or cell
arrays.
Objects don't count as any of the scalar types, which is why the "workarounds" all involve using a cell array as the output. One thing to try is using cell2mat to convert the output to your desired form; it can be done in one line. (I haven't tested it though.)
s = cell2mat(arrayfun(#(id) ID(id), ids,'UniformOutput',false));
This is how I would create an array of objects:
s = ID.empty(0,5);
for i=5:-1:1
s(i) = ID(i);
end
It is always a good idea to provide a "default constructor" with no arguments, or at least use default values:
classdef ID < handle
properties
id
end
methods
function obj = ID(id)
if nargin<1, id = 0; end
obj.id = id;
end
end
end
Here's another one:
ValidFirings = ((DwellTimes > 30/(24*60*60)) | (GroupCount > 1));
for i = length(ValidFirings):-1:2
if(~ValidFirings(i))
DwellTimes(i-1) = DwellTimes(i)+DwellTimes(i-1);
GroupCount(i-1) = GroupCount(i)+GroupCount(i-1);
DwellTimes(i) = [];
GroupCount(i) = [];
ReducedWallTime(i) = [];
ReducedWallId(i) = [];
end
end
It appears that the intent is to sum up 'dwelltimes' based on whether or not the sensor firing is considered valid. So I have a vector of sensor firings that Im walking through backwards and summing into the previous row if the current row is not marked as valid.
I can visualize this in C/C++ but I don't know how to translate it into better Matlab vector notation. As it stands now, this loop is v slow.
EDIT:
Could I use some form of DwellTimes = DwellTimes( cumsum( ValidFirings ))?
As with your previous question, replacing the for loop should improve the performance.
%# Find the indices for invalid firings
idx = find(~(DwellTimes > 30/(24*60*60)) | (GroupCount > 1));
%# Index the appropriate elements and add them (start the addition
%# from the second element)
%# This eliminates the for loop
DwellTimes(idx(2:end)-1) = DwellTimes(idx(2:end)-1)+DwellTimes(idx(2:end));
GroupCount(idx(2:end)-1) = GroupCount(idx(2:end)-1)+GroupCount(idx(2:end));
%# Now remove all the unwanted elements (this removes the
%# first element if it was a bad firing. Modify as necessary)
GroupCount(idx)=[];
DwellTimes(idx)=[];
I would consolidate first as shown, then eliminate the invalid data. This avoids the constant resizing of the data. Note that you can't reverse the order of the FOR loop due to the way that the values propagate.
ValidFirings = ((DwellTimes > 30/(24*60*60)) | (GroupCount > 1));
for i = length(ValidFirings):-1:2
if (~ValidFirings(i))
DwellTimes(i-1) = DwellTimes(i) + DwellTimes(i-1);
GroupCount(i-1) = GroupCount(i) + GroupCount(i-1);
end
end
DwellTimes = DwellTimes(ValidFirings);
GroupCount = GroupCount(ValidFirings);
ReducedWallTime = ReducedWallTime(ValidFirings);
ReducedWallId = ReducedWallId(ValidFirings);
Using Rails 3 with memcachestore and the memcache-client gem.
Local memcache on a macbook-pro or memcache servers on the staging environment.
When I do a
Rails.cache.increment(key, 1)
followed very quickly (w/in a few lines) by a
Rails.cache.read(key, :raw => true)
I get my original value. If it sits for a second and then I call read (or in the console), I get the correctly incremented value.
As my work around, I'm using the returned value from the increment call, but this doesn't seem like it should be happening.
Any ideas?
This problem is described in a blog post
http://thomasmango.com/2009/06/25/a-better-rails-cache-increment/
and the suggested fix is:
class Util::Cache
def self.increment(key, amount = 1)
if (value = Rails.cache.read(key)).nil?
Rails.cache.write(key, (value = amount))
else
Rails.cache.write(key, (value = value + amount))
end
return value
end
def self.decrement(key, amount = 1)
if (value = Rails.cache.read(key)).nil?
value = 0
else
Rails.cache.write(key, (value = value - amount))
end
return value
end
end