Matlab) what should I put more with function for, sttrep, cell? - matlab

I want to make the results like this:
phraseblanks
phrasemat = Hello and how are you?
Hi there everyone!
How is it going?
WHazzup?
Phrase 1 had 4 blanks
Phrase 2 had 3 blanks
Phrase 3 had 2 blanks
Phrase 4 had 0 blanks
New phrasemat is :
Hello&and&how&are&you?
Hi&there&everyone!
How&is&it&going?
WHazzup?
so I made script "phraseblanks.m":
phrasemat = char('Hello and how are you?', ...
'Hi there everyone!', 'How is it going?', 'WHazzup?')
[r, c] = size(phrasemat);
for i = 1:r
phrasemat_new = cell(r, c);
howmany = countblanks(phrasemat(i, :));
fprintf('Phrase %d had %d blanks\n', i, howmany);
phrasemat(i,:) = strrep(phrasemat(i,:),' ','&')
phrasemat_new{i,:} = [phrasemat(i,:)];
end
fprintf('Changing one is %s\n', eval('phrasemat_new'));
script "countblanks.m":
function num = countblanks(phrase)
% countblanks returns the # of blanks in a trimmed string
% Format: countblanks(string)
num = length(strfind(strtrim(phrase), ' '));
end
and I keep having errors.
please help me..

I modified slightly your phraseblanks.m so that it works.
phrasemat = {'Hello and how are you?', ...
'Hi there everyone!', ...
'How is it going?', ...
'WHazzup?'};
r = numel(phrasemat);
phrasemat_new = cell(1, r);
for i = 1:r
howmany = countblanks(phrasemat{i});
fprintf('Phrase %d had %d blanks\n', i, howmany);
phrasemat{i} = strrep(phrasemat{i}, ' ', '&');
phrasemat_new(i) = phrasemat(i);
end
fprintf('Changing one is %s\n', phrasemat_new{:});
Obviously it could be written in a nicer, more "matlaby-way", but I didn't want to stride too far from your original version. Also you could consider using regular expressions, since if you have to spaces next to each other and you want to treat them as one blank space.

Related

Excel Range object throws error 0x800A03EC because of a string longer than 255 characters

