How do I fix this uigetfile multiselect error?
显示 更早的评论
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.
采纳的回答
更多回答(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 个评论
Gavin Brown
2015-1-21
dpb
2015-1-21
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...
类别
在 帮助中心 和 File Exchange 中查找有关 Logical 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!