Reproducible protocol for the extraction and semi-automated quantification of macroscopic charcoal from soil
Javier Ruiz-Pérez, Julie C. Aleman, Joseph W. Veldman
Disclaimer
USE AT YOUR OWN RISK
Any action you take or refrain from taking using or relying upon the information presented in this protocol is strictly at your own risk. You agree that neither the Company nor any of the authors, contributors, administrators, or anyone else associated with protocols.io 1) can be held responsible for your use of the information contained in or linked to this protocol or any of our Sites/Apps and Services; 2) can be liable for any special, incidental, indirect, or consequential damages whatsoever arising out of or in connection with your access or use the protocol; and 3) can be liable to you or anyone else for any decision made or action taken in reliance on the information given by the protocol or for any consequential, special or similar damages, even if advised of the possibility of such damages.
Abstract
Charcoal fragments preserved in soils or sediments are used by scientists to reconstruct fire histories and thereby improve our understanding of past vegetation dynamics and human-plant relationships. Unfortunately, most published methods for charcoal extraction and analysis are incompletely described and are therefore difficult to reproduce. To improve the standardization and replicability of soil charcoal analysis, as well as to facilitate accessibility for non-experts, we developed a detailed, step-by-step protocol to isolate charcoal from soil and to efficiently count and measure charcoal fragments. The extraction phase involves the chemical soaking and wet sieving of soils followed by the collection of macrocharcoal (≥500 μm). The analysis phase is performed semi-automatically using the open-source software ImageJ to count and measure the area, length, and width of fragments from light stereo microscope images by means of threshold segmentation. The protocol yields clean charcoal fragments, a set of charcoal images, and datasets containing total charcoal mass, number of fragments, and morphological measurements (area, length, and width) for each sample. We tested and validated the protocol on 339 soil samples from tropical savannas and forests in eastern lowland Bolivia. We hope that this protocol will be a valuable resource for scientists in a variety of fields who currently study, or wish to study, macroscopic charcoal in soils as a proxy for past fires.
Before start
The extraction procedure and the counting and measurement method are independent, and therefore the extraction phase can be used for purposes other than counting and measuring charcoal fragments (e.g., radiocarbon dating), while the quantification phase can be performed on charcoal samples obtained following other extraction procedures.
For reference, a list of equipment, chemicals, consumables, and software that we used to develop and test this protocol is provided in the Materials section.
Steps
Charcoal extraction
Preparation of samples
1.A. Oven-dry soil samples to constant weight at 40 ºC.
1.B. Label ≥200 mL beakers.
1.C. Place 20 g of each soil sample in a beaker and record weight (after taring the weight of the beaker).

Dispersion and digestion of soils
2.A. To each beaker containing 20 g of soil, add 100 mL of a solution of 2.5% sodium hexametaphosphate (Na6P6O18) and 5% hydrogen peroxide (H2O2)—prepared as a 1:1 mixture of 50 mL of 5% sodium hexametaphosphate and 50 mL of 10% hydrogen peroxide.
2.B. Place the beakers in an orbital shaker at 250-300 RPM and leave them reacting for 24 hours.

Sieving of samples
3.A. Place a sieve with a 500-micron mesh over a container or sink and gently pour each sample (i.e., the soil sample with the solution) from the beaker into the sieve using a wash bottle with purified water.
3.B. Carefully rinse each sample with purified water, utilizing either a wash bottle or running water from a faucet, until only particles ≥500 microns are retained, separated from each other, and charcoal fragments are clean.

Collection of macroscopic charcoal and storage
4.A. Label sample containers (e.g., vials), weigh them, and record weight. Carefully collect the charcoal fragments from the sieve using tweezers and transfer them to the containers. Discard all non-charcoal material.
4.B. To remove moisture from the charcoal fragments, oven-dry the containers while open at 40 ºC.
4.C. Visually inspect the extracted material in the containers, with the naked eye or under magnification, to remove non-charcoal bodies (i.e., extraneous material, like plant parts or sand grains, may attach to the charcoal fragments or be mistaken for charcoal while the samples are wet in step 4.A). Weigh the containers with the extracted charcoal and record weight. Store the containers with their lids closed in a dry environment; the samples are ready for analysis.

