Public script
Crystallite_size_distr_calculations
Doctoral Researcher
Description
The script reads a file containing in the last column observations of carbon black crystallite sizes from TEM images and computes the size distributions, printing in a text file the frequency of the observations, average size and standard deviation
This public script can be saved to your dashboard or opened in GetHug to run and modify. Its raw server storage path is not exposed.
Show Code Preview
import math
import statistics
units = {}
# Known constants
BIN_MIN_NM = 0.0
units["BIN_MIN_NM"] = "nm"
BIN_MAX_NM = 25.0
units["BIN_MAX_NM"] = "nm"
BIN_WIDTH_NM = 0.25
units["BIN_WIDTH_NM"] = "nm"
OUTPUT_FILE = "crystallite_size_distribution.txt"
units["OUTPUT_FILE"] = "text filename"
# Files to analyze
INPUT_FILE_1 = "file_1.txt"
# Calculations
num_bins = int(round((BIN_MAX_NM - BIN_MIN_NM) / BIN_WIDTH_NM))
units["num_bins"] = "count"
length_values = []
bin_counts = [0] * num_bins
with open(INPUT_FILE_1, "r", encoding="utf-8") as f:
lines = f.readlines()
# Skip the first line (weird header)
lines = lines[1:]
for line in lines:
stripped = line.strip()
# Skip empty or comment lines
if not stripped or stripped.startswith("#"):
continue
parts = stripped.split("\t")
# Skip malformed rows
if len(parts) < 1:
continue
cleaned_parts = [p.strip() for p in parts]
# Length values are in the last column
length_text = cleaned_parts[-1]
# Skip missing values
if length_text == "" or length_text.lower() == "nan":
continue
try:
length_nm = float(length_text)
units["length_nm"] = "nm"
except ValueError:
continue
# Keep only values inside the requested histogram range
if BIN_MIN_NM <= length_nm < BIN_MAX_NM:
length_values.append(length_nm)
bin_index = int((length_nm - BIN_MIN_NM) / BIN_WIDTH_NM)
if 0 <= bin_index < num_bins:
bin_counts[bin_index] += 1
observation_count = len(length_values)
units["observation_count"] = "count"
if observation_count == 0:
raise ValueError("No valid Length observations were found in the file within the requested range.")
average_crystallite_size = statistics.mean(length_values)
units["average_crystallite_size"] = "nm"
if observation_count > 1:
standard_deviation = statistics.stdev(length_values)
else:
standard_deviation = 0.0
units["standard_deviation"] = "nm"
total_counts_in_bins = sum(bin_counts)
units["total_counts_in_bins"] = "count"
with open(OUTPUT_FILE, "w", encoding="utf-8") as out_file:
out_file.write("Summary\n")
out_file.write(f"Average_crystallite_size_nm\t{average_crystallite_size:.6f}\n")
out_file.write(f"Standard_deviation_nm\t{standard_deviation:.6f}\n")
out_file.write(f"Total_observations\t{observation_count}\n")
out_file.write("\n")
out_file.write("Bin_start_nm\tBin_end_nm\tBin_center_nm\tCount\tFrequency\n")
for idx in range(num_bins):
bin_start_nm = BIN_MIN_NM + idx * BIN_WIDTH_NM
units["bin_start_nm"] = "nm"
bin_end_nm = bin_start_nm + BIN_WIDTH_NM
units["bin_end_nm"] = "nm"
bin_center_nm = (bin_start_nm + bin_end_nm) / 2.0
units["bin_center_nm"] = "nm"
count_in_bin = bin_counts[idx]
units["count_in_bin"] = "count"
frequency = count_in_bin / observation_count
units["frequency"] = "fraction"
out_file.write(
f"{bin_start_nm:.2f}\t{bin_end_nm:.2f}\t{bin_center_nm:.2f}\t{count_in_bin}\t{frequency:.6f}\n"
)
# Outputs
print(f"Processed file: {INPUT_FILE_1}")
print(f"Output written to: {OUTPUT_FILE}")
print(f"Average crystallite size: {average_crystallite_size:.6f} nm")
print(f"Standard deviation: {standard_deviation:.6f} nm")
print(f"Total observations: {observation_count}")
print("=== Variable Summary ===")
for k, v in units.items():
try:
if not isinstance(eval(k), (list, dict, set)):
print(f" {k} = {eval(k)} [{v}]")
except:
pass