How do I fix this uigetfile multiselect error?
Show older comments
I have developed a script to process raw data from wind turbine noise. I am attempting to adapt it to automatically process a number of files as opposed to running the script for each file individually. The script is shown below:
function ruk_am_v1_OPTI
%%Initiatilise Variables and Setup Environment
% RenewableUK AM Assessment Program - V1 December 2013
% ########################################
% Clear all variables and workspace data from system memory
clear all;
% Clear command window
clc;
% Clear all old figures
close all;
% Configure run and initialise all variables
repository = 'C:\';
blockTime = 10; % Main analysis interval (here 10 sec)
sampPerSec = 10; % Number of Leq periods per second (here 10 Hz, or 100 msec)
maxBlocks = 1440; % Maxiumum number of blocks program can process at once (4 hours)
%%Ask user to specify blade passing frequency
bladePassingFrequency = 1.25;
%%Select data file using UI control
[filename,pathname] = uigetfile('*.txt','Select the TXT file to process',repository,'Multiselect','on');
if isequal(filename, 0)
disp('User selected Cancel')
return;
end
for n = 1:length(filename)
% Create name for output file and open for output
filename = lower([pathname,filename(n)]);
filenameOut= strrep(filename(n), 'txt', 'out');
filenameOut= char(filenameOut);
fid = fopen(filenameOut, 'w');
%%Read input data
blockLength = blockTime * sampPerSec;
% Open input TXT file and read first line, which contains number of items
filename=char(filename);
fidtxt = fopen(filename(n), 'r');
dummy = fgetl(fidtxt);
totalSamples = str2double(dummy);
LeqWholePeriod = zeros(1,totalSamples);
end
% Create progress bar for reading input data
h = waitbar(0,'Reading LAeq,100msec levels from TXT file...');
for i = 1:totalSamples
dummy = fgetl(fidtxt);
LeqWholePeriod(1,i) = str2double(dummy);
waitbar(i/totalSamples);
end
close(h);
% Close input TXT data file
fclose(fidtxt);
% Determine how many 10 sec periods the input TXT file contains
numBlocks = max(1,floor(totalSamples / blockLength));
% Check that this is not more than maxBlocks, which is the maximum
if numBlocks > maxBlocks
msgBox('Cannot process more than ''maxblocks'' blocks','Program Termination Warning','warn');
return;
end
%%Put information on screen and in 'Out' file
for fileHandle = [1,fid]
fprintf(fileHandle,'Input file name %s\r\n',filename);
fprintf(fileHandle,'Output file name %s\r\n',filenameOut);
fprintf(fileHandle,'Number of samples in file %9i\r\n',totalSamples);
fprintf(fileHandle,'No of samples per sec. %9i\r\n',sampPerSec);
fprintf(fileHandle,'Duration of file %9.2f s\r\n',totalSamples/sampPerSec);
fprintf(fileHandle,'Length of data blocks %9i s\r\n',blockTime);
fprintf(fileHandle,'No of data blocks %9i\r\n',numBlocks);
% Detrend using 5th order polynomial
fprintf(fileHandle,'Detrending Method. Polynomial(');
fprintf(fileHandle,'Order 5)\r\n');
fprintf(fileHandle,'Blade passing frequency %9.2f Hz (User chosen)\r\n',bladePassingFrequency);
end
% Print file headers for output 'Out' file
fprintf(fid,'\r\n');
fprintf(fid,' Block No.| Spec Line| Frequency/Hz| Raw Spec Level/dB| Int Spec Level/dB\r\n');
%%Now loop over the whole input file in 'blockTime' second blocks
n2 = 0;
hold off
% Start processing each block in turn
for iblock = 1:numBlocks
% Block counter
disp(['Processing Block Number ',num2str(iblock),' of ',num2str(numBlocks)]);
t = 0:1/sampPerSec:blockTime-(1/sampPerSec);
n1 = 1 + n2;
n2 = min(blockLength,totalSamples) + n2;
Leq = LeqWholePeriod(1,n1:n2);
nsamp = length(Leq);
time = nsamp / sampPerSec;
if blockLength ~= nsamp(1,1)
msgbox('blockLength differs from nsamp!','Program Termination Warning','error');
end
if blockTime ~= time(1,1)
msgbox('blockTime differs from time!','Program Termination Warning','error');
end
%%Check for bad data
% Calculate Leq for 'blockTime' seconds
LeqTotal = 10*log10(1/sampPerSec*(sum(10.^(Leq/10)))/blockTime);
% Test whether max value of Leq is > 10 dB more than mean
% (implies non-stationarity rather than error) or data which
% has spikes, i.e. overal level >= 60 dB(A)
if max(Leq) - mean(Leq) > 10
iBad = 1; % set to bad data
elseif LeqTotal > 60
iBad = 1; % set to bad data
else
iBad = 0;
end
If block data NOT bad then proceed, otherwise discard it
if iBad == 0
%%Detrend and plot the Leq Data
p = polyfit(t,Leq,5);
deT = polyval(p,t);
Leq = Leq - deT; % detrend data
%%Now perform the spectral analysis of the detrended data
% Create spectrum object and call its PSD method.
h = spectrum.periodogram('Rectangular');
hopts = psdopts(h,Leq);
set(hopts,'Fs',sampPerSec,'SpectrumType','onesided');
amspec = psd(h,Leq,hopts);
% Extract results from object
Fw = amspec.Frequencies;
Pw = amspec.Data;
FreqRes = Fw(2) - Fw(1);
maxFreq = sampPerSec/2;
Pw_max = 10.0;
Pw_min = 0;
% Convert spectrum results to dB levels
ampMod = 2*sqrt(2*FreqRes*Pw);
%%Integrate the spectrum to determine the 'true' level
% Integrate the PSD to determine the energy in a critical band. The
% critical band is defined as the +/-10% of the BPF
critBand = 2 * 0.1 * bladePassingFrequency;
% determine the number of frequency intervals this includes.
windowSize = floor(critBand /FreqRes) + 1;
if mod(windowSize,2) == 0
halfWindow = windowSize/2;
else
halfWindow = (windowSize - 1)/2;
end
intAmpMod = zeros(1,length(Fw));
% Calculate rolling sum over entire spectrum
for j = 1:length(Fw)
if j <= halfWindow
% Portion of spectrum < halfWindow from beginning
intAmpMod(j) = sum(Pw(1:j + halfWindow));
elseif j >= length(Fw)- halfWindow + 1
% Portion of spectrum < halfWindow from end
intAmpMod(j) = sum(Pw(j - halfWindow:length(Fw)));
else
% rest of spectrum
intAmpMod(j) = sum(Pw(j - halfWindow:j + halfWindow));
end
end
% Convert to dB units, as before
intAmpMod = 2 * sqrt(2 * FreqRes * intAmpMod);
% Print out results to text file
for j = 1:length(Fw)
fprintf(fid,'%12i|%12i|%18.6f|%18.3f|%18.3f\r\n',iblock,j,Fw(j),ampMod(j),intAmpMod(j));
end
else %iBad ~= 0
fprintf(fid,'%12i| Bad data - affected by ',iblock);
fprintf(fid,'high energy peaks - not analysed\r\n');
end
end
%%Close all files and exit
% Turn warnings back on
warning('on','all');
% Close 'Out' text file
fprintf(fid,'\r\nRun Date: %s',datestr(now));
fclose(fid);
% Alert user that data processing is complete
msgbox('Data processing complete!','Warning Message!','warn');
The error I am receiving is as follows:
Error using fgets
Invalid file identifier. Use fopen to generate a valid file identifier.
Error in fgetl (line 33)
[tline,lt] = fgets(fid);
Error in ruk_am_v1_OPTI (line 52)
dummy = fgetl(fidtxt);
Does anyone know how to correct this?
Thanks.
Accepted Answer
More Answers (1)
In future, please trim amount of code to include only significant sections...this is a lot to wade thru to find the pertinent lines only...
Here's your problem...
...
filename=char(filename);
fidtxt = fopen(filename(n), 'r');
...
Don't convert the full array to character; simply the one cellstring needed when need to...
fidtxt = fopen(filename{n}, 'r');
"Use the curlies, Luke..."
AMPLIFICATION
As mentioned, have to cleanup TMW's mess when use the multiselect option...the portion for the input file open would then look something like--
% Select data file using UI control
[filename,pathname] = uigetfile('*.txt', ...
'Select the TXT file to process', ...
repository, ...
'Multiselect','on');
if isequal(filename, 0)
disp('User selected Cancel')
return;
end
% If user only selected one, it'll be a character string instead
% of cell string; simplest is to convert to cellstr for later
if isstr(filename), filename={filename}; end
% now length() is always over the cell array size as needed
for n = 1:length(filename)
...
fidtxt=fopen(filename{n}, 'r');
...
ADDENDUM
Tutorial info--
Once you converted the whole array, then the subscript n refers only to a single character, not a cell. But, fopen and friends haven't been "smartened up" to know how to deal with a cellstring input so you have to ensure you return the character string stored in the cell, not the cellstring. Somewhat subtle, yes, but a critical difference to learn.
2 Comments
Gavin Brown
on 21 Jan 2015
dpb
on 21 Jan 2015
OK, W.Owen reminded me of the issue with uigetfile and the MultiSelect option being as I tend to say, "user belligerent" in that it returns a different class result depending on what the user does. This is a pit(proverbial)a(ppendage) and TMW should be seriously castigated for having done it to us...anyway, as he shows, you need to test the result when using the multiple selection option...
I have run into the same problem in the past but it's been long-enough ago that it slipped my mind earlier...
See the updated response for my solution that I think is a little simpler than his altho his does work...
Categories
Find more on Logical in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!