Charcoal counting and measurement
Images acquisition
5.A. For each sample, carefully place the extracted charcoal on a Petri dish (with the help of tweezers, a Chattaway spatula, or purified water, for example). To avoid dense clusters and overlapping fragments, add small amounts to the Petri dish, proceed to step 5.B, and repeat until all charcoal has been photographed. We recommend using a gridded Petri dish to facilitate image acquisition when the microscope field of view does not cover the entire Petri dish and multiple pictures per sample need to be taken.
5.B. Take pictures of the charcoal fragments under a light stereo microscope mounted with a digital camera. A magnification of 10-15x should be appropriate for charcoal fragments ≥500 µm. Images must have comparable settings (e.g., resolution, exposure, white balance) and same magnification. At least one image with a reference scale on it (e.g., scale bar) must be acquired to calculate the scale parameters in ImageJ in step 6.C.
5.C. Save all images in one folder and create another folder where to save the results to be obtained with ImageJ in step 6.C.


Counting and measurement
6.A. Download ImageJ from https://imagej.net/ij/download.html. ImageJ is an open source and multi-platform software that runs on Microsoft Windows, macOS, and Linux.
6.B. Copy the macro code from below and save it as a text file (i.e., with extension .txt). The macro allows the user to automatically isolate charcoal fragments from a group of images by means of global threshold segmentation (i.e., classification of pixels into two classes using a certain cut-off value), count and measure them (area, length, and width), and export the results. The output files consist of 1) a CSV file with the parameters set for analysis (see 6.C), date of analysis, and software versions; 2) a CSV file containing the counting and measurement data; and 3) outline image(s) in JPEG or TIFF format. The macro has been written and tested using ImageJ version 1.54d for Microsoft Windows with Java version 1.8.0_345.
6.C. Start ImageJ, go to Plugins -> Macros -> Run... , and open the macro saved in step 6.B. A parameters window will open and the following settings can be entered:
- Folder containing the images to be analyzed and the destination folder to save the output files.
- Scale unit of the images, known distance in original unit, and its equivalent in pixels. To obtain the scale values in ImageJ, 1) open an image with a reference scale such a scale bar ( File -> Open... ); 2) select the tool Straight Line (i.e., fifth tool from the left on the ImageJ toolbar); 3) draw a line along the length of the scale bar while holding the Shift key in the keyboard; and 4) go to Analyze -> Set Scale... and record the distance in pixels and the known distance values.
- Thresholding method and, if Manual method is selected, minimum and maximum pixel values (from 0 to 255) to discriminate the charcoal fragments against the background and non-charcoal particles. Automatic thresholding methods are described at https://imagej.net/plugins/auto-threshold#available-methods. Manual threshold values can be explored in ImageJ by 1) opening an image ( File -> Open... ); 2) transforming the image to grayscale ( Image -> Type -> 8-bit ); and 3) directly adjusting threshold values with the Threshold tool ( Image -> Adjust -> Threshold... ). Note that, when manual thresholding is selected, the macro applies the same minimum and maximum threshold values entered in the dialogue box to all images; in contrast, when an automatic threshold method is selected, it will calculate new threshold values for each image. To learn more about the threshold tool, visit https://imagej.net/ij/docs/guide/146-28.html#sub:Threshold...[T].
- Size range (in the set unit, from 0 to Infinity) of the fragments to be counted and measured. Note that fragments touching the edges of the images are excluded from analysis.
- Watershed segmentation to automatically separate fragments in contact (https://imagej.net/ij/docs/menus/process.html#watershed).
- Holes filling to fill holes within charcoal.
- Outline images format as JPEG or TIFF.
// 1. TITLE
// Macro to automatically detect, count, and measure charcoal fragments from a batch of images in ImageJ
// 2. AUTHORS, DATE, AND LICENSE
// Javier Ruiz-Pérez (jruizperez@tamu.edu, javier.ruizperez.academic@gmail.com) - Department of Ecology and Conservation Biology, Texas A&M University; Julie C. Aleman - Centre Européen de Recherche et d’Enseignement des Géosciences de l’Environnement, Centre National de la Recherche Scientifique; Joseph W. Veldman - Department of Ecology and Conservation Biology, Texas A&M University
// 2024
// This macro is distributed under the terms of a CC BY 4.0 license
// 3. DESCRIPTION
// Macro to automatically detect, count, and measure (i.e., area, length, and width) charcoal fragments in a set of images via global thresholding (i.e., classification of pixels into two classes using a cut-off value) and export the results. The output files consist of 1) a CSV file with the parameters set for analysis, date of analysis, and software versions; 2) a CSV file containing the counting and measurement data; and 3) outline image(s) in JPEG or TIFF format. This macro has been written and tested using ImageJ version 1.54d for Microsoft Windows with Java version 1.8.0_345. To use it, download ImageJ from https://imagej.net/ij/download.html, open it, go to Plugins -> Macros -> Run..., and open this macro as a .txt file
// 4. SCRIPT
// The script has two sections: definition of parameters (section 4.1) and batch analysis (section 4.2). The following parameters are entered in a dialog box:
// 1) Folder containing the images to be analyzed (input) and destination folder to save the output files (output)
// 2) Scale unit of the images (unit), known distance in original unit (distanceUnit), and its equivalent in pixels (distancePixels). To obtain the scale values in ImageJ, 1) open an image with a reference scale such a scale bar (File -> Open...); 2) select the tool Straight Line (i.e., fifth tool from the left on the ImageJ toolbar); 3) draw a line along the length of the scale bar while holding the Shift key in the keyboard; and 4) go to Analyze -> Set Scale... and record the distance in pixels and the known distance values
// 3) Thresholding method (thresholdMethod) and, if Manual method is selected, minimum and maximum pixel values (thresholdMin, thresholdMax, respectively, from 0 to 255) to discriminate the charcoal fragments against the background and non-charcoal particles. Automatic thresholding methods are described at https://imagej.net/plugins/auto-threshold#available-methods. Manual threshold values can be explored in ImageJ by 1) opening an image (File -> Open...); 2) transforming the image to grayscale (Image -> Type -> 8-bit); and 3) directly adjusting threshold values with the Threshold tool (Image -> Adjust -> Threshold...). Note that, when manual thresholding is selected, the macro applies the same minimum and maximum threshold values entered in the dialogue box to all images; in contrast, when an automatic threshold method is selected, it will calculate new threshold values for each image. To learn more about the threshold tool, visit https://imagej.net/ij/docs/guide/146-28.html#sub:Threshold...[T]
// 4) Size range (in the set unit, from 0 to Infinity) of the fragments to be counted and measured (sizeMin, sizeMax). Note that fragments touching the edges of the images are excluded from analysis
// 5) Watershed segmentation (separation) to automatically separate fragments in contact (https://imagej.net/ij/docs/menus/process.html#watershed)
// 6) Holes filling (holes) to fill holes within charcoal
// 7) Outline images format as JPEG or TIFF (format)
// 4.1. Parameters dialog
// List of parameters and default values
input = "Input folder";
output = "Output folder";
unit = newArray("micron", "mm", "cm");
distanceUnit = 1000;
distancePixels = 185.75;
thresholdAutoMethods = getList("threshold.methods");
thresholdMethod = Array.concat("Manual", thresholdAutoMethods);
thresholdMin = 0;
thresholdMax = 116;
sizeMin = 500;
sizeMax = "Infinity";
separation = newArray("No", "Yes");
holes = newArray("No", "Yes");
format = newArray("Jpeg", "Tiff");
// Parameters dialog box
Dialog.create("Select parameters");
Dialog.addDirectory("Folder containing the images to be analyzed:", input);
Dialog.addDirectory("Folder where to save the results:", output);
Dialog.addChoice("Scale unit:", unit);
Dialog.addNumber("Scale distance in original unit:", distanceUnit);
Dialog.addNumber("Scale distance in pixels:", distancePixels);
Dialog.addChoice("Thresholding method:", thresholdMethod);
Dialog.addNumber("Minimum manual threshold (0 to 255):", thresholdMin);
Dialog.addNumber("Maximum manual threshold (0 to 255):", thresholdMax);
Dialog.addNumber("Minimum charcoal size in set unit:", sizeMin);
Dialog.addNumber("Maximum charcoal size in set unit:", sizeMax);
Dialog.addChoice("Watershed separation:", separation);
Dialog.addChoice("Fill holes:", holes);
Dialog.addChoice("Outline image(s) format:", format);
Dialog.show();
// List of parameters, entered values, date of analysis, and software versions
input = Dialog.getString();
output = Dialog.getString();
unit = Dialog.getChoice();
distanceUnit = Dialog.getNumber();
distancePixels = Dialog.getNumber();
thresholdMethod = Dialog.getChoice();
thresholdMin = Dialog.getNumber();
thresholdMax = Dialog.getNumber();
sizeMin = Dialog.getNumber();
sizeMin2 = Math.pow(sizeMin, 2);
sizeMax = Dialog.getNumber();
sizeMax2 = Math.pow(sizeMax, 2);
separation = Dialog.getChoice();
holes = Dialog.getChoice();
format = Dialog.getChoice();
monthNames = newArray("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
getDateAndTime(year, month, week, day, hour, min, sec, msec);
dateTime = ""+day+"/"+monthNames[month]+"/"+year+" "+hour+":"+min+":"+sec;
versionIJ = getVersion();
versionJava = getInfo("java.version");
// Export parameters, values, date, and versions list
Table.create("Parameters");
selectWindow("Parameters");
listParameters = Array.concat("Folder containing the charcoal images", "Folder containing the results", "Scale unit", "Scale distance in original unit", "Scale distance in pixels", "Thresholding method", "Minimum manual threshold", "Maximum manual threshold", "Minimum charcoal size", "Maximum charcoal size", "Watershed separation", "Fill holes", "Outline image(s) format", "Date and time", "ImageJ version", "Java version");
listParametersSelected = Array.concat(input, output, unit, distanceUnit, distancePixels, thresholdMethod, thresholdMin, thresholdMax, sizeMin, sizeMax, separation, holes, format, dateTime, versionIJ, versionJava);
for (i = 0; i < 16; i++) {
Table.set("Parameter", i, listParameters[i]);
Table.set("Value", i, listParametersSelected[i])
}
Table.save(output + "Parameters" + ".csv");
run("Close");
// 4.2. Batch to process every image from the input folder and export the results
// Names list from the images in the input folder
setBatchMode(true);
listNames = getFileList(input);
listNamesOutput = getFileList(input);
for (i = 0; i < listNamesOutput.length; i++) {
dotIndex = indexOf(listNamesOutput[i], ".");
listNamesOutput[i] = substring(listNamesOutput[i], 0, dotIndex);
}
// Batch analysis
Table.create("Table of results");
for (i = 0; i < listNames.length; i++) {
open(input + listNames[i]);
run("8-bit");
run("Set Scale...", "distance=distancePixels known=distanceUnit unit=unit");
if (thresholdMethod == "Manual") {
setThreshold(thresholdMin, thresholdMax);
setOption("BlackBackground", false);
run("Convert to Mask");
} else {
setAutoThreshold(thresholdMethod);
setOption("BlackBackground", false);
run("Convert to Mask");
}
if (separation == "Yes"){
run("Watershed");
}
if (holes == "Yes"){
run("Fill Holes");
}
run("Set Measurements...", "area feret's redirect=None");
run("Analyze Particles...", "size=sizeMin2-sizeMax2 show=Outlines display exclude clear");
if (nResults > 0) {
saveAs(format, output + listNamesOutput[i]);
selectWindow("Results");
count = nResults;
area = Table.getColumn("Area");
length = Table.getColumn("Feret");
width = Table.getColumn("MinFeret");
run("Close");
selectWindow("Table of results");
totalCount = Table.size;
for (j = 0; j < count; j++) {
Table.set("Image", totalCount+j, listNamesOutput[i]);
Table.set("Charcoal", totalCount+j, j+1);
Table.set("Area", totalCount+j, area[j]);
Table.set("Length", totalCount+j, length[j]);
Table.set("Width", totalCount+j, width[j]);
}
Table.setLocationAndSize(100, 100, 750, 750);
Table.update;
close();
} else {
selectWindow("Table of results");
totalCount = Table.size;
Table.set("Image", totalCount, listNamesOutput[i]);
Table.set("Charcoal", totalCount, 0);
Table.set("Area", totalCount, 0);
Table.set("Length", totalCount, 0);
Table.set("Width", totalCount, 0);
Table.setLocationAndSize(100, 100, 750, 750);
Table.update;
close();
}
}
Table.save(output + "Results" + ".csv");
// Message of completion/error
if (File.exists(output + "Results" + ".csv") == true) {
showMessage("Analysis completed.");
} else {
showMessage("An error has occurred.");
}



