The unit ODIN_01 was deployed at Coles place between the 24\(^{th}\) of May and the 3\(^{rd}\) of June 2014.
odin_01 <- read.table("~/data/ODIN_data/christchurch/ODIN_01/odin_01.txt", header=T, quote="")
#force GMT as the time zone to avoid openair issues with daylight saving switches
#The actual time zone is 'NZST'
odin_01$date=as.POSIXct(paste(odin_01$Date,odin_01$Time),tz='GMT')
odin_01$Time<-NULL
odin_01$Date<-NULL
odin_01$Battery<-5*odin_01$Battery/1024
The data from the Coles Place site was obtained from Environment Canterbury through Teresa Aberkane.
ecan_data <- read.delim("~/data/ODIN_data/christchurch/ecan_data20140603.txt",
quote="")
ecan_data$date<-as.POSIXct(ecan_data$date,tz='GMT')
ECan’s data was provided as 10 minute values while ODIN reports every 1 minute so before merging the data, the timebase must be homogenized
odin_01.10min<-timeAverage(odin_01,avg.time='10 min')
all_merged<-merge(odin_01.10min,ecan_data,by='date',all=TRUE)
names(all_merged)<-c('date','Dust.01','Humidity.01','Temperature.01',
'Battery.01', 'CO','PM10_fdms','PM2.5_fdms',
'BC','uvBC','pm10_sharp','Temperature_1m',
'Temperature_10m','RH')
lag_test=ccf(all_merged$Temperature.01,all_merged$Temperature_1m,na.action=na.pass,lag.max=1000,type='correlation',ylab='Correlation',main='Temperature correlation as function of clock lag')
odin01_lag=lag_test$lag[which.max(lag_test$acf)]
The current solar panel arrangement of ODIN does allow for a full recovery of the battery during daytime but the deployment life of the unit is still uncertain.
timePlot(all_merged,pollutant = c('Temperature.01','Temperature_1m'),
group=TRUE)
timePlot(all_merged,pollutant = c('Humidity.01','RH'),group=TRUE)
With ECan’s PM10 data available, a more accurate calibration can be applied to the raw Dust signal from ODIN.
First the data was divided in one training set (70% of observations) and validation set (30% of observations).
set.seed(50)
data_selector<-rbinom(length(all_merged$date),1,0.7)
training_10min=all_merged[data_selector==1,]
validation_10min=all_merged[data_selector==0,]
Training a linear model for the data:
odin1.lm.calib<-lm(data=training_10min,PM10_fdms~Dust.01+Temperature.01)
summary(odin1.lm.calib)
##
## Call:
## lm(formula = PM10_fdms ~ Dust.01 + Temperature.01, data = training_10min)
##
## Residuals:
## Min 1Q Median 3Q Max
## -63.71 -12.67 -3.03 10.74 70.85
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -439.3347 10.2651 -42.8 <2e-16 ***
## Dust.01 1.1064 0.0229 48.3 <2e-16 ***
## Temperature.01 -3.8597 0.0765 -50.5 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 18.6 on 1023 degrees of freedom
## (105 observations deleted due to missingness)
## Multiple R-squared: 0.755, Adjusted R-squared: 0.754
## F-statistic: 1.58e+03 on 2 and 1023 DF, p-value: <2e-16
| Parameter | ODIN_1 |
|---|---|
| Intercept | -439 \(\pm\) 20.1 |
| Slope Temperature | -3.86 \(\pm\) 0.15 |
| Slope Raw Dust | 1.11 \(\pm\) 0.045 |
Applying the calibration function to the raw dust data:
all_merged$Dust.01.corr.2<-int1 +
slp1T*all_merged$Temperature.01 +
slp1D*all_merged$Dust.01
Now quantifying the errors in the calibration:
validation_10min$Dust.01.corr.2<-int1 +
slp1T*validation_10min$Temperature.01 +
slp1D*validation_10min$Dust.01
me_01<-mean(validation_10min$Dust.01.corr.2 - validation_10min$PM10_fdms,
na.rm = TRUE)
rmse_01<-(mean((validation_10min$Dust.01.corr.2 - validation_10min$PM10_fdms)^2,
na.rm = TRUE))^0.5
rse_01<-mean((validation_10min$Dust.01.corr.2 - validation_10min$PM10_fdms)^2,
na.rm = TRUE) /
mean((mean(validation_10min$PM10_fdms,na.rm = TRUE) -
validation_10min$PM10_fdms)^2,na.rm = TRUE)
rsq_01<-1-rse_01
| Indicator | ODIN_1 |
|---|---|
| Mean Error | -0.751 |
| Root Mean Squared Error | 16.8 |
| R\(^2\) | 0.76 |
timeVariation(all_merged,pollutant=c('Dust.01.corr.2',
'PM10_fdms',
'PM2.5_fdms'),
ylab='PM [ug/m3]')
timePlot(all_merged,pollutant=c('Dust.01.corr.2',
'PM10_fdms',
'PM2.5_fdms'),
group=TRUE,avg.time='60 min',ylab='PM [ug/m3]')
timePlot(all_merged,pollutant=c('Dust.01.corr.2',
'BC',
'uvBC'),
group=TRUE,avg.time='60 min',ylab='PM, BC [ug/m3]')