#load packages
library(survival)
library(survminer)
library(cmprsk)
library(RegParallel)

#load in sample information including survival time and death/censoring for subsequent univariate analysis
sample_information <- read.table("sample_information_file.txt", header = TRUE, comment.char = "", sep = "\t")

#raw data in VCF format obtained from "haarz.x callmethyl" software were combined into single matrix containing raw methylation values for all tested samples
#rows denote individual CpG positions with added annotation and genomic coordinate, columns denote individual samples
raw_meth_data <- read.table("raw_methylation_data_file.txt", header = TRUE, comment.char = "", sep = "\t")

#transfer CpG ID into rownames, remove annotation and coordinate columns from raw data table
rownames(raw_meth_data) <- raw_meth_data$CpG_ID
raw_meth_data <- raw_meth_data[,6:ncol(raw_meth_data)]

#filter no. 1, keeping only those CpG positions, which have non-NA values in at least 75 % of all samples
filt_meth_data <- raw_meth_data[rowSums(!is.na(raw_meth_data)) >= (ncol(raw_meth_data) * 0.75),]

#filter no. 2, keeping only those CpG positions, where difference between min and max methylation values across all samples is at least 0.2 (20 %)
tmp_logic1 <- apply(X = filt_meth_data, MARGIN = 1, FUN = function(x){max(x, na.rm = T) - min(x, na.rm = T)}) >= 0.2
filt_meth_data <- filt_meth_data[tmp_logic1,]

#transpose filtered methylation data, rows will now represent samples and columns will represent CpG positions
trans_meth_data <- t(filt_meth_data)

#add survival information to transposed methylation table
trans_meth_data <- data.frame(sample_information$time_to_event, sample_information$death_censored, trans_meth_data)

#perform Univariate Cox regression analysis on all CpG positions left after initial filtering
#this step is computationaly demanding, on Windows machine with 32 GB of memory and 8 cores it took approximately 2 hours to finish
meth_results <- RegParallel(data = trans_meth_data, formula = 'Surv(time_to_event, death_censored) ~ [*]',
                            FUN = function(formula, data){coxph(formula = formula, data = data)},
                            FUNtype = 'coxph', variables = colnames(trans_meth_data)[3:ncol(trans_meth_data)], blocksize = 2000, cores = 8)

#merge non-transposed filtered data table with reuslts from univariate Cox regression analysis and keep only those CpGs which are significant (p < 0.05) according to unadjusted p-value
trans_meth_data_results <- data.frame(filt_meth_data, meth_results)
signif_meth_data <- trans_meth_data_results[trans_meth_data_results$P < 0.05,]

#prepare sample matrix for linear combination of methylation values with beta coeficients obtained from univariate Cox regression analysis
matrix1 <- trans_meth_data_results[,"sample_columns"]

#calculate MethScore for each chosen sample
beta_coef <- as.numeric(trans_meth_data_results$Beta)
matrix2 <- matrix1*beta_coef
MethScore <- apply(X = matrix2, MARGIN = 2, FUN = sum, na.rm = TRUE)

#add MethScore values into sample information table and calculate normalized z-MethScore
sample_information$MethScore <- MethScore
sample_information$z_MethScore <- (sample_information$MethScore - mean(sample_information$MethScore))/sd(sample_information$MethScore)

#use MethScore and z-MethScore in subsequent statistical analyses
