How to find 3 hourly averages? - matlab
In the below code, each y is of 8 min duration. Once I generate the Powerr matrix I have what I Need but How do i do 3 hour averages? Should i do within the for loop or once I generate the Powerr matrix can i still be able to find out the 3 hourly averages of my data? thanks in advance.
tic
profile on
warning('off','MATLAB:audiovideo:wavread:functionToBeRemoved');
neglect_the_first_few= 5;
lastfile = 10;
Powerr = zeros(2049,10);
count =[];
parfor count = neglect_the_first_few + 1 :lastfile
% time_spectrum(timeindex) = timecount;
warning('off','MATLAB:audiovideo:wavread:functionToBeRemoved');
% infiles = find(timestamp >= timecount & timestamp <= (timecount + timestep));
% if ~isempty(infiles)
% if isnan(time_spectrum)
% time_spectrum(timeindex) = NaN
% end
y= [];
% for inputfile = infiles'
fn = [directory '/001/' file_names(count,:)];
[y,fs,nbits] = wavread(fn,'native');
disp(['sampling freq is ',num2str(fs),' hz. length of y is ',num2str(size(y)),'filenumber is ',num2str(count)])
% end
y = y- mean(y);
Y = double(y).*(1.49365435131571e-07);%CONVERSION - volts per bit for 24bit channel
% clear y;
nooverlap =[];%number of overlapped segments set to zero on Nov20th 2017
[Poww,fr] = pwelch(Y,hanning_window,nooverlap,nfft,fs);%no overlap taken into account%
Powerr(:,count) = Poww;
end
fr is independent from the parfor iteration count. So,this variable did not get transferred to the host from workers. Write fr(count)=...
You've done it correctly for Powerr.
Related
Faster way to calculate the distance of each point to all other points in imported 3D point data
I have 3D coordinate data of 221275 points. Also, I have an iterative process according to the values that I imported to MATLAB for each point. In this process, the average values of neighboring points near r<4 mm of each point are calculated. I wrote MATLAB code for this process, but the line " sqrt(sum((A - A(i1,:)).^2, 2)); " takes up a lot of the total time. I wrote down the process times for each line below. Is there a way I can run this code faster? A = dlmread('E:\3D_point_data.txt'); % (221275 x 3) my_input = dlmread('E:\my_input.txt'); % (221275 x 1) my_output = dlmread('E:\my_output.txt'); % (221275 x 1) len1 = length(A); par_new = zeros(len1,1); for i1=1:len1 C = sqrt(sum((A - A(i1,:)).^2, 2)); % 1006 seconds C(i1,1) = 1; % ind = find(C<4); % 57 seconds mean_par = (mean(my_input(ind)))*2; % 15 seconds par_new(i1) = my_input(i1,1) / mean_par; end par_new = par_new - my_output; ind1 = find(par_new>0); ind2 = find(par_new<0); my_output(ind1) = my_output(ind1).*1.5; my_output(ind2) = my_output(ind2)./1.5; my_output(my_output>1)=1; my_output(my_output<0.00001)=0.00001; dlmwrite('E:\my_output.txt',my_output)
How do I create a sliding window using a for loop?
I have neural data collected across 16 different channels. This data was recorded over a 30 second period. Over a 10s period (from 20 - 30s), I want to record the number of neural data points that are greater than or equal to a specified threshold. I would like to do this according to bins of 0.001s. I am using MATLAB 2019b. My code so far looks like this: t1 = 20; t2 = 30; ind1 = find(tim_trl>=t1, 1); ind2 = find(tim_trl>=t2, 1); time1 = tim_trl(ind1:ind2); %10s window sampRate = 24414; %sampling freq (Hz), samples per sec muaWindow = 0.001; %1ms window binWidth = round(muaWindow*sampRate); %samples per 1ms window threshold = 0.018; for jj = 1:16 %ch data = AbData(ind1:ind2, jj); %10 sec of data for kk = 1:10000 abDataBin = data(1:binWidth,jj); %data in 1 bin dataThreshold = find(abDataBin >= threshold); %find data points >= threshold mua(kk,jj) = sum(dataThreshold); %number of data pts over threshold per ch end end So far, I'm just having a bit of trouble at this point: abDataBin = data(1:binWidth,jj); %data in 1 bin When I run the loop, the data in bin 1 gets overwritten, rather than shift to bin 2, 3...10000. I'd appreciate any feedback on fixing this. Many thanks.
You forgot to use the running variable as index to access your data. Try % create data with 16 channels AbData = rand(10000,16); binWidth = 24; threshold = 0.001; for channel=1:16 data = AbData(2001:3000,channel); counter = 1; % needed for mua indexing % looping over the bin starting indeces for window=1:binWidth:length(data)-(binWidth) % access data in one bin bindata = data(window:window+binWidth); % calculate ms above threshold mua(counter, channel) = sum(bindata >= threshold); counter = counter+1; end end EDIT: your data variable is of dimension nx1, therefore doenst need the column indexing with jj
Simulate a queue using Lindley's equation in Matlab
I have to simulate a simple queue in Matlab using Lindley's equation: W_{n+1}^Q = max(0, W_n^Q + S_n - X_{n+1} I think I have done so, with the following code, but I am trying to run it several times and cannot save the information correct. The variables I want to save at the end of running the simulation are only saving the information from the last attempt (here for m=3).. while I clearly would like to see this for all runs (m=1,2,3). for m=1:3 l = 1.1; % try this value for lambda N = 10000; % let 1000 people arrive X = exprnd(l,[1,N]); % make 1000 exponential interarrivals S = 2*rand(1,N); % uniform on [0,2] w = zeros(1,N); sum1 = zeros(1,m); avg1 = zeros(1,m); max1 = zeros(1,m); for i=1:N if i==1 % first customer doesn't have to wait w(i) = 0; else % following customers follow lindley's equation w(i) = max(w(i-1) + S(i-1) - X(i), 0); % n-th customer's waiting time count(i) = w(i) > 15; % count number of times greater than 15 end end max1(m) = max(w); sum1(m) = sum(count); % sum number of times greater than 15 avg1(m) = sum1(m)/N; % divide by 1000 to get probability delay is greater than 15 end
You are initializing sum1, avg1 and max1 inside the for loop so in every iteration, these variables are set to zero (i.e. by initialization). This is the reason you loose your previous iteration value. To avoid this, initialize sum1, avg1 and max1 before you for loop. Refer below code for reference. HTH sum1 = zeros(1,m); avg1 = zeros(1,m); max1 = zeros(1,m); for m=1:3 l = 1.1; % try this value for lambda N = 10000; % let 1000 people arrive X = exprnd(l,[1,N]); % make 1000 exponential interarrivals S = 2*rand(1,N); % uniform on [0,2] w = zeros(1,N); for i=1:N if i==1 % first customer doesn't have to wait w(i) = 0; else % following customers follow lindley's equation w(i) = max(w(i-1) + S(i-1) - X(i), 0); % n-th customer's waiting time count(i) = w(i) > 15; % count number of times greater than 15 end end max1(m) = max(w); sum1(m) = sum(count); % sum number of times greater than 15 avg1(m) = sum1(m)/N; % divide by 1000 to get probability delay is greater than 15 end
plotting volume-time graph of .wav file
I'm trying to get volume-time graph of .wav file. First, I recorded sound (patient exhalations) via android as .wav file, but when I read this .wav file in MATLAB it has negative values. What is the meaning of negative values? Second, MATLAB experts could you please check if the code below does the same as written in my comments? Also another question. Y = fft(WindowArray); p = abs(Y).^2; I took the power of values returned from fft...is that correct and what is the goal of this step?? [data, fs] = wavread('newF2'); % read exhalation audio wav file (1 channel, mono) % frequency is 44100 HZ % windows of 0.1 s and overlap of 0.05 seconds WINDOW_SIZE = fs*0.1; %4410 = fs*0.1 array_size = length(data); % array size of data numOfPeaks = (array_size/(WINDOW_SIZE/2)) - 1; step = floor(WINDOW_SIZE/2); %step size used in loop transformed = data; start =1; k = 1; t = 1; g = 1; o = 1; % performing fft on each window and finding the peak of windows while(((start+WINDOW_SIZE)-1)<=array_size) j=1; i =start; while(j<=WINDOW_SIZE) WindowArray(j) = transformed(i); j = j+1; i = i +1; end Y = fft(WindowArray); p = abs(Y).^2; %power [a, b] = max(abs(Y)); % find max a and its indices b [m, i] = max(p); %the maximum of the power m and its indices i maximum(g) = m; index(t) = i; power(o) = a; indexP(g) = b; start = start + step; k = k+1; t = t+1; g = g+1; o=o+1; end % low pass filter % filtering noise: ignor frequencies that are less than 5% of maximum frequency for u=1:length(maximum) M = max(maximum); %highest value in the array Accept = 0.05* M; if(maximum(u) > Accept) maximum = maximum(u:length(maximum)); break; end end % preparing the time of the graph, % Location of the Peak flow rates are estimated TotalTime = (numOfPeaks * 0.1); time1 = [0:0.1:TotalTime]; if(length(maximum) > ceil(numOfPeaks)); maximum = maximum(1:ceil(numOfPeaks)); end time = time1(1:length(maximum)); % plotting frequency-time graph figure(1); plot(time, maximum); ylabel('Frequency'); xlabel('Time (in seconds)'); % plotting volume-time graph figure(2); plot(time, cumsum(maximum)); % integration over time to get volume ylabel('Volume'); xlabel('Time (in seconds)');
(I only answer the part of the question which I understood) Per default Matlab normalizes the audio wave to - 1...1 range. Use the native option if you want the integer data.
First, in your code it should be p = abs(Y)**2, this is the proper way to square the values returned from the FFT. The reason why you take the absolute value of the FFT return values is because those number are complex numbers with a Real and Imaginary part, therefore the absolute value (or modulus) of an imaginary number is the magnitude of that number. The goal of taking the power could be for potentially obtaining an RMS value (root mean squared) of your overall amplitude values, but you could also have something else in mind. When you say volume-time I assume you want decibels, so try something like this: def plot_signal(file_name): sampFreq, snd = wavfile.read(file_name) snd = snd / (2.**15) #Convert sound array to floating point values #Floating point values range from -1 to 1 s1 = snd[:,0] #left channel s2 = snd[:,1] #right channel timeArray = arange(0, len(snd), 1) timeArray = timeArray / sampFreq timeArray = timeArray * 1000 #scale to milliseconds timeArray2 = arange(0, len(snd), 1) timeArray2 = timeArray2 / sampFreq timeArray2 = timeArray2 * 1000 #scale to milliseconds n = len(s1) p = fft(s1) # take the fourier transform m = len(s2) p2 = fft(s2) nUniquePts = ceil((n+1)/2.0) p = p[0:nUniquePts] p = abs(p) mUniquePts = ceil((m+1)/2.0) p2 = p2[0:mUniquePts] p2 = abs(p2) ''' Left Channel ''' p = p / float(n) # scale by the number of points so that # the magnitude does not depend on the length # of the signal or on its sampling frequency p = p**2 # square it to get the power # multiply by two (see technical document for details) # odd nfft excludes Nyquist point if n % 2 > 0: # we've got odd number of points fft p[1:len(p)] = p[1:len(p)] * 2 else: p[1:len(p) -1] = p[1:len(p) - 1] * 2 # we've got even number of points fft plt.plot(timeArray, 10*log10(p), color='k') plt.xlabel('Time (ms)') plt.ylabel('LeftChannel_Power (dB)') plt.show() ''' Right Channel ''' p2 = p2 / float(m) # scale by the number of points so that # the magnitude does not depend on the length # of the signal or on its sampling frequency p2 = p2**2 # square it to get the power # multiply by two (see technical document for details) # odd nfft excludes Nyquist point if m % 2 > 0: # we've got odd number of points fft p2[1:len(p2)] = p2[1:len(p2)] * 2 else: p2[1:len(p2) -1] = p2[1:len(p2) - 1] * 2 # we've got even number of points fft plt.plot(timeArray2, 10*log10(p2), color='k') plt.xlabel('Time (ms)') plt.ylabel('RightChannel_Power (dB)') plt.show() I hope this helps.
Optimizing repetitive estimation (currently a loop) in MATLAB
I've found myself needing to do a least-squares (or similar matrix-based operation) for every pixel in an image. Every pixel has a set of numbers associated with it, and so it can be arranged as a 3D matrix. (This next bit can be skipped) Quick explanation of what I mean by least-squares estimation : Let's say we have some quadratic system that is modeled by Y = Ax^2 + Bx + C and we're looking for those A,B,C coefficients. With a few samples (at least 3) of X and the corresponding Y, we can estimate them by: Arrange the (lets say 10) X samples into a matrix like X = [x(:).^2 x(:) ones(10,1)]; Arrange the Y samples into a similar matrix: Y = y(:); Estimate the coefficients A,B,C by solving: coeffs = (X'*X)^(-1)*X'*Y; Try this on your own if you want: A = 5; B = 2; C = 1; x = 1:10; y = A*x(:).^2 + B*x(:) + C + .25*randn(10,1); % added some noise here X = [x(:).^2 x(:) ones(10,1)]; Y = y(:); coeffs = (X'*X)^-1*X'*Y coeffs = 5.0040 1.9818 0.9241 START PAYING ATTENTION AGAIN IF I LOST YOU THERE *MAJOR REWRITE*I've modified to bring it as close to the real problem that I have and still make it a minimum working example. Problem Setup %// Setup xdim = 500; ydim = 500; ncoils = 8; nshots = 4; %// matrix size for each pixel is ncoils x nshots (an overdetermined system) %// each pixel has a matrix stored in the 3rd and 4rth dimensions regressor = randn(xdim,ydim, ncoils,nshots); regressand = randn(xdim, ydim,ncoils); So my problem is that I have to do a (X'*X)^-1*X'*Y (least-squares or similar) operation for every pixel in an image. While that itself is vectorized/matrixized the only way that I have to do it for every pixel is in a for loop, like: Original code style %// Actual work tic estimate = zeros(xdim,ydim); for col=1:size(regressor,2) for row=1:size(regressor,1) X = squeeze(regressor(row,col,:,:)); Y = squeeze(regressand(row,col,:)); B = X\Y; % B = (X'*X)^(-1)*X'*Y; %// equivalently estimate(row,col) = B(1); end end toc Elapsed time = 27.6 seconds EDITS in reponse to comments and other ideas I tried some things: 1. Reshaped into a long vector and removed the double for loop. This saved some time. 2. Removed the squeeze (and in-line transposing) by permute-ing the picture before hand: This save alot more time. Current example: %// Actual work tic estimate2 = zeros(xdim*ydim,1); regressor_mod = permute(regressor,[3 4 1 2]); regressor_mod = reshape(regressor_mod,[ncoils,nshots,xdim*ydim]); regressand_mod = permute(regressand,[3 1 2]); regressand_mod = reshape(regressand_mod,[ncoils,xdim*ydim]); for ind=1:size(regressor_mod,3) % for every pixel X = regressor_mod(:,:,ind); Y = regressand_mod(:,ind); B = X\Y; estimate2(ind) = B(1); end estimate2 = reshape(estimate2,[xdim,ydim]); toc Elapsed time = 2.30 seconds (avg of 10) isequal(estimate2,estimate) == 1; Rody Oldenhuis's way N = xdim*ydim*ncoils; %// number of columns M = xdim*ydim*nshots; %// number of rows ii = repmat(reshape(1:N,[ncoils,xdim*ydim]),[nshots 1]); %//column indicies jj = repmat(1:M,[ncoils 1]); %//row indicies X = sparse(ii(:),jj(:),regressor_mod(:)); Y = regressand_mod(:); B = X\Y; B = reshape(B(1:nshots:end),[xdim ydim]); Elapsed time = 2.26 seconds (avg of 10) or 2.18 seconds (if you don't include the definition of N,M,ii,jj) SO THE QUESTION IS: Is there an (even) faster way? (I don't think so.)
You can achieve a ~factor of 2 speed up by precomputing the transposition of X. i.e. for x=1:size(picture,2) % second dimension b/c already transposed X = picture(:,x); XX = X'; Y = randn(n_timepoints,1); %B = (X'*X)^-1*X'*Y; ; B = (XX*X)^-1*XX*Y; est(x) = B(1); end Before: Elapsed time is 2.520944 seconds. After: Elapsed time is 1.134081 seconds. EDIT: Your code, as it stands in your latest edit, can be replaced by the following tic xdim = 500; ydim = 500; n_timepoints = 10; % for example % Actual work picture = randn(xdim,ydim,n_timepoints); picture = reshape(picture, [xdim*ydim,n_timepoints])'; % note transpose YR = randn(n_timepoints,size(picture,2)); % (XX*X).^-1 = sum(picture.*picture).^-1; % XX*Y = sum(picture.*YR); est = sum(picture.*picture).^-1 .* sum(picture.*YR); est = reshape(est,[xdim,ydim]); toc Elapsed time is 0.127014 seconds. This is an order of magnitude speed up on the latest edit, and the results are all but identical to the previous method. EDIT2: Okay, so if X is a matrix, not a vector, things are a little more complicated. We basically want to precompute as much as possible outside of the for-loop to keep our costs down. We can also get a significant speed-up by computing XT*X manually - since the result will always be a symmetric matrix, we can cut a few corners to speed things up. First, the symmetric multiplication function: function XTX = sym_mult(X) % X is a 3-d matrix n = size(X,2); XTX = zeros(n,n,size(X,3)); for i=1:n for j=i:n XTX(i,j,:) = sum(X(:,i,:).*X(:,j,:)); if i~=j XTX(j,i,:) = XTX(i,j,:); end end end Now the actual computation script xdim = 500; ydim = 500; n_timepoints = 10; % for example Y = randn(10,xdim*ydim); picture = randn(xdim,ydim,n_timepoints); % 500x500x10 % Actual work tic % start timing picture = reshape(picture, [xdim*ydim,n_timepoints])'; % Here we precompute the (XT*Y) calculation to speed things up later picture_y = [sum(Y);sum(Y.*picture)]; % initialize est = zeros(size(picture,2),1); picture = permute(picture,[1,3,2]); XTX = cat(2,ones(n_timepoints,1,size(picture,3)),picture); XTX = sym_mult(XTX); % precompute (XT*X) for speed X = zeros(2,2); % preallocate for speed XY = zeros(2,1); for x=1:size(picture,2) % second dimension b/c already transposed %For some reason this is a lot faster than X = XTX(:,:,x); X(1,1) = XTX(1,1,x); X(2,1) = XTX(2,1,x); X(1,2) = XTX(1,2,x); X(2,2) = XTX(2,2,x); XY(1) = picture_y(1,x); XY(2) = picture_y(2,x); % Here we utilise the fact that A\B is faster than inv(A)*B % We also use the fact that (A*B)*C = A*(B*C) to speed things up B = X\XY; est(x) = B(1); end est = reshape(est,[xdim,ydim]); toc % end timing Before: Elapsed time is 4.56 seconds. After: Elapsed time is 2.24 seconds. This is a speed up of about a factor of 2. This code should be extensible to X being any dimensions you want. For instance, in the case where X = [1 x x^2], you would change picture_y to the following picture_y = [sum(Y);sum(Y.*picture);sum(Y.*picture.^2)]; and change XTX to XTX = cat(2,ones(n_timepoints,1,size(picture,3)),picture,picture.^2); You would also change a lot of 2s to 3s in the code, and add XY(3) = picture_y(3,x) to the loop. It should be fairly straight-forward, I believe.
Results I sped up your original version, since your edit 3 was actually not working (and also does something different). So, on my PC: Your (original) version: 8.428473 seconds. My obfuscated one-liner given below: 0.964589 seconds. First, for no other reason than to impress, I'll give it as I wrote it: %%// Some example data xdim = 500; ydim = 500; n_timepoints = 10; % for example estimate = zeros(xdim,ydim); %// initialization with explicit size picture = randn(xdim,ydim,n_timepoints); %%// Your original solution %// (slightly altered to make my version's results agree with yours) tic Y = randn(n_timepoints,xdim*ydim); ii = 1; for x = 1:xdim for y = 1:ydim X = squeeze(picture(x,y,:)); %// or similar creation of X matrix B = (X'*X)^(-1)*X' * Y(:,ii); ii = ii+1; %// sometimes you keep everything and do %// estimate(x,y,:) = B(:); %// sometimes just the first element is important and you do estimate(x,y) = B(1); end end toc %%// My version tic %// UNLEASH THE FURY!! estimate2 = reshape(sparse(1:xdim*ydim*n_timepoints, ... builtin('_paren', ones(n_timepoints,1)*(1:xdim*ydim),:), ... builtin('_paren', permute(picture, [3 2 1]),:))\Y(:), ydim,xdim).'; %' toc %%// Check for equality max(abs(estimate(:)-estimate2(:))) % (always less than ~1e-14) Breakdown First, here's the version that you should actually use: %// Construct sparse block-diagonal matrix %// (Type "help sparse" for more information) N = xdim*ydim; %// number of columns M = N*n_timepoints; %// number of rows ii = 1:N; jj = ones(n_timepoints,1)*(1:N); s = permute(picture, [3 2 1]); X = sparse(ii,jj(:), s(:)); %// Compute ALL the estimates at once estimates = X\Y(:); %// You loop through the *second* dimension first, so to make everything %// agree, we have to extract elements in the "wrong" order, and transpose: estimate2 = reshape(estimates, ydim,xdim).'; %' Here's an example of what picture and the corresponding matrix X looks like for xdim = ydim = n_timepoints = 2: >> clc, picture, full(X) picture(:,:,1) = -0.5643 -2.0504 -0.1656 0.4497 picture(:,:,2) = 0.6397 0.7782 0.5830 -0.3138 ans = -0.5643 0 0 0 0.6397 0 0 0 0 -2.0504 0 0 0 0.7782 0 0 0 0 -0.1656 0 0 0 0.5830 0 0 0 0 0.4497 0 0 0 -0.3138 You can see why sparse is necessary -- it's mostly zeros, but will grow large quickly. The full matrix would quickly consume all your RAM, while the sparse one will not consume much more than the original picture matrix does. With this matrix X, the new problem X·b = Y now contains all the problems X1 · b1 = Y1 X2 · b2 = Y2 ... where b = [b1; b2; b3; ...] Y = [Y1; Y2; Y3; ...] so, the single command X\Y will solve all your systems at once. This offloads all the hard work to a set of highly specialized, compiled to machine-specific code, optimized-in-every-way algorithms, rather than the interpreted, generic, always-two-steps-away from the hardware loops in MATLAB. It should be straightforward to convert this to a version where X is a matrix; you'll end up with something like what blkdiag does, which can also be used by mldivide in exactly the same way as above.
I had a wee play around with an idea, and I decided to stick it as a separate answer, as its a completely different approach to my other idea, and I don't actually condone what I'm about to do. I think this is the fastest approach so far: Orignal (unoptimised): 13.507176 seconds. Fast Cholesky-decomposition method: 0.424464 seconds First, we've got a function to quickly do the X'*X multiplication. We can speed things up here because the result will always be symmetric. function XX = sym_mult(X) n = size(X,2); XX = zeros(n,n,size(X,3)); for i=1:n for j=i:n XX(i,j,:) = sum(X(:,i,:).*X(:,j,:)); if i~=j XX(j,i,:) = XX(i,j,:); end end end The we have a function to do LDL Cholesky decomposition of a 3D matrix (we can do this because the (X'*X) matrix will always be symmetric) and then do forward and backwards substitution to solve the LDL inversion equation function Y = fast_chol(X,XY) n=size(X,2); L = zeros(n,n,size(X,3)); D = zeros(n,n,size(X,3)); B = zeros(n,1,size(X,3)); Y = zeros(n,1,size(X,3)); % These loops compute the LDL decomposition of the 3D matrix for i=1:n D(i,i,:) = X(i,i,:); L(i,i,:) = 1; for j=1:i-1 L(i,j,:) = X(i,j,:); for k=1:(j-1) L(i,j,:) = L(i,j,:) - L(i,k,:).*L(j,k,:).*D(k,k,:); end D(i,j,:) = L(i,j,:); L(i,j,:) = L(i,j,:)./D(j,j,:); if i~=j D(i,i,:) = D(i,i,:) - L(i,j,:).^2.*D(j,j,:); end end end for i=1:n B(i,1,:) = XY(i,:); for j=1:(i-1) B(i,1,:) = B(i,1,:)-D(i,j,:).*B(j,1,:); end B(i,1,:) = B(i,1,:)./D(i,i,:); end for i=n:-1:1 Y(i,1,:) = B(i,1,:); for j=n:-1:(i+1) Y(i,1,:) = Y(i,1,:)-L(j,i,:).*Y(j,1,:); end end Finally, we have the main script which calls all of this xdim = 500; ydim = 500; n_timepoints = 10; % for example Y = randn(10,xdim*ydim); picture = randn(xdim,ydim,n_timepoints); % 500x500x10 tic % start timing picture = reshape(pr, [xdim*ydim,n_timepoints])'; % Here we precompute the (XT*Y) calculation picture_y = [sum(Y);sum(Y.*picture)]; % initialize est2 = zeros(size(picture,2),1); picture = permute(picture,[1,3,2]); % Now we calculate the X'*X matrix XTX = cat(2,ones(n_timepoints,1,size(picture,3)),picture); XTX = sym_mult(XTX); % Call our fast Cholesky decomposition routine B = fast_chol(XTX,picture_y); est2 = B(1,:); est2 = reshape(est2,[xdim,ydim]); toc Again, this should work equally well for a Nx3 X matrix, or however big you want.
I use octave, thus I can't say anything about the resulting performance in Matlab, but would expect this code to be slightly faster: pictureT=picture' est=arrayfun(#(x)( (pictureT(x,:)*picture(:,x))^-1*pictureT(x,:)*randn(n_ti mepoints,1)),1:size(picture,2));