Changing a function to take an input of cells rather than a matrix

7 views (last 30 days)
So I have a Matlab function created by friend of mine and I need to change it such that it will work properly with an input of cells rather than just a single matrix.
the code is :
%%QDViewer v1.5 September 18 2009
function [] = QDViewer(data,threshold)
close all %closes figures
disp(' ');
disp('Running QDViewer.m');
disp('To terminate the program (a la ctrl-alt-del) hit CTRL+C.');
tic;
%Overload program to accept no input for threshold
if nargin == 1
disp('Threshold set to default (35%).');
threshold = 35;
else
if threshold>100 || threshold<0
error('The value for threshold is supposed to be a percentage of the highest peak, a value between 0 and 100. Please run the program again with an appropriate parameter.');
else
disp(['Threshold set to ' int2str(threshold) '%.']);
end
end
%This new version of the qd program knows how to take the metadata away
%from the formatted matlab files.
dotwavelength=data(1,2);
pixelx = data(2,2);
pixely = data(3,2);
% date = data(4,2);
% datestr = int2str(date);
% datestr = [datestr(1:4) '-' datestr(5:6) '-' datestr(7:8)];
runname = ['blinky' int2str(data(5,2))];
numcycle = data(6,2);
time = data(7,2); %in seconds
numwavelengths = data(8,2);
wavelengths = data(9:(9+numwavelengths-1),2)';
pointdata = ['[' int2str(dotwavelength) 'nm, ' '05222012' ': ' runname ' (' int2str(pixelx) ',' int2str(pixely) ')]'] %#ok<NOPRT> %This string will be used in plots later.
%Now remove that data so that we have an array that looks like the old
%version:
data = data((9+numwavelengths):end,:);
result = zeros(numcycle,3);
maxintensity = max(data);
maxintensity = maxintensity(2); %global max intensity
threshold = maxintensity*threshold/100;
time=(time/60)/numcycle; %time in minutes per cycle
Z=zeros(numcycle,numwavelengths); %Variable used in the 3D plot
% Initialize
count = 0;
intensity=zeros(1,numcycle);
for i = 1:numcycle
submatrix = data((i-1)*numwavelengths+1:i*numwavelengths,2);
if (max(submatrix))>threshold
count=count+1;
result(count,2) = max(submatrix); %max intensity for field
intensity(i) = max(submatrix);
index=mod(find(submatrix==result(count,2)),numwavelengths);
if index==0
index=numwavelengths;
end
result(count,3) = wavelengths(index(1));%wavelength
result(count,1) = i*time + index(1)*time/numwavelengths;
%time per cycle + time between wavelengths
end
for j=1:numwavelengths
if submatrix(j)>threshold;
Z(i,j)=submatrix(j)/maxintensity*100;
else
Z(i,j)=0;
end
end
end
%Normalized Intensity
normintensity = zeros(size(intensity));%Loop normalizes telegraph to be 0 / 1
for i=1:length(intensity)
if intensity(i)~=0
normintensity(i) = 1;
else
normintensity(i) = 0;
end
end
%On / Off time probabilities
%Initialize to zero
jon = 0;
kon = 0;
joff = 0;
koff = 0;
oncount = zeros(1,length(normintensity)); %On-times, in cycles (not seconds)
offcount = zeros(1,length(normintensity));
for i=1:length(normintensity)
if normintensity(i)==1
jon = jon+1;
koff = koff+1;
offcount(koff)=joff;
joff=0;
elseif normintensity(i)==0
joff = joff+1;
kon = kon+1;
oncount(kon)=jon;
jon=0;
end
end
oncount(oncount==0)=[]; %remove all zeros.
offcount(offcount==0)=[];
onfreq = zeros(1,length(oncount)); %Frequency of a blink being on this long
offfreq= zeros(1,length(offcount));
for i = 1:max(length(oncount),length(offcount))
onfreq(i)= sum(oncount==i);
offfreq(i)= sum(offcount==i);
end
onfreq = onfreq/sum(onfreq); %Normalize to percentages.
offfreq = offfreq/sum(offfreq);
%MLE Algorithm (fitting to Probs):
S_on_MLE = 1/length(oncount)*sum(log(oncount));
crit_on = (1+1/S_on_MLE) %#ok<NOPRT>
S_off_MLE = 1/length(offcount)*sum(log(offcount));
crit_off = (1+1/S_off_MLE) %#ok<NOPRT>
t_min = 1;
t_max = numcycle;
tonlast = (find(onfreq~=0, 1, 'last'));
if(isempty(tonlast))
tonlast = numcycle;
end
t_on = linspace(1,tonlast); %set up our timedomain, starting from lowest resolution to highest occupied on-time.
A_on = (crit_on-1)/(t_min^(1-crit_on)-t_max^(1-crit_on)); %normalizing constant
P_on = A_on*t_on.^(-crit_on);
tofflast = (find(offfreq~=0, 1, 'last'));
if(isempty(tofflast))
tofflast = numcycle;
end
t_off = linspace(1,tofflast);
A_off = (crit_off-1)/(t_min^(1-crit_off)-t_max^(1-crit_off));
P_off = A_off*t_off.^(-crit_off);
%%Marcel's Stuff
offtimes((1:length(offfreq)),1) = (1:length(offfreq))*time;
offtimes((1:length(offfreq)),2) = offfreq;
ontimes((1:length(onfreq)),1) = (1:length(onfreq))*time;
ontimes((1:length(onfreq)),2) = onfreq;
[row col] = find(offtimes == 0);
offtimes(row,:) = [];
[row col] = find(ontimes == 0);
ontimes(row,:) = [];
xlswrite('offtime.xls',offtimes);
xlswrite('ontime.xls',ontimes);
F = @(a,x)(a(2)*x.^(-a(1)));
param = [6 1];
[fit_off] = nlinfit(offtimes(:,1),offtimes(:,2),F,param);
F = @(a,x)(a(2)*x.^(-a(1)));
param = [6 1];
[fit_on] = nlinfit(ontimes(:,1),ontimes(:,2),F,param);
display(fit_off);
display(fit_on);
%%Plot results
result=result(1:count,1:3);
result(:,2)=result(:,2)/maxintensity*100;
intensity = intensity/maxintensity*100;
threshold = threshold/maxintensity*100;
regression=[ones(count,1) result(:,1)]\result(:,3); %#ok<NOPRT>
trendline(1:numcycle) = regression(1)+regression(2)*time*(1:numcycle);
% %Blinking telegraph
figure(1)
hold on;
title(['Intensity vs. Time ' pointdata], 'FontSize',16);
plot(time*(1:numcycle),intensity,'-black');
plot(time*(1:numcycle),threshold,'-r'); %show threshold line
xlabel('Time (min)','FontSize',14);
ylabel('Intensity (normalized a.u.)','FontSize',14);
axis([0 time*numcycle 0 105]);
hold off;
end
What I really need to know is how to properly edit the recursive stuff so that my the stuff I'm displaying (fit_off, fit_on, crit_on and crit_off) end up as nice outputs.
Sorry if this isn't so clear. Its hard to explain particularly because I didn't write the code myself and I'm not a pro at Matlab yet.
Thanks,
Marcel
  2 Comments
