Commit 7482370a authored by baumanph's avatar baumanph
Browse files

Update data input, transformation and modeling scripts because there is new data

parent e942e5ce
......@@ -16,9 +16,11 @@
pkgs <- c("tidyverse", "simplerspec")
lapply(pkgs, library, character.only = TRUE)
## Load all plant element data =================================================
elements_yam_leaf <- read_csv("data/training/elements/leaf_elements.csv")
elements_yam_tuber <- read_csv("data/training/elements/tuber_elements.csv")
elements_yam_leaf <- read_csv("data/elements/leaf_elements.csv")
elements_yam_tuber <- read_csv("data/elements/tuber_elements.csv")
################################################################################
## Decription:
################################################################################
\ No newline at end of file
################################################################################
## Author: Philipp Baumann || philipp.baumann@usys.ethz.ch
## License: GPL-3.0
## Project: Biophysical, institutional and economic drivers of sustainable
## soil use in yam systems for improved food security in West Africa (YAMSYS)
## Description: Tune and evaluate PLS regression models to predict Yam
## root and leaf elemental concentrations
################################################################################
library("tidyverse")
library("simplerspec")
## Register parallel backend for using multiple cores ==========================
# Allows to tune the models using parallel processing (e.g. use all available
# cores of a CPU); caret package automatically detects the registered backend
library("doParallel")
# Make a cluster with all possible threads (more than physical cores)
cl <- makeCluster(detectCores())
# Register backend
registerDoParallel(cl)
# Return number of parallel workers
getDoParWorkers() # 8 threads on MacBook Pro (Retina, 15-inch, Mid 2015);
# Quadcore processor
################################################################################
## Part 1: Read and pre-process spectra, Read chemical data, and join
## spectral and chemical data sets
################################################################################
## List of OPUS files obtained from Bruker ALPHA spectrometer at ETH Zürich
lf_leaf <- dir("data/training/spectra/leaf", full.names = TRUE)
lf_tuber <- dir("data/training/spectra/tuber", full.names = TRUE)
## Read files: ETH Zürich
spc_lst_leaf <- read_opus_univ(
fnames = lf_leaf,
extract = c("spc", "ScSm", "ScRf"),
parallel = TRUE)
spc_lst_tuber <- read_opus_univ(
fnames = lf_tuber,
extract = c("spc", "ScSm", "ScRf"),
parallel = TRUE)
## Spectral data processing pipe ===============================================
## ETH Alpha
spc_tbl_leaf <- spc_lst_leaf %>%
gather_spc() %>%
resample_spc(wn_lower = 500, wn_upper = 3996, wn_interval = 2) %>%
average_spc() %>%
preprocess_spc(select = "sg_1_w21")
spc_tuber_train <- spc_lst_tuber %>%
gather_spc() %>%
resample_spc(wn_lower = 500, wn_upper = 3996, wn_interval = 2) %>%
average_spc() %>%
preprocess_spc(select = "sg_1_w21") %>%
group_by(sample_id) %>%
slice(1L)
################################################################################
## Author: Philipp Baumann || philipp.baumann@usys.ethz.ch
## License: GPL-3.0
## Project: Biophysical, institutional and economic drivers of sustainable
## soil use in yam systems for improved food security in West Africa (YAMSYS)
## Description: Tune and evaluate PLS regression models to predict yam
## tuber elemental concentrations
################################################################################
## Register parallel backend for using multiple cores ==========================
# Allows to tune the models using parallel processing (e.g. use all available
# cores of a CPU); caret package automatically detects the registered backend
library("doParallel")
# Make a cluster with all possible threads (more than physical cores)
cl <- makeCluster(detectCores())
# Register backend
registerDoParallel(cl)
# Return number of parallel workers
getDoParWorkers() # 8 threads on MacBook Pro (Retina, 15-inch, Mid 2015);
# Quadcore processor
## Prepare final data for spectral modeling ====================================
# Join spectra tibble and chemical reference analysis tibble
spc_elements_tuber <- join_spc_chem(
spc_tbl = spc_tuber_train, chem_tbl = elements_yam_tuber, by = "sample_id")
spc_elements_leaf <- join_spc_chem(
spc_tbl = spc_tbl_leaf, chem_tbl = elements_yam_leaf, by = "sample_id")
################################################################################
## Tune and cross-validate training models for yam tubers
################################################################################
## Run PLS regression models for all measured soil properties
## Use 5 times repeated 10-fold cross-validation for model tuning and
## use by resampling repeat averaged (mean) held-out predictions at
## finally chosen of PLS regression components for model evaluation;
## argument `resampling_method` = "rep_kfold_cv" creates 5 times repeated
## cross-validation; always exclude missing values for samples that have missing
## values in the target soil property variable
## =============================================================================
## Use 5 times repeated 10-fold cross-validation
# Total N
pls_tuber_N <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$N), ],
response = N,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total C
# Omit outlier at > 800 g / kg C
pls_tuber_C <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$C) &
spc_elements_tuber$C < 800, ],
response = C,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total S
pls_tuber_S <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$S), ],
response = S,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total P
# Remove outlier at > 4000 mg P / kg
pls_tuber_P <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$P) &
spc_elements_tuber$P < 4000, ],
response = P,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total K
pls_tuber_K <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$K), ],
response = K,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Ca
# Remove outlier at > 2000 mg Ca / kg
pls_tuber_Ca <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$Ca) &
spc_elements_tuber$Ca < 2000, ],
response = Ca,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Mg
# Remove outlier at > 3000 mg Mg / kg
pls_tuber_Mg <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$Mg) &
spc_elements_tuber$Mg < 3000, ],
response = Mg,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Fe
# Remove outliers at > 150 mg Fe / kg
pls_tuber_Fe <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$Fe) &
spc_elements_tuber$Fe < 150, ],
response = Fe,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Zn
# Remove outliers at > 75mg Zn / kg
pls_tuber_Zn <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$Zn) &
spc_elements_tuber$Zn < 75, ],
response = Zn,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Cu
pls_tuber_Cu <- fit_pls(
spec_chem = spc_elements_tuber[!is.na(spc_elements_tuber$Cu), ],
response = Cu,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
################################################################################
## Write all pls models (R objects) into separate files
## using the saveRDS function
## .Rds files are R data files that contain a single R object, in our case
## it is a list from the output of the fit_pls() function
## These files can be directly loaded into a new R session where e.g. calibrated
## properties are predicted based on new sample spectra
################################################################################
saveRDS(pls_tuber_N, "models/training/tuber/pls_tuber_N.Rds")
saveRDS(pls_tuber_C, "models/training/tuber/pls_tuber_C.Rds")
saveRDS(pls_tuber_S, "models/training/tuber/pls_tuber_S.Rds")
saveRDS(pls_tuber_P, "models/training/tuber/pls_tuber_P.Rds")
saveRDS(pls_tuber_K, "models/training/tuber/pls_tuber_K.Rds")
saveRDS(pls_tuber_Ca, "models/training/tuber/pls_tuber_Ca.Rds")
saveRDS(pls_tuber_Mg, "models/training/tuber/pls_tuber_Mg.Rds")
saveRDS(pls_tuber_Fe, "models/training/tuber/pls_tuber_Fe.Rds")
saveRDS(pls_tuber_Zn, "models/training/tuber/pls_tuber_Zn.Rds")
saveRDS(pls_tuber_Cu, "models/training/tuber/pls_tuber_Cu.Rds")
################################################################################
## Author: Philipp Baumann || philipp.baumann@usys.ethz.ch
## License: GPL-3.0
## Project: Biophysical, institutional and economic drivers of sustainable
## soil use in yam systems for improved food security in West Africa (YAMSYS)
## Description: Process tuber test data; data set of Patricia Schwitter
################################################################################
## Register parallel backend for using multiple cores ==========================
# Allows to tune the models using parallel processing (e.g. use all available
# cores of a CPU); caret package automatically detects the registered backend
library("doParallel")
# Make a cluster with all possible threads (more than physical cores)
cl <- makeCluster(detectCores())
# Register backend
registerDoParallel(cl)
# Return number of parallel workers
getDoParWorkers() # 8 threads on MacBook Pro (Retina, 15-inch, Mid 2015);
# Quadcore processor
################################################################################
## Part 1: Read and pre-process spectra, Read chemical data, and join
## spectral and chemical data sets
################################################################################
## List of OPUS files obtained from Bruker ALPHA spectrometer at ETH Zürich
lf_tuber_test <- dir("data/test/tuber/spectra", full.names = TRUE)
lf_tuber_beatrice <- dir("data/test_beatrice", full.names = TRUE)
## Read files into list
spc_lst_tuber_test <- read_opus_univ(
fnames = lf_tuber_test,
extract = "spc",
parallel = TRUE)
spc_lst_tuber_beatrice <- read_opus_univ(
fnames = lf_tuber_beatrice,
extract = "spc",
parallel = TRUE)
## Spectral data processing pipeline ===========================================
spc_tuber_test <- spc_lst_tuber_test %>%
gather_spc() %>%
resample_spc(wn_lower = 500, wn_upper = 3996, wn_interval = 2) %>%
average_spc() %>%
preprocess_spc(select = "sg_1_w21")
spc_tuber_beatrice <- spc_lst_tuber_beatrice %>%
gather_spc() %>%
resample_spc(wn_lower = 500, wn_upper = 3996, wn_interval = 2) %>%
average_spc() %>%
preprocess_spc(select = "sg_1_w21")
\ No newline at end of file
## Plot training and test spectra ==============================================
pdf(file = "out/figs/spc-train-test-expl.pdf", width = 5, height = 5)
plot_spc_ext(
spc_tbl_l = list(
"Training set" = spc_tuber_train %>%
mutate(group_id = "Comparison test and training spectra"),
"Test set" = spc_tuber_test %>%
mutate(group_id = "Comparison test and training spectra")),
lcols_spc = c("spc", "spc_pre"), group_id = "group_id")
dev.off()
\ No newline at end of file
################################################################################
## Evaluate the the Yam tuber testing set based on the training models
################################################################################
## Read test reference tuber element data (ICP-OES) ============================
elements_yam_tuber_test <- read_csv(
"data/test/tuber/elements/tuber_elements_test.csv")
## Read the yam tuber training models ==========================================
pls_tuber_N <- readRDS(file = "models/training/tuber/pls_tuber_N.Rds")
pls_tuber_C <- readRDS(file = "models/training/tuber/pls_tuber_C.Rds")
pls_tuber_S <- readRDS(file = "models/training/tuber/pls_tuber_S.Rds")
pls_tuber_P <- readRDS(file = "models/training/tuber/pls_tuber_P.Rds")
pls_tuber_K <- readRDS(file = "models/training/tuber/pls_tuber_K.Rds")
pls_tuber_Ca <- readRDS(file = "models/training/tuber/pls_tuber_Ca.Rds")
pls_tuber_Mg <- readRDS(file = "models/training/tuber/pls_tuber_Mg.Rds")
pls_tuber_Fe <- readRDS(file = "models/training/tuber/pls_tuber_Fe.Rds")
pls_tuber_Zn <- readRDS(file = "models/training/tuber/pls_tuber_Zn.Rds")
pls_tuber_Cu <- readRDS(file = "models/training/tuber/pls_tuber_Cu.Rds")
# Nest all models in a list for prediction
pls_tuber_all <- list(
"pls_tuber_N" = pls_tuber_N,
"pls_tuber_C" = pls_tuber_C,
"pls_tuber_S" = pls_tuber_S,
"pls_tuber_P" = pls_tuber_P,
"pls_tuber_K" = pls_tuber_K,
"pls_tuber_Ca" = pls_tuber_Ca,
"pls_tuber_Mg" = pls_tuber_Mg,
"pls_tuber_Fe" = pls_tuber_Fe,
"pls_tuber_Zn" = pls_tuber_Zn,
"pls_tuber_Cu" = pls_tuber_Cu
)
## Predict tuber nutrients based on training model and new spectra =============
pred_tuber_test <- predict_from_spc(
model_list = pls_tuber_all,
spc_tbl = spc_tuber_test
)
# Join test set predictions and test reference data
predobs_tuber_test <- inner_join(x = pred_tuber_test,
y = elements_yam_tuber_test)
# Gather all predicted elements in one column
gather(predobs_tuber_test, key = element_pred, value = pred,
pls_tuber_N, pls_tuber_C, pls_tuber_S, pls_tuber_P, pls_tuber_K,
pls_tuber_Ca, pls_tuber_Mg, pls_tuber_Fe, pls_tuber_Zn, pls_tuber_Cu)
measure_obs <- c("N", "C", "P", "K", "Ca", "Mg", "Fe", "Zn", "Cu")
measure_pred <- c("pls_tuber_N", "pls_tuber_C", "pls_tuber_P", "pls_tuber_K",
"pls_tuber_Ca", "pls_tuber_Mg", "pls_tuber_Fe", "pls_tuber_Zn",
"pls_tuber_Cu")
evaluate_multimodels <- function(data, cols_obs, cols_pred) {
}
library("data.table")
obs_test_long <- data.table::melt(as.data.table(predobs_tuber_test),
measure = measure_obs, variable.name = "variable_obs",
value.name = "value_obs", variable.factor = FALSE) %>%
select(sample_id, variable_obs, value_obs) %>%
mutate(variable = variable_obs) %>%
as.tibble()
pred_test_long <- data.table::melt(as.data.table(predobs_tuber_test),
measure = measure_pred, variable.name = "variable_pred",
value.name = "value_pred", variable.factor = FALSE) %>%
select(sample_id, variable_pred, value_pred) %>%
as.tibble()
predobs_tuber_test_long <- bind_cols(obs_test_long,
pred_test_long)
# Perform model evaluation per variable
model_eval_train <- predobs_tuber_test_long %>%
group_by(variable) %>%
nest() %>%
mutate(model_eval = map(data,
~ summary_df(.x, x = "value_obs", y = "value_pred"))) %>%
unnest(model_eval) %>%
select(-data)
## Graphical model evaluation
predobs_tuber_test_long %>%
ggplot(aes(x = value_obs, y = value_pred)) +
geom_point() +
facet_wrap(~ variable_obs, scales = "free")
################################################################################
plot_spc_ext(spc_tbl_l =
list("Training ref." = spc_tbl_tuber %>% mutate(group_id = "Test"),
"Beatrice test" = spc_tuber_beatrice %>% mutate(group_id = "Test")),
lcols_spc = c("spc","spc_pre"),
group_id = "group_id")
\ No newline at end of file
spc_elements_tuber_test <- spc_tuber_test %>%
inner_join(x = ., y = elements_yam_tuber_test)
spc_elements_tuber_all <- spc_elements_tuber %>%
select(sample_id, spc_pre, C, N, P, K, Ca, Mg, Fe, Zn, Cu) %>%
bind_rows(spc_elements_tuber_test %>%
select(sample_id, spc_pre, C, N, P, K, Ca, Mg, Fe, Zn, Cu))
pls_tuber_N_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$N), ],
response = N,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
pls_tuber_C_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$C) &
spc_elements_tuber_all$C < 800 & spc_elements_tuber_all$C > 383, ],
response = C,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total P
# Remove outlier at > 4000 mg P / kg
pls_tuber_P_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$P) &
spc_elements_tuber_all$P < 4000, ],
response = P,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total K
pls_tuber_K_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$K), ],
response = K,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Ca
# Remove outlier at > 2000 mg Ca / kg
pls_tuber_Ca_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$Ca) &
spc_elements_tuber_all$Ca < 2000, ],
response = Ca,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Mg
# Remove outlier at > 3000 mg Mg / kg
pls_tuber_Mg_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$Mg) &
spc_elements_tuber_all$Mg < 3000, ],
response = Mg,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Fe
# Remove outliers at > 150 mg Fe / kg
pls_tuber_Fe_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$Fe) &
spc_elements_tuber_all$Fe < 150, ],
response = Fe,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Zn
# Remove outliers at > 75mg Zn / kg
pls_tuber_Zn_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$Zn) &
spc_elements_tuber_all$Zn < 75, ],
response = Zn,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
# Total Cu
pls_tuber_Cu_all <- fit_pls(
spec_chem = spc_elements_tuber_all[!is.na(spc_elements_tuber_all$Cu), ],
response = Cu,
evaluation_method = "resampling",
tuning_method = "resampling",
resampling_method = "rep_kfold_cv",
pls_ncomp_max = 10
)
pdf(file = "out/figs/model-eval-yam-tuber-all.pdf", width = 10, height = 15)
cowplot::plot_grid(pls_tuber_C_all$p_model, pls_tuber_N_all$p_model,
pls_tuber_P_all$p_model, pls_tuber_K_all$p_model, pls_tuber_Ca_all$p_model,
pls_tuber_Mg_all$p_model, pls_tuber_Zn_all$p_model, pls_tuber_Cu_all$p_model,
ncol = 2)
dev.off()
sample_ID,country,site,category,material,N_perc,C_perc,S_perc
CI_tb_01_tuber_x1,CI,tb,ref,tuber,1.0095,40.3243,0.1079
CI_tb_02_tuber,CI,tb,ref,tuber,1.0837,39.1344,0.0942
CI_tb_03_tuber,CI,tb,ref,tuber,1.074,39.4732,0.0716
CI_tb_04a_tuber,CI,tb,ref,tuber,1.2283,39.6649,0.0673
CI_tb_04b_tuber,CI,tb,ref,tuber,1.0218,39.3409,0.0595
CI_tb_05_tuber_x2,CI,tb,ref,tuber,1.1051,40.3163,0.0702
CI_tb_06_tuber_x3,CI,tb,ref,tuber,1.2135,40.1294,0.0887
CI_tb_07_tuber_x4,CI,tb,ref,tuber,0.9133,40.2266,0.0775
CI_tb_08_tuber_x5,CI,tb,ref,tuber,1.1747,40.2292,0.0749
CI_tb_01_tuber_x1,CI,tb,ref,tuber,0.9932,40.2671,0.07
CI_tb_09_tuber,CI,tb,ref,tuber,0.502,39.8867,0.0396
CI_tb_10_tuber,CI,tb,ref,tuber,0.9931,39.7161,0.0683
CI_tb_11_tuber_x6,CI,tb,ref,tuber,0.7243,39.8494,0.0673
CI_tb_12_tuber_x7,CI,tb,ref,tuber,0.9876,40.1559,0.0849
CI_tb_13_tuber,CI,tb,ref,tuber,1.1646,39.4043,0.0854
CI_tb_14_tuber_x8,CI,tb,ref,tuber,0.9455,39.799,0.0758
CI_tb_15_tuber_x9,CI,tb,ref,tuber,0.7852,40.2089,0.0625
CI_tb_16_tuber,CI,tb,ref,tuber,1.6781,40.0941,0.0907
CI_tb_01_tuber_x1,CI,tb,ref,tuber,1.021,40.275,0.0851
CI_tb_18_tuber,CI,tb,ref,tuber,1.5816,39.557,0.0961
CI_tb_19_tuber,CI,tb,ref,tuber,0.5807,39.5731,0.0461
CI_tb_20_tuber,CI,tb,ref,tuber,1.0144,39.2474,0.0654
CI_tb_20_tuber,CI,tb,ref,tuber,1.0335,39.2417,0.0802
CI_tb_20_tuber,CI,tb,ref,tuber,1.0181,39.2038,0.0769
CI_sb_01_tuber,CI,sb,ref,tuber,0.6544,39.6101,0.0767
CI_sb_02_tuber_x1,CI,sb,ref,tuber,1.3493,39.2415,0.1115
CI_sb_03b_tuber,CI,sb,ref,tuber,1.5752,40.3228,0.1213
CI_sb_04_tuber,CI,sb,ref,tuber,1.8656,39.3012,0.1655
CI_sb_05_tuber,CI,sb,ref,tuber,0.9773,39.0753,0.0877
CI_sb_06_tuber,CI,sb,ref,tuber,1.0049,39.7355,0.088
CI_sb_07_tuber,CI,sb,ref,tuber,0.8524,39.4246,0.0869
CI_sb_08_tuber,CI,sb,ref,tuber,0.6186,39.407,0.0781
CI_sb_01_tuber,CI,sb,ref,tuber,0.6899,39.501,0.083
CI_sb_09_tuber,CI,sb,ref,tuber,0.9002,39.0967,0.0885
CI_sb_10_tuber,CI,sb,ref,tuber,0.6767,39.2129,0.1028
CI_sb_11_tuber,CI,sb,ref,tuber,0.8167,38.8496,0.0836
CI_sb_12_tuber,CI,sb,ref,tuber,0.6306,39.4329,0.0666
CI_sb_13_tuber,CI,sb,ref,tuber,0.6248,39.3116,0.0682
CI_sb_14_tuber,CI,sb,ref,tuber,0.5432,37.3434,0.0542