Appendix
The MATLABTM code developed for determining the free space length and the agglomeration length is included in this appendix. The general algorithm of the code is as outlined:
- A 500x500 pixel bitmap (.bmp) black/white TEM image is imported to MATLABTM, and stored as matrix ‘A’, it’s elements being the grayscale values associated with each of the 250,000 pixels.
- With a threshold grayscale value of 150 to distinguish particles from the matrix, particle area fraction (‘af’) is evaluated.
- A ‘data’ matrix is next generated, which has periodic boundary conditions. In other words, the data matrix is composed of the ‘A’ pixel matrix at the core, adjoined by portions of the ‘A’ matrix such that a periodic boundary is obtained at the edge of the ‘data’ matrix. This is illustrated in figure A1, where I, II, III, IV indicate the quadrants of the original ‘A’ matrix. Note that the ‘data’ matrix is a 1000x1000 square matrix.
- An initial value of box size is inputted from the user, together with the number of random boxes that the user wishes to analyze the image with. The value of ‘xf’ is an initial, starting value. Also, if the user wishes, an image scale may also be inputted.
- Depending on whether the distribution is bimodal or not, the code iterates in steps of 1.5% of image width, reducing the initial value of ‘xf’ iteratively, until a length scale ‘ls’ yields a zero-mode. If the distribution is bimodal, the ‘false’ mode is suppressed in order to obtain the correct value of ‘ls’.
- Results are displayed, together with a histogram of particle occurrences for the given ‘Nsquare’ boxes.
Figure A1. (a) The image pixel-matrix ‘A’, with its four quadrants indicated by numerals. (b) The ‘data’ matrix, with ‘A’ at its core, and periodic boundaries along the edges. Note that ‘A’ is of order 500x500, the ‘data’ matrix is of order 1000x1000.
clear
clc
close all
%Read TEM b/w bitmap (500px x 500px) and generate pixel matrix 'A'
[filename,PathName] = uigetfile('*.bmp','Select the bmp image');
A = imread([PathName,filename],'bmp');
offx=ceil(size(A,1)/2); %Offset for periodic boundary
offy=ceil(size(A,2)/2); %Offset for periodic boundary
%Area fraction calculation
filledcells=0;
totalcells=0;
%Calculate pixels with particles (grayscale value of 150 used as threshold)
for i=1:size(A,1);
for j=1:size(A,2);
totalcells=totalcells+1;
if A(i,j)<150;
filledcells = filledcells+1;
end
end
end
af=filledcells/totalcells;
disp('Particle area fraction:')
disp(af)
%Create data matrix with periodic boundary condition
%Top layer: Elements (1,1) through (250,1000) of data matrix
for i = 1:offx;
for j = 1:offy;
Matrix(i,j)=A(offx+i,(offy+j));
end
end
for i = 1:size(A,1);
for j = 1:offy;
Matrix(i+offx,j)=A(i,j+offy);
end
end
for i = 1:offx;
for j = 1:offy;
Matrix(i+offx+size(A,1),j)=A(i,j+offy);
end
end
%Middle layer: Elements (251,1) through (750,1000) of data matrix)
for i = 1:offx;
for j = 1:size(A,2);
Matrix(i,j+offy)=A(i+offx,j);
end
end
for i = 1:size(A,1);
for j = 1:size(A,2);
Matrix(i+offx,j+offy)=A(i,j);
end
end
for i = 1:offx;
for j = 1:size(A,2);
Matrix(i+offx+size(A,1),j+offy)=A(i,j);
end
end
%Bottom layer: Elements (751,1) through (1000,1000) of data matrix
for i = 1:offx;
for j = 1:offy;
Matrix(i,j+offy+size(A,2))=A(i+offx,j);
end
end
for i = 1:size(A,1);
for j = 1:offy;
Matrix(i+offx,j+offy+size(A,2))=A(i,j);
end
end
for i = 1:offx;
for j = 1:offy;
Matrix(i+offx+size(A,1),j+offy+size(A,2))=A(i,j);
end
end
% Define initial square parameters
xf = input('Enter initial length fraction of characteristic square: ');
Nsquares = input('Enter number of squares: ');
scale= input('Enter scale for image (nm/pixels or um/pixels). Enter 0 if unknown: ');
%First count to Nsquares (corresponding to manual input of 'xf')
length = ceil(xf*size(A,1));
for i = 1:Nsquares;
x=ceil(rand*size(A,1))+offx;
y=ceil(rand*size(A,2))+offy;
counter=0;
for s = 1:length;
for t = 1:length;
mx=x-floor(length/2)+s;
my=y-floor(length/2)+t;
if Matrix(mx,my)<150;
counter=counter+1;
end
end
end
P(i)=counter;
end
data=P';
h1=hist(P,2500);
[m,n1]=max(h1);
%Automatic interation to obtain a zero-mode (iterative determination of
%'optimal' 'xf')
itr=0;
if n1~=2500 %If distribution is not bi-modal
while n1~=1
itr=itr+.015;
ls=xf-itr;
length = ceil(ls*size(A,1));
for i = 1:Nsquares;
x=ceil(rand*size(A,1))+offx;
y=ceil(rand*size(A,2))+offy;
counter=0;
for s = 1:length;
for t = 1:length;
mx=x-floor(length/2)+s;
my=y-floor(length/2)+t;
if Matrix(mx,my)<150;
counter=counter+1;
end
end
end
P(i)=counter;
end
data=P';
h2=hist(P,2500);
[m,n1]=max(h2);
end
end
if n1==2500 %If distribution is bi-modal
h1(1,n1)=0; %Supresses 'false' mode
while n1~=1
itr=itr+.015;
ls=xf-itr;
length = ceil(ls*size(A,1));
for i = 1:Nsquares;
x=ceil(rand*size(A,1))+offx;
y=ceil(rand*size(A,2))+offy;
counter=0;
for s = 1:length;
for t = 1:length;
mx=x-floor(length/2)+s;
my=y-floor(length/2)+t;
if Matrix(mx,my)<150;
counter=counter+1;
end
end
end
P(i)=counter;
end
data=P';
h1=hist(P,2500);
[m,n1]=max(h1);
h1(1,n1)=0; %Supresses 'false' mode
[m,n1]=max(h1);
end
end
disp('Value of required fractional length scale is: ')
disp(ls)
if scale~=0
lss=ls*500*scale;
disp('Value of required length is (in nm/um): ')
disp(lss)
else
disp('Cannot compute length, scale unknown')
end
hist(P,2500), xlabel('# of particle pixels in a box'), ylabel('# of occurrences')