This package was created for use at the University of Bergen to convert data from an X-ray fluorescence machine from kilo-counts per second to micromolar. It requires that your files are constructed in a very specific way, as explained in this vignette, so is meant to be used with instructions. The instructions document is available here. The package was created with R version 4.0.3.
The functions included in this package are:
readxrf()
: This function joins the data frame containing raw data with the data frame containing project information like where each sample was taken and how much water was filtered. The output of this function is a new data frame. convertxrf()
: This function uses the data frame created by readxrf()
and the data frame containing base information like crystal drift and detection limits for each element. The output of this function is a long data frame where the counts from the machine have been converted from kcps to µM. widen()
: This function takes the the data frame created with readxrf()
and makes it wider, so each element has its own column. widen_above()
: This function both widens your data and excludes any concentrations that are below the detection limits. widen_means()
: This function both widens your data and calculates mean concentration based on one or two factors. widen_means_above()
: This function first calculates mean concentrations based on one or two factors, then excludes those values that are below the detection limits. show_blanks()
: This function creates a data frame showing only the mean blanks in your dataset. transformssd()
: This function transforms hexadecimal values (obtained from a .ssd file created by the XRF computer) to a data frame showing results from one sample. The data frame will be in the same format as the .txt file created by the XRF computer, so it is possible to then use the readxrf()
and convertxrf()
functions on this data frame. There are three files you need for your analysis, the first of which is a file with raw data from the XRF machine. You also need a file with information about the samples and project, like which location the samples are from, whether they are blank samples, and the volume of the filtrated water. Lastly, you need a file containing information about the machine, filters and elements, like crystal drift and calibrated constants.
This file is created by the XRF machine when you export your data from it. You should not edit this file unless there are errors in the sample names. This file will be a .txt file using comma (,) as a decimal mark and tabs to separate columns. It will contain a column named "Sample", a column named "Date", and several columns with results from the machine's analysis. The ones we are interested in in this case are those with "(Int)" behind the element.
This file should contain all relevant information that you wish to include about your data that is not from the XRF machine. There are several columns that must be included for the functions in this package to work:
You may include as many more columns as you want, for example dates, depth, or location, but these columns all need to be present in your project information file.
This file must contain all the relevant information related to the XRF machine, filters, and elements. This is a file that will not change between experiments unless the crystal drift has been measured again. The base info file must contain these columns:
All these files must be imported to RStudio as data frames before you can use the xrfr package. Your raw data file will be a .txt file, which can be imported using the read_delim()
function from the readr package. This code should work: read_delim("name_of_your_file.txt", delim = "\t", locale = locale(decimal_mark = ","))
. How you import your other files depends on which format they are saved as. For Excel files, use the readxl package and the function read_excel()
. For CSV files use either read_csv()
(comma as separator and . as decimal point) or read_csv2()
(tab as separator and , as decimal point) from the readr package.
This section explains what each function does, and which arguments you need to define to make it work. The examples given show real data from an experiment at UiB. The raw files are available here.
This function will import and rearrange your files with raw data and project information and then join them into one data frame. To use this function there are two arguments you must define:
Here is a possible input:
rawdata.df <- read_delim("xrf_rawdata.txt", delim = "\t", locale = locale(decimal_mark = ",")) projectinfo.df <- read_excel("xrf_projectinfo.xlsx") imported.df <- readxrf(raw_data = rawdata.df, project_info = projectinfo.df)
This code will give a data frame that looks something like this. The table shows the first rows and columns of the linked data file:
|Sample|Date.x|C|N|O|Na|Mg|Al|Si|P|S|Cl|...| |:----|:------|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-| |COM001|04.12.2019 10:16:35|58.0957|0.438|2.9889|0.4874|1.796|32.3646|5.6097|0.3945|1.0494|1.0383|...| |COM002|04.12.2019 10:28:50|54.2361|0.4313|3.3708|1.1547|4.3948|37.2398|17.5392|0.5557|1.538|1.8231|...| |COM003|04.12.2019 10:41:07|59.0261|0.4458|2.8878|0.4234|1.2589|33.6267|2.6512|0.3778|0.9904|1.2301|...| |...|...|...|...|...|...|...|...|...|...|...|...|...|
Specifically, this function extracts the necessary columns from the raw data file ("Sample", "Date", and those with "(Int)" in the column name), then joins this file and the project information file in a single data frame by their shared column "Sample".
This data frame will further be used in the function convertxrf()
, where these values are converted from kcps to µM.
Once you have your data frame created with readxrf()
, you go on to perform the actual calculations to convert your values from kcps to µM, ending up with another data frame. For this function to work you will need to define several arguments:
readxrf()
. readxrf()
that is an element. For example, in the example above, there are the columns "Sample" and "Date.x" first, then the column named "C", so "C" is what we include in the function. The formula that is used to calculate the concentration in µM from kcps is this: Concentration = ((Net_count * Cal_const) * filter_area * (1000 / Volume) * 1000 * (\Drift_2008 / Drift_YEAR) / MolarW)
.
Note that the detection limit is adjusted based on the volume filtered for each element and sample like this: (1000 / Volume) * Detection_limit
.
Here is a possible input:
baseinfo.df <- read_excel("xrf_setup.xlsx") data.df <- convertxrf(project_data = imported.df, base_info = baseinfo.df, year = "2019", first_element = "C", last_element = "As")
This code will give a long data frame - you can see the first 96 rows here. The table below shows the first few rows of this file:
|Sample|Date.x|Filter_type|...|Day|Treatment|Element|Concentration|Detection_limit| |:----|:-----|:----------|:---|:--|:--------|:------|:------------|:--------------| |COM001|04.12.2019 10:16:35|PC|...|0|K1|C|-4.19727307987776|1.22193802149026| |COM001|04.12.2019 10:16:35|PC|...|0|K1|N|0.292013243234358|0.312338639119395| |COM001|04.12.2019 10:16:35|PC|...|0|K1|O|0.328051062623146|0.0322146560280234| |...|...|...|...|...|...|...|...|...|
The data frame created here is a good idea to save, as this is the file you will likely use to perform statistical analyses, make plots, etc. You can save it as a CSV file by using the write_csv()
function from the readr package (part of tidyverse).
The file created using convertxrf()
is good for further work in R/Rstudio, but if you want to look at your data it is not ideal. The widen()
function will show your data as is, only excluding the blanks and detection limits, and turning the data frame from a long to a wide format. For this function to work you will need to define this argument:
convertxrf()
. A possible input could be this:
df <- widen(project_data = data.df)
Running this code will give you a data frame that looks something like this. The table below shows the first few rows of this file:
|Sample|...|Day|Treatment|C|N|O|Na|Mg|...| |:----|:---|:--|:-------|:-|:-|:-|:-|:-|:-| |COM001|...|0|K1|-4.19727308|0.29201324|0.32805106|-0.05557942|0.0353942597|...| |COM002|...|0|K2|-21.69354177|0.14490883|0.90309406|-0.01586340|0.1147511764|...| |COM003|...|0|K3|0.02039932|0.46326913|0.17582051|-0.05938854|0.0189933824|...| |...|...|...|...|...|...|...|...|...|...|...|
This data frame is a lot easier to read with human eyes than the long format.
In addition to widening your data, you may wish to exclude the values that are below the detection limits. This can be done with the widen_above()
function. It will give you the same data frame as the widen()
function, only with "NA" or "NULL" written in the cells where the concentration was lower than the detection limit. You will need to define this argument:
convertxrf()
. Here is a possible input for this function:
df <- widen_above(project_data = data.df)
The output of this code will be a data frame that looks like this. The table below shows the first few rows of this file:
|Sample|O|Mg|Si|P|S|...|N|Na|...| |:----|:-|:-|:-|:-|:-|:-|:-|:-|:-| |COM001|0.32805106|0.035394260|0.214839894|0.057113603|0.008732699|...|NA|NA|...| |COM002|0.90309406|0.114751176|0.719814744|0.086571942|0.017652209|...|NA|NA|...| |COM003|0.17582051|0.018993382|0.089606809|0.054061778|0.007655639|...|0.4632691|NA|...| |...|...|...|...|...|...|...|...|...|...|
You may also wish to calculate the mean concentrations based on different factors such as depth, location, treatment, etc. The widen_means()
function does this, based on one or two factors that you must define. To use this function you must define these arguments:
convertxrf()
.A possible input:
df <- widen_means(project_data = data.df, first_factor = "Treatment", second_factor = "Day")
The output of this code will be a data frame showing the factor(s) chosen and the mean concentration for each element, like this. The table below shows the first few rows of this file:
|Day|Treatment|C|N|O|Na|Mg|Al|...| |:-|:--------|:-|:-|:-|:-|:-|:-|:-| |0|K1|-0.7737613|0.25055436|-1.587303e-01|-0.07999250|0.10809891|-2.2312739|...| |0|K2|-9.4292147|0.16635012|5.019141e-05|-0.01811514|0.19980153|-0.6574871|...| |0|K3|1.2544674|0.34920146|-2.354479e-01|-0.05398931|0.11028071|-1.9058621|...| |...|...|...|...|...|...|...|...|...|
This function combines the widen_above()
and widen_means()
functions by calculating means and then excluding the mean concentrations not above the detection limits. Like with the widen_means()
function, you define one or two factors to calculate the means based on. You must define these arguments to use this function:
convertxrf()
.A possible input:
df <- widen_means_above(project_data = data.df, first_factor = "Treatment", second_factor = "Day")
This code will create a data frame that shows mean concentrations only if they are above the detection limit, like this. The table below shows the first few rows of this file:
|Day|Treatment|Volume|Ca|Fe|Mg|...|Cl|C|N| |:--|:--------|:-----|:-|:-|:-|:-|:-|:-|:-| |0|K1|1000|0.28964915|0.10624892|0.10809891|...|NA|NA|NA| |0|K2|1000|0.56820057|0.13436192|0.19980153|...|0.6633487|NA|NA|NA| |0|K3|1000|0.09041592|0.05313665|0.11028071|...|NA|1.254467|0.3492015| ...|...|...|...|...|...|...|...|...|...|
Note that columns where no mean concentration is above the detection limit (empty columns) are removed, so pay attention to the number of columns and which columns they are!
This function calculates the mean values for the blank values based on filter type, filter size, and filter box number, and presents these in a data frame. There are 3 arguments that must be defined:
readxrf()
. A possible input:
blanks.df <- show_blanks(imported_data = imported.df, first_element = "C", last_element = "As")
The created data frame will contain the mean blank values and look something like this:
|Filter_type|Filter_size|Filter_box_nr|Al|As|...|Si| |:----------|:----------|:------------|:-|:-|:-|:-| |GFF|NA|1|78.6387|4.81653333333333|...|687.3644666666667| |GFF|NA|2|79.5244666666667|4.87406666666667|...|693.0419| |PC|0.8|1|38.194|1.038433333333333|...|0.53433333333333| |PC|0.8|1|38.95749999999996|1.046066666666667|...|0.56293333333333|
This function will convert the hexadecimal values from a .txt file (created from a .ssd file from the XRF computer) to a data frame with results from one sample. This data frame can then be used in the readxrf()
function. There is one argument that must be defined for this function:
readLines()
function. A possible input:
string <- readLines("sample_hex.txt") df <- transformssd(hex_data = string)
The created data frame will look like this:
|Sample|Date|As (Int)|C (Int)|...|Zn (Int)| |:-----|:---|:-------|:------|:--|:-------| |sr-cal120|27.11.2014 14:02:43|1.632752776145935|54.286903381347656|...|0.7868552803993225|
There will always be only be results from one sample in this data frame, as each sample is saved as its own .ssd file. The different data frames from samples in the same dataset can be combined into one data frame using rbind()
.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.