Using an ActiveX server from MATLAB, I am trying to highlight many cells in an Excel sheet at once. These are not in specific columns or rows so I use Range('A1,B2,...') to access them. However the string accepted by the Range object has to be less than 255 characters or an error:
Error: Object returned error code: 0x800A03EC
is thrown. The following code reproduces this error with an empty Excel file.
hActX = actxserver('Excel.Application');
hWB = hActX.Workbooks.Open('C:\Book1.xlsx');
hSheet = hWB.Worksheets.Item('Sheet1');
col = repmat('A', 100, 1);
row = num2str((1:100)'); %'
cellInd = strcat(col, strtrim(cellstr(row)));
str1 = strjoin(cellInd(1:66), ','); %// 254 characters
str2 = strjoin(cellInd(1:67), ','); %// 258 characters
hSheet.Range(str1).Interior.Color = 255; %// Works
hSheet.Range(str2).Interior.Color = 255; %// Error 0x800A03EC
hWB.Save;
hWB.Close(false);
hActX.Quit;
How can I get around this? I found no other relevant method of calling Range, or of otherwise getting the cells I want to modify.
If you start with a String, you can test its length to determine if Range() can handle it. Here is an example of building a diagonal range:
Sub DiagonalRange()
Dim BigString As String, BigRange As Range
Dim i As Long, HowMany As Long, Ln As String
HowMany = 100
For i = 1 To HowMany
BigString = BigString & "," & Cells(i, i).Address(0, 0)
Next i
BigString = Mid(BigString, 2)
Ln = Len(BigString)
MsgBox Ln
If Ln < 250 Then
Set BigRange = Range(BigString)
Else
Set BigRange = Nothing
arr = Split(BigString, ",")
For Each a In arr
If BigRange Is Nothing Then
Set BigRange = Range(a)
Else
Set BigRange = Union(BigRange, Range(a))
End If
Next a
End If
BigRange.Select
End Sub
For i = 10, the code will the the direct method, but if the code were i=100, the array method would be used.
The solution, as Rory pointed out, is to use the Union method. To minimize the number of calls from MATLAB to the ActiveX server, this is what I did:
str = strjoin(cellInd, ',');
isep = find(str == ',');
isplit = diff(mod(isep, 250)) < 0;
isplit = [isep(isplit) (length(str) + 1)];
hRange = hSheet.Range(str(1:(isplit(1) - 1)));
for ii = 2:numel(isplit)
hRange = hActX.Union(hRange, ...
hSheet.Range(str((isplit(ii-1) + 1):(isplit(ii) - 1))));
end
I used 250 in the mod to account for the cell names being up to 6 characters long, which is sufficient for me.

Matlab; how to extract information from a header's file (text file)

I have many text files that have 35 lines of header followed by a large matrix with data of an image (that info can be ignored and do not need to read it at the moment). I want to be able to read the header lines and extract information contained on those lines. For instance the first few lines of the header are..
File Version Number: 1.0
Date: 06/05/2015
Time: 10:33:44 AM
===========================================================
Beam Voltage (-kV) = 13.000
Filament (W) = 4.052
Cond. (-kV) = 8.885
CenterX1 (V) = 10.7
CenterY1 (V) = -45.9
Objective (%) = 71.40
OctupoleX = -0.4653
OctupoleY = -0.1914
Angle (deg) = 0.00
.
I would like to be able to open this text file and read the vulue of the day and time the file was created, filament power, the condenser voltage, the angle, etc.. and save these in variables or send them to a text box on a GUI program.
I have tried several things but since the values I want to extract some times are after a '=' or after a ':' or simply after a '' then I do not know how to approach this. Perhaps reading each line and look for a match of a word?
Any help would be much appreciated.
Thanks,
Alex
This is not particularly difficult, and one of the ways to do it would be to parse line-by-line as you suggested. Something like this:
MAX_LINES_TO_READ = 35;
fid = fopen('input.txt');
lineCount = 0;
dateString = '';
beamVoltage = 0;
while ~eof(fid)
line = fgetl(fid);
lineCount = lineCount + 1;
%//check conditions for skipping loop body
if isempty(line)
continue
elseif lineCount > MAX_LINES_TO_READ
break
end
%//find headers you are interested in
if strfind(line, 'Date')
%//find the first location of the header separator
idx = find(line, ':', 1);
%//extract substring starting from 1 char after separator
%//note: the trim is to get rid of leading/trailing whitespace
dateString = strtrim(line(idx + 1 : end));
elseif strfind(line, 'Beam Voltage')
idx = find(line, '=', 1);
beamVoltage = str2double(line(idx + 1 : end));
end
end
fclose(fid);

Extraction of data from DWT subband

I am attempting to extract data from a DWT subband. I am able to embed data correctly (I have followed it in the debugger),cal PSNR etc. PSNR rate seem very high 76.2?? however,I am having lot of trouble extracting data back!It is sometimes extracting the number 128?? Can anyone help or have any idea why this is? I would be very thankful.I have been working on this all day & having no luck!I am very curious to know??
Data Embedding:
coverImage = imread('lena.bmp');
message = importdata('minutiaTest.txt');
%message = 'Bifurcations:';
[LL,LH,HL,HH] = dwt2(coverImage,'haar');
if size(message) > size(coverImage,1) * size(coverImage,2)
error ('message too big to embed');
end
bit_count = 0;
steg_coeffs = [4, 4.75, 5.5, 6.25, 7];
for jj=1:size(message,2)+1
if jj > size(message,2)
charbits = [0,0,0,0,0,0,0,0];
else
charbits = dec2bin(message(jj),8)';
charbits = charbits(:)'-'0';
end
for ii=1:8
bit_count = bit_count + 1;
if charbits(ii) == 1
if HH(bit_count) <= 0
HH(bit_count) = steg_coeffs(randi(numel(steg_coeffs)));
end
else
if HH(bit_count) >= 0
HH(bit_count) = -1 * steg_coeffs(randi(numel(steg_coeffs)));
end
end
end
end
stego_image = idwt2(LL,LH,HL,HH,'haar');
imwrite(uint8(stego_image),'newStego.bmp');
Data Extraction:
new_Stego = imread('newStego.bmp');
[LL,LH,HL,HH] = dwt2(new_Stego,'haar');
message = '';
msgbits = '';
for ii = 1:size(HH,1)*size(HH,2)
if HH(ii) > 0
msgbits = strcat (msgbits, '1');
elseif HH(ii) < 0
msgbits = strcat (msgbits, '0');
else
return;
end
if mod(ii,8) == 0
msgChar = bin2dec(msgbits);
if msgChar == 0
break;
end
msgChar = char (msgChar);
message = [message msgChar];
msgbits = '';
end
end
The problem arises from reading your data with importdata.
This command will load the data to an array. Since you have 39 lines and 2 columns (skipping any empty lines), its size will be 39 2. However, the program assumes that your message will be a string. For example, 'i am a string' has a size 1 13. This expectation of the program compared to the data you actually give it creates all sorts of problems.
What you want is to read your data as a single string, where the number 230 is not one element, but 3 individual characters. Tabs and newlines will also be read in as well.
To read your file:
message = fileread('minutiaTest.txt');
After you extract your message, to save it to a file:
fid = fopen('myFilename.txt','w');
fprintf(fid,message);
fclose(fid);

nested for loop query

I am trying to do something rather simple, but can't seem to get it...
I have 3 cell-arrays with strings,
A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage';...
'Sugar'}
I want to produce a vector with the concatenated (strcat?) combinations, as it this were a "tree diagram", like:
strcat(A(1),B(1),C(1))
strcat(A(1),B(1),C(2))
strcat(A(1),B(1),C(3))
strcat(A(1),B(1),C(4))
strcat(A(1),B(1),C(5))
strcat(A(1),B(1),C(6))
strcat(A(1),B(1),C(7))
strcat(A(1),B(2),C(1))
So what the first elements I am trying to get are (in a column ideally):
ConditionACase1Rice
ConditionACase1Beans
ConditionACase1Carrots
ConditionACase1Cereal
ConditionACase1Tomato
ConditionACase1Cabbage
ConditionACase1Sugar
ConditionACase2Rice
etc etc etc...
I know that:
for i=1:length(A)
E(i) = strcat(A(i),B(1),C(1))
end
Works for one "level". I have tried:
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(i) = strcat(A(i),B(j),C(k));
end
end
end
But this doesn't work...
I would be really grateful if I could be helped with this.
Thanks in advance!
From what I understood, you want all possible combinations of the strings of the input arrays as specified. If so, simply replace your nested loops with the following:
P = cell(length(A)*length(B)*length(C),1);
t=1;
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(t) = strcat(A(i),B(j),C(k));
t = t+1;
end
end
end
For the input arrays,
>> A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
>> B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
>> C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage';'Sugar'};
The value of P would be:
>> P
P =
'ConditionACase1Rice'
'ConditionACase1Beans'
'ConditionACase1Carrots'
'ConditionACase1Cereal'
'ConditionACase1Tomato'
'ConditionACase1Cabbage'
'ConditionACase1Sugar'
'ConditionACase2Rice'
'ConditionACase2Beans'
'ConditionACase2Carrots'
'ConditionACase2Cereal'
'ConditionACase2Tomato'
'ConditionACase2Cabbage'
'ConditionACase2Sugar'
'ConditionACase3Rice'
'ConditionACase3Beans'
'ConditionACase3Carrots'
'ConditionACase3Cereal'
'ConditionACase3Tomato'
'ConditionACase3Cabbage'
'ConditionACase3Sugar'
'ConditionACase4Rice'
'ConditionACase4Beans'
'ConditionACase4Carrots'
'ConditionACase4Cereal'
'ConditionACase4Tomato'
'ConditionACase4Cabbage'
'ConditionACase4Sugar'
'ConditionBCase1Rice'
'ConditionBCase1Beans'
'ConditionBCase1Carrots'
'ConditionBCase1Cereal'
'ConditionBCase1Tomato'
'ConditionBCase1Cabbage'
'ConditionBCase1Sugar'
'ConditionBCase2Rice'
'ConditionBCase2Beans'
'ConditionBCase2Carrots'
'ConditionBCase2Cereal'
'ConditionBCase2Tomato'
'ConditionBCase2Cabbage'
'ConditionBCase2Sugar'
'ConditionBCase3Rice'
'ConditionBCase3Beans'
'ConditionBCase3Carrots'
'ConditionBCase3Cereal'
'ConditionBCase3Tomato'
'ConditionBCase3Cabbage'
'ConditionBCase3Sugar'
'ConditionBCase4Rice'
'ConditionBCase4Beans'
'ConditionBCase4Carrots'
'ConditionBCase4Cereal'
'ConditionBCase4Tomato'
'ConditionBCase4Cabbage'
'ConditionBCase4Sugar'
'ConditionCCase1Rice'
'ConditionCCase1Beans'
'ConditionCCase1Carrots'
'ConditionCCase1Cereal'
'ConditionCCase1Tomato'
'ConditionCCase1Cabbage'
'ConditionCCase1Sugar'
'ConditionCCase2Rice'
'ConditionCCase2Beans'
'ConditionCCase2Carrots'
'ConditionCCase2Cereal'
'ConditionCCase2Tomato'
'ConditionCCase2Cabbage'
'ConditionCCase2Sugar'
'ConditionCCase3Rice'
'ConditionCCase3Beans'
'ConditionCCase3Carrots'
'ConditionCCase3Cereal'
'ConditionCCase3Tomato'
'ConditionCCase3Cabbage'
'ConditionCCase3Sugar'
'ConditionCCase4Rice'
'ConditionCCase4Beans'
'ConditionCCase4Carrots'
'ConditionCCase4Cereal'
'ConditionCCase4Tomato'
'ConditionCCase4Cabbage'
'ConditionCCase4Sugar'
'ConditionDCase1Rice'
'ConditionDCase1Beans'
'ConditionDCase1Carrots'
'ConditionDCase1Cereal'
'ConditionDCase1Tomato'
'ConditionDCase1Cabbage'
'ConditionDCase1Sugar'
'ConditionDCase2Rice'
'ConditionDCase2Beans'
'ConditionDCase2Carrots'
'ConditionDCase2Cereal'
'ConditionDCase2Tomato'
'ConditionDCase2Cabbage'
'ConditionDCase2Sugar'
'ConditionDCase3Rice'
'ConditionDCase3Beans'
'ConditionDCase3Carrots'
'ConditionDCase3Cereal'
'ConditionDCase3Tomato'
'ConditionDCase3Cabbage'
'ConditionDCase3Sugar'
'ConditionDCase4Rice'
'ConditionDCase4Beans'
'ConditionDCase4Carrots'
'ConditionDCase4Cereal'
'ConditionDCase4Tomato'
'ConditionDCase4Cabbage'
'ConditionDCase4Sugar'
Let me know if you need further assistance.
I am not really familiar with matlab.. but maybe try something like this?
for A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
for B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
for C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage'; 'Sugar'}
P(i) = strcat(A(i),B(j),C(k));
end
end
end
{
x = 1;
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(x) = strcat(A(i),B(j),C(k));
x = x + 1;
end
end
end
}
Please basically check your code before posting to PO as this is a very simple debugging