Matt Fig
Matt Fig on 13 Aug 2012
Please give an example of inputs as the function is now and the inputs you would like to pass.
Marcel
Marcel on 14 Aug 2012
Edited: Marcel on 14 Aug 2012
I want to be able to input an array of cells in 1xN form and within each cell is a Nx2 matrix of times and intensities from an image.
right now I have to manually input all each different matrix I want to input a cell array

Sign in to comment.

Answers (2)

Babak
Babak on 13 Aug 2012
All you need to do is to change all the occurances of data(.,.) in your function to data{.,.}. This way wherever you are accessing the elemnts of the matrix with (.,.) you access the coresponding element of the cell with {.,.} instead.
As for where you're saying:
wavelengths = data(9:(9+numwavelengths-1),2)';
you need to keep it same as it is, but again wavelengths will still be a cell and later you need to change all the occurances of wavelengths(.,.) to wavelengths{.,.}
YOu got to do same for the line
submatrix = data((i-1)*numwavelengths+1:i*numwavelengths,2);
  3 Comments
Marcel
Marcel on 14 Aug 2012
So I selected all the 'data()' and changed them to data{1,k}() where k is the index for my for loop around the algorithm that is: k = 1:length(data).
For some reason with this, the first iteration works just fine but the rest dont.
any ideas?
thanks
Babak
Babak on 14 Aug 2012
You don't need for loop! data{.,.} accesses a component of data object which is a cell similar to data(.,.) which accesses an element of a matrix. by replacing I mean do the following for example, replace:
dotwavelength=data(1,2); pixelx = data(2,2); pixely = data(3,2);
with
dotwavelength=data{1,2}; pixelx = data{2,2}; pixely = data{3,2};
After you do all these replacements, data is considered a cell and you can no longer use this function for input of data as a matrix! the data that is the input to the function has to be a cell object.

Sign in to comment.


per isakson
per isakson on 13 Aug 2012
Edited: per isakson on 15 Aug 2012
Do you really need to change your friends function?
function My_QDViewer( my_cell_array, threshold)
data = ...
QDViewer( data, threshold );
end
.
or better something like
function My_QDViewer( my_input, threshold)
if isa( my_input, 'double' )
data = my_input;
elseif isa( my_input, 'cell' )
% convert to double array
data = ...
else
error( 'My_QDViewer:...', 'Illegal input: ... ),
end
QDViewer( data, threshold );
end
  2 Comments
Marcel
Marcel on 14 Aug 2012
So I tried this as well and it wont accept my cell input or my double input anymore. I have what you have but with a for loop in a similar fashion to above. I can't seem to figure out why it won't accept my input. Maybe its just evening brain.
per isakson
per isakson on 14 Aug 2012
Edited: per isakson on 15 Aug 2012
From my point of view:
  1. make sure that your friends QDViewer runs with some test data
  2. figure out the exact requirement on the input data of QDViewer
  3. write your own program, My_QDViewer, which is a wrapper around QDViewer. The purpose of My_QDViewer is to convert your cell array input data to the double array form required by QDViewer.
  4. do not change QDViewer
  5. My_QDViewer may call QDViewer several times in a loop

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!