How do I fix this uigetfile multiselect error?

조회 수: 3 (최근 30일)
Gavin Brown
Gavin Brown 2015년 1월 19일
댓글: dpb 2015년 2월 13일
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.

채택된 답변

W. Owen Brimijoin
W. Owen Brimijoin 2015년 1월 21일
Don't know if this is the cause of your problem, but I can say that uigetfile in 'MultiSelect' mode has the bothersome behavior where it returns a variable of a different class depending on whether the user picks one or more than one file. Very frustrating! In the first instance your variable 'filename' will be a char, so
fopen(filename{n}, 'r');
will fail, saying 'Cell contents reference from a non-cell array object.' Which is true, because it's not a cell array! Similarly if you use brackets:
fopen(filename(n), 'r');
will fail, but this time it's because you have specified the filename as the first letter in the name of the file. The first method works if the user has picked more than one file... so I would advise you to first check the number of files selected as follows:
n_files = numel(cellstr(filename));
because this will accurately report the number of files selected, instead of reporting the number of files as being the number of characters in the name of the one file you picked, then loop through n_files using an if statement for the special case of one file selected:
for file = 1:n_files,
if n_files==1,
filenameOut = filename;
else filenameOut = filename{file};
end
load(filenameOut)
%load your shiny new data and do something here
end
Does this make any sense?
  댓글 수: 14
Gavin Brown
Gavin Brown 2015년 2월 13일
편집: dpb 2015년 2월 13일
I'm now trying to save all the files into a folder. I've created the folder where I want it with:
prompt1 = 'Name the destination folder:';
dlg_title1 = 'Create a destination folder';
num_lines = 1;
folder = inputdlg(prompt1,dlg_title1,num_lines);
m=cell2mat(folder);
str=sprintf('/%s',m);
mkdir('\\Biggar\noise\out. files',str);
The problem is I cant seem to get the files to save into the folder...
Any ideas?
dpb
dpb 2015년 2월 13일
Well, you show nor give no hint as to either the error(s) received nor even the code with which you tried to save the files, so, "no"...

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

dpb
dpb 2015년 1월 19일
편집: dpb 2015년 1월 21일
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
Gavin Brown 2015년 1월 21일
Okay I've removed that line and replaced the brackets around n with the curlies but I'm still getting the same error? Any more ideas?
Thanks for your help
dpb
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...

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 MATLAB에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by