How can I load 100 files with similar names and/or string in just one step in MATLAB?

I have 100 ASCII files in my directory all named as follows:
int_001.ASC
int_002.ASC
int_003.ASC
.
.
.
int_099.ASC
int_100.ASC
I have to import them in MATLAB all with importdata, which should work as follows:
A = importdata('int_001.ASC', ' ', 9)
x = A.data(:,1)
y = A.data(:,2)
My question is: how can I avoid writing 100 times importdata? Is there a way to write the first string only and then have all data uploaded?
Thanks
fls = dir( 'int_*.ASC' );
for fi=1:numel(fls)
A{fi} = importdata( fls(fi).name, ' ', 9 );
% ...
end
UPDATE:
You may use string formatting to read the files according to their numbers:
for fi=1:100
A{fi} = importdata( sprintf('int_%03d.ASC', fi ), ' ', 9 );
% ...
end
You can use strcat function in a for loop :
for k=1:n
fileName = strcat('int_',num2str(k, '%03d'),'.ASC');
A(k) = importdata(fileName, ' ', 9);
x(k) = A(k).data(:,1);
y(k) = A(k).data(:,2);
end
If you want to take this a little overboard:
alldata = arrayfun(...
#(dirEntry)importdata(dirEntry.name, ' ', 9), ...
dir('int_*.ASC'),...
'uniformoutput',false);
This line does the following
Gets a listing of all files matching the partial filename, as an array of structures (h/t Shai)
For each element in that array, performs the importdata call from your original post.
Compiles all the outputs into a cell array.