Analyzes nanoparticles in polymer matrices to quantify the dispersion and the spacing of the particles.
This program calculates the free space length of a 2D image of particle locations. The program can analyze files of particle locations (-f), or it can simulate and analyze slices of a crystalline lattice of particles (--SC, --BCC, --FCC), or it can parse and analyze a simulation of nanoparticles in 3D (-s).
- Free-Space Length
- How To Use It
- File Formats
- Helpful Tools
- Simulator
- Current Status
- Acknowledgements
Nanoparticles are often added into polymer matrices in order to provide increased strength and toughness; however, the reinforcement they provide is highly dependant on how dispersed they are. Ideally they would be uniformally dispersed in a crystal lattice, although in practice random dispersion or agglomerated clumps is more realistic. These clumps that can form are less helpful to the polymer, and can in fact even weaken the material. Because of the major impact of the dispersion, a method of quantifying it is important. With a 3D sample, tactics such as X-ray scattering can help to figure out the dispersion, but in addition to having high complexities, they can be logistically difficult because they require the physical 3D sample. The Free-Space Length provides an alternate method of quantifying the dispersion solely based on a 2D TEM image.
The Free-Space Length, or Lf, is calculated typically as a function of the area concentration, or xf, in the image. This is the fraction of the area that is covered by particle. Lf is calculated by first starting with a square size L. A square with this side length is placed onto the image, and the number of particles contained is counted. This is repeated a statistically significant number of times, in this case 20,000 times, to find the most likely number of particles contained in a square of that size (the mode number of particles). L is then decreased, and this process repeated, until the mode is 0. The side length of the largest square containing a mode of 0 particles is called the free-space length Lf. If this square is randomly placed onto the image, it is more likely going to contain 0 particles than any other number of particles.
A larger Lf means that there is more spacing between particles. With a constant xf, a larger Lf indicates that particles are less well dispersed, because there are significant empty regions with no particles. Note that in this experiment, if a square was placed such that it crosses the edge of the image, the region outside the image "wraps around" to the opposite side of the image.
This method was proposed in this paper, and was further analyzed by Kai Zhang, me, and others. When available, the results will be linked here.
First, to compile it, the SFML library is required. It can be downloaded from this website.
To compile, from within the main directory:
$ cd Source
$ make
Then, move the resulting executible (SquareCalculator
) to a folder with the files to analyze. To run the program, do:
$ ./SquareCalculator [flags]
For example,
-f
sets the FILE to be analyzed. Must be followed by a string representing valid filepath. This flag cannot be set with a crystal lattice flag or with the -s flag.-l
sets the LENGTH DECREMENT by which a length will be decremented each iteration. A smaller numbers will get a more precise result but take longer. The default is 0.01. The final result will only be accurate based on the length decrement. This has no effect if the -s flag is set.-r
RENDERS the file in a window.help
shows these helpful descriptions.
--SC
indicates that a SIMPLE CUBIC lattice should be created and analyzed. This flag cannot be set with -f or -s.--BCC
indicates that a BODY CENTERED CUBIC lattice should be created and analyzed. This flag cannot be set with -f or -s.--FCC
indicates that a FACE CENTERED CUBIC lattice should be created and analyzed. This flag cannot be set with -f or -s.-v
sets the VOLUME FRACTION. Must be followed by a positive double. Note that it has no effect if no lattice flag has been set.-d
sets the DEPTH. Must be followed by a positive int. Note that it has no effect if the -f or -s flag is also set.-m
sets the MAX DEPTH and automatically indicates that all depths up to the maxdepth should be analyzed. Must be followed by a positive int. Note that it has no effect if the -f flag is also set. Note that some of the .crcl files parsed might be overridden by later .crcl files with higher depths, so although the data will be taken properly, not all of the .crcl files of every depth will be present.-i
indicates that the program ITERATE through all depths by cutting slices of every depth up to the max depth from the set depth or 1, if no depth was set. Then it will analyze at each depth. Note that it has no effect if the -f flag is also set.-a
indicates that ALL circle files that are created or parsed will be analyzed. Note that it has no effect if the -f flag is also set.-s
indicates that a movie_0.xyz file from a SIMULATOR should be parsed and analyzed. There must be a movie_0.xyz file in the directory. This flag cannot be set with a crystal lattice flag or with the -f flag. The -l and -d flags have no effect with -s. See the Simulator section below.
[number of particles] [diameter (1.0)] [box size] [volume fraction (can have dummy value)]
[x position] [y position] [opacity (only used for visualizer)]
[x position] [y position] [opacity]
[x position] [y position] [opacity]
...
There should be a number of lines after the header equal to [number of particles]
. The [diameter]
is generally 1
, so that the free-space length is in terms of the particle size. The [box size]
should be in the same units as [diameter]
and should be the size of the image. Finally, the [volume fraction]
is only used to keep track of the value, but is not used in the calculations. If the volume fraction is unknown, a negative value can help indicate that. Each line following the header line should be a pair of doubles represent a particle that at the position described in that line. If not using the [opacity]
, it can just be set to 0.99999
or something similar. Otherwise, it can be used as a number between 0 and 1 indicating how dark the circle should be for the visualizer, where lighter circles are supposed to be further away (deeper in the sample).
Example:
9 1.0 83.55533333 -1.0
64.79206667 0.3758666667 0.99999
2.051333333 2.674266667 0.99999
67.42993333 14.7334 0.99999
36.75553333 20.2894 0.99999
32.8416 27.88813333 0.99999
0.2868 34.95346667 0.99999
70.84446667 46.59573333 0.99999
81.302 57.742 0.99999
78.12006667 82.09406667 0.99999
Here, the image size is around 83.5 particle diameters, so all coordinates are between 0 and that bound. The points are from a TEM scan, and the volume fraction is irrelevant, so that is set to -1.0
, and opacity is defaulted to 0.99999
.
[box size 1] [free space length 1] [area fraction 1] [volume fraction 1] [depth 1]
[box size 2] [free space length 2] [area fraction 2] [volume fraction 2] [depth 2]
...
Each line stores the output of a single run of the program with certain settings. The [box size]
is the size of the entire image of particles, in units of particle diameters. The [free space length]
is the calculated side length of the square that contains 0 particles more than any other number of particles when placed randomly in the box. It is also in units of particle diameters. The [area fraction]
is the fraction of the 2D image taken up by particles, out of the whole area.
Note: both [volume fraction]
and [depth]
should be ignored if the program analyzed a given file of particle positions (such as a TEM image). This means that it was neither particles from a crystal lattice nor a frame from the simulation. The [volume fraction]
is the fraction of the 3D space that is taken up by particles, out of the whole volume. The 2D image may be a slice of the 3D image that has been flattened into 2D. The [depth]
is the height of the slice, again in units of particle diameters.
Example:
51.177554 6.667554 0.010124 0.002000 3.333330
51.177554 7.237554 0.010990 0.002000 3.333330
51.177554 8.677554 0.010423 0.002000 3.333330
51.177554 8.537554 0.008337 0.002000 3.333330
51.177554 9.017554 0.006850 0.002000 3.333330
51.177554 8.217554 0.008898 0.002000 3.333330
29.928815 2.748815 0.043918 0.010000 3.333330
29.928815 3.318815 0.042464 0.010000 3.333330
29.928815 2.838815 0.053807 0.010000 3.333330
29.928815 2.568815 0.047782 0.010000 3.333330
29.928815 3.058815 0.052229 0.010000 3.333330
29.928815 4.538815 0.042347 0.010000 3.333330
Here, 12 samples give the free-space length (in units of particle diameters) based on given particle configurations. There are two sets of 6 trials, where each set has a specific volume concentration with simulated particles. Each trial is a slice of a 3D image of the simulated particles. The depth was held constant.
See analyzeData.py
in Helpful Tools below for a python file that analyzes the output data to find a line of best fit.
[box size]
[initial side length] [mode number of particles contained]
[next side length] [mode number of particles contained]
...
[next side length] [mode number of particles contained]
[final side length] 0
After the first line, each line represents a tested box size. The [side length]
is the size of that box. It is units of particle diameters. When a large number of boxes are randomly placed onto the image, and the number of particles contained are counted, the mode (more boxes contain that many particles than any other number of particles) is the [mode number of particles contained]
. The side length of the first box with a mode of 0
contained particles is the free-space length, so the simulation will stop when it gets to a box that has a mode of 0
.
Example:
10.235511
0.807960 2
0.806960 2
0.805960 2
...
0.018960 1
0.017960 1
0.016960 0
Here, the first tested side length is 0.807960
, and the size of the box is decreased by 0.001
every iteration. The initial box has a mode of 2 particles contained. The free space length is 0.016960
because that is the largest box containing a mode of 0
particles.
Note that if the initial box has a mode of 0 particles, the side length is increased until the mode isn't 0
. This ensures that the largest box with a mode of 0
is found, as opposed to an arbitrary one with a mode of 0
.
[box size] [current side length] [mode with given square length]
0 [number of boxes with 0 particles]
1 [number of boxes with 1 particle]
2 [number of boxes with 2 particles]
...
As the program goes through different side lengths, it will periodically record data on the number of squares that had a each number of particles, for a given square size. The histogram for the final square size tested (the free-space length) will always be recorded. The largest square size to contain 0 particles more often than any other number of particles is the free-space length. The [box size]
is the size of the entire image. The [current side length]
is the size of the square. The [mode]
is the most common number of particles contained in teh square when many are randomly placed throughout the entire image. The [box size]
and the [side length]
are in units of particle diameters.
Intermediate histogram example:
47.509033 7.509033 6
0 3
1 105
2 360
3 847
4 1772
5 2349
6 2736
7 2493
8 2112
9 1875
10 1625
11 1212
12 895
13 691
14 446
15 290
16 148
17 36
18 5
19 0
20 0
Last histogram example:
47.509033 2.129033 0
0 7336
1 7265
2 3704
3 1299
4 324
5 70
6 2
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 0
15 0
16 0
17 0
18 0
19 0
20 0
Here, the first example is a histogram taken with a square size greater than the free-space length. The mode is 6 because more boxes (2736) contain 6 particles than any other number of particles. Because the mode is greater than 0, this is not the free-space length. The second example shows a box size where the square length is the free-space length. That is because there, the mode is 0.
See HistogramVisualizer.py
in Helpful Tools below for a python file that analyzes the output data to find a line of best fit.
[number of squares] [box size]
[x position] [y position] [side length]
[x position] [y position] [side length]
[x position] [y position] [side length]
...
This file is typically used by the visualizer for drawing squares on a picture of the particles. There should be a number of lines after the header equal to [number of particles]
. This is typically 1. [x position]
and [y position]
are used for rendering the square. [side length]
is the calculated free-space length, which is the side length of the square for which the mode number of particles contained is 0.
Example:
1 10.235511
7.922514 10.171255 0.016960
Here, there will be 1 square drawn of side length 0.016960
at position (7.922514, 10.171255)
. The size of the entire image is 10.235511
.
Run python histogramVisualizer.py [n]
to view the histogram stored within the file, distribution_n.txt.
The nth distribution file must exist in the Run directory.
In the window that is opened, the button with a magnifying glass can be used to zoom in on a specific region of the graph, and the home button will reset all zooms and translations.
This python script will attempt to find the linear relationship between two variables.
The default is that the free-space length (Lf
) is graphed as a function of the area concentration (xf
), using the file output.txt
(note that using this file means that each run of the program results in only a single data point.).
python analyzeData.py
will find Lf
as a function of xf
from output.txt
.
python analyzeData.py [filename]
will find Lf
as a function of xf
from the specified file.
python analyzeData.py [x] [y]
will find y as a function of x from the output.txt
.
python analyzeData.py [filename] [x] [y]
will find y as a function of x from the specified file.
Note that the possibilities for x and y are:
lf
: The free-space length (square size)xf
: The area fractionv
: The volume fraction (irrelevant with TEM images)d
: The depth of each slice (irrelevant with TEM images)- anything else: The side length of the box
Run ./clear
to clear the directory. WARNING: This will remove all distribution_*.txt
, mode.txt
, and *.sqr files
.
output.txt
files are not affected. They must be manually removed.
If this can't be run, first run chmod +x clear
in the directory with clear
. This turns the file into a script which can be executed.
The -s flag indicates that a simulated 3D cube of particles will be analyzed. The program will parse a movie_0.xyz file (see below), then cut the resulting cube into slices with a thickness equal to the depth, outputting a .crcl file for each slice (on all 3 axes). Then, each .crcl file is analyzed. movie_0.xyz files can be created using Kai Zhang's Hard Sphere simulator.
When the program is being run in this mode, settings can be set using an external file. The file makecalcinput can be editted to set the following parameters.
- framesToIgnore — The number of frmes of the simulation from the movie file to ignore. Because the Hard Sphere simulator begins with the particles in a lattice configuration before they move randomly, ignoring the first few frames, say 10, is necessary to get particles in random 3D positions.
- framesToRecord — This is the number of frames to parse and slice up. This is typically 1, but especially with very large depths, if a single frame doesn't provide enough samples, then this can be increased.
- depth — This OVERRIDES a depth provided with the -d flag.
- squareLengthDecrement — This OVERRIDES a decrement provided with the -l flag.
This program was made with the help of Kai Zhang for Prof. Sanat Kumar in the Department of Chemical Engineering at Columbia University. It would not have been possible without the assistance and guidance of Kai.