The scope of EU-kalat study was to measure concentrations of persistent organic pollutants (POPs) including dioxin (PCDD/F), PCB and BDE in fish from Baltic sea and Finnish inland lakes and rivers. [1][2][3].
Answer
The original sample results can be acquired from Opasnet base. The study showed that levels of PCDD/Fs and PCBs depends especially on the fish species. Highest levels were on salmon and large sized herring. Levels of PCDD/Fs exceeded maximum level of 4 pg TEQ/g fw multiple times. Levels of PCDD/Fs were correlated positively with age of the fish.
Mean congener concentrations as WHO2005-TEQ in Baltic herring can be printed out with this link or by running the codel below.
# This code is Op_en on page [[EU-kalat]].
library(OpasnetUtils)
library(ggplot2)
eu <- Ovariable("eu", ddata = "Op_en3104", subset = "POPs")
eu <- EvalOutput(eu)
#levels(eu$POP)
eu <- eu[eu$Fish_species == "Baltic herring" , ]
tef <- Ovariable("tef", ddata = "Op_en4017", subset = "TEF values")
tef <- EvalOutput(tef)
colnames(eu@output)[colnames(eu@output) == "POP"] <- "Congener"
levels(eu$Congener) <- gsub("HCDD", "HxCDD", levels(eu$Congener))
levels(eu$Congener) <- gsub("HCDF", "HxCDF", levels(eu$Congener))
levels(eu$Congener) <- gsub("CoPCB", "PCB", levels(eu$Congener))
#levels(eu$Congener)
euteq <- eu * tef
#head(euteq@output)
temp <- aggregate(euteq@output["Result"], by = c(euteq@output["Congener"], euteq@output["Catch_location"]), FUN = mean)
temp2 <- temp
temp2$Result <- temp2$Result / sum(temp2$Result)
cat("Congener TEQ profile of Baltic herring.\n")
oprint(temp2)
ggplot(temp, aes(x = Congener, y = Result, fill = Congener)) + geom_bar(stat = "identity") + facet_wrap(~ Catch_location) +
labs(x = "Congener", y = "TEQ concentration (pg/g fat)") + theme_gray(base_size = 18) + coord_flip()
temp2 <- temp[temp$Congener %in% levels(temp$Congener)[1:17],]
ggplot(temp2, aes(x = Congener, y = Result, fill = Congener)) + geom_bar(stat = "identity") + facet_wrap(~ Catch_location) +
labs(
title="Dioxin concentrations in Baltic herring",
x = "Congener",
y = "TEQ concentration (pg/g fat)"
) + theme_gray(base_size = 18) + coord_flip()
Rationale
Data
Data was collected between 2009-2010. The study contains years, tissue type, fish species, and fat content for each concentration measurement. Number of observations is 285.
There is a new study EU-kalat 3, which will produce results in 2016.
Model run 19.5.2017 without ovariable concentration [18]⇤--#: . The model does not mix well, so the results should not be used for final results. --Jouni (talk) 19:37, 19 May 2017 (UTC) (type: truth; paradigms: science: attack)
----#: . Maybe we should just estimate TEQs until the problem is fixed. --Jouni (talk) 19:37, 19 May 2017 (UTC) (type: truth; paradigms: science: comment)
Model run 22.5.2017 with TEQdx and TEQpcb as the only Compounds [19]
Model run 24.5.2017 TEQdx, TECpcb -> PCDDF, PCB [23]
Model run 11.10.2017 with small and large herring [24] (removed in update)
Model run 12.3.2018: bugs fixed with data used in Bayes. In addition, redundant fish species removed and Omega assumed to be the same for herring and salmon. [25]
Model run 22.3.2018 [26] Model does not mix well. Thinning gives little help?
Model run 25.3.2018 with conc.param as ovariable [27]
# This is code Op_en3104/bayes on page [[EU-kalat]]
library(OpasnetUtils)
library(reshape2)
library(rjags) # JAGS
library(ggplot2)
library(MASS) # mvrnorm
library(car) # scatterplotMatrix
objects.latest("Op_en3104", code_name = "preprocess") # [[EU-kalat]] eu, eu2, euRatio, indices
conl <- indices$Compound.TEQ2
# fisl <- indices$Fish.Fish16
# fisl <- c("Baltic herring","Large herring","Salmon","Small herring")
fisl <- c("Baltic herring","Salmon")
C <- length(conl)
Fi <- length(fisl)
N <- 1000
conl
fisl
eu2 <- EvalOutput(eu2)
# Hierarchical Bayes model.
# PCDD/F concentrations in fish.
# It uses the TEQ sum of PCDD/F (PCDDF) as the total concentration
# of dioxin and PCB respectively for PCB in fish.
# PCDDF depends on size of fish, fish species, catchment time, and catchment area,
# but we omit catchment area. In addition, we assume that size of fish has
# zero effect for other fish than Baltic herring.
# Catchment year affects all species similarly.
eu2 <- eu2[eu2$Compound %in% conl & eu2$Fish %in% fisl & eu2$Matrix == "Muscle" , ]
eu3 <- reshape(
eu2@output,
v.names = "euResult",
idvar = c("THLcode", "Fish"),
timevar = "Compound",
drop = c("Matrix"),
direction = "wide"
)
oprint(head(eu3))
#> colnames(eu3)
#[1] "THLcode" "Fish" "N" "Length" "Year"
#[6] "euResult.PCDDF" "euResult.PCB"
conc <- data.matrix(eu3[6:ncol(eu3)])
if(FALSE){
# Find the level of quantification for dinterval function
LOQ <- unlist(lapply(eu3[6:ncol(eu3)], FUN = function(x) min(x[x!=0])))
# With TEQ, there are no zeros. So this is useful only if there are congener-specific results.
names(LOQ) <- conl
conc <- sapply(
1:length(LOQ),
FUN = function(x) ifelse(conc[,x]==0, 0.5*LOQ[x], conc[,x])
)
}
# This version of the model looks only at Baltic herring and salmon.
# It assumes that all fish groups have the same Omega but mu varies.
mod <- textConnection(
"
model{
for(i in 1:S) { # S = fish sample
# below.LOQ[i,j] ~ dinterval(-conc[i,j], -LOQ[j])
conc[i,1:C] ~ dmnorm(muind[i,], Omega[fis[i],,])
muind[i,1:C] <- mu[fis[i],1:C] + lenp[fis[i]]*length[i] + timep*year[i]
}
# Priors for parameters
# Time trend. Assumed a known constant because at the moment there is little time variation in data.
# https://www.evira.fi/elintarvikkeet/ajankohtaista/2018/itameren-silakoissa-yha-vahemman-ymparistomyrkkyja---paastojen-rajoitukset-vaikuttavat/
# PCDDF/PCB-concentations 2001: 9 pg/g fw, 2016: 3.5 pg/g fw. (3.5/9)^(1/15)-1=-0.06102282
timep ~ dnorm(-0.0610, 10000)
lenp[1] ~ dnorm(0.01,0.01) # length parameter for herring
lenp[2] ~ dnorm(0,10000) # length parameter for salmon: assumed zero
for(i in 1:Fi) { # Fi = fish species
Omega[i,1:C,1:C] ~ dwish(Omega0[1:C,1:C],S)
pred[i,1:C] ~ dmnorm(mu[i,1:C]+lenp[i]*lenpred+timep*timepred, Omega[i,,]) # Model prediction.
for(j in 1:C) {
mu[i,j] ~ dnorm(0, 0.0001) # mu1[j], tau1[j]) # Congener-specific mean for fishes
}
}
}
")
jags <- jags.model(
mod,
data = list(
S = nrow(eu3),
C = C,
Fi = Fi,
conc = log(conc),
length = eu3$Length-170, # Subtract average herring size
year = eu3$Year-2009, # Substract baseline year
fis = match(eu3$Fish, fisl),
lenpred = 233-170,
timepred = 2009-2009,
Omega0 = diag(C)/100000
),
n.chains = 4,
n.adapt = 100
)
update(jags, 1000)
samps.j <- jags.samples(
jags,
c(
'mu', # mean by fish and compound
'Omega', # precision matrix by compound
'lenp',# parameters for length
'timep', # parameter for Year
'pred' # predicted concentration for year 2009 and length 17 cm
),
# thin=1000,
N
)
dimnames(samps.j$Omega) <- list(Fish = fisl, Compound = conl, Compound2 = conl, Iter=1:N, Chain=1:4)
dimnames(samps.j$mu) <- list(Fish = fisl, Compound = conl, Iter = 1:N, Chain = 1:4)
dimnames(samps.j$lenp) <- list(Fish = fisl, Iter = 1:N, Chain = 1:4)
dimnames(samps.j$pred) <- list(Fish = fisl, Compound = conl, Iter = 1:N, Chain = 1:4)
dimnames(samps.j$timep) <- list(Dummy = "time", Iter = 1:N, Chain = 1:4)
##### conc.param contains expected values of the distribution parameters from the model
conc.param <- Ovariable(
"conc.param",
dependencies = data.frame(Name = "samps.j", Ident=NA),
formula = function(...) {
conc.param <- list(
Omega = apply(samps.j$Omega, MARGIN = 1:3, FUN = mean),
lenp = cbind(
mean = apply(samps.j$lenp, MARGIN = 1, FUN = mean),
sd = apply(samps.j$lenp, MARGIN = 1, FUN = sd)
),
mu = apply(samps.j$mu, MARGIN = 1:2, FUN = mean),
timep = cbind(
mean = apply(samps.j$timep, MARGIN = 1, FUN = mean),
sd = apply(samps.j$timep, MARGIN = 1, FUN = sd)
)
)
names(dimnames(conc.param$lenp)) <- c("Fish","Metaparam")
names(dimnames(conc.param$timep)) <- c("Dummy","Metaparam")
conc.param <- melt(conc.param)
colnames(conc.param)[colnames(conc.param)=="value"] <- "Result"
colnames(conc.param)[colnames(conc.param)=="L1"] <- "Parameter"
conc.param$Dummy <- NULL
conc.param$Metaparam <- ifelse(is.na(conc.param$Metaparam), conc.param$Parameter, as.character(conc.param$Metaparam))
return(Ovariable(output=conc.param, marginal=colnames(conc.param)!="Result"))
}
)
objects.store(conc.param, samps.j)
cat("Lists conc.params and samps.j stored.\n")
######################3
cat("Descriptive statistics:\n")
# Leave only the main fish species and congeners and remove others
#oprint(summary(
# eu2[eu2$Compound %in% indices$Compound.PCDDF14 & eu$Fish %in% fisl , ],
# marginals = c("Fish", "Compound"), # Matrix is always 'Muscle'
# function_names = c("mean", "sd")
#))
ggplot(eu2@output, aes(x = euResult, colour=Compound))+stat_ecdf()+
facet_wrap( ~ Fish)+scale_x_log10()
ggplot(eu2@output,
aes(x = Length, y = euResult, colour=Compound))+geom_point()+
facet_grid(Compound ~ Fish, scale="free_x")+scale_y_log10()
scatterplotMatrix(t(exp(samps.j$pred[1,,,1])), main = "Predictions for all compounds for Baltic herring")
scatterplotMatrix(t(exp(samps.j$pred[,1,,1])), main = "Predictions for all fish species for PCDDF")
scatterplotMatrix(t(samps.j$Omega[,1,1,,1]))
#scatterplotMatrix(t(cbind(samps.j$Omega[1,1,1,,1],samps.j$mu[1,1,,1])))
plot(coda.samples(jags, 'Omega', N))
plot(coda.samples(jags, 'mu', N))
plot(coda.samples(jags, 'lenp', N))
plot(coda.samples(jags, 'timep', N))
plot(coda.samples(jags, 'pred', N))
↑A. Hallikainen, H. Kiviranta, P. Isosaari, T. Vartiainen, R. Parmanne, P.J. Vuorinen: Kotimaisen järvi- ja merikalan dioksiinien, furaanien, dioksiinien kaltaisten PCB-yhdisteiden ja polybromattujen difenyylieettereiden pitoisuudet. Elintarvikeviraston julkaisuja 1/2004. [1]
↑E-R.Venäläinen, A. Hallikainen, R. Parmanne, P.J. Vuorinen: Kotimaisen järvi- ja merikalan raskasmetallipitoisuudet. Elintarvikeviraston julkaisuja 3/2004. [2]
↑Anja Hallikainen, Riikka Airaksinen, Panu Rantakokko, Jani Koponen, Jaakko
Mannio, Pekka J. Vuorinen, Timo Jääskeläinen, Hannu Kiviranta. Itämeren kalan ja muun kotimaisen kalan ympäristömyrkyt: PCDD/F-, PCB-, PBDE-, PFC- ja OT-yhdisteet. Eviran tutkimuksia 2/2011. ISSN 1797-2981 ISBN 978-952-225-083-4 [3]