Code for the manuscript "Machine learning reveals STAT motifs as predictors for GR-mediated gene repression"

public public 1yr ago 0 bookmarks

Code for the manuscript "Machine learning reveals STAT motifs as predictors for GR-mediated gene repression"

TODO: Add citation once paper is accepted

Table of contents

  1. Software dependencies

Code Snippets

54
55
shell:
    "wget {params.url} -P {params.outdir}"
SnakeMake From line 54 of main/Snakefile
68
69
shell:
    "bowtie-build -f {input[fa]} {params.outdir}/{params.basename}"
81
82
83
84
85
86
87
88
89
90
91
92
shell:
    """
    wget http://mitra.stanford.edu/kundaje/akundaje/release/blacklists/mm10-mouse/mm10.blacklist.bed.gz -P {params.outdir} && \
    wget http://ftp.ensembl.org/pub/release-100/gtf/mus_musculus/Mus_musculus.GRCm38.100.gtf.gz -P {params.outdir} && \
    wget http://hgdownload.cse.ucsc.edu/goldenPath/mm9/liftOver/mm9ToMm10.over.chain.gz -P {params.outdir} && \
    gunzip data/current/mm9ToMm10.over.chain.gz && \

    mkdir -p "data/current/gencode_annotations" && \
    wget https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_mouse/release_M1/gencode.vM1.annotation.gtf.gz -P {params.outdir}/gencode_annotations/ && \
    wget https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_mouse/release_M23/gencode.vM23.annotation.gtf.gz -P {params.outdir}/gencode_annotations/ && \
    zcat data/current/gencode_annotations/gencode.vM23.annotation.gtf.gz | grep -P '\tgene\t' > data/current/gencode_annotations/gencode.vM23.annotation.gene.gtf
    """  
SnakeMake From line 81 of main/Snakefile
104
105
106
107
108
109
110
111
112
shell:
    """
    mkdir -p {params.outdir} && \
    wget {params.downloadlink} -P {params.outdir} && \
    gunzip -c {params.outdir}/remap2022_all_macs2_mm10_v1_0.bed.gz > {output.fullbed} && \
    sed -E "s/(\\w+)\\.(\\w+)\\.(\\w+)/\\1\\t\\2\\t\\3/g" {output.fullbed} > {output.separatedfulltsv} && \
    awk -F'\t' '$6~/BMDM|macrophage/' {output.separatedfulltsv} > {output.filteredtsv} && \
    awk '{{print $1"\t"$2"\t"$3"\t"$4","$5","$6}}' FS='\t' {output.filteredtsv} > {output.filteredbed}
    """
SnakeMake From line 104 of main/Snakefile
119
120
121
122
123
124
125
    shell:
        "gunzip -c {input} > {output}" # -c keeps the original file unchanged

rule scan_nr3c1_genomewide:
    input:
        motif="data/current/motifs/custom/nr3c1_simplified_{sitelength}.motif",
        fa= "data/current/genome/GRCm38.primary_assembly.standchr.fa"
SnakeMake From line 119 of main/Snakefile
128
129
130
131
132
shell:
    """
    mkdir -p $(dirname {output}) && \
    scanMotifGenomeWide.pl {input.motif} {input.fa} -bed > {output}
    """
SnakeMake From line 128 of main/Snakefile
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--ABC_DexLPS_all"),
              type="character",
              help="Path to file with all ABC predictions passing 0.02 (in DexLPS condition)"),
  make_option(c("--ABC_LPS_all"),
              type="character",
              help="Path to file with all ABC predictions passing 0.02 (in LPS condition)"),
  make_option(c("--fimo_results_summitregion"),
              type="character",
              help="Path to rds file of fimo motifcounts within summitregions"),
  make_option(c("--fimo_results_dexlps"),
              type="character",
              help="Path to rds file of fimo motifcounts within ABC regions (in DexLPS condition)"),
  make_option(c("--fimo_results_lps"),
              type="character",
              help="Path to rds file of fimo motifcounts within ABC regions (in LPS condition)"),
  make_option(c( "--chipseq_ranges"),
              type="character",
              help="Path to summit file of IDR peaks"),
  make_option(c("--outdir"),
              type="character",
              help="Path to output directory")
)

opt <- parse_args(OptionParser(option_list=option_list))

dir.create(opt$outdir)

#change default for stringAsFactors
options(stringsAsFactors = FALSE)

suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=10, family = "ArialMT", colour="black"),
             title=element_text(size=10, family="ArialMT", colour="black"),
             panel.grid.major = element_blank(),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=10, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"))

set.seed(12345)

#-------------------------------
## read in  data
#-------------------------------
ABC_DexLPS_all <- read.delim(opt$ABC_DexLPS_all) %>% plyranges::as_granges(., seqnames=chr)
ABC_LPS_all <- read.delim(opt$ABC_LPS_all) %>% plyranges::as_granges(., seqnames=chr)
fimo_results_dexlps <- readRDS(opt$fimo_results_dexlps)
fimo_results_lps <- readRDS(opt$fimo_results_lps)
fimo_results_summitregion <- readRDS(opt$fimo_results_summitregion)
chipseq_ranges <- readRDS(opt$chipseq_ranges)

# assign a name to allow for matching for prox based assignment later
chipseq_ranges$name <- paste(seqnames(chipseq_ranges),
                             start(chipseq_ranges),
                             end(chipseq_ranges),
                             sep="_")

#--------------------------------------------
#--------------------------------------------
## prepare motifcounts
#--------------------------------------------
#--------------------------------------------

## summitregions
#--------------------------------------------

get_summitregion_motifcounts <- function(summits, fimo_results){

  # Take 100bp windows around ChIP-seq summits to recreate the original query
  fimo_queries_summitregion <- summits %>% 
    plyranges::anchor_center() %>% 
    plyranges::mutate(width = 100)

  ## intersect queries with fimo hits
  summitregion_leftjoin_query_hits <- fimo_queries_summitregion %>% 
    plyranges::join_overlap_left(fimo_results)

  # aggregate motifcounts per query
  # seqnames is needed for the train test split later
  summitregion_leftjoin_query_hits_motifsaggregated <-
    as.data.frame(summitregion_leftjoin_query_hits) %>% 
    group_by(name, seqnames, motif_alt_id) %>%
    summarize(motifcount = n())
  # if a region has no motifmatches at all, it get's an NA which showes up as motifname after doing pivor_wider

  # cast it in a way, so we have unique regions as rows and all observed motifs as columns
  motifcounts <- 
    summitregion_leftjoin_query_hits_motifsaggregated %>%
    tidyr::pivot_wider(names_from = motif_alt_id,
                       values_from = motifcount,
                       values_fill = 0) %>%
    dplyr::select(!'NA') # remove NA motif that got introduced by region without any matches

  return(motifcounts)
}

motifcounts_summitregion <- get_summitregion_motifcounts(
  chipseq_ranges,
  fimo_results_summitregion
)

## ABC enhancerregions
#--------------------------------------------

get_ABC_motifcounts <- function(ABC_results, fimo_results){
  # intersect queries with fimo hits
  ABC_results_unique <- ABC_results %>% unique()
  ABC_results_leftjoin_query_hits <- ABC_results_unique %>% 
    plyranges::join_overlap_left(fimo_results)

  # aggregate motifcounts per query
  ABC_results_leftjoin_query_hits_motifsaggregated <-
    as.data.frame(ABC_results_leftjoin_query_hits) %>% 
    group_by(name, seqnames ,motif_alt_id) %>%
    summarize(motifcount = n())

  # cast it in a way, so we have unique regions as rows and all observed motifs as columns
  motifcounts_abcregion <- 
    ABC_results_leftjoin_query_hits_motifsaggregated %>%
    tidyr::pivot_wider(names_from = motif_alt_id,
                       values_from = motifcount,
                       values_fill = 0) %>%
    dplyr::select(!'NA') # remove NA motif that got introduced by region without any matches

  return(motifcounts_abcregion)
}

motifcounts_abcregion_dexlps <- get_ABC_motifcounts(
  ABC_DexLPS_all,
  fimo_results_dexlps
)
motifcounts_abcregion_lps <- get_ABC_motifcounts(
  ABC_LPS_all,
  fimo_results_lps
)

#--------------------------------------------
## ASSIGNMENTS
#--------------------------------------------

## prox based
#--------------------------------------------

# these are mgi_symbols, the ones from ABC are ensemble IDs. Is this a problem?
assignment_summit_prox <- as.data.frame(chipseq_ranges) %>%
  dplyr::rename(anno=mgi_symbol) %>%
  dplyr::select(name, anno)

## hybrid
#--------------------------------------------
# we need an assignment of the regionIDs (from the ChIPseq summtiregion)
# to the ABC derived assignments

get_assignment_summit_ABCregion <- function(summit, ABCregions){
  # what summit lies in what ABC region
  assignment_summit_ABCregion <- summit %>% 
    plyranges::join_overlap_left(ABCregions)

  assignment_summit_ABCregion <- as.data.frame(assignment_summit_ABCregion) %>% 
    dplyr::select(name.x, TargetGene, ABC.Score, ABC.Score.Numerator, class, isSelfPromoter) %>%
    magrittr::set_colnames(c("name","anno","abcscore","abcnumerator","class","isSelfPromoter")) 

  return(assignment_summit_ABCregion)
}

assignment_summits_ABCregion_dexlps <- get_assignment_summit_ABCregion(
  chipseq_ranges,
  ABC_DexLPS_all
)
assignment_summits_ABCregion_lps <- get_assignment_summit_ABCregion(
  chipseq_ranges,
  ABC_LPS_all
)

## ABC based
#--------------------------------------------
assignment_abcregion_dexlps <- as.data.frame(ABC_DexLPS_all) %>% 
  dplyr::select(name,TargetGene,ABC.Score,ABC.Score.Numerator,class,isSelfPromoter) %>%
  magrittr::set_colnames(c("name","anno","abcscore","abcnumerator","class","isSelfPromoter")) %>%
  dplyr::mutate(anno=gsub("\\.[0-9]*$","",anno))

assignment_abcregion_lps <- as.data.frame(ABC_LPS_all) %>% 
  dplyr::select(name,TargetGene,ABC.Score,ABC.Score.Numerator,class,isSelfPromoter) %>%
  magrittr::set_colnames(c("name","anno","abcscore","abcnumerator","class","isSelfPromoter")) %>%
  dplyr::mutate(anno=gsub("\\.[0-9]*$","",anno))

#--------------------------------------------
## export objects
#--------------------------------------------

# assignments
saveRDS(assignment_summit_prox, paste0(opt$outdir,"assignment_summit_prox.rds"))
saveRDS(assignment_summits_ABCregion_dexlps, paste0(opt$outdir,"assignment_summits_ABCregion_dexlps.rds"))
saveRDS(assignment_summits_ABCregion_lps, paste0(opt$outdir,"assignment_summits_ABCregion_lps.rds"))
saveRDS(assignment_abcregion_dexlps, paste0(opt$outdir,"assignment_abcregion_dexlps.rds"))
saveRDS(assignment_abcregion_lps, paste0(opt$outdir,"assignment_abcregion_lps.rds"))
# motifcoutns
saveRDS(motifcounts_summitregion, paste0(opt$outdir,"motifcounts_summitregion.rds"))
saveRDS(motifcounts_abcregion_dexlps, paste0(opt$outdir,"motifcounts_abcregion_dexlps.rds"))
saveRDS(motifcounts_abcregion_lps, paste0(opt$outdir,"motifcounts_abcregion_lps.rds"))
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--contrast_DexLPSvLPS"),
              type="character",
              help="Path to annotated tsv file of DeSeq2 contrast of DexLPS vs LPS"),
  make_option(c("--assignment_summit_prox"),
              type="character",
              help="Path to rds file of proximity based assignment of peak summits to genes"),
  make_option(c("--assignment_summits_abcregion_dexlps"),
              type="character",
              help="Path to rds file of assignment of peak summits within abcregions to genes (in DexLPS condition)"),
  make_option(c("--assignment_summits_abcregion_lps"),
              type="character",
              help="Path to rds file of assignment of peak summits within abcregions to genes (in LPS condition)"),
  make_option(c("--assignment_abcregion_dexlps"),
              type="character",
              help="Path to rds file of assignment of abcregions to genes (in DexLPS condition)"),
  make_option(c( "--assignment_abcregion_lps"),
              type="character",
              help="Path to rds file of assignment of abcregions to genes (in LPS condition)"),
  make_option(c("--motifcounts_summitregion"),
              type="character",
              help="Path to rds file of fimo motifcounts within summitregions"),
  make_option(c("--motifcounts_abcregion_dexlps"),
              type="character",
              help="Path to rds file of fimo motifcounts within ABC regions (in DexLPS condition)"),
  make_option(c("--motifcounts_abcregion_lps"),
              type="character",
              help="Path to rds file of fimo motifcounts within ABC regions (in LPS condition)"),
  make_option(c( "--outdir"),
              type="character",
              help="Path to output directory")
  )

opt <- parse_args(OptionParser(option_list=option_list))

dir.create(opt$outdir)

#change default for stringAsFactors
options(stringsAsFactors = FALSE)

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(org.Mm.eg.db, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(DESeq2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ComplexHeatmap, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=6, family = "ArialMT", colour="black"),
             title=element_text(size=8, family="ArialMT", colour="black"),
             panel.grid.major = element_line(colour="grey", size=0.2),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=6, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"),
             legend.key.size = unit(6, 'points'), #change legend key size
             legend.key.height = unit(6, 'points'), #change legend key height
             legend.key.width = unit(6, 'points'), #change legend key width
             legend.text = element_text(size=6, family="ArialMT", colour="black"))

set.seed(12345)

#-------------------------------
## read in  data
#-------------------------------

contrast_DexLPSvLPS <- read.delim(opt$contrast_DexLPSvLPS)

for (optname in names(opt)[2:9]){ #except for the outdir
  print(paste0("Loading ", optname))
  assign(optname, readRDS( opt[[optname]] ))
}

#--------------------------------------------
## ---- function definitions
#--------------------------------------------

coerce_coef2df <- function(model_coef){
  model_coef <- as.matrix(model_coef)
  model_coef <- as.data.frame(model_coef)
  model_coef$names <- rownames(model_coef)
  colnames(model_coef) <- c("estimates", "names")
  return(model_coef)
}

#------------function will------------:
# * merge the motifdata with gene assignments and 
# * then merge the gene expression changes,
# * filter for DE genes and aggregate per gene
#--------------------------------------
merge_motifdata_with_assignments <- function( motifcounts, assignments, contrast, 
                                              maxonly=FALSE, excludepromoters=FALSE, weightby=FALSE, sepPromEnh=FALSE){

  # check if we should use all abc assignments, or only the max one of each peakID
  if(maxonly==TRUE){
    assignments <- assignments %>% group_by(name) %>% filter(abcscore==max(abcscore)) %>% distinct()
  } else{
    assignments <- assignments
  }

  if(excludepromoters=="all"){
    assignments <- assignments %>% filter(!class=="promoter")
  } else if (excludepromoters=="onlyNONself"){
    assignments <- assignments %>% filter(!c(class=="promoter" & isSelfPromoter=="False"))
  } else{
    assignments <- assignments
  }

  motifdf <- merge(motifcounts, assignments, 
                   by.x="name", by.y="name")

  motifdf <- motifdf %>% relocate(c(anno))

  # merge the expression change
  # use mgi_symbol for prox based, otherwise ensemblID
  # We DONT set all.x=TRUE because we don't care about predicting gene that aren't even expressed or that we don't have a clear label for
  if(maxonly=="prox"){
    motifdf <- merge(motifdf, contrast, 
                     by.x="anno", by.y="mgi_symbol")
  } else {
    motifdf <- merge(motifdf, contrast, 
                     by.x="anno", by.y="Row.names")
  }

  #recode the logFC and padj into a label (optionally through command line arguments)
  motifdf <- motifdf %>% 
    mutate(label=case_when(log2FoldChange>0.58 & padj < 0.05 ~ "up",
                           log2FoldChange<(-0.58) & padj < 0.05 ~ "down",
                           TRUE ~ "no_change")) %>%
    filter(label!="no_change") %>%
    mutate(label=factor(label,
                        levels=c("down","up"),
                        labels=c(0,1))) %>%
    relocate(label)

  # chr 2, 3 and 4 (20%) were used as the tuning set for hyperparameter tuning. 
  # Regions from chromosomes 1, 8 and 9 (20%) were used as the test set for performance evaluation 
  # The remaining regions were used for model training.

  #------aggregate over gene SYMBOL
  if ("abcscore" %in% colnames(motifdf)) { # loop for ABC based assignments

    if (weightby=="abcscore"){
      unselect_col <- "abcnumerator"
    } else if(weightby=="abcnumerator") {
      unselect_col <- "abcscore"
    } else{
      unselect_col <- c("abcscore","abcnumerator")
    }

    if (sepPromEnh==TRUE){
      motifdf_aggr <-
        motifdf %>% 
        dplyr::select(!c(unselect_col,"name","baseMean","log2FoldChange","lfcSE","stat","pvalue","padj","gene_biotype","mgi_symbol")) %>%
        { if(weightby!=FALSE) mutate(.,across(where(is.numeric), ~ (.x * get(weightby)))) else .} %>% # weight features by score
        dplyr::select(!any_of(as.character(weightby))) %>% # then we can drop the score since it will be nonsensical after the aggregation anyways
        group_by(label,seqnames,anno,class) %>%
        dplyr::summarise(across( where(is.numeric), .fns=sum )) %>% # sum up genewise feature counts
        ungroup()

      # From here we need to cast the motifcounts for the promoterregions, so that in the end we have one row per gene (instead of 1-2)
      motifdf_aggr <- motifdf_aggr %>% tidyr::pivot_wider(id_cols=c(label,seqnames,anno), 
                                                          names_from=class, 
                                                          values_from = !c(label,seqnames,anno, class),
                                                          values_fill = 0)
    } else {
      motifdf_aggr <-
        motifdf %>% 
        dplyr::select(!c(unselect_col,"name","baseMean","log2FoldChange","lfcSE","stat","pvalue","padj","gene_biotype","mgi_symbol")) %>%
        { if(weightby!=FALSE) mutate(., across(where(is.numeric), ~ (.x * get(weightby)))) else .} %>% # weight features by score
        dplyr::select(!any_of(as.character(weightby))) %>% # then we can drop the score since it will be nonsensical after the aggregation anyways
        group_by(label,seqnames,anno) %>%
        dplyr::summarise(across( where(is.numeric), .fns=sum )) %>% # sum up genewise feature counts
        ungroup()
    }


  } else { # loop for prox based assignments
    motifdf_aggr <-
      motifdf %>% 
      dplyr::select(!c("name","baseMean","log2FoldChange","lfcSE","stat","pvalue","padj","gene_biotype")) %>% 
      group_by(label,seqnames,anno) %>%
      dplyr::summarise(across( where(is.numeric), .fns=sum )) %>% # sum up genewise feature counts
      ungroup()
  }

  return(motifdf_aggr)

}


#------------function needs------------:
# featurematrix and indexes to perform split of test vs trainval set
# (trainval set is used for CV to find optimal regularization)
#------------function will------------:
# run cv.glmnet (as elastic net regression) and pick lambda.1se as regularization
# determine model performance on test set
# plots for raw counts of certain factors are currently turned of
complete_GLM_analysis <- function(motifdf, trainvalidx, genenames){

  # Create training subset for model development & testing set for model performance testing
  # make it based on chromosomes, instead of completely random
  # as in bpnet, we set aside chr 1,8 and 9 for testing

  #inTrain <- sort(sample(nrow(motifdata_abc_aggr), nrow(motifdata_abc_aggr)*0.75))

  features_train <- motifdf[ trainvalidx, -c(1,2,3)] %>% as.matrix()
  features_test <- motifdf[ -trainvalidx, -c(1,2,3)] %>% as.matrix()
  targets_train <- motifdf[ trainvalidx, ] %>% pull(label) %>% as.numeric(levels(.))[.] %>% as.matrix()
  targets_test <- motifdf[ -trainvalidx, ] %>% pull(label) %>% as.numeric(levels(.))[.] %>% as.matrix()

  #------------------------
  ## Elastic net
  #------------------------

  cvfit_net <- glmnet::cv.glmnet(x=features_train, 
                                 y=targets_train, 
                                 family="binomial", 
                                 type.measure = "auc",
                                 nfolds = 6,
                                 alpha=0.5)


  # Performance on training data
  targets_train_net.prob <- predict(cvfit_net,
                                    type="response",
                                    newx = features_train,
                                    s = 'lambda.min')
  pred_train_net <- ROCR::prediction(targets_train_net.prob[,1], targets_train) #only need the probabilities for 1's

  auc_ROCR_train_net <- ROCR::performance(pred_train_net, measure = "auc") #to assess AUC for model
  auc_ROCR_train_net@y.values[[1]]

  # Predict on unseen data
  targets_net.prob <- predict(cvfit_net,
                              type="response",
                              newx = features_test,
                              s = 'lambda.min')
  pred_net <- ROCR::prediction(targets_net.prob[,1], targets_test) #only need the probabilities for 1's

  auc_ROCR_net <- ROCR::performance(pred_net, measure = "auc") #to assess AUC for model
  auc_ROCR_net@y.values[[1]]

  #------------------------
  ## Model coefficients
  #------------------------

  coef_df_net <- coerce_coef2df( coefficients(cvfit_net, s = 'lambda.min'))

  gg_net <- ggplot( data=coef_df_net %>% filter(abs(estimates)>0) )+
    geom_bar(aes(x=reorder(names, -estimates), y=estimates),
             stat="identity")+
    labs(title=" ",x="", y="Net coefs")+
    #coord_flip()+
    theme(axis.text.x = element_text(angle = 45, hjust=1),
          plot.margin = unit(c(0, 0, -6, 10), "points"))

  #------------------------
  # ROC curves
  #------------------------
  # calculate probabilities for TPR/FPR for predictions
  perf_train_net <- ROCR::performance(pred_train_net,"tpr","fpr")
  perf_net <- ROCR::performance(pred_net,"tpr","fpr")

  # plot ROC curve

  gg_ROC <- ggplot()+
    geom_line( aes(x=perf_train_net@x.values[[1]], y=perf_train_net@y.values[[1]], colour = "train_net") ) +
    geom_line( aes(x=perf_net@x.values[[1]],y=perf_net@y.values[[1]], colour = "test_net") ) +
    geom_abline(intercept=0,slope=1, linetype=4, colour="grey")+
    scale_colour_manual(values=c("darkblue", "blue"), 
                        name=" ",
                        breaks=c("train_net", "test_net"),
                        labels=c(paste("net train. AUC:",round( auc_ROCR_train_net@y.values[[1]], 2)) ,
                                 paste("net test. AUC:", round( auc_ROCR_net@y.values[[1]], 2))
                        )
    )+
    labs(x="False positive rate", y="True positive rate")+
    theme(
      legend.position=c(0.65,0.15)
    )

  # add metric to global variable
  new_metrics = data.frame(
    net_train = auc_ROCR_train_net@y.values[[1]],
    net_test = auc_ROCR_net@y.values[[1]] 
  )


  full_panel <- ggpubr::ggarrange(gg_ROC,gg_net, nrow=2,
                                  labels=c("A","B"),
                                  heights = c(1,1))

  results <- list()
  results[[1]] <- full_panel
  results[[2]] <- new_metrics
  results[[3]] <- coef_df_net
  results[[4]] <- cvfit_net
  return(results)
}



#------------------------------------------------
## initialize object to track performance metrics
#------------------------------------------------

AUC_metrics = data.frame(
  # parameter combination
  condition=character(),
  motifdata=character(),
  excludepromoters=character(),
  onlymax=character(),
  weight=character(),
  sepPromEnh=character(),
  # performance
  net_train = numeric(),
  net_test = numeric()
)

net_model_coefs = list()


#------------------------------------------------
## run proximity based
#------------------------------------------------

# This is independent of the ABC results (no need to loop through different assignment variations)

print("Running GLM on prox-based assignments")
my_rdsfile <- paste0(opt$outdir,"prox.rds")
if(!file.exists(my_rdsfile)){

  motifdata_aggr <- merge_motifdata_with_assignments(motifcounts_summitregion,
                                                     assignment_summit_prox,
                                                     contrast_DexLPSvLPS,
                                                     maxonly="prox",
                                                     excludepromoters=FALSE,
                                                     weightby = FALSE,
                                                     sepPromEnh = FALSE)
  motifdata_aggr_scaled <- motifdata_aggr %>% mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector)))

  motifdata_aggr_tranval_idx <- motifdata_aggr_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))

  performance <- complete_GLM_analysis (motifdata_aggr_scaled, motifdata_aggr_tranval_idx, genenames=genenames)

  #------------------------
  ## Raw counts
  #------------------------
  nr3c1counts <- motifdata_aggr %>% 
    group_by(label) %>% 
    dplyr::count(NR3C1) %>% 
    mutate(counts_fac = case_when(NR3C1>=1 ~ ">=1",
                                  NR3C1==0 ~ "0"), # aggregate it towards to top end
           counts_fac = factor(as.character(counts_fac), levels=c("0",">=1")) ) %>%
    group_by(counts_fac) %>% 
    mutate(freq = n / sum(n)) %>%
    group_by(label,counts_fac) %>%
    dplyr::summarize(sum_n=sum(n),
              sum_freq=sum(freq))

  gg_nr3c1counts <- ggplot(data=nr3c1counts , aes(x=counts_fac,y=sum_freq,fill=label)) + 
    geom_bar(stat="identity", position="dodge", alpha=0.5)+
    geom_text(aes(label=format(sum_freq, digits=2)),
              position = position_dodge(.9), 
              vjust = -0.5, 
              size = 3) + 
    scale_fill_manual(values=c("0"="blue", "1"="red"),
                      labels=c("DOWN","UP"))+
    labs(x="NR3C1 matches", y="% genes", fill="")+
    theme(
      plot.margin = unit(c(10, 6, 0, 10), "points")
    )
  gg_nr3c1counts

  relcounts <- motifdata_aggr %>% 
    group_by(label) %>% 
    dplyr::count(REL) %>% 
    mutate(counts_fac = case_when(REL>=1 ~ ">=1",
                                  REL==0 ~ "0"), # aggregate it towards to top end
           counts_fac = factor(as.character(counts_fac), levels=c("0",">=1")) ) %>%
    group_by(counts_fac) %>%
    mutate(freq = n / sum(n)) %>%
    group_by(label,counts_fac) %>%
    dplyr::summarize(sum_n=sum(n),
              sum_freq=sum(freq))

  gg_relcounts <- ggplot(data=relcounts , aes(x=counts_fac,y=sum_freq,fill=label)) + 
    geom_bar(stat="identity", position="dodge", alpha=0.5)+
    geom_text(aes(label=format(sum_freq, digits=2)),
              position = position_dodge(.9), 
              vjust = -0.5, 
              size = 3) + 
    scale_fill_manual(values=c("0"="blue", "1"="red"),
                      labels=c("DOWN","UP"))+
    labs(x="REL matches", y="% genes", fill="")+
    theme(
      plot.margin = unit(c(10, 6, 0, 10), "points")
    )
  gg_relcounts

  gg_rawcounts <-  ggpubr::ggarrange( gg_nr3c1counts, gg_relcounts, ncol=2, common.legend = TRUE, legend="bottom")
  saveRDS(gg_rawcounts, paste0(opt$outdir,"gg_rawcounts.rds"))

  #------------------------


  saveRDS(performance,
          file=my_rdsfile)
} else {
  performance <- readRDS(my_rdsfile)
}

plot(performance[[1]])

AUC_metrics <- rbind(AUC_metrics,
                     "prox" = c(
                       condition="dexlps",
                       motifdata="motifcounts_summitregion",
                       excludepromoters=FALSE,
                       onlymax="prox",
                       weight=FALSE,
                       sepPromEnh=FALSE,
                       performance[[2]]
                       )
                     )

net_model_coefs[["prox"]] <- performance[[3]]


## Raw counts
gg_firstgene <- ggplot() + 
  geom_bar(data=motifdata_aggr , aes(NR3C1,fill=label), position="dodge", alpha=0.5)+
  scale_fill_manual(values=c("0"="blue", "1"="red"),
                    labels=c("DOWN","UP"))+
  labs(x="NR3C1", y="counts", fill="")+
  theme(
    plot.margin = unit(c(10, 6, 0, 10), "points")
  )
gg_firstgene

#------------------------------------------------
## run example
#------------------------------------------------


# motifdata_aggr <- merge_motifdata_with_assignments(
#   motifcounts_summitregion,
#   assignment_summitregion_abc_dexlps,
#   contrast_DexLPSvLPS,
#   maxonly=FALSE, 
#   excludepromoters=FALSE, 
#   weightby=FALSE, 
#   sepPromEnh=FALSE)
# 
# motifdata_aggr_tranval_idx <- motifdata_aggr %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))
# performance <- complete_GLM_analysis (motifdata_aggr, motifdata_aggr_tranval_idx, genenames=genenames)
# plot(performance[[1]])
# AUC_metrics <- rbind(AUC_metrics,
#                      "test" = c(condition="dexlps",
#                                 motifdata="motifcounts_peak",
#                                 onlymax=FALSE,
#                                 excludepromoters=FALSE,
#                                 weight=FALSE,
#                                 sepPromEnh=FALSE,
#                                 performance[[2]]))
# net_model_coefs[["test"]] <- performance[[3]]
# 
# gg_firstgene <- ggplot() + 
#   geom_bar(data=performance[[5]] , aes(NR3C1,fill=label), position="dodge", alpha=0.5)+
#   scale_fill_manual(values=c("0"="blue", "1"="red"),
#                     labels=c("DOWN","UP"))+
#   labs(x="NR3C1", y="counts", fill="")+
#   theme(
#     plot.margin = unit(c(10, 6, 0, 10), "points")
#   )
# gg_firstgene


#------------------------------------------------
## peakregion_counts - proxbased assignment
## peakregion_counts - abcbased assignment (both conditions)
## enhancerregion_counts - abcbased assignment (2 conditions)
#------------------------------------------------

# rewrite to assign values for both conditions and then use those to compute the difference as well

not_all_na <- function(x) any(!is.na(x))

for (motifdata in c("motifcounts_abcregion","motifcounts_summitregion")){
  for(excludepromoters in c(FALSE,"all","onlyNONself")){
    for (onlymax in c(TRUE,FALSE)){
      for (sepPromEnh in c(TRUE,FALSE)){
        for (weight in c(FALSE, "abcscore")){

          # set assignments fitting for the input data
          if(motifdata=="motifcounts_abcregion"){
            assignment_dexlps <- assignment_abcregion_dexlps
            assignment_lps <- assignment_abcregion_lps
            motifcounts_dexlps <- motifcounts_abcregion_dexlps
            motifcounts_lps <- motifcounts_abcregion_lps
          } else if (motifdata=="motifcounts_summitregion" ){
            # in this case the motifcounts for the 2 conditions are the same, but there assignments differ
            assignment_dexlps <- assignment_summits_abcregion_dexlps
            assignment_lps <- assignment_summits_abcregion_lps
            motifcounts_dexlps <- motifcounts_summitregion
            motifcounts_lps <- motifcounts_summitregion
          } else {break}

          #-----------------------DEXLPS------------------------------
          featurematrix_dexlps <- merge_motifdata_with_assignments(motifcounts_dexlps,
                                                                   assignment_dexlps,
                                                                   contrast_DexLPSvLPS,
                                                                   weightby=weight, 
                                                                   maxonly=onlymax, 
                                                                   excludepromoters=excludepromoters, 
                                                                   sepPromEnh=sepPromEnh)

          # remove columns that are NA after scaling 
          featurematrix_dexlps_scaled <- featurematrix_dexlps %>% 
            mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector))) %>%
            dplyr::select(where(not_all_na))

          #-----

          motifdata_aggr_tranval_idx <- featurematrix_dexlps_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))
          modelname <- paste(motifdata,"condition_dexlps_exclprom",excludepromoters,"onlymax",onlymax,"sepPromEnh",sepPromEnh,"weight",weight, sep="_")
          print(modelname)

          my_rdsfile <- here( paste0(opt$outdir, modelname,".rds"))
          if(!file.exists(my_rdsfile)){
            performance <- complete_GLM_analysis (featurematrix_dexlps_scaled, motifdata_aggr_tranval_idx, genenames=genenames)
            saveRDS(performance,file=my_rdsfile)
          } else {
            performance <- readRDS(my_rdsfile)
          }

          AUC_metrics <- rbind(AUC_metrics,
                               c(
                                 condition="dexlps",
                                 motifdata=motifdata,
                                 excludepromoters=excludepromoters,
                                 onlymax=onlymax,
                                 weight=weight,
                                 sepPromEnh=sepPromEnh,
                                 performance[[2]]
                                 )
                               )%>%
            magrittr::set_rownames(c(rownames(AUC_metrics),modelname))

          net_model_coefs[[modelname]] <- performance[[3]]

          #--------------------------LPS---------------------------
          featurematrix_lps <- merge_motifdata_with_assignments(motifcounts_lps,
                                                                assignment_lps,
                                                                contrast_DexLPSvLPS,
                                                                weightby=weight, 
                                                                maxonly=onlymax, 
                                                                excludepromoters=excludepromoters, 
                                                                sepPromEnh=sepPromEnh)
          featurematrix_lps_scaled <- featurematrix_lps %>% 
            mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector))) %>%
            dplyr::select(where(not_all_na))
          #-----
          motifdata_aggr_tranval_idx <- featurematrix_lps_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))
          modelname <- paste(motifdata,"condition_lps_exclprom",excludepromoters,"onlymax",onlymax,"sepPromEnh",sepPromEnh,"weight",weight, sep="_")
          print(modelname)

          my_rdsfile <- here(paste0(opt$outdir, modelname,".rds"))
          if(!file.exists(my_rdsfile)){
            performance <- complete_GLM_analysis (featurematrix_lps_scaled, motifdata_aggr_tranval_idx, genenames=genenames)
            saveRDS(performance,file=my_rdsfile)
          } else {
            performance <- readRDS(my_rdsfile)
          }

          AUC_metrics <- rbind(AUC_metrics,
                               c(
                                 condition="lps",
                                 motifdata=motifdata,
                                 excludepromoters=excludepromoters,
                                 onlymax=onlymax,
                                 weight=weight,
                                 sepPromEnh=sepPromEnh,
                                 performance[[2]]
                                 )
                               )%>%
            magrittr::set_rownames(c(rownames(AUC_metrics),modelname))

          net_model_coefs[[modelname]] <- performance[[3]]


          #-----------------------DIFFERENCE------------------------------

          # they contain the same motifs, but not the same genes. 
          # doublecheck that all columnnames are identical
          table(colnames(featurematrix_dexlps) == colnames(featurematrix_lps))

          #  motifcounts missing in one condition should be set to 0 

          merged_featurematrix <- merge(featurematrix_dexlps,
                                        featurematrix_lps, 
                                        by=c("anno","label","seqnames"),
                                        all=TRUE)

          # replace missing counts in one of the conditions with 0
          merged_featurematrix[is.na(merged_featurematrix)] <- 0

          # use dataframe suffix to grab respective columns
          featurematrix_diff <- 
            merged_featurematrix[grep(".x$",colnames(merged_featurematrix))] - 
            merged_featurematrix[grep(".y$",colnames(merged_featurematrix))] 
          # tidy up column names
          colnames(featurematrix_diff) <- gsub(".x$","", colnames(featurematrix_diff))

          # add first 3 columns back after computing the difference of the counts
          featurematrix_diff <- cbind(merged_featurematrix[1:3],featurematrix_diff)

          featurematrix_diff_scaled <- featurematrix_diff %>% 
            mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector))) %>%
            dplyr::select(where(not_all_na))

          # run GLM and look at performance  
          featurematrix_diff_tranval_idx <- featurematrix_diff_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))

          modelname <- paste(motifdata,"condition_DexLPS-LPS_exclprom",excludepromoters,"onlymax",onlymax,"sepPromEnh",sepPromEnh,"weight",weight, sep="_")
          print(modelname)
          my_rdsfile <- here(paste0(opt$outdir, modelname,".rds"))
          if(!file.exists(my_rdsfile)){
            performance <- complete_GLM_analysis (featurematrix_diff_scaled, featurematrix_diff_tranval_idx, genenames=genenames)
            saveRDS(performance,file=my_rdsfile)
          } else {
            performance <- readRDS(my_rdsfile)
          }

          AUC_metrics <- rbind(AUC_metrics,
                               c(
                                 condition="DexLPS-LPS",
                                 motifdata=motifdata,
                                 excludepromoters=excludepromoters,
                                 onlymax=onlymax,
                                 weight=weight,
                                 sepPromEnh=sepPromEnh,
                                 performance[[2]]
                                 )
                               )%>%
            magrittr::set_rownames(c(rownames(AUC_metrics),modelname))

          net_model_coefs[[modelname]] <- performance[[3]]


        }
      }
    }
  }
}


#------------------------------------------------
## put model coefs into dataframes
#------------------------------------------------
motifnames <- colnames(motifcounts_summitregion)[3:ncol(motifcounts_summitregion)]

# make empty dataframe with all motifs
model_coefs_joint <- data.frame(featurename=motifnames)

# when we treat promoters and enhancers separately, the featurenames differ
model_coefs_sep <- data.frame(featurename= c(paste(motifnames,"genic",sep="_"),
                                             paste(motifnames,"promoter",sep="_"),
                                             paste(motifnames,"intergenic",sep="_"))
)

for (model in names(net_model_coefs)){
  if (grepl("sepPromEnh_FALSE",model)){
    model_coefs_joint <- merge(model_coefs_joint,
                               net_model_coefs[[model]],
                               by.x="featurename", by.y="names",
                               all=TRUE) %>% 
      dplyr::rename(!! model := "estimates")
  } else if (model=="prox"){
    model_coefs_joint <- merge(model_coefs_joint,
                               net_model_coefs[[model]],
                               by.x="featurename", by.y="names",
                               all=TRUE) %>% 
      dplyr::rename(!! model := "estimates")
  } else if (grepl("sepPromEnh_TRUE",model)){
    model_coefs_sep <- merge(model_coefs_sep,
                             net_model_coefs[[model]],
                             by.x="featurename", by.y="names",
                             all=TRUE) %>% 
      dplyr::rename(!! model := "estimates")
  } else { stop("The modelnames don't match the expected pattern.") }
}

#------------------------------------------------
## save data for plotting
#------------------------------------------------
saveRDS (model_coefs_joint, paste0(opt$outdir, "model_coefs_joint.rds"))
saveRDS (model_coefs_sep, paste0(opt$outdir, "model_coefs_sep.rds"))
saveRDS (AUC_metrics, paste0(opt$outdir, "AUC_metrics.rds"))

#------------------------------------------------
sessionInfo()
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--ABC_DexLPS_all"),
              type="character",
              help="Path to file with all ABC predictions passing 0.02 (in DexLPS condition)"),
  make_option(c("--ABC_LPS_all"),
              type="character",
              help="Path to file with all ABC predictions passing 0.02 (in LPS condition)"),
  make_option(c("--contrast_DexVSDexLPS"),
              type="character",
              help="Path to annotated tsv file of DeSeq2 contrast of DexLPS vs LPS"),
  make_option(c("--chipseq_summits"),
              type="character",
              help="Path to summit file of IDR peaks"),
  make_option(c("--igv"),
              type="character",
              help="Path to IGV snapshot of genomic locus (created manually)")
)

opt <- parse_args(OptionParser(option_list=option_list))

options(stringsAsFactors = FALSE)

suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(org.Mm.eg.db, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(DESeq2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ComplexHeatmap, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(TxDb.Mmusculus.UCSC.mm10.knownGene, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(topGO, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggExtra, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=8, family = "ArialMT", colour="black"),
             title=element_text(size=10, family="ArialMT", colour="black"),
             panel.grid.major = element_blank(),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=8, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"))

#----------------------------------------------------------------------
##--NOTE: example code for additional plots can be found in abc_visualizations.Rmd
#----------------------------------------------------------------------

#----------------------------------------------------------------------
##----------- load data
#----------------------------------------------------------------------

chipseq_summits <- rtracklayer::import.bed(opt$chipseq_summits)

contrast_DexLPSvLPS <- read.delim(opt$contrast_DexVSDexLPS)
# rename first column for merge later
colnames(contrast_DexLPSvLPS)[1] <- "EnsemblID"

ABC_DexLPS_all <- read.delim(opt$ABC_DexLPS_all)
ABC_LPS_all <- read.delim(opt$ABC_LPS_all)
# remove version number from ensembl IDs
ABC_DexLPS_all$TargetGene = gsub("\\.[0-9]*$","",ABC_DexLPS_all$TargetGene)
ABC_LPS_all$TargetGene = gsub("\\.[0-9]*$","",ABC_LPS_all$TargetGene)


#----------------------------------------------------------------------
##----------- data exploration
#----------------------------------------------------------------------

# What do the distributions of ABC scores look like

ggplot()+
  geom_density(data=ABC_DexLPS_all %>% filter(!class=="promoter"), aes(x=ABC.Score, colour="DexLPS"))+
  geom_density(data=ABC_LPS_all %>% filter(!class=="promoter"), aes(x=ABC.Score, colour="LPS"))+
  scale_colour_manual("",
                      breaks = c("DexLPS", "LPS"),
                      values = c("#339966", "#0066CC"))

# How do the ABC scores of promoters compare to those of enhancers?

ggplot()+
geom_density(data=ABC_DexLPS_all %>% filter(class=="promoter"), aes(x=ABC.Score, colour="promoter"))+
geom_density(data=ABC_DexLPS_all %>% filter(class=="genic"), aes(x=ABC.Score, colour="genic"))+
geom_density(data=ABC_DexLPS_all %>% filter(class=="intergenic"), aes(x=ABC.Score, colour="intergenic"))+
scale_colour_manual("",
                    breaks = c("promoter", "genic", "intergenic"),
                    values = c("red", "green", "blue"))

# What distance is used to define sth as promoter?

ggplot()+
  geom_density(data=ABC_DexLPS_all, aes(x=distance, colour=class))+
  scale_x_continuous(trans = "log10")+
  scale_colour_manual("",
                      breaks = c("promoter", "genic", "intergenic"),
                      values = c("red", "green", "blue"))

ggplot()+
  geom_density(data=ABC_DexLPS_all %>% filter(class=="promoter"), aes(x=distance, colour=isSelfPromoter))+
  scale_x_continuous(trans = "log10")+
  scale_colour_manual("isSelfPromoter",
                      breaks = c("True", "False"),
                      values = c("red", "blue"))+
  labs(title="All promoter regions, split by whether they're promoters for their target gene")+
  theme(
    plot.title = element_text(size=12)
  )
#----------------------------------------------------------------------
# ------ ------  Number of enhancers per gene
#----------------------------------------------------------------------
# Are most genes regulated by a single enhancer region or by multiple? How many does the ABC model assign per gene?

plot_enhancers_per_gene <- function(){
  DexLPS_TargetGeneCounts <- plyr::count(ABC_DexLPS_all %>% filter(!class=="promoter"), vars="TargetGene")
  LPS_TargetGeneCounts <- plyr::count(ABC_LPS_all %>% filter(!class=="promoter"), vars="TargetGene")

  gg <- ggplot()+
    geom_histogram(data=DexLPS_TargetGeneCounts, aes(x=freq, fill="DexLPS", colour="DexLPS"), binwidth = 1,  alpha=0.2)+
    geom_histogram(data=LPS_TargetGeneCounts, aes(x=freq, fill="LPS", colour="LPS"), binwidth = 1, alpha=0.2)+
    scale_fill_manual("",
                      breaks = c("DexLPS", "LPS"),
                      values = c("#339966", "#0066CC")) +
    scale_colour_manual("",
                        breaks = c("DexLPS", "LPS"),
                        values = c("#339966", "#0066CC")) +
    guides(color = "none")+
    theme(legend.position = c(0.8,0.8))+
    labs(title=" ",
         x="# of enhancers per gene",
         y="counts")

  return(gg)
}

gg_enh_per_gene <- plot_enhancers_per_gene()
gg_enh_per_gene

print("We find an average of")
plyr::count(ABC_DexLPS_all %>% filter(!class=="promoter"), vars="TargetGene") %>% pull(freq) %>% mean()
print("enhancers per gene for the DexLPS condition and")
plyr::count(ABC_LPS_all %>% filter(!class=="promoter"), vars="TargetGene") %>% pull(freq) %>% mean()
print("in LPS.")

#----------------------------------------------------------------------
# ------ ------  Number of genes per enhancer
#----------------------------------------------------------------------
# ABC allows for multiple assignments (an individual enhancer assigned to more than one promoter)  

plot_genes_per_enhancer <- function(){

  DexLPS_EnhancerCounts <- plyr::count(ABC_DexLPS_all %>% filter(!class=="promoter"),vars="name")
  LPS_EnhancerCounts <- plyr::count(ABC_LPS_all %>% filter(!class=="promoter"),vars="name")

  gg_full <- ggplot()+
    geom_histogram(data=DexLPS_EnhancerCounts, aes(x=freq, fill="DexLPS",colour="DexLPS"), binwidth = 1, alpha=0.2)+
    geom_histogram(data=LPS_EnhancerCounts, aes(x=freq, fill="LPS",colour="LPS"), binwidth = 1, alpha=0.2)+
    scale_fill_manual("",
                      breaks = c("DexLPS", "LPS"),
                      values = c("#339966", "#0066CC")) +
    scale_colour_manual("",
                        breaks = c("DexLPS", "LPS"),
                        values = c("#339966", "#0066CC")) +
    guides(color = FALSE)+
    labs(title="Number of genes an individual enhancer is assigned to",
         x="# of genes per enhancer",
         y="counts")
  plot(gg_full)

  gg_zoom <- ggplot()+
    geom_histogram(data=DexLPS_EnhancerCounts, aes(x=freq, fill="DexLPS",colour="DexLPS"), binwidth = 1, alpha=0.2)+
    geom_histogram(data=LPS_EnhancerCounts, aes(x=freq, fill="LPS",colour="LPS"), binwidth = 1, alpha=0.2)+
    scale_fill_manual("",
                      breaks = c("DexLPS", "LPS"),
                      values = c("#339966", "#0066CC")) +
    scale_colour_manual("",
                        breaks = c("DexLPS", "LPS"),
                        values = c("#339966", "#0066CC")) +
    xlim(c(0,8))+
    guides(color = FALSE)+
    theme(legend.position = c(0.8,0.8))+
    labs(title=" ",
         x="# of genes per enhancer",
         y="counts")
  plot(gg_zoom)

  print("We find an average of")
  DexLPS_EnhancerCounts %>% pull(freq) %>% mean() %>% print()
  print("genes per enhancer in the DexLPS condition and")
  LPS_EnhancerCounts %>% pull(freq) %>% mean() %>% print()
  print("in LPS.")

  return(gg_zoom)
}

gg_genes_per_enhancer_zoom <- plot_genes_per_enhancer()


#----------------------------------------------------------------------
# ------ Comparing ABC Scores (including promoter regions) between the conditions
#----------------------------------------------------------------------

# merge regions from both conditions but also keep those that are only in one
# 
# add info no whether the target genes are DE or now and what direction they're changed

LPS_GR<- plyranges::as_granges(ABC_LPS_all, seqnames=chr)
DexLPS_GR <- plyranges::as_granges(ABC_DexLPS_all, seqnames=chr)

#----------------------------------------------------------------------
merge_LPSandDexLPS_ABCdata <- function(ABC_LPS_all_GR, ABC_DexLPS_all_GR){
  ABC_LPS_all_unique <- unique(ABC_LPS_all_GR)
  ABC_DexLPS_all_unique <- unique(ABC_DexLPS_all_GR)

  # and then figure out which ones overlap with one another
  overlap_ABC_all_unique <- ChIPpeakAnno::findOverlapsOfPeaks (ABC_LPS_all_unique,
                                                               ABC_DexLPS_all_unique,
                                                               connectedPeaks = "keepAll",
                                                               ignore.strand = TRUE)
  # we coerce the info of overlapping regions into a dataframe
  overlap_ABC_all_unique_df <- as.data.frame(overlap_ABC_all_unique$overlappingPeaks)

  # and clean up column names
  colnames(overlap_ABC_all_unique_df)<- gsub("ABC_LPS_all_unique...ABC_DexLPS_all_unique.","", colnames(overlap_ABC_all_unique_df))
  colnames(overlap_ABC_all_unique_df)<- gsub(".1", "", colnames(overlap_ABC_all_unique_df))
  colnames(overlap_ABC_all_unique_df)<- paste( c(rep("LPS_",27),rep("DexLPS_",27),rep("",2)), colnames(overlap_ABC_all_unique_df), sep="")

  # we use this overlap to define a new variable that holds the info of which regions of the conditions form a pair
  overlap_ABC_all_unique_df$pairID <- paste("pair", seq(1, nrow(overlap_ABC_all_unique_df)), sep="" )

  #-----------------for DexLPS-------------------
  # merge the pairID onto the original dataframes
  ABC_DexLPS_all_wpairID <- merge(ABC_DexLPS_all,
                                  overlap_ABC_all_unique_df[,c("DexLPS_name","pairID")],
                                  by.x="name",
                                  by.y="DexLPS_name",
                                  all.x=TRUE)
  # for those that don't correspond to a pair, we assign condition and name as pairID
  ABC_DexLPS_all_wpairID <- ABC_DexLPS_all_wpairID %>% 
    mutate(pairID = case_when(is.na(pairID) ~ paste("DexLPS",name, sep="_"),
                              TRUE ~ pairID) )
  # combination of pairID and gene they're assigned to forms the assignment variable.
  # we will use this later to plot values from the 2 conditions, that have the same assignment
  ABC_DexLPS_all_wpairID$assignment <- paste(ABC_DexLPS_all_wpairID$pairID,
                                             ABC_DexLPS_all_wpairID$TargetGene,
                                             sep="_")

  #-----------------for LPS-------------------
  # merge the pairID onto the original dataframes
  ABC_LPS_all_wpairID <- merge(ABC_LPS_all,
                               overlap_ABC_all_unique_df[,c("LPS_name","pairID")],
                               by.x="name",
                               by.y="LPS_name",
                               all.x=TRUE)
  # for those that don't correspond to a pair, we assign condition and name as pairID
  ABC_LPS_all_wpairID <- ABC_LPS_all_wpairID %>% 
    mutate(pairID = case_when(is.na(pairID) ~ paste("LPS",name, sep="_"),
                              TRUE ~ pairID) )

  ABC_LPS_all_wpairID$assignment <- paste(ABC_LPS_all_wpairID$pairID,
                                          ABC_LPS_all_wpairID$TargetGene,
                                          sep="_")

  merged_conditions <- merge(ABC_DexLPS_all_wpairID,
                                 ABC_LPS_all_wpairID,
                                 by="assignment", 
                                 all=TRUE,
                                 suffixes = c(".DexLPS", ".LPS"))
  merged_conditions <- merged_conditions %>%
    mutate(TargetGene = case_when(TargetGene.DexLPS==TargetGene.LPS ~ TargetGene.DexLPS,
                                  is.na(TargetGene.DexLPS) ~ TargetGene.LPS,
                                  is.na(TargetGene.LPS) ~ TargetGene.DexLPS,
                                  TRUE ~ NA_character_)
    )

  return(merged_conditions)
}

merged_conditions_ABC <- merge_LPSandDexLPS_ABCdata(LPS_GR,DexLPS_GR)

#----------------------------------------------------------------------
# ------ merge on gene expression results
#----------------------------------------------------------------------

# merge the RNAseq results to use as colour later
merged_conditions_ABC <- merge(merged_conditions_ABC, contrast_DexLPSvLPS, 
                               by.x="TargetGene", by.y="EnsemblID")
merged_conditions_ABC <- merged_conditions_ABC %>%
  mutate(change=case_when(padj<0.05 & log2FoldChange>0.58 ~ "up",
                          padj<0.05 & log2FoldChange<(-0.58) ~ "down",
                          TRUE ~ "no change"))

# replace the na with 0
merged_conditions_ABCnomissing <- merged_conditions_ABC %>% 
  mutate(ABC.Score.DexLPS = case_when(is.na(ABC.Score.DexLPS) ~ 0,
                                      TRUE ~ ABC.Score.DexLPS) ) %>%
  mutate(ABC.Score.LPS = case_when(is.na(ABC.Score.LPS) ~ 0,
                                   TRUE ~ ABC.Score.LPS) )

cor_ABCscores <- cor(merged_conditions_ABCnomissing$ABC.Score.DexLPS,
                     merged_conditions_ABCnomissing$ABC.Score.LPS)

gg_merged_conditions_ABCnomissing <- ggplot(merged_conditions_ABCnomissing)+
  geom_point(aes(x=ABC.Score.DexLPS, y=ABC.Score.LPS, fill=log2FoldChange), alpha=0.2, size=1, stroke = 0, shape=21)+
  scale_fill_gradient(low="blue", high="red")+
  ylim(c(0,0.8))+
  xlim(c(0,0.8))+
  geom_text(x=0.2, y=0.75, label=paste("r = ",format(cor_ABCscores, digits = 2)))+
  labs(fill="log2FC", x="ABC score Dex+LPS", y="ABC score LPS")+
  theme(legend.position = "top")

gg_merged_conditions_ABCnomissing

#----------------------------------------------------------------------
# ------ plot foldchange in ABC score vs foldchange in expression
#----------------------------------------------------------------------

cor_ABCdiff_log2FC <- with(merged_conditions_ABCnomissing %>% filter(change!="no change"),
                           cor((ABC.Score.DexLPS - ABC.Score.LPS),log2FoldChange))

gg_ABCdiff_log2FC <- ggplot(merged_conditions_ABCnomissing %>% filter(change!="no change"), aes(x=(ABC.Score.DexLPS - ABC.Score.LPS), y=log2FoldChange)) +
  geom_hex(bins=70)+
  viridis::scale_fill_viridis()+
  geom_smooth(method = "lm", colour="black")+
  geom_text(x=0.6, y=5, label=paste("r = ",format(cor_ABCdiff_log2FC, digits = 2)))+
  labs(x="ABC score Dex+LPS - ABC score LPS", y="expression log2FC(Dex+LPS / LPS)")+
  theme(legend.position = "top")



#----------------------------------------------------------------------
# ------ ABC score by peak presence
#----------------------------------------------------------------------

plot_ABC_with_marginals <- function(whatchange){
  gg <- ggplot(data= merged_conditions_ABCnomissing %>% filter(change==whatchange) , 
               aes(x=ABC.Score.DexLPS, y=ABC.Score.LPS ) )+
    geom_point( aes( fill=whatchange) , size=1, alpha=1,stroke = 0, shape=21) +
    geom_abline(slope = 1)+
    ylim(c(0,0.8))+
    xlim(c(0,0.8))+
    labs(x="ABC score Dex+LPS", y="ABC score LPS")+
    scale_fill_manual(
      breaks=c("up","no change","down"),
      values=c("red","black","blue") )+
    theme(legend.position = "none")

  gg_marg <- ggExtra::ggMarginal(gg, type="histogram", size=2,
                                 xparams = list(bins=85), yparams = list(bins=85))

  return(gg_marg)
}

ggplot_ABC_with_marginals_up <- plot_ABC_with_marginals("up")
ggplot_ABC_with_marginals_up
ggplot_ABC_with_marginals_down <-plot_ABC_with_marginals("down")
ggplot_ABC_with_marginals_down

#----------------------------------------------------------------------
# ------ show marginals as bar plot
#----------------------------------------------------------------------
gg_marginals_dexlps <- 
  ggplot()+
  geom_histogram(data=merged_conditions_ABCnomissing %>% filter(change=="up"), aes(x=ABC.Score.DexLPS, fill="up"), alpha=0.2, bins=85)+
  geom_histogram(data=merged_conditions_ABCnomissing %>% filter(change=="down"), aes(x=ABC.Score.DexLPS, fill="down"), alpha=0.2, bins=85)+
  scale_fill_manual(
    breaks=c("up","down"),
    values=c("red","blue") )+
  xlim(c(NA,0.3))+
  labs(fill="gene expression change",x="ABC score DexLPS", y="ABC score LPS")+
  theme(legend.position = c(0.7,0.7))
gg_marginals_lps <- 
  ggplot()+
  geom_histogram(data=merged_conditions_ABCnomissing %>% filter(change=="up"), aes(x=ABC.Score.LPS, fill="up"), alpha=0.2, bins=85)+
  geom_histogram(data=merged_conditions_ABCnomissing %>% filter(change=="down"), aes(x=ABC.Score.LPS, fill="down"), alpha=0.2, bins=85)+
  scale_fill_manual(
    breaks=c("up","down"),
    values=c("red","blue") )+ 
  xlim(c(NA,0.3))+
  labs(fill="gene expression change",x="ABC score DexLPS", y="ABC score LPS")+
  theme(legend.position = c(0.7,0.7))

#----------------------------------------------------------------------
# ------ ABC score by peak presence
#----------------------------------------------------------------------
# Is there a difference in ABC score between the enhancers overlapping with a GR summit vs the ones that don't?


DexLPS_GR_summits_overlap <- IRanges::findOverlaps(DexLPS_GR,chipseq_summits) #(query,subject)
DexLPS_GR$haspeakID <- FALSE
DexLPS_GR$haspeakID[queryHits(DexLPS_GR_summits_overlap)] <- TRUE


plot_ABCscore_ofDEgenes_byGRoverlap <- function(){
  DE_ENSEMBL <- contrast_DexLPSvLPS %>%  filter(padj<0.05 & abs(log2FoldChange)>0.58 ) %>% pull(EnsemblID)

  DexLPS_enhancers_DEsubset <- 
    as.data.frame(DexLPS_GR) %>% 
    filter(TargetGene %in% DE_ENSEMBL) %>%
    filter(!class=="promoter")

  DexLPS_enhancers_DEsubset %>% filter(haspeakID==TRUE) %>% dplyr::pull(ABC.Score) %>% mean() %>% print()
  DexLPS_enhancers_DEsubset %>% filter(haspeakID==FALSE) %>% dplyr::pull(ABC.Score) %>% mean() %>% print()

  # show distribution for the two groups

  gg1 <- ggplot()+
    geom_density(data=DexLPS_enhancers_DEsubset %>% filter(haspeakID==TRUE), 
                 aes(x=ABC.Score, colour="haspeakID", fill="haspeakID"), alpha=0.3)+
    geom_density(data=DexLPS_enhancers_DEsubset %>% filter(haspeakID==FALSE), 
                 aes(x=ABC.Score, colour="nopeakID", fill="nopeakID"), alpha=0.3)+
    scale_x_continuous(trans = "log2")+
    scale_colour_manual("",
                        labels = c("has GR peak", "no GR peak"),
                        breaks = c("haspeakID", "nopeakID"),
                        values = c("darkmagenta", "cadetblue"))+
    scale_fill_manual("",
                      labels = c("has GR peak", "no GR peak"),
                      breaks = c("haspeakID", "nopeakID"),
                      values = c("darkmagenta", "cadetblue"))+
    guides(colour="none")+
    #xlim(c(-3,0))+
    labs(title=" ",
         x="ABC score Dex+LPS",
         y="density")+
    theme(
      axis.text = element_text(size=12, family="ArialMT", colour="black"),
      axis.title = element_text(size=12, family="ArialMT", colour="black"),
      axis.text.x = element_text(angle = 45, vjust = 1, hjust=1),
      legend.position = c(0.8,0.8)
    )
  plot(gg1)

  gg2 <- DexLPS_enhancers_DEsubset %>%
    ggplot( aes(x=hic_contact_pl_scaled_adj, y=log2(activity_base))) +
    geom_hex()+
    facet_wrap(~haspeakID, labeller="label_both")+
    viridis::scale_fill_viridis()+
    labs(title = " ", x="Hi-C contact", y="log2(base activity)")

  plot(gg2)
  all_plots=list()
  all_plots[[1]] <- gg1
  all_plots[[2]] <- gg2
  return(all_plots)
}

gg_ABCscore_ofDEgenes_byGRoverlap <- plot_ABCscore_ofDEgenes_byGRoverlap()


#----------------------------------------------------------------------
# ------ load IGV plot
#----------------------------------------------------------------------
igv <- png::readPNG( opt$igv )

gg_igv <- ggplot() + 
  ggpubr::background_image(igv) +
  # so it doesn't get squished
  #coord_fixed()+
  # This ensures that the image leaves some space at the edges
  theme(plot.margin = margin(t=0, l=0, r=0, b=0, unit = "cm"),
        axis.line = element_blank())


#----------------------------------------------------------------------
# ------ put figure panel together
#----------------------------------------------------------------------

# save giant files separately
ggsave(here("./results/current/Figures/Figure_abcresults_3B.bmp"), gg_merged_conditions_ABCnomissing,
       width=75, height=100, units="mm",
       bg="white")
ggsave(here("./results/current/Figures/Figure_abcresults_3B.png"), gg_merged_conditions_ABCnomissing,
       width=75, height=100, units="mm",
       bg="white")

gg_placeholder <- ggplot() + 
  theme(plot.margin = margin(t=0, l=0, r=0, b=0, unit = "cm"),
        axis.line = element_blank())

# first row
gg_r1c1 <-  ggpubr::ggarrange(gg_enh_per_gene, gg_genes_per_enhancer_zoom,
                            labels = c("A", NA),
                            ncol = 1, nrow = 2, heights = c(1,1))

gg_r1c2 <-  ggpubr::ggarrange(gg_placeholder, ggplot_ABC_with_marginals_up, ggplot_ABC_with_marginals_down, 
                            labels = c("B", "C", NA),
                            ncol = 3, nrow=1, widths=c(1,1,1))

gg_r1 <- ggpubr::ggarrange(gg_r1c1, gg_r1c2, 
                           labels = c(NA, NA),
                           ncol = 2, nrow=1, widths=c(1,3))

# second row
gg_r2 <-  ggpubr::ggarrange(gg_ABCdiff_log2FC, gg_ABCscore_ofDEgenes_byGRoverlap[[1]], gg_ABCscore_ofDEgenes_byGRoverlap[[2]], 
                            labels = c("D","E", "F"),
                            ncol = 3, nrow=1, widths=c(1,1,1.5))


gg_tophalf <- ggpubr::ggarrange(gg_r1, gg_r2, 
                                nrow=2, heights =c(1,1))
gg_tophalf

full_panel <- ggpubr::ggarrange(gg_tophalf, gg_igv, 
                                labels=c(NA,"G"),
                                nrow=2, heights = c(1.8,1))

#full_panel
ggsave(here("./results/current/Figures/Figure_abcresults.png"), full_panel,
       width=300, height=300, units="mm",
       bg="white")
ggsave(here("./results/current/Figures/Figure_abcresults.pdf"), full_panel,
       width=300, height=300, units="mm",
       bg="white")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--bw_DexLPS_h3k27ac"),
              type="character",
              help="Path to H3K27ac bigwig file from DexLPS condition"),
  make_option(c("--bw_LPS_h3k27ac"),
              type="character",
              help="Path to H3K27ac bigwig file from LPS condition"),
  make_option(c("--counts_h3k27ac"),
              type="character",
              help="Path to file with adjusted libsize (number of reads in bam file overlappign joint peak universe)"),
  make_option(c( "--bw_DexLPS_atac"),
              type="character",
              help="Path to ATAC bigwig file from DexLPS condition"),
  make_option(c("--bw_LPS_atac"),
              type="character",
              help="Path to ATAC bigwig file from LPS condition"),
  make_option(c("--counts_atac"),
              type="character",
              help="Path to file with adjusted libsize (number of reads in bam file overlappign joint peak universe)"),
  make_option(c("--gtf"),
              type="character",
              help="Path to gtf file of genomic reference")
  )

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(rtracklayer, warn.conflicts=F, quietly=T))

#-----------------------------------------
#------- H3K27ac
#-----------------------------------------

bw_DexLPS_h3k27ac <- import.bw( opt$bw_DexLPS_h3k27ac )
bw_LPS_h3k27ac <- import.bw( opt$bw_LPS_h3k27ac )
counts_h3k27ac <- read.table(opt$counts_h3k27ac)

# normalization is important in this case as seen by the ratio
as.numeric(counts_h3k27ac[2,1]) / as.numeric(counts_h3k27ac[4,1])

# scale by "adjusted" library size (number of reads overlapping peak universe)
score(bw_DexLPS_h3k27ac) <- score(bw_DexLPS_h3k27ac) / ( as.numeric(counts_h3k27ac[2,1]) / 10^6)
score(bw_LPS_h3k27ac) <- score(bw_LPS_h3k27ac) / ( as.numeric(counts_h3k27ac[4,1]) / 10^6)

# reexport the normalized tracks
export.bw(bw_DexLPS_h3k27ac,
          here("./results/current/ChIP/H3K27ac/bw/DexLPS_histone_H3K27ac_PE_merged_GRCm38_libnorm.bw"))

export.bw(bw_LPS_h3k27ac,
          here("./results/current/ChIP/H3K27ac/bw/LPS_histone_H3K27ac_PE_merged_GRCm38_libnorm.bw"))

rm(list=c("bw_DexLPS_h3k27ac", "bw_LPS_h3k27ac"))

#-----------------------------------------
#------- ATAC
#-----------------------------------------

bw_DexLPS_atac <- import.bw( opt$bw_DexLPS_atac )
bw_LPS_atac <- import.bw( opt$bw_LPS_atac )

counts_atac <- read.table(opt$counts_atac)

# normalization is NOT so important in this case as seen by the ratio
as.numeric(counts_atac[2,1]) / as.numeric(counts_atac[4,1])

# scale by "adjusted" library size (number of reads overlapping peak universe)
score(bw_DexLPS_atac) <- score(bw_DexLPS_atac) / ( as.numeric(counts_atac[2,1]) / 10^6)
score(bw_LPS_atac) <- score(bw_LPS_atac) / ( as.numeric(counts_atac[4,1]) / 10^6)

# reexport the normalized tracks
export.bw(bw_DexLPS_atac,
          here("./results/current/atacseq/bw/merged_DexLPS_GRCm38_libnorm.bw"))

export.bw(bw_LPS_atac,
          here("./results/current/atacseq/bw/merged_LPS_GRCm38_libnorm.bw"))

#-----------------------------------------
#------- reference gtf file for IGV
#-----------------------------------------
#import gtf file with rtracklayer
gtf <- rtracklayer::import(opt$gtf)
gtf_nogene <- gtf %>% filter(type!="gene")
rtracklayer::export(gtf_nogene,
                    here("./data/current/Mus_musculus.GRCm38.100_ftrnogene.gtf"))
rtracklayer::export.gff3(gtf_nogene,
                         here("./data/current/Mus_musculus.GRCm38.100_ftrnogene.gff3"))
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("-c", "--counts"),
              type="character",
              help="Path to count matrix"),
  make_option(c("-a", "--annotation"),
              type="character",
              help="Path to metadata with annotation"),
  make_option(c("-o", "--outdir"),
              type="character",
              help="Path to output directory"),
  make_option(c("-k", "--biomart_ensembl_version"),
              type="numeric",
              help="version of ensembl biomart to use for ensembl2mgi gene annotation"))
opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(edgeR, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(DESeq2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(biomaRt, warn.conflicts=F, quietly=T))

dir.create(opt$outdir)

#-------------------------------------------------
#---------Load data
#-------------------------------------------------
# Let's start by loading the count matrix holding the gene counts for all samples and by making a dataframe holding metadata such as treatment conditions.

counts <- as.matrix(read.table(opt$counts, quote = "\"", header=TRUE, row.names = 1 ))
anno <- read.delim(opt$annotation)

# parse relevant info from treatment variable
anno$treat <- anno$treatment %>%
  gsub(";4sU", "", .) %>%
  gsub("LPS, Dex", "LPS_Dex", .) %>%
  as.factor() %>%
  relevel(treat, ref = "Vehicle")

# parse total vs nascent from Foreign.ID
anno$group [ grepl('total|Total', anno$Foreign.ID) ] <- "total"
anno$group [ grepl('nascent', anno$Foreign.ID) ] <- "nascent"

# making sure anno is sorted to match column order in counts matrix
anno <- anno[ match(colnames(counts), 
                    anno$Foreign.ID),]
# check after resorting
all(anno$Foreign.ID == colnames(counts))

#-------------------------------------------------
#---------Filter genes
#-------------------------------------------------

# For now, we are not interested in making comparisons with the total RNA samples, so we exclude those before doing the normalization (and gene filtering) and running DESeq
anno <- anno[ anno$group == "nascent", ]

counts <- counts[,match(anno$Foreign.ID, colnames(counts))]

# do simple cpm computation without any library factors, to exclude lowly expressed genes
cpm_counts <- edgeR::cpm(counts, 
                         normalized.lib.sizes = FALSE)

# what does the read count distribution look like?
# compute median per gene and plot it as histogram
median_genecounts <- apply(cpm_counts, 1, FUN=median)

ggplot()+
  geom_histogram(aes(log(median_genecounts+1)), bins=30)

#Filter to keep genes that have a cpm of at least 0.2 in at least 1 samples

print("Filtering out lowly expressed genes")
keepRows <- rowSums(cpm_counts >=0.2) >= 1
table(keepRows)
median_genecounts <- median_genecounts[keepRows]

ggplot()+
  geom_histogram(aes(log(median_genecounts+1)), bins=30)

# use this to filter the gene counts matrix
counts <- counts[keepRows,]

#-------------------------------------------------
#---------Normalize counts
#-------------------------------------------------

# Create DESeq2Dataset object
dds <- DESeqDataSetFromMatrix(countData = counts,
                              colData = anno,
                              design= ~ treat)


# relevel to set Vehicle treated sample as reference
dds$treat <- relevel(dds$treat, ref = "Vehicle")

# this would also be done automatically when calling the DESeq() function
dds <- estimateSizeFactors(dds)

# NOTE: DESeq2 doesn’t actually use normalized counts, rather it uses the raw counts and models the normalization inside the Generalized Linear Model (GLM). 
# These normalized counts will be useful for downstream visualization of results, but cannot be used as input to DESeq2 or any other tools that perform differential expression analysis which use the negative binomial model.
normalized_counts <- counts(dds, normalized=TRUE)

write.table(normalized_counts, paste0(opt$outdir,"/DESeq_normalized_counts_nototal.tsv"), 
            col.names = TRUE,
            row.names = TRUE,
            sep="\t",
            quote=FALSE)

saveRDS(normalized_counts, paste0(opt$outdir,"/DESeq_normalized_counts_nototal.rds"))

write.table(anno, paste0(opt$outdir,"/anno_nototal.tsv"), 
            col.names = TRUE,
            row.names = FALSE,
            sep="\t",
            quote=FALSE)

#-------------------------------------------------
#---------Run DESeq2
#-------------------------------------------------
print("Running DESeq")
dds <- DESeq(dds)

res <- results(dds)

# based on the computed coefficients, we now compute a contrast of LPS vs LPS+Dex
res_DexLPSvLPS <- results(dds, contrast=c("treat","LPS_Dex","LPS"))
res_LPSvVeh <- results(dds, contrast=c("treat","LPS","Vehicle"))
res_DexLPSvVeh <- results(dds, contrast=c("treat","LPS_Dex","Vehicle"))

saveRDS(res_DexLPSvLPS, paste0(opt$outdir,file = "/contrast_DexVSDexLPS.rds"))
saveRDS(res_LPSvVeh, paste0(opt$outdir,file = "/contrast_LPSvVeh.rds"))
saveRDS(res_DexLPSvVeh, paste0(opt$outdir,file = "/contrast_DexLPSvVeh.rds"))

#-------------------------------------------------
#---------Annotate genes
#-------------------------------------------------

print("Annotating genes")

f_genekey <- paste0(opt$outdir,"/geneKey_biomart_mm_k",opt$biomart_ensembl_version,".txt")
if (!file.exists(f_genekey)){
  ensembl_mm <- biomaRt::useEnsembl(biomart = 'ensembl',
                                    dataset="mmusculus_gene_ensembl",
                                    version = as.numeric(opt$biomart_ensembl_version))
  # retrieve the geneKey to map ensembl IDs to mgi_symbols
  geneKey<- biomaRt::getBM(mart=ensembl_mm, attributes=c("ensembl_gene_id","gene_biotype","mgi_symbol"))
  write.table(geneKey, f_genekey, sep="\t")

} else {
  geneKey <- read.table(f_genekey, header=TRUE, sep="\t")
}
print("Done getting genekey")

#merge gene annotations to results table
res_DexLPSvLPS_ext <- merge(as.data.frame(res_DexLPSvLPS),
                            geneKey, 
                            by.x="row.names", 
                            by.y="ensembl_gene_id", 
                            all.x=TRUE)

res_LPSvVeh_ext <- merge(as.data.frame(res_LPSvVeh),
                         geneKey, 
                         by.x="row.names", 
                         by.y="ensembl_gene_id", 
                         all.x=TRUE)

res_DexLPSvVeh_ext <- merge(as.data.frame(res_DexLPSvVeh),
                            geneKey, 
                            by.x="row.names", 
                            by.y="ensembl_gene_id", 
                            all.x=TRUE)
#-------------------------------------------------
#---------Export contrasts
#-------------------------------------------------

print("Exporting the contrasts")

write.table(res_DexLPSvLPS_ext,paste0(opt$outdir,"/res_DexLPSvLPS_ext.tsv"),
            col.names = TRUE,
            row.names = FALSE,
            sep="\t",
            quote=FALSE)

write.table(res_LPSvVeh_ext,paste0(opt$outdir,"/res_LPSvVeh_ext.tsv"),
            col.names = TRUE,
            row.names = FALSE,
            sep="\t",
            quote=FALSE)

write.table(res_DexLPSvVeh_ext,paste0(opt$outdir,"/res_DexLPSvVeh_ext.tsv"),
            col.names = TRUE,
            row.names = FALSE,
            sep="\t",
            quote=FALSE)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("-n", "--norm"),
              type="character",
              help="Path to normalized counts"),
  make_option(c("--contrast"),
              type="character",
              help="Path to annotated tsv file of DeSeq2 contrast"),
  make_option(c("-a", "--annotation"),
              type="character",
              help="Path to metadata with annotation"),
  make_option(c( "--log2fcthresh"),
              type="numeric",
              help="Log2FC threshold used in addition to adj.pval to define significant genes"),
  make_option(c("-o", "--outdir"),
              type="character",
              help="Path of output directory")
    )

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(ComplexHeatmap, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(topGO, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=6, family = "ArialMT", colour="black"),
             title=element_text(size=8, family="ArialMT", colour="black"),
             panel.grid.major = element_line(colour="grey", size=0.2),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=6, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"),
             legend.key.size = unit(6, 'points'), #change legend key size
             legend.key.height = unit(6, 'points'), #change legend key height
             legend.key.width = unit(6, 'points'), #change legend key width
             legend.text = element_text(size=6, family="ArialMT", colour="black")
)

dir.create(opt$outdir)
res_DexLPSvLPS_ext <- read.delim( opt$contrast )


#-------------------------------------------------
#---------Check for enrichements
#-------------------------------------------------

# Note: GenTable returns the scores of topGOresult as character which is a problem, since some pvalues are simply returned as "1e-30" and turn into NA when coercing back to numeric
# that's why why made our own custom version of it, where we set the eps cutoff for these small values to FALSE
source("./src/scripts/mytopGOGenTable.R")


maketopGO <- function(ont, all_genes) {
  topgo <- new("topGOdata",
               description = "Test", ontology = ont,
               allGenes = all_genes, nodeSize = 20,
               annot = annFUN.org, mapping="org.Mm.eg.db", ID="ensembl")

  # After initializing the topGO object, we can perform the significance tests with a number of differene methods
  resultFisher <- runTest(topgo, algorithm = "classic", statistic = "fisher")
  resultFisher.parentchild <- runTest(topgo, algorithm = "parentchild", statistic = "fisher")

  showSigOfNodes(topgo, score(resultFisher.parentchild),
                 firstSigNodes = 10, useInfo ='all')

  # initialize empty list for results we want to return later
  results = list()
  #print("Top 50 nodes sorted by Fisher parentchild")
  res_gentable <- mytopGOGenTable(topgo, classicFisher = resultFisher,
                                  parentchildFisher = resultFisher.parentchild,
                                  #classicKS = resultKS, elimKS = resultKS.elim,
                                  orderBy = "parentchildFisher", ranksOf = "classicFisher", topNodes = 50)
  results[["gentable"]] <- res_gentable

  # also retrieve and return the gene mapping of those top significant categories
  # get the GO IDs
  top_GOs <- res_gentable %>%
    mutate(parentchildFisher = as.numeric(parentchildFisher)) %>%
    mutate(classicFisher = as.numeric(classicFisher)) %>%
    filter(parentchildFisher<0.05) %>%
    top_n(50, wt=-parentchildFisher) %>%
    pull(GO.ID)

  # save the genes within them and their scores to a list
  for (GO in top_GOs){
    df <- data.frame(scores=unlist(scoresInTerm(topgo,GO)),
                     genes=unlist(genesInTerm(topgo,GO)))
    DEgenes <- df %>%
      filter(scores==2)

    GOname <- res_gentable %>%
      filter(GO.ID == GO) %>%
      pull(Term)
    GOname <- paste(GO, ":", GOname)

    results[[GOname]] <- DEgenes$genes
  }

  return(results)

}

# We create a binary vector indicating which of the investigates genes came up as significant
all_sig <- as.integer(res_DexLPSvLPS_ext$padj < 0.05)
names(all_sig) <- res_DexLPSvLPS_ext$Row.names
up_sig <- as.integer( (res_DexLPSvLPS_ext$padj < 0.05) & (res_DexLPSvLPS_ext$log2FoldChange > opt$log2fcthresh) )
names(up_sig) <- res_DexLPSvLPS_ext$Row.names
down_sig <- as.integer( (res_DexLPSvLPS_ext$padj < 0.05) & (res_DexLPSvLPS_ext$log2FoldChange < (-opt$log2fcthresh)) )
names(down_sig) <- res_DexLPSvLPS_ext$Row.names

for (cat in c("BP", "MF")){ # iterate over GP categories of interest
  for (set in c("all","down","up")){ #iterate over our genesets
    print(cat)
    print(set)
    if (!file.exists(paste0("results/current/rnaseq_4sU/figures/topGO_enrichment_",cat,"_",set,".rds")) ){
      # open graphics device, that the outgenerated plot will get saved to when calling topGO
      png(paste0(opt$outdir,"/topGO_enrichment_",cat,"_",set,"_network.png"))
      assign(paste0(cat,"_",set), maketopGO(cat, factor(get(paste0(set,"_sig"))) ) )
      dev.off()
      # save the returned object as rds, so it doesn't have to get rerun next time
      saveRDS(get(paste0(cat,"_",set)),
              file=paste0("results/current/rnaseq_4sU/figures/topGO_enrichment_",cat,"_",set,".rds"))
      } else {
        assign(paste0(cat,"_",set), readRDS(file=paste0("results/current/rnaseq_4sU/figures/topGO_enrichment_",cat,"_",set,".rds")) )
        }
  }
}

# We start by looking into the "BP"(=Biological Process) ontology
# pdf(paste0(opt$outdir,"/topGO_enrichment_BP_all_network.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
# BP_all <- maketopGO("BP", factor(all_sig))
# dev.off()
# pdf(paste0(opt$outdir,"/topGO_enrichment_BP_down_network.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
# BP_down <- maketopGO("BP", factor(down_sig))
# dev.off()
# pdf(paste0(opt$outdir,"/topGO_enrichment_BP_up_network.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
# BP_up <- maketopGO("BP", factor(up_sig))
# dev.off()

# And now for the molecular function

# pdf(paste0(opt$outdir,"/topGO_enrichment_MF_all_network.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
# MF_all <- maketopGO("MF", factor(all_sig))
# dev.off()
# pdf(paste0(opt$outdir,"/topGO_enrichment_MF_down_network.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
# MF_down <- maketopGO("MF", factor(down_sig)) 
# dev.off()
# pdf(paste0(opt$outdir,"/topGO_enrichment_MF_up_network.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
# MF_up <- maketopGO("MF", factor(up_sig))
# dev.off()


for (res in c("BP_all","BP_up","BP_down","MF_all","MF_up","MF_down")){
  gg <- get(res)[[1]] %>% 
    mutate(parentchildFisher=as.numeric(parentchildFisher))%>%
    top_n(30, wt=-parentchildFisher) %>% 
    mutate(hitsperc=Significant*100/Annotated) %>% 
    ggplot(aes(x=-log10(parentchildFisher), 
               y=reorder(Term,-parentchildFisher), 
               colour=hitsperc, 
               size=Annotated)) +
    geom_point() +
    scale_colour_gradient(low = "skyblue3", high = "purple2", guide="colourbar",limits=c(0,100))+
    guides(colour = guide_colourbar(barheight = 7))+
    geom_vline(xintercept=-log10(0.05), linetype="dashed")+
    expand_limits(x=0) +
    labs(x="-log10(pvalue)", y="GO term", colour="Hits (%)", size="Termsize")
  ggsave(paste0(opt$outdir,"/topGO_enrichment",res,".png"), gg)
  assign(paste0("gg_enrichment_",res),gg)
}

#-------------------------------------------------
#
#-------------------------------------------------

anno <- read.delim(opt$annotation)

#-------------------------------------------------
#---------library normalization
#-------------------------------------------------

normalized_counts <- read.delim(opt$norm, 
            header = TRUE)

counts_long <- as.data.frame(normalized_counts) %>%
  tidyr::pivot_longer(everything(),
                      names_to="sample",
                      values_to = "counts")

counts_boxplot <- ggplot(data=counts_long)+
  geom_boxplot(aes(x=sample, y=log(counts)))+
  theme(axis.text.x = element_text(angle=90))
counts_boxplot
ggsave(paste0(opt$outdir,"/counts_boxplot.png"), counts_boxplot)
#-------------------------------------------------
#---------PCA
#-------------------------------------------------

# Run PCA on log of normalized counts
#PCA_all = prcomp(log2(normalized_counts+1) %>% t(), 
#                center=TRUE, 
#                scale=FALSE) #center to change mean to 0, scale to change SD to 1


transposed_variables <- as.data.frame(t(log2(normalized_counts+1))) %>%
  mutate(treat=factor(anno$treat, levels=c("Vehicle","LPS","LPS_Dex")) ) %>%
  dplyr::select("treat",everything())

PCA_all <- FactoMineR::PCA(X = transposed_variables, # transposed so that the variables (=genes) are columns
                           scale.unit = TRUE, # whether we scale the variance or not (centering gets done automatically)
                           ncp = 5, # Number of PCs
                           quali.sup = 1, # Position of the qualitative variable
                           graph = FALSE) # No graphic outputs (lib. factoextra)

gg_elbow <- factoextra::fviz_eig(PCA_all, 
                     addlabels = FALSE,
                     ncp=10,
                     main=NULL,
                     ylab="% var",
                     ggtheme = theme(plot.title = element_blank())
)


gg_pca1 <- factoextra::fviz_pca_ind(PCA_all,
                         #col.ind="cos2",
                         axes=c(1,2),
                         pointsize=4,
                         habillage = PCA_all$call$X$treat,
                         legend.title = "",
                         title="",
                         #addEllipses = TRUE, #too few points for ellipse
                         label=FALSE,
                         palette = c("#CD8500","#8DA0CB","#66C2A5"), #c("veh" =  "#CD8500", "lps" = "#8DA0CB","lps_dex" = "#66C2A5"))
                         invisible="quali") # in order to disable displaing centroid 

gg_pca2 <- factoextra::fviz_pca_ind(PCA_all,
                         #col.ind="cos2",
                         axes=c(3,4),
                         pointsize=4,
                         habillage = PCA_all$call$X$treat,
                         legend.title = "",
                         #addEllipses = TRUE, #too few points for ellipse
                         label=FALSE,
                         palette = c("#CD8500","#8DA0CB","#66C2A5"), #c("veh" =  "#CD8500", "lps" = "#8DA0CB","lps_dex" = "#66C2A5"))
                         invisible="quali") # in order to disable displaing centroid


gg_pca <- ggpubr::ggarrange(gg_pca1,gg_pca2,
                            common.legend=TRUE)
gg_pca
ggsave(paste0(opt$outdir,"/PCA.png"),gg_pca)

#-------------------------------------------------
#---------Volcano plots
#-------------------------------------------------

res_DexLPSvLPS_ext <- res_DexLPSvLPS_ext %>% 
      mutate(change=case_when(padj<0.05 & log2FoldChange > opt$log2fcthresh ~ "sig up",
                              padj<0.05 & log2FoldChange < (-opt$log2fcthresh) ~ "sig down",
                              TRUE ~ "no change"))
table(res_DexLPSvLPS_ext$change)

gg_volcano <- res_DexLPSvLPS_ext %>%
  ggplot()+
  geom_point(aes(x=log2FoldChange, y=-log10(padj), colour=change))+
  coord_cartesian(ylim=c(-5,120),xlim=c(-8,8))+
  scale_color_manual(name="",
                     values = c("no change"="#000000","sig down"="#8DA0CB","sig up"="#66C2A5"))+
  ggrepel::geom_text_repel(data=dplyr::filter(res_DexLPSvLPS_ext,-log10(padj) > 28 | abs(log2FoldChange) > 6), 
                           aes(x=log2FoldChange, y=-log10(padj), label=mgi_symbol, colour=change), size=2,
                           min.segment.length = 0, max.overlaps = 100, box.padding = 0.1,
                           show.legend = FALSE)+
  labs(title="DexLPS vs LPS")+
  theme(legend.position = c(0.15, 0.8))
gg_volcano
ggsave(paste0(opt$outdir,"/volcano_plot_DexLPSvLPS.png"), gg_volcano)

#-------------------------------------------------
#---------Heatmap, ALL genes
#-------------------------------------------------

# For the visualizations in heatmaps, we use the normalized counts (counts normalized by DESeq's sizefactors) and add a pseudocount (+1) before taking the log.  
# We then z-scale those log-transformed counts row-wise (for each gene).

LOG.all_zn <- t(apply(log(normalized_counts+1),
                      1, 
                      function(x) (x-mean(x))/sd(x)
                      )
                ) #z-scale normalized values by row (by gene)

#create annotation labels for the heatmap
ha.tmp <- HeatmapAnnotation(df = anno %>% dplyr::select("treat"),
                            col = list(treat = c("Vehicle" =  "#CD8500", 
                                                 "LPS" = "#8DA0CB", 
                                                 "LPS_Dex" = "#66C2A5")),#red,green, blue
                            show_annotation_name = c(bar = FALSE),
                            show_legend = c(treat=TRUE),
                            annotation_legend_param =  list(
                              labels_gp = gpar(fontsize=6),
                              title_gp = gpar(fontsize=6)
                            )

                            #subset=setNames(RColorBrewer::brewer.pal(6,"Set1") ,levels(met.all$subset))
                            #annotation_legend_param=list( )  #instead of manually assigning each value a color, we can just assign our factor levels the colours of a brewer pallette
                            )


heatmap_allgenes <- Heatmap(
  LOG.all_zn, 
  top_annotation = ha.tmp, 
  column_title="All genes, all samples",
  column_title_gp = gpar(fontsize = 6, fontface = "bold"), 
  name="Row Z-Score", #Title on top of legend
  clustering_distance_rows = "euclidean", 
  clustering_method_rows = "complete", 
  show_row_dend = FALSE,
  show_row_names = FALSE,
  show_column_names = FALSE,
  column_dend_height = unit(1, "cm"),
  row_names_gp = gpar(fontsize = 6),
  heatmap_legend_param = list(
    title_position = "leftcenter-rot",
    legend_direction="vertical",
    labels_gp = gpar(fontsize=6),
    title_gp = gpar(fontsize=6),
    legend_height = unit(2, "cm"),
    at = c(-2, 0, 2), 
    labels = c("-2", "0", "2")
    )
)

pdf(paste0(opt$outdir,"/heatmap_allgenes.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
draw(heatmap_allgenes, heatmap_legend_side="right", merge_legend = TRUE)
dev.off()

gg_heatmap_allgenes <- grid.grabExpr(draw(heatmap_allgenes, heatmap_legend_side="right", merge_legend = TRUE))
gg_heatmap_allgenes

#-------------------------------------------------
#---------Heatmap, SIGgenes
#-------------------------------------------------

#remove those entries in results that have NA as padj and filter for the significant ones
res_DexLPSvLPS_sig <- res_DexLPSvLPS_ext %>%
  filter(!is.na(padj)) %>%
  filter(padj<0.05) %>%
  filter(abs(log2FoldChange) > opt$log2fcthresh)

heatmap_siggenes <- Heatmap(
  LOG.all_zn[res_DexLPSvLPS_sig$Row.names,] , 
  top_annotation = ha.tmp, 
  column_title="DexLPSvsLPS DE genes",
  column_title_gp = gpar(fontsize = 6, fontface = "bold"), 
  name="Row Z-Score", #Title on top of legend
  clustering_distance_rows = "euclidean", 
  clustering_method_rows = "complete", 
  show_row_dend = FALSE,
  show_row_names = FALSE,
  show_column_names = FALSE,
  column_dend_height = unit(1, "cm"),
  row_names_gp = gpar(fontsize = 6),
  heatmap_legend_param = list(
    title_position = "leftcenter-rot",
    legend_direction="vertical",
    labels_gp = gpar(fontsize=6),
    title_gp = gpar(fontsize=6),
    legend_height = unit(2, "cm"),
    at = c(-2, 0, 2), 
    labels = c("-2", "0", "2")
  )
)

pdf(paste0(opt$outdir,"/heatmap_siggenes_DexLPSvsLPS.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
draw(heatmap_siggenes, heatmap_legend_side="bottom")
dev.off()

gg_heatmap_siggenes <- grid.grabExpr(draw(heatmap_siggenes, heatmap_legend_side="right", merge_legend = TRUE))

#---------------------------------------------------------------
#---------Heatmap for DE genes within GO category of interest
#---------------------------------------------------------------
# "GO:0060089 : molecular transducer activity"
# "GO:0001067 : transcription regulatory region nucleic ..."
mapping <- res_DexLPSvLPS_ext %>%
  filter(padj<0.05 & abs(log2FoldChange) > opt$log2fcthresh) %>%
  filter(Row.names %in% MF_all[["GO:0060089 : molecular transducer activity"]]) %>%
  dplyr::select(c(Row.names,mgi_symbol))

heatmap_GO  <- Heatmap(
  LOG.all_zn[mapping$Row.names,], 
  top_annotation = ha.tmp, 
  column_title="Sig genes in GO:0060089 : \n molecular transducer activity",
  column_title_gp = gpar(fontsize = 6, fontface = "bold"), 
  name="Row Z-Score", #Title on top of legend
  clustering_distance_rows = "euclidean", 
  clustering_method_rows = "complete", 
  row_labels = mapping$mgi_symbol,
  show_row_dend = FALSE,
  show_row_names = TRUE,
  show_column_names = FALSE,
  column_dend_height = unit(1, "cm"),
  row_names_gp = gpar(fontsize = 5),
  heatmap_legend_param = list(
    title_position = "leftcenter-rot",
    legend_direction="vertical",
    labels_gp = gpar(fontsize=6),
    title_gp = gpar(fontsize=6),
    legend_height = unit(2, "cm"),
    at = c(-2, 0, 2), 
    labels = c("-2", "0", "2")
  )
)
heatmap_GO

pdf(paste0(opt$outdir,"/heatmap_siggenesGO0_DexLPSvsLPS.pdf"), width=6, height=7, useDingbats = F, pointsize=5)
draw(heatmap_GO, heatmap_legend_side="bottom")
dev.off()

gg_heatmap_GO <- grid.grabExpr(draw(heatmap_GO, heatmap_legend_side="right", merge_legend = TRUE))

#------------------------------------------------------------------------------------
#------ include the GO terms 
#------------------------------------------------------------------------------------

GO_network <- png::readPNG("results/current/rnaseq_4sU/figures/topGO_enrichment_MF_all_network.png")

gg_GO_network <- ggplot() + 
  ggpubr::background_image(GO_network) +
  # so it doesn't get squished
  coord_fixed()+
  # This ensures that the image leaves some space at the edges
  theme(plot.margin = margin(t=0, l=0, r=0, b=0, unit = "cm"),
        axis.line = element_blank())



#---------------------------------------------------------------
#---------Pull the figures together
#---------------------------------------------------------------

#lay <- rbind(c(1,2,2),
#             c(3,4,7),
#             c(3,4,7),
#             c(5,5,6),
#             c(5,5,6))

#m1 <- gridExtra::grid.arrange(gg_elbow, gg_pca2, 
#                              gg_heatmap_allgenes, gg_volcano, 
#                              gg_enrichment_MF_all, gg_heatmap_GO0016772,
#                              gg_GO_network,
#                              layout_matrix=lay)


#ggsave("results/current/Figure_2.png",m1, width = 20, height = 30, units = "cm")

gg_r1 <-  ggpubr::ggarrange(gg_elbow, gg_pca1,
                            labels = c("A", NA),
                            ncol = 2, nrow = 1, widths=c(1.4,1))

gg_r2c1 <-  ggpubr::ggarrange(gg_volcano, gg_enrichment_MF_all, gg_GO_network,
                                 labels = c("B", "D","F"),
                                 ncol = 1, nrow = 3, heights = c(1,1,0.5))

gg_r2c2 <-  ggpubr::ggarrange(gg_heatmap_siggenes, gg_heatmap_GO, 
                                 labels = c("C", "E"),
                                 ncol = 1, nrow=2, heights=c(1,1))

gg_r2 <-  ggpubr::ggarrange(gg_r2c1, gg_r2c2, 
                            labels = c(NA, NA),
                            ncol = 2, nrow=1, widths=c(1,1))

full_panel <- ggpubr::ggarrange(gg_r1, gg_r2, 
                                nrow=2, heights=c(0.4,2))

full_panel

ggsave("results/current/Figures/Figure_rnaseq.png", full_panel,
       width=190, height=250, units="mm",
       bg="white")

ggsave("results/current/Figures/Figure_rnaseq.pdf", full_panel,
       width=190, height=250, units="mm",
       bg="white")
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--summitAnno"),
              type="character",
              help="Path to dataframe object of GR summits annotated to closest gene"),
  make_option(c("--chipseq_peaks"),
              type="character",
              help="Path to IDR ChIPseq peaks"),
  make_option(c("--chipseq_summits"),
              type="character",
              help="Path to summit file of IDR peaks"),
  make_option(c("--sm_summitranges"),
              type="character",
              help="Path to rds file of genomation score matrix around peak summits"),
  make_option(c("--nr3c1fullsitematches"),
              type="character",
              help="Path to homer hits of nr3c1 fullsite motif"),
  make_option(c("--nr3c1halfsitematches"),
              type="character",
              help="Path to homer hits of nr3c1 halfsite motif"),
  make_option(c( "--streme"),
              type="character",
              help="Path to XML streme output file of enrichment around peak summits"))

opt <- parse_args(OptionParser(option_list=option_list))

# set output for logfile to retrieve stats for plot later
sink(file="results/current/figure_chipseq.out")

suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(grid, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(memes, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(universalmotif, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(rtracklayer, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ChIPseeker, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(genomation, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=12, family = "ArialMT", colour="black"),
             title=element_text(size=16, family="ArialMT", colour="black"),
             panel.grid.major = element_line(colour="grey", size=0.2),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=12, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"),
             legend.key.size = unit(12, 'points'), #change legend key size
             legend.key.height = unit(12, 'points'), #change legend key height
             legend.key.width = unit(12, 'points'), #change legend key width
             legend.text = element_text(size=8, family="ArialMT", colour="black")
)

#----------------------------------------------
#------ load input data
#----------------------------------------------
chipseq <- rtracklayer::import.bed(opt$chipseq_peaks)
chipseq <- GenomeInfoDb::keepStandardChromosomes(chipseq, pruning.mode = "tidy")
names(chipseq) <- c(1:length(chipseq))
print(paste("We find a total of ", length(chipseq),"ChIPseq peaks"))

chipseq_summits <- read.table(opt$chipseq_summits)
chipseq_summits <- GRanges(seqnames = chipseq_summits[,c("V1")],
                           ranges = IRanges(start=chipseq_summits[,c("V2")],
                                            end=chipseq_summits[,c("V3")]-1)) # to make up for 0 vs 1 encoding
chipseq_summits$id <- c(1:length(chipseq_summits))

chipseq_summitranges <- chipseq_summits %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 1000) 

sm_summitranges <- readRDS(opt$sm_summitranges)

#----------------------------------------------
#------ peak width
#----------------------------------------------
xbreaks <- c(200,500,1000,3000)
gg_peakwidth <- 
  ggplot(as.data.frame(chipseq))+
  geom_histogram(aes(log10(width)), bins=50,
               colour="black")+
  scale_x_continuous("width (bp)", breaks=log10(xbreaks), labels=xbreaks, limits=log10(c(200,4000)) )
gg_peakwidth

print(paste("The peak width has a mean of", format(mean(width(chipseq)), digits = 6), 
            "and a median of", format(median(width(chipseq)),digits = 6)))

#----------------------------------------------
#------ peak wrt reference
#----------------------------------------------
summitAnno <- readRDS(opt$summitAnno)

## 1. where do the peaks lie
#-------------------------------
annostat <- as.data.frame(summitAnno@annoStat)
gg_annopie <- ggplot(annostat, aes(x="", y=Frequency, fill=Feature))+
  geom_bar(stat="identity", width=1, color="white") +
  geom_text(aes(label = paste(round(Frequency, 1), "%"), x = 1.5),
            position = position_stack(vjust = 0.5), size=2) +
  coord_polar("y", start=0)+
  #scale_fill_brewer(palette="Set3")+
  scale_fill_manual(values= c(rev(RColorBrewer::brewer.pal(9,"YlGnBu")),"white", "darkseagreen"))+
  theme_void()+
  theme(
    text=element_text(size=6, family = "ArialMT", colour="black"),
    legend.key.height = unit(6, 'points'), #change legend key height
    legend.key.width = unit(6, 'points'), #change legend key width
    legend.text = element_text(size=6, family="ArialMT", colour="black")
  )
gg_annopie

print(paste("Frequency of peaks within promoters <3kb:", format(sum(annostat[1:3,"Frequency"]),digits=4)))
print(paste("Frequency of peaks in introns:", format(sum(annostat[8:9,"Frequency"]),digits=4)))
print(paste("Frequency of peaks in distal intergenic regions:", format(sum(annostat[11,"Frequency"]),digits=4)))


## 2. how far are they from closest TSS
#-------------------------------
xbreaks <- c(-100, -75, -50, -25,  0, 25, 50, 75, 100)
gg_distexpr <- 
  as.data.frame(summitAnno) %>%
  ggplot( aes(x=distanceToTSS)) +
  geom_histogram(binwidth = 3000) +
  coord_cartesian(
    #  ylim=c(0,2000),
    xlim=c(-100*10^3, 100*10^3)
  )+
  geom_segment(aes(x = 30*1000, y = 0, xend = 30*1000, yend = 3000), colour="black", linetype=2)+
  geom_segment(aes(x = -30*1000, y = 0, xend = -30*1000, yend = 3000), colour="black", linetype=2)+
  scale_x_continuous(
    breaks = xbreaks*1000,
    labels = paste(xbreaks, "kb")
  )+
  labs(title="",
       y="Counts")+
  theme(axis.text.x = element_text(angle=45, vjust=1, hjust=1))
gg_distexpr

print(paste("Out of all our peaks, a total of",
as.data.frame(summitAnno) %>% filter(abs(distanceToTSS) < 30000) %>% nrow(),
"where within 30000kb of a TSS"))

print(paste("This corresponds to",
format(as.data.frame(summitAnno) %>% filter(abs(distanceToTSS) < 30000) %>% nrow() / length(chipseq) *100, digits=4), "%"))

print(paste("They annotated to ",
as.data.frame(summitAnno) %>% filter(abs(distanceToTSS) < 30000) %>% pull(SYMBOL) %>% unique() %>% length(),
"unique gene symbols"))

#----------------------------------------------
#------ load motif query and match
#----------------------------------------------


load_sitematches <- function(bedpath){
  sitematches <- rtracklayer::import.bed(bedpath)
  # remove weird repetition of seqname
  seqlevels(sitematches) <- gsub(" .*$","",seqlevels(sitematches))
  sitematches <- GenomeInfoDb::keepStandardChromosomes(sitematches, pruning.mode = "tidy")
  names(sitematches) <- c(1:length(sitematches))
  return(sitematches)
}

nr3c1fullsitematches <- load_sitematches(opt$nr3c1fullsitematches)
nr3c1halfsitematches <- load_sitematches(opt$nr3c1halfsitematches)

print(paste("Genome-wide,  we found", length(nr3c1fullsitematches), "matches for the fullsite and",
            length(nr3c1halfsitematches), "matches for the halfsite"))

#----------------------------------------------
#------ # counts for overlap with nr3c1 motif
#----------------------------------------------

# crashes if including halfsites
#overlap_wfullsite <- ChIPpeakAnno::findOverlapsOfPeaks(chipseq,
#                                                       nr3c1fullsitematches,
#                                                       nr3c1halfsitematches,
#                                                       minoverlap=1)
#gg_venn <- grid.grabExpr(
#  ChIPpeakAnno::makeVennDiagram(overlap_wfullsite,
#                                fill=c("#669933", "#ff9900", "#c01311"), # circle fill color (green, orange)
#                                col=c("#669933", "#ff9900", "#c01311"), #circle border color
#                                cat.col=c("#669933", "#ff9900", "#c01311"),
#                                method = NULL,
#                                cex = 0.6,
#                                connectedPeaks = "keepFirstListConsistent"),
#  vp = viewport(w = .6, h = 1.0)
#)


chipseq_nr3c1fullsitematches_counts <- plyranges::count_overlaps(chipseq, nr3c1fullsitematches) %>% 
  as.data.frame() %>% 
  magrittr::set_colnames(c("sitecounts")) %>% 
  count(sitecounts) %>%
  mutate(freq = n / sum(n),
         site = "full")

print(paste("The number of peaks which have at least 1 fullsite match:", 
            sum(chipseq_nr3c1fullsitematches_counts$n) - chipseq_nr3c1fullsitematches_counts$n[1] ))
print(paste("This corresponds to",
            sum(chipseq_nr3c1fullsitematches_counts$freq) - chipseq_nr3c1fullsitematches_counts$freq[1], "%" ))

chipseq_nr3c1halfsitematches_counts <- plyranges::count_overlaps(chipseq, nr3c1halfsitematches)%>% 
  as.data.frame() %>% 
  magrittr::set_colnames(c("sitecounts")) %>% 
  count(sitecounts) %>%
  mutate(freq = n / sum(n),
         site="half")

print(paste("The number of peaks which have at least 1 halfsite match:", 
            sum(chipseq_nr3c1halfsitematches_counts$n) - chipseq_nr3c1halfsitematches_counts$n[1] ))
print(paste("This corresponds to",
            sum(chipseq_nr3c1halfsitematches_counts$freq) - chipseq_nr3c1halfsitematches_counts$freq[1], "%" ))

rm(nr3c1fullsitematches)
rm(nr3c1halfsitematches)

chipseq_nr3c1sitematches_counts <- rbind(chipseq_nr3c1fullsitematches_counts,chipseq_nr3c1halfsitematches_counts)
chipseq_nr3c1sitematches_counts <- chipseq_nr3c1sitematches_counts %>%
  mutate(sitecounts_fac = case_when(sitecounts<=15 ~ as.character(sitecounts),
                                    sitecounts>15 ~ ">15"), # aggregate it towards to top end
         sitecounts_fac = factor(as.character(sitecounts_fac)) )
# set order of factor levels
my_levels <- levels(chipseq_nr3c1sitematches_counts$sitecounts_fac)[gtools::mixedorder(levels(chipseq_nr3c1sitematches_counts$sitecounts_fac))]         
chipseq_nr3c1sitematches_counts <- chipseq_nr3c1sitematches_counts %>%
  mutate(sitecounts_fac = factor(sitecounts_fac, levels=my_levels)) %>%
  group_by(site, sitecounts_fac) %>%
  summarize(freq=sum(freq),
            total=sum(n))

gg_barplotmotifhits <- ggplot(data=chipseq_nr3c1sitematches_counts, aes(x=sitecounts_fac, y= freq*100, group=site))+
  geom_bar(aes(colour=site, fill=site), stat="identity",
           alpha=0.7, position = position_dodge2(width=0.4, padding=0.1, preserve = "single") )+
  scale_fill_manual("",
                    labels = c("NR3C1 fullsite", "NR3C1 halfsite"),
                    breaks = c("full", "half"),
                    values = c("black", "darkgrey")) +
  scale_colour_manual("",
                      labels = c("NR3C1 fullsite", "NR3C1 halfsite"),
                      breaks = c("full", "half"),
                      values = c("black", "darkgrey"))+
  labs(x="# of motifmatches",
       y="% of ChIPseq peaks")+
  theme(legend.position = c(0.7, 0.8),
        axis.text.x = element_text(angle=45, vjust=1, hjust=1))
gg_barplotmotifhits


# can we use the scorematrix function from genomation to get a distribution of reads wrt handpicked motifs

#------------------------------------------------------------------------------------
#------ memes
#------------------------------------------------------------------------------------
# conda activate py_3
# perlbrew use perl-5.34.0
# nohup Rscript memes_runanalyses.R & (from within the script directory)

#------ STREME
#-----------------
streme_results <- memes::importStremeXML( opt$streme )
streme_results <- streme_results %>% 
  mutate(name = paste(consensus, pval))

#DT::datatable(streme_results %>% dplyr::relocate("eval",.after="consensus"),
#              extensions = c('Buttons'), 
#              width=1080,
#              options = list(dom = 'Bfrtip', buttons = c('csv', 'excel'), scrollX = TRUE), 
#              caption = htmltools::tags$caption(style = 'caption-side: bottom; text-align: center;', htmltools::em('Motif enrichment - Discriminative analysis'))
#)

gg_streme <-
  streme_results[1:5,] %>% 
  to_list() %>% 
  view_motifs(names.pos = "top", 
              tryRC = FALSE # we don't care about maximizing based on alignment score, just wanna display the discovered motifs
              )
gg_streme

# why are the lists with pos distr not the same length? Let's pad them
padna <- function(myvector, outlength){
  # check length of vector and how was it's off from desired length
  tofill <- outlength - length(myvector)
  if (tofill<0) {
    stop("Desired length is longer than current length")
  } else if(tofill > 1) {
    # check if it's even
    if((tofill %% 2) == 0) {
      outvector = c(rep(NA,tofill/2), myvector,rep(NA,tofill/2))
    } else {
      outvector = c(rep(NA,floor(tofill/2)), myvector,rep(NA,ceiling(tofill/2)))
    }
    # if uneven, put -1 before and +1 after
    return(outvector)
  }
}

pos_distr <- streme_results$site_distr %>%
  stringr::str_trim(side = c("both")) %>%
  stringr::str_split(pattern=" ")

pos_distr <- lapply(pos_distr, function(x) padna(x,outlength=101))

pos_distr <- as.data.frame(do.call(rbind, pos_distr))
colnames(pos_distr) <- 1:ncol(pos_distr)

pos_distr_top_long <- pos_distr %>%
  mutate(altname = streme_results$altname) %>%
  filter(altname %in% paste0("STREME-",c(1,2,3,4,5)) ) %>%
  relocate(altname) %>%
  tidyr::pivot_longer(cols=1:ncol(pos_distr)+1, names_to="position", values_to = "signal") %>%
  mutate(position=as.numeric(position),
         signal=as.numeric(signal)) 

gg_pos_distr <- ggplot(pos_distr_top_long,aes(x=position, y=signal))+
  geom_point(size=0.5)+
  geom_smooth()+
  facet_wrap(~altname, ncol=1, scales="free_y")+
  labs(x="potision",y="frequency")+
  scale_x_continuous(breaks=c(1,51,101), labels=c(-50,0,50))+
  theme(
    strip.background = element_blank(),
    strip.text.x = element_blank(),
    axis.ticks.y  = element_blank(),
    axis.text.y  = element_blank()
  )

gg_pos_distr

#------------------------------------------------------------------------------------
#------ read distribution around peak summit ?
#------------------------------------------------------------------------------------

genomation_profiledata <- genomation::plotMeta(sm_summitranges)

# make sure the xcoords match the values specified in the summitranges (or the xaxis labels will be wrong)
gg_chipseq_genomationprofileplot <-
  ggplot()+
  geom_line(aes(x=seq(1:length(genomation_profiledata)),y=genomation_profiledata))+
  scale_x_continuous("bases", breaks=c(0,250,500,750,1000), labels=c(-500,-250,0,250,500))+
  labs(x="bases",y="average score")+
  theme(plot.margin = margin(1,2,0,0, "cm"))

sm_scaled = genomation::scaleScoreMatrix(sm_summitranges)
gg_chipseq_genomationheatmap <- grid.grabExpr(
  genomation::heatMatrix(sm_scaled, xcoords = c(-500, 500)) 
)

#------------------------------------------------------------------------------------
#------ plot aggregated figure
#------------------------------------------------------------------------------------

gg_c1 <-  ggpubr::ggarrange(gg_barplotmotifhits,gg_peakwidth, 
                            labels = c("A","B"),
                            ncol = 1, nrow = 2, heights=c(1,0.8))

gg_c2 <-  ggpubr::ggarrange(gg_chipseq_genomationprofileplot, gg_chipseq_genomationheatmap, 
                            labels = c("C",NA),
                            ncol = 1, nrow = 2, heights=c(1,2))

gg_c3_r1 <-  ggpubr::ggarrange(gg_streme, gg_pos_distr,
                            labels = c("D",NA),
                            ncol = 2, nrow = 1, widths = c(1,0.5)) 

gg_c3_r2 <-  ggpubr::ggarrange(gg_annopie, gg_distexpr,
                            labels = c("E", "F"),
                            ncol = 2, nrow = 1, widths = c(1,1)) 

gg_c3 <-  ggpubr::ggarrange(gg_c3_r1, gg_c3_r2,
                               labels = c(NA,NA),
                               ncol = 1, nrow = 2, heights=c(1,1)) 

full_panel <-  ggpubr::ggarrange(gg_c1, gg_c2, gg_c3,
                                 labels = NA,
                                 ncol = 3, nrow=1, widths = c(1,1,2))
full_panel
# usually 190(width) by 100(height)
# scale it up, so motifs are displayed correctly
ggsave(here("./results/current/Figures/Figure_chipseq.png"), full_panel,
       width=380, height=200, units="mm",
       bg="white")
ggsave(here("./results/current/Figures/Figure_chipseq.pdf"), full_panel,
       width=380, height=200, units="mm",
       bg="white")
sink()
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--chipseq_bam"),
              type="character",
              help="Path to BAM file with deduplicated reads from DexLPS condition"),
  make_option(c("--chipseq_summits"),
              type="character",
              help="Path to summit file of IDR peaks"),
  make_option(c("--nr3c1fullsitematches"),
              type="character",
              help="Path to homer hits of nr3c1 fullsite motif"),
  make_option(c("--nr3c1halfsitematches"),
              type="character",
              help="Path to homer hits of nr3c1 halfsite motif"),
  make_option(c("-o", "--outdir"),
              type="character",
              help="Path to output directory"))

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(rtracklayer, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(genomation, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))

#------ chipseq summits
#----------------------------------------------
chipseq_summits <- read.table(opt$chipseq_summits)
chipseq_summits <- GRanges(seqnames = chipseq_summits[,c("V1")],
                           ranges = IRanges(start=chipseq_summits[,c("V2")],
                                            end=chipseq_summits[,c("V3")]-1)) # to make up for 0 vs 1 encoding
chipseq_summits$id <- c(1:length(chipseq_summits))

chipseq_summitranges <- chipseq_summits %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 1000) 

#------ motifmatches
#----------------------------------------------

nr3c1fullsitematches <- rtracklayer::import.bed(opt$nr3c1fullsitematches)
# remove weird repetition of seqname
seqlevels(nr3c1fullsitematches) <- gsub(" .*$","",seqlevels(nr3c1fullsitematches))
nr3c1fullsitematches <- GenomeInfoDb::keepStandardChromosomes(nr3c1fullsitematches, pruning.mode = "tidy")
names(nr3c1fullsitematches) <- c(1:length(nr3c1fullsitematches))
nr3c1fullsitematches_ranges <- nr3c1fullsitematches %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 1000) 

#------ make subsets by combining chipseq summits and motifhits
#----------------------------------------------
# only use the4 summitranges containing an nr3c1 motif
chipseq_summitranges_inner_hits <- chipseq_summitranges %>% 
  plyranges::join_overlap_inner(nr3c1fullsitematches)
width(chipseq_summitranges_inner_hits)
length(chipseq_summitranges_inner_hits)

# only use the nr3c1 coordinates that fall within summitranges
chipseq_summitranges_intersect_hits <- chipseq_summitranges %>% 
  plyranges::join_overlap_intersect(nr3c1fullsitematches)
width(chipseq_summitranges_intersect_hits)
length(chipseq_summitranges_intersect_hits)
# size it up from 14bp to 1000bp around the motifhit
chipseq_summitranges_intersect_hits <- 
  chipseq_summitranges_intersect_hits %>%
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 1000) 


#----------------------------------------------
#------ compute score matrix
#----------------------------------------------

# for each summitregion, get coverage of how many reads in bam file overlap it at each position
# aggregate it across all peaks

sm_summitranges <- ScoreMatrix(target = opt$chipseq_bam,
                               windows = chipseq_summitranges,
                               weight.col = "score")

sm_nr3c1fullsitematches_ranges <- ScoreMatrix(target = opt$chipseq_bam,
                                              windows = nr3c1fullsitematches_ranges,
                                              weight.col = "score")

sm_summitranges_w_nr3c1fullsitehit <- ScoreMatrix(target = opt$chipseq_bam,
                                                  windows = chipseq_summitranges_inner_hits,
                                                  weight.col = "score")

sm_nr3c1fullsitehits_within_summitranges <- ScoreMatrix(target = opt$chipseq_bam,
                                                        windows = chipseq_summitranges_intersect_hits,
                                                        weight.col = "score")

test_coverage <- chipseq_summitranges_intersect_hits %>% plyranges::compute_coverage()
score(test_coverage)
#----------------------------------------------
#------ export data
#----------------------------------------------

saveRDS(sm_summitranges,
        paste0(opt$outdir,"sm_summitranges.rds"))
saveRDS(sm_nr3c1fullsitematches_ranges,
        paste0(opt$outdir,"sm_nr3c1fullsitematches_ranges.rds"))
saveRDS(sm_summitranges_w_nr3c1fullsitehit,
        paste0(opt$outdir,"sm_summitranges_w_nr3c1fullsitehit.rds"))
saveRDS(sm_nr3c1fullsitehits_within_summitranges,
        paste0(opt$outdir,"sm_nr3c1fullsitehits_within_summitranges.rds"))
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--model_coefs_joint"),
              type="character",
              help="Path to rds file with model coefficients of joint models"),
  make_option(c("--model_coefs_sep"),
              type="character",
              help="Path to rds file with model coefficients of models tha include enhancers and promoters separately"),
  make_option(c("--auc"),
              type="character",
              help="Path to rds file with auc results of all models"),
  make_option(c("--motifcounts_summitregion"),
              type="character",
              help="Path to rds file with motifcounts within summitregions"),
  make_option(c("--raw_counts"),
              type="character",
              help="Path to rds file of raw counts within the prox based model")
  )

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggcorrplot, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(RColorBrewer, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(circlize, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggpubr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ComplexHeatmap, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=6, family = "ArialMT", colour="black"),
             title=element_text(size=8, family="ArialMT", colour="black"),
             panel.grid.major = element_line(colour="grey", size=0.2),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=6, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"),
             legend.key.size = unit(6, 'points'), #change legend key size
             legend.key.height = unit(6, 'points'), #change legend key height
             legend.key.width = unit(6, 'points'), #change legend key width
             legend.text = element_text(size=6, family="ArialMT", colour="black")
)

#----------------------------------------------
#------ load data
#----------------------------------------------

model_coefs_joint <- readRDS ( opt$model_coefs_joint )
model_coefs_sep <- readRDS ( opt$model_coefs_sep ) 
AUC_metrics <- readRDS ( opt$auc ) 

AUC_metrics <- AUC_metrics %>% 
  mutate_at(1:6,as.factor) %>%
  mutate(motifdata = dplyr::recode_factor(motifdata, 
                                          motifcounts_abcregion  = "abcregion",
                                          motifcounts_summitregion = "summitregion")) # make factor names shorter

AUC_metrics <- AUC_metrics %>% 
  mutate(names=rownames(.)) # we can't remove the rownames, since we need them for the heatmap annotation later

#---------------------------------------------
#---- show correlation structure
#---------------------------------------------
motifcounts_summitregion <- readRDS( opt$motifcounts_summitregion ) 
#motifdf <- read.table("~/projects/pipeline_ChIP-nexus/results/current/integrate_RNAseq/fimo_featurematrix/merged_matchedpeaks_bygene_30kb_slop50_thresh0.0001_withgenenames.tsv", header=TRUE)
# drop metadata
motifdf <- motifcounts_summitregion[,-c(1:2)]

# determine most variable motifs
motifdf_var <- motifdf %>% dplyr::summarise(across(where(is.numeric), var))
top30perc_var_motif <- sort(motifdf_var, decreasing = T)[1:ceiling(ncol(motifdf_var)*0.3)] %>% names()
# compute and plot their correlation
cor_mat_topvar <- cor(x=motifdf %>% dplyr::select(all_of(top30perc_var_motif)) )
gg_cor <- ggcorrplot(corr = cor_mat_topvar,
                     hc.order = TRUE, # reorders variables according to their correlations
                     outline.col = "white", 
                     colors = c("#6D9EC1", "white", "#E46726"),
                     tl.cex=3)
gg_cor

ggsave(here("./results/current/Figures/Figure_motifcorrelations.png"), gg_cor,
       width=190, height=190, units="mm",
       bg="white")
ggsave(here("./results/current/Figures/Figure_motifcorrelations.pdf"), gg_cor,
       width=190, height=190, units="mm",
       bg="white")
#---------------------------------------------
#---- AUC barplots
#---------------------------------------------
melted_AUC_metrics <- AUC_metrics %>%
  reshape::melt(., measure.vars=c("net_train","net_test"))

# retrieve name of top 25 best performing models (to filter heatmap)
top_models <- melted_AUC_metrics %>% filter(variable=="net_test") %>% arrange(desc(value)) %>% top_n(25) #(with this cutoff the prox based one gets included)
top_models

# overall best performance
max_net_test <- melted_AUC_metrics %>% filter(variable=="net_test") %>% filter(value==max(value)) #%>% summarize(max(value)) %>% as.numeric()
max_net_test

#remove the proximity based model and add it in shape of a reference line instead
prox_reference <- melted_AUC_metrics %>% filter(variable=="net_test") %>% filter(names=="prox") %>% pull(value) %>% as.numeric()
prox_coefs <- model_coefs_joint %>% filter(prox!=0) %>% dplyr::pull(featurename)


# Create the plot
gg_AUC <- ggplot(melted_AUC_metrics %>% filter(variable=="net_test") %>% filter(names!="prox"))+
  geom_bar(aes(x=weight, y=value, fill=condition, alpha=onlymax), 
           colour="black", size=0.5, width=0.9, 
           stat="identity",
           position=position_dodge())+
  geom_hline(aes(yintercept=prox_reference, linetype="reference"), colour="purple")+
  scale_linetype_manual(name="", values = c(2))+
  facet_grid( cols = vars(sepPromEnh,excludepromoters),
              rows= vars(motifdata),
              labeller = labeller(
                motifdata=c("abcregion"="active regions",
                            "summitregion"="GR summitregions"),
                excludepromoters=c("FALSE"="excl.prom: none",
                                   "onlyNONself"="excl.prom: nonself",
                                   "all"="excl.prom: all"),
                sepPromEnh=c("TRUE"="sep prom and enh",
                             "FALSE"= "aggr prom and enh")
              )
  )+
  scale_fill_manual(
    values=c("#339966","#0066CC", "orange"),
    breaks=c("dexlps","lps", "DexLPS-LPS"),
    labels=c("DexLPS","LPS", "\u0394 DexLPS-LPS")
  )+
  scale_alpha_manual(
    values=c(1,0.5),
    breaks=c("FALSE","TRUE"),
    labels=c("1-to-many", "1-to-1")
  )+
  labs(x="Weight features during aggregation",
       y="AUC",
       alpha="mapping"
  )+
  theme(
    legend.position = "bottom")

gg_AUC

#---------------------------------------------
#---- coefficient heatmap
#---------------------------------------------

#AUC_metrics <- AUC_metrics %>% mutate_if(is.character,as.factor)

make_coefficient_heatmap <- function(model_coefs){
  # check what the input was to filter models accordingly later
  if (substitute(model_coefs) == "model_coefs_joint"){
    is_separate=FALSE
  } else if (substitute(model_coefs) == "model_coefs_sep"){
    is_separate=TRUE
  } else {
    stop("The coefficient input matrix doesn't match the expected size")
  }

  #assign any 0 coefficients an NA (so they don't get affected by scaling)
  model_coefs[model_coefs==0] <- NA
  # remove the intercept term for plotting
  #model_coefs <- model_coefs %>% filter(featurename!="(Intercept)")

  # count how many models have the motif included with a non-zero coef
  model_coefs_ftr <- model_coefs %>%
    mutate( sum = rowSums(across(where(is.numeric)), na.rm = TRUE)) %>%
    mutate( motifhascoef_counts = rowSums(!is.na(.)) ) %>%
    dplyr::select(any_of(
      c("featurename", "sum", "motifhascoef_counts", top_models$names))) %>% # only plot models with best performance
    mutate(motifhascoef_counts_topmodels = rowSums( !is.na( dplyr::select(., 3:ncol(.)) ) )) %>%
    mutate(., across(3:(ncol(.)-1), ~(scale(.) %>% as.vector))) %>% #scale before filtering on spec. factors
    slice_max(motifhascoef_counts_topmodels,n=40)

  # remove extra columns before passing it to heatmap
  model_coefs_numeric <- model_coefs_ftr %>% 
    tibble::column_to_rownames("featurename") %>%
    dplyr::select(!c(sum, motifhascoef_counts, motifhascoef_counts_topmodels))

  row_ha = rowAnnotation(
    counts = anno_barplot(model_coefs_ftr$motifhascoef_counts_topmodels)
  )

  # take annotation from AUC_metrics
  #create annotation labels for the heatmap
  myreds <- brewer.pal(3,"OrRd")
  col_ha <- HeatmapAnnotation(df = AUC_metrics %>% 
                                filter(names %in% names(model_coefs_numeric)) %>%
                                arrange(match(names,names(model_coefs_numeric))) %>%
                                dplyr::select(c(condition,motifdata,excludepromoters, onlymax,weight)),
                              col = list(
                                condition = c("lps" = "#0066CC", "dexlps" = "#339966", "DexLPS-LPS" = "orange"),
                                motifdata=c("summitregion" = "purple", "abcregion" = "chocolate4"),
                                excludepromoters= c("FALSE"=myreds[1], "onlyNONself"=myreds[2], "all"=myreds[3]),
                                onlymax=c("prox"="black", "TRUE"="lightgrey", "FALSE"="darkgrey"),
                                weight=c("FALSE"="lightgoldenrod", "abcscore"="goldenrod")
                              ),
                              AUC = anno_barplot(AUC_metrics %>%
                                                   filter(names %in% names(model_coefs_numeric)) %>%
                                                   arrange(match(names,names(model_coefs_numeric))) %>%
                                                   dplyr::pull(net_test),
                                                 ylim=c(0.5,0.8)),
                              show_annotation_name = c(FALSE,FALSE, FALSE,FALSE,FALSE,TRUE),
                              show_legend = c(group=TRUE),
                              annotation_legend_param =  list(
                                labels_gp = gpar(fontsize=6),
                                title_gp = gpar(fontsize=6)
                              ),
                              simple_anno_size = unit(2,"mm")
  )

  mycolorramp <- circlize::colorRamp2(breaks=c(-1.5,0,1.5),
                                      colors=c("blue","white","red"))

  heatmap <- Heatmap(
    col=mycolorramp,
    model_coefs_numeric,
    top_annotation = col_ha, 
    right_annotation = row_ha,
    row_split = 4,
    column_title="Model coefficients",
    column_title_gp = gpar(fontsize = 6, fontface = "bold"), 
    column_names_gp = gpar(fontsize = 6), 
    row_names_gp = gpar(fontsize = 6),
    name="z-scaled coefficient", #Title on top of legend
    clustering_distance_rows = "euclidean", 
    clustering_method_rows = "ward.D2", 
    clustering_distance_columns = "euclidean", 
    clustering_method_columns = "ward.D2", 
    show_column_dend = TRUE,
    show_row_dend = TRUE,
    cluster_rows = TRUE,
    cluster_columns = TRUE,
    show_row_names = TRUE,
    show_column_names = FALSE,
    row_names_side = "left",
    column_dend_height = unit(0.5, "cm"),

    heatmap_legend_param = list(
      title_position = "leftcenter-rot",
      legend_direction="vertical",
      labels_gp = gpar(fontsize=6),
      title_gp = gpar(fontsize=6),
      legend_height = unit(1, "cm"),
      at = c(-1.5, 0, 1.5), 
      labels = c("-1.5", "0", "1.5")
    )
  )

  return (
    grid.grabExpr( draw(heatmap, heatmap_legend_side="right", merge_legend = TRUE) )
  )

}

gg_model_coefs_joint_heatmap <-  make_coefficient_heatmap(model_coefs_joint)

#---------------------------------------------
#----  coefficients summitranges
#---------------------------------------------

make_summitranges_coefficients_heatmap <- function(model_coefs){
  #assign any 0 coefficients an NA (so they don't get affected by scaling)
  model_coefs[model_coefs==0] <- NA

  model_coefs <- model_coefs %>% 
    #filter(featurename!="(Intercept)") %>% # remove the intercept term for plotting
    dplyr::select("featurename","prox" , contains("summitregion")) # select only models based on summitregion

  # count how many models have the motif included with a non-zero coef
  model_coefs_ftr <- model_coefs %>%
    mutate( sum = rowSums(across(where(is.numeric)), na.rm = TRUE)) %>% 
    mutate( motifhascoef_counts = rowSums(!is.na(.)) ) %>%
    mutate(., across(3:(ncol(.)-2), ~(scale(.) %>% as.vector))) %>% #scale before filtering on spec. factors 
    filter( motifhascoef_counts >= 15 )
    #filter(prox!=0)

  # remove extra columns before passing it to heatmap
  model_coefs_numeric <- model_coefs_ftr %>% 
    tibble::column_to_rownames("featurename") %>%
    dplyr::select(!c( sum, motifhascoef_counts))

  row_ha = rowAnnotation(
    counts = anno_barplot(model_coefs_ftr$motifhascoef_counts)
  )

  # take annotation from AUC_metrics
  #create annotation labels for the heatmap
  myreds <- brewer.pal(3,"OrRd")
  col_ha <- HeatmapAnnotation(df = AUC_metrics %>% 
                                filter(names %in% names(model_coefs_numeric)) %>%
                                arrange(match(names,names(model_coefs_numeric))) %>%
                                dplyr::select(c(condition,motifdata,excludepromoters, onlymax,weight)),
                              col = list(
                                condition = c("lps" = "#0066CC", "dexlps" = "#339966", "DexLPS-LPS" = "orange"),
                                motifdata=c("summitregion" = "purple", "abcregion" = "chocolate4"),
                                excludepromoters= c("FALSE"=myreds[1], "onlyNONself"=myreds[2], "all"=myreds[3]),
                                onlymax=c("prox"="black", "TRUE"="lightgrey", "FALSE"="darkgrey"),
                                weight=c("FALSE"="lightgoldenrod", "abcscore"="goldenrod")
                              ),
                              AUC = anno_barplot(AUC_metrics %>% 
                                                   filter(names %in% names(model_coefs_numeric)) %>%
                                                   arrange(match(names,names(model_coefs_numeric))) %>%
                                                   dplyr::pull(net_test),
                                                 ylim=c(0.5,0.8)),
                              show_annotation_name = c(FALSE,FALSE, FALSE,FALSE,FALSE,TRUE),
                              show_legend = FALSE,
                              annotation_legend_param =  list(
                                labels_gp = gpar(fontsize=6),
                                title_gp = gpar(fontsize=6)
                              ),
                              simple_anno_size = unit(2,"mm")
  )

  mycolorramp <- circlize::colorRamp2(breaks=c(-1.5,0,1.5),
                                      colors=c("blue","white","red"))

  heatmap <- Heatmap(
    col=mycolorramp,
    model_coefs_numeric,
    top_annotation = col_ha, 
    right_annotation = row_ha,
    row_split = 4,
    column_title="Model coefficients",
    column_title_gp = gpar(fontsize = 6, fontface = "bold"), 
    column_names_gp = gpar(fontsize = 6), 
    row_names_gp = gpar(fontsize = 6),
    name="z-scaled coefficient", #Title on top of legend
    clustering_distance_rows = "euclidean", 
    clustering_method_rows = "ward.D2", 
    clustering_distance_columns = "euclidean", 
    clustering_method_columns = "ward.D2", 
    show_column_dend = TRUE,
    show_row_dend = TRUE,
    cluster_rows = TRUE,
    cluster_columns = TRUE,
    show_row_names = TRUE,
    show_column_names = FALSE,
    row_names_side = "left",
    column_dend_height = unit(0.5, "cm"),
    show_heatmap_legend = FALSE
  )

  return (
    grid.grabExpr( draw(heatmap, heatmap_legend_side="right", merge_legend = TRUE) )
  )

}

gg_model_summitregioncoefs_joint_heatmap <-  make_summitranges_coefficients_heatmap(model_coefs_joint)

#---------------------------------------------
#---- compare model coefficients of best models
#---------------------------------------------

# check in AUC what is the best model
max_net_test$names #"motifcounts_abcregion_condition_DexLPS-LPS_exclprom_onlyNONself_onlymax_FALSE_sepPromEnh_FALSE_weight_FALSE"

# keep those rows where at least one of the models has a non-zero coefficient
keepRows <- which(rowSums(model_coefs_joint [,c("prox",max_net_test$names)]) != 0 )

model_coefs_long <- model_coefs_joint[keepRows,] %>% 
  dplyr::select(c(featurename,prox,max_net_test$names)) %>%
  dplyr::rename(abc=max_net_test$names)%>%
  tidyr::pivot_longer(.,
                      col=c('prox','abc'),
                      names_to = "model",
                      values_to = "coefficients")
model_coefs_long <- model_coefs_long %>%
  mutate(my_color = case_when(coefficients>0 & model=="prox" ~ "darkred",
                              coefficients<0 & model=="prox" ~ "darkblue",
                              coefficients>0 & model!="prox" ~ "lightred",
                              coefficients<0 & model!="prox" ~ "lightblue"

  ))


gg_bestmodels <- ggplot(data=model_coefs_long)+
  geom_bar(aes(x=reorder(featurename,-coefficients), y=coefficients, fill=model),stat="identity", position = position_dodge(width = 0.5),width=0.5)+
  scale_fill_manual(values=c("prox"="purple",
                             "abc" = "brown"),
                      labels=c("prox. based",
                               "ABC based"))+
  labs(x="motifname", y="coefficient")+
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        legend.position = c(0.8, 0.8))
gg_bestmodels
#---------------------------------------------
#---- or just display the prox based one
#---------------------------------------------
keepRows <- which(model_coefs_joint [,"prox"] != 0 )
model_coefs_data <- model_coefs_joint[keepRows,] %>% 
  mutate(my_color = case_when(prox>0  ~ "positive",
                              prox<0  ~ "negative"))

gg_proxmodel <- ggplot(data= model_coefs_data)+
  geom_bar(aes(x=reorder(featurename,-prox), y=prox, fill=my_color), stat="identity", 
           position = position_dodge(width = 0.5),width=0.5)+
  scale_fill_manual(values=c("positive"="red",
                             "negative" = "blue"))+
  labs(x="motifname", y="coefficient", fill="coefficient sign")+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1),
        legend.position = c(0.8,0.8),
        panel.grid.major = element_blank())
gg_proxmodel

#---------------------------------------------
#---- with red and blue, paired dark and light for the 2 models
#---------------------------------------------

#my_pal <- RColorBrewer::brewer.pal(6,"Paired")
#gg_bestmodels <- ggplot(data=model_coefs_long)+
#  geom_bar(aes(x=featurename, y=coefficients, fill=my_color, colour=model),stat="identity", position = position_dodge(width = 0.5),width=0.5)+
#  scale_fill_manual(values=c("darkred"=my_pal[6],
#                             "darkblue"=my_pal[2],
#                             "lightred"=my_pal[5],
#                             "lightblue"=my_pal[1]),
#                    labels=c("only peakregions\n- proxbased - up", 
#                             "only peakregions\n- proxbased - down", 
#                             "all enhancers\n- abcbased - up",
#                             "all enhancers\n- abcbased - down"
#                             ))+
#  scale_colour_manual(values=c("prox"="red",
#                               "motifcounts_peak_condition_dexlps_exclprom_all_onlymax_FALSE_sepPromEnh_FALSE_weight_abcscore" = "blue"),
#                      labels=c("prox. based",
#                               "ABC based"))+
#  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))+
#  guides(fill="none")


#---------------------------------------------
#---- load raw counts ggplot
#---------------------------------------------

gg_rawcounts <- readRDS(opt$raw_counts)

#---------------------------------------------
#---- put figure together
#---------------------------------------------



gg_coef_heatmaps <-  ggpubr::ggarrange(gg_model_coefs_joint_heatmap, gg_model_summitregioncoefs_joint_heatmap,
                                       labels = c("B", "C"),
                                       ncol = 2, nrow = 1, widths=c(1.2,1)
                                       )
gg_coef_heatmaps

#gg_bottomrow <-  ggpubr::ggarrange(gg_proxmodel, gg_rawcounts,
#                                       labels = c("D", "E"),
#                                       ncol = 2, nrow = 1, widths=c(2,1)
#)
#gg_bottomrow
#full_panel <- ggpubr::ggarrange(gg_AUC, gg_coef_heatmaps, gg_bottomrow,

full_panel <- ggpubr::ggarrange(gg_AUC, gg_coef_heatmaps, gg_bestmodels,
                                labels = c("A", NA, "D"),
                                nrow=3, heights=c(0.5,1,0.3))

full_panel

ggsave(here("./results/current/Figures/Figure_GLMs.png"), full_panel,
       width=190, height=240, units="mm",
       bg="white")
ggsave(here("./results/current/Figures/Figure_GLMs.pdf"), full_panel,
       width=190, height=240, units="mm",
       bg="white")
#---------------------------------------------
#---- save models with enhancers and promoters as separate features
#---------------------------------------------

# possible supplemental:
gg_model_coefs_sep_heatmap <-  make_coefficient_heatmap(model_coefs_sep)
gg_model_coefs_sep_heatmap


gg <-  ggpubr::ggarrange(gg_model_coefs_sep_heatmap, 
                         labels = c(NA),
                         ncol = 1, nrow = 1, widths=c(1))
gg
ggsave(here("./results/current/Figures/Figure_GLMs_coefssep.png"), gg,
       width=190, height=190, units="mm",
       bg="white")
ggsave(here("./results/current/Figures/Figure_GLMs_coefssep.pdf"), gg,
       width=190, height=190, units="mm",
       bg="white")
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--summitAnno_expr"),
              type="character",
              help="Path to file with GR idr summits annotated to expressed genes (as anno object)"),
  make_option(c("--summitAnno_df_expr"),
              type="character",
              help="Path to file with GR idr summits annotated to expressed genes (as dataframe)"),
  make_option(c("--permtest_res"),
              type="character",
              help="Path to rds file with results of permutation test of group differences"),
  make_option(c("--fimo_results"),
              type="character",
              help="Path to rds file with fimo hits within summitregions (1000bp)"),
  make_option(c("--chipseq_summit_granges"),
              type="character",
              help="Path to summit file of IDR peaks"),
  make_option(c("--deeptools"),
              type="character",
              help="Path to png of deeptoolsheatmap split by activating vs repressing peaks"),
  make_option(c("--streme_100bp_up"),
              type="character",
              help="Path to streme xml file for 100bp regions around activating peak regions"),
  make_option(c( "--streme_100bp_down"),
              type="character",
              help="Path to streme xml file for 100bp regions around repressing peak regions"))

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(memes, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(universalmotif, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(png, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=8, family = "ArialMT", colour="black"),
             title=element_text(size=10, family="ArialMT", colour="black"),
             panel.grid.major = element_blank(),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=8, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"),
             legend.key.size = unit(8, 'points'), #change legend key size
             legend.key.height = unit(8, 'points'), #change legend key height
             legend.key.width = unit(8, 'points'), #change legend key width
             legend.text = element_text(size=8, family="ArialMT", colour="black")
)

#-------------------------------
## 0. load data
#-------------------------------

summitAnno_expr <- readRDS( opt$summitAnno_expr)
summitAnno_df_expr <- readRDS( opt$summitAnno_df_expr )
permtest_res <- readRDS( opt$permtest_res )
fimo_results <- readRDS( opt$fimo_results )
ChIPseq_summit_Granges <- readRDS( opt$chipseq_summit_granges )

# Take 100bp windows around ChIP-seq summits
summit_flank_100bp <- ChIPseq_summit_Granges %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 100) 

# Take 100bp windows around ChIP-seq summits
summit_flank_1000bp <- ChIPseq_summit_Granges %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 1000) 


#---------------------------------
#### Peak distance from TSS
#---------------------------------

#Turning things around, let's check 
#* how far the closest peak is from the TSS of up-vs downregulated gene  
#* how far we need to go from the TSS to have 2 or 3 peaks mapping to the gene

distbygene <-  summitAnno_df_expr  %>% 
  group_by(SYMBOL, change) %>%
  summarise(min_dist=min(abs(distanceToTSS)), 
            mean_dist=mean(abs(distanceToTSS))) %>%
  ungroup() %>%
  mutate(logmindist=log2(min_dist+1))

ggplot( ) +
  geom_histogram(data=distbygene %>% filter(change=="up"), aes(x=min_dist, fill="up"), alpha=.3, binwidth = 5000) +
  geom_histogram(data=distbygene %>% filter(change=="down"), aes(x=min_dist, fill="down"), alpha=.3,  binwidth = 5000) +
  expand_limits(x=c(0,400000))+
  labs(title="Dist. to nearest peak: split by direction of expression change")+
  scale_x_continuous(breaks = seq(0, 400000, by = 100000),
                     labels = paste(seq(0, 400000, by = 100000) / 1000,"kb"))+
  scale_fill_manual(name = "", values = c( "up" = "red", "down" = "blue"))

# Zoom into reasonable region

gg_distbychange <- ggplot( ) +
  geom_histogram(data=distbygene %>% filter(change=="ns"), aes(x=logmindist,y=..density.., fill="ns"), binwidth=0.5, alpha=.2) +
  geom_histogram(data=distbygene %>% filter(change=="up"), aes(x=logmindist,y=..density.., fill="up"), binwidth=0.5, alpha=.2) +
  geom_histogram(data=distbygene %>% filter(change=="down"), aes(x=logmindist,y=..density.., fill="down"), binwidth=0.5, alpha=.2) +

  geom_density(data=distbygene %>% filter(change=="up"), aes(x=logmindist, colour="up"), alpha=.3, show.legend = FALSE) +
  geom_density(data=distbygene %>% filter(change=="down"), aes(x=logmindist, colour="down"), alpha=.3, show.legend = FALSE) +
  geom_density(data=distbygene %>% filter(change=="ns"), aes(x=logmindist, colour="ns"), alpha=.3, show.legend = FALSE) +

  geom_vline(xintercept = log2(30000), size=1, colour="black", linetype=2)+
  scale_x_continuous(breaks = c( log2(0+1), log2(1000+1), log2(5000+1), log2(10000+1), log2(30000+1),log2(100000+1) ),
                     labels = paste(c(0,1000,5000,10000,30000,100000) / 1000,"kb"))+
  scale_fill_manual(name = "", values = c( "up" = "red", "down" = "blue", "ns" = "black"))+
  scale_colour_manual(name = "", values = c( "up" = "red", "down" = "blue", "ns" = "black"))+
  guides(colour="none")+
  theme(axis.text.x = element_text(angle=45, vjust=1, hjust=1),
        legend.position = c(0.15,0.8))+
  labs(x="Distance to nearest peak - genecentric")

gg_distbychange

#---------------------------------
# --- load deeptools figure
#---------------------------------

deeptools <- png::readPNG( opt$deeptools )

gg_deeptools <- ggplot() + 
  ggpubr::background_image(deeptools) +
  # so it doesn't get squished
  #coord_fixed()+
  # This ensures that the image leaves some space at the edges
  theme(plot.margin = margin(t=0, l=0, r=0, b=0, unit = "cm"),
        axis.line = element_blank())


#--------------------------------------
#- permutations
#--------------------------------------
groupdiff <- as.numeric(permtest_res[[3]])

gg_perm_dist <- ggplot()+
  geom_histogram(aes(x=permtest_res[[2]]), bins=100)+
  labs(title="",
       x="Permutation based \n group differences")+
  xlim(-10000,10000)+
  geom_vline( xintercept = groupdiff, size=1, colour="red", linetype=1)

#--------------------------------------
#- memes
#--------------------------------------

streme_up_results <- memes::importStremeXML( opt$streme_100bp_up )
streme_up_results <- streme_up_results %>% 
  mutate(name = paste(consensus, pval))

gg_streme_up <-
  streme_up_results[1:5,] %>% 
  to_list() %>% 
  view_motifs(text.size = 7,
              tryRC = TRUE)
  #theme(plot.margin = margin(0,0,2.4,0, "cm"))
gg_streme_up

streme_down_results <- memes::importStremeXML( opt$streme_100bp_down )
streme_down_results <- streme_down_results %>% 
  mutate(name = paste(consensus, pval))

gg_streme_down <-
  streme_down_results[1:5,] %>% 
  to_list() %>% 
  view_motifs(text.size = 7,
              tryRC = TRUE)
gg_streme_down

#---------------------------------
# --- fimo chi-square
#---------------------------------

make_fimo_chisquare_plot <- function(summit_flank, fimo_results, seqwidth){
  input_intersect_hits <- summit_flank %>% 
    plyranges::join_overlap_intersect(fimo_results)

  fimo_counts <- 
    as.data.frame(input_intersect_hits) %>% 
    group_by(motif_alt_id,directionchange) %>% 
    summarize(count=n())

  fimo_counts <- fimo_counts %>% tidyr::pivot_wider(
    names_from = directionchange, 
    values_from = count)

  tbl_directionchange <- table(summit_flank$directionchange)
  setsize <- tbl_directionchange[["down"]] + tbl_directionchange[["up"]]

  fimo_counts <- fimo_counts %>%
    na.omit()

  fimo_counts <- fimo_counts %>%
    rowwise() %>% 
    mutate(
      test_stat = chisq.test(c(down, up),
                             p=c(tbl_directionchange[["down"]] / setsize,
                                 tbl_directionchange[["up"]] / setsize) 
      )$statistic,
      p_val = chisq.test(c(down, up),
                         p=c(tbl_directionchange[["down"]] / setsize,
                             tbl_directionchange[["up"]] / setsize) 
      )$p.value
    )
  fimo_counts$p_adj <-p.adjust(fimo_counts$p_val, method="fdr") 
  # available methods: c("holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none")

  # plot fimo results
  #------------------------------------------------
  colnames(fimo_counts) <- c("motif_name","counts_down","ns","counts_up","test_stat","p_val","p_adj")

  fimo_counts <- fimo_counts %>%
    mutate(
      categories = case_when(grepl("NR3C", motif_name, ignore.case = TRUE) | motif_name=="Ar" | motif_name=="Nr2F6" ~ "NR",
                             grepl("NFKB", motif_name, ignore.case = TRUE) | motif_name=="REL" | motif_name=="RELA" | motif_name=="RELB" ~ "NFKB",
                             grepl("CREB", motif_name, ignore.case = TRUE) | motif_name=="Atf1"| motif_name=="CREM" ~ "CREB",
                             grepl("POU", motif_name, ignore.case = TRUE)  ~ "POU",
                             grepl("KLF", motif_name, ignore.case = TRUE)  ~ "KLF",
                             grepl("JDP", motif_name, ignore.case = TRUE) ~ "AP-1",
                             grepl("JUN", motif_name, ignore.case = TRUE) ~ "AP-1",
                             grepl("IRF", motif_name, ignore.case = TRUE) ~ "IRF",
                             grepl("Stat", motif_name, ignore.case = TRUE) ~ "STAT",
                             TRUE ~ "Other")
    )

  # compute fit and plot regression line
  fit <- lm(fimo_counts$counts_up ~ fimo_counts$counts_down, data = fimo_counts)
  gg <- ggplot(fit$model, aes_string(x = names(fit$model)[2], y = names(fit$model)[1])) + 
    geom_point(colour="grey") +
    stat_smooth(method = "lm", col = "blue") +

    ggrepel::geom_label_repel(data= fimo_counts %>% dplyr::arrange(p_adj) %>% head(20) %>% dplyr::filter(counts_down<counts_up) ,
                              aes(x=counts_down, y=counts_up, label=motif_name, colour=categories), size=2, 
                              min.segment.length = 0,
                              position = ggrepel::position_nudge_repel(x=-(seqwidth/2), y=(seqwidth/2)),
                              label.padding = 0.1, box.padding = 0.1, show.legend=FALSE)+

    ggrepel::geom_label_repel(data= fimo_counts %>% dplyr::arrange(p_adj) %>% head(20) %>% dplyr::filter(counts_down>counts_up) ,
                              aes(x=counts_down, y=counts_up, label=motif_name, colour=categories), size=2,
                              min.segment.length = 0, force_pill=0.5, force = 5, max.overlaps = 50,
                              position = ggrepel::position_nudge_repel(x=(seqwidth/2), y=-(seqwidth/2)),
                              label.padding = 0.1, box.padding = 0.1, show.legend=FALSE)+

    #highlight the same motifs by coloring the point
    geom_point(data= fimo_counts %>% dplyr::arrange(p_adj) %>% head(20),
               aes(x=counts_down, y=counts_up, colour=categories))+
    scale_colour_manual(name="Motif family",
                        values=c("NR"="firebrick","NFKB"="darkblue","IRF"="seagreen","KLF"="deeppink",
                                 "STAT"="darkolivegreen3","POU"="coral","Other"="black"))+

    expand_limits(x=-(seqwidth/2), y=-(seqwidth/2))+ # use the slop to dynamically code this (when windows around summit are smaller, we don't have overplotting issues in the lower left)

    labs(title=paste0("Peakregion ",seqwidth," bp."),
         x="#Motifmatches in peaks of downregulated genes",
         y="#Motifmatches in peaks of upregulated genes",
         subtitle = paste("Adj R2 = ",signif(summary(fit)$adj.r.squared, 2) ) ) +
    theme(legend.position = "bottom")
  results=list()
  results[["fimo_counts"]] <- fimo_counts
  results[["plot"]] <- gg
  return(results)
}

fimo_100_results <- make_fimo_chisquare_plot(summit_flank_100bp,fimo_results, 100)
gg_fimo_100 <- fimo_100_results[["plot"]]
fimo_100_results[["fimo_counts"]] %>% arrange(p_adj) %>% head(n=20)

fimo_1000_results <- make_fimo_chisquare_plot(summit_flank_1000bp,fimo_results, 1000)
gg_fimo_1000 <- fimo_1000_results[["plot"]]

#undebug(make_fimo_chisquare_plot)

#---------------------------------
# --- merge figures into panel
#---------------------------------

gg_r1 <-  ggpubr::ggarrange(gg_distbychange, gg_perm_dist , 
                            labels = c("A","B"), widths = c(1,0.6),
                            ncol = 2, nrow=1)

gg_r2 <-  ggpubr::ggarrange(gg_streme_up, gg_streme_down, 
                            labels = c("D","E"), widths = c(1,1),
                            ncol = 2, nrow=1)

gg_c1 <-  ggpubr::ggarrange(gg_r1, gg_r2, 
                            labels = c(NA, NA),
                            ncol = 1, nrow=2, heights=c(1,1))


full_top <- ggpubr::ggarrange(gg_c1, gg_deeptools, 
                              labels = c(NA, "C"),
                              ncol = 2, nrow=1,
                              widths = c(1.7,1))

gg_bottomrow <-  ggpubr::ggarrange(gg_fimo_100, gg_fimo_1000 , 
                                   labels = c("F","G"), widths = c(1,1),
                                   ncol = 2, nrow=1)


full_panel <- ggpubr::ggarrange(full_top, gg_bottomrow, 
                                labels = c(NA, NA),
                                nrow = 2, ncol=1,
                                heights = c(1.7,1))
full_panel

ggsave(here("./results/current/Figures/Figure_peakgeneannotation.png"), full_panel,
       width=190, height=200, units="mm",
       bg="white")

ggsave(here("./results/current/Figures/Figure_peakgeneannotation.pdf"), full_panel,
       width=190, height=200, units="mm",
       bg="white")
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--log2fcthresh"),
              type="numeric",
              help="Log2FC threshold used in addition to adj.pval to define significant genes"),
  make_option(c("--chipseq_summits"),
              type="character",
              help="Path to summit file of IDR peaks"),
  make_option(c("--genekey"),
              type="character",
              help="Path to biomart genekey that mapps ensembl geeneIDs to MGI symbols"),
  make_option(c("--contrast_DexVSDexLPS"),
              type="character",
              help="Path to annotated tsv file of DeSeq2 contrast of DexLPS vs LPS"),
  make_option(c("--meme_db_path"),
              type="character",
              help="Path to JASPAR motif db file"),
  make_option(c( "--rna_nascent_fpkm"),
              type="character",
              help="FPKM matrix of 4sU experiment"),
  make_option(c("-o", "--outdir"),
              type="character",
              help="Path to output directory"))

opt <- parse_args(OptionParser(option_list=option_list))

# set output for logfile to retrieve stats for plot later
sink(file=paste0(opt$outdir,"figure_proxanno_prepdata.out"))

suppressPackageStartupMessages(library(memes, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(universalmotif, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(biomaRt, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(TxDb.Mmusculus.UCSC.mm10.knownGene, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(BSgenome.Mmusculus.UCSC.mm10, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ChIPseeker, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(stringr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))

#-------------------------------
## Import references
#-------------------------------
# for gene annotation
txdb <- TxDb.Mmusculus.UCSC.mm10.knownGene
# for the sequence
# either use masked or unmasked (the mask does NOT seem to be for repeats though)
mm.genome <- BSgenome.Mmusculus.UCSC.mm10

#-------------------------------
### Determine expressed genes
#-------------------------------
rna_nascent <- read.table(opt$rna_nascent_fpkm, header=TRUE)
print("Determine expressed genes using 4sU data")
# what does the read count distribution look like?
# compute median per gene and plot it as histogram
rna_nascent$median_genecounts <- apply(rna_nascent[,-1], 1, FUN=median)
# lots of medians that are below 1
hist(log10(rna_nascent$median_genecounts))
# filter based on expression
expressed_genes <- rna_nascent %>% 
  dplyr::filter(median_genecounts > 0) 

#-------------------------------
### Load genekey to annotate ensembl to mgi
#-------------------------------
geneKey <- read.delim(opt$genekey)

#merge gene annotations to results table
expressed_genes <- merge(expressed_genes,
                         geneKey, 
                         by.x="Geneid", 
                         by.y="ensembl_gene_id")

#-------------------------------
## Getting the sequences
#-------------------------------
# import summit of ChIPseq peaks
ChIPseq_summits <- read.table(opt$chipseq_summits)
ChIPseq_ranges <- GRanges(seqnames = ChIPseq_summits[,c("V1")],
                          ranges = IRanges(start=ChIPseq_summits[,c("V2")],
                                           end=ChIPseq_summits[,c("V3")]-1)) # to make up for 0 vs 1 encoding
ChIPseq_ranges$id <- c(1:length(ChIPseq_ranges))


# NOTE: if we only want to annotate to genes that are expressed, we could use ChIPpeakAnno and a filtered annoDB object instead
# annotate it to genes
print("Annotate ChIPseq summit to closest gene (using genomic reference)")
summitAnno <- annotatePeak(ChIPseq_ranges, 
                           tssRegion=c(-3000, 3000), 
                           TxDb=txdb, annoDb = "org.Mm.eg.db")

summitAnno_df <- summitAnno %>% as.data.frame()

# see which ones are DE genes and add that info to GRanges as column "directionchange"
print("Add info on which genes are DE to the annotated summits")
DE_4sU <- read.delim(opt$contrast_DexVSDexLPS)

summitAnno_df <- left_join(summitAnno_df, 
                           DE_4sU[,c("mgi_symbol","padj","log2FoldChange")],
                           by = c("SYMBOL" = "mgi_symbol"))

summitAnno_df <- summitAnno_df %>% mutate(change = case_when(padj<0.05 & log2FoldChange > opt$log2fcthresh ~ "up",
                                                             padj<0.05& log2FoldChange < -opt$log2fcthresh ~"down",
                                                             TRUE ~ "ns")
)

# save info on gene annotation
ChIPseq_ranges$mgi_symbol[match(summitAnno_df$id, ChIPseq_ranges$id )] <- summitAnno_df$SYMBOL

# assign directionchange as metadata column
ChIPseq_ranges$directionchange[match(summitAnno_df$id, ChIPseq_ranges$id )] <- summitAnno_df$change

# ass distance to TSS
ChIPseq_ranges$distanceToTSS[match(summitAnno_df$id, ChIPseq_ranges$id )] <- summitAnno_df$distanceToTSS

#-------------------------------
## Prefilter motifdb to motifs that are expressed in celltype
#-------------------------------
print("Prefilter meme_db for those motifs expressed in our 4sU data")
meme_db <- read_meme(opt$meme_db_path) %>% 
  to_df()

meme_db_expressed <- meme_db %>% 
  # the altname slot of meme_db contains the gene symbol (this is database-specific)
  # avoid mismatches cased by casing and keep motif if at least one part of composite is expressed
  tidyr::separate(altname, into=c("tf1", "tf2"), sep="::",remove=FALSE) %>%
  filter( str_to_upper(tf1) %in% str_to_upper(expressed_genes$mgi_symbol) | str_to_upper(tf2) %in% str_to_upper(expressed_genes$mgi_symbol)) %>%
  # we don't need the split TF info downstream
  dplyr::select(!c("tf1","tf2"))


print("Number of motifs pre-filtering: ")
nrow(meme_db)
print("Number of motifs post-filter: ")
nrow(meme_db_expressed)

#-------------------------------
## OPTIONAL: only run with motifs of interest
#-------------------------------
meme_motifsOI <- 
  meme_db_expressed %>% 
  filter(
    grepl("STAT", str_to_upper(altname)) |
      grepl("NR3C", str_to_upper(altname))
  )

#-------------------------------
## FIGURES on peak gene annotation
#-------------------------------

# filter peaks for those annotated to genes that are expressed
summitAnno_expr <- subset(summitAnno,
                          summitAnno@anno$SYMBOL %in% expressed_genes$mgi_symbol)

# filter the df version in the same fashion
summitAnno_df_expr <- summitAnno_df %>% filter(SYMBOL %in% expressed_genes$mgi_symbol)

#---------------------------------
# --- some stats
#---------------------------------

distbygene <-  summitAnno_df_expr  %>% 
  group_by(SYMBOL, change) %>%
  summarise(min_dist=min(abs(distanceToTSS)), 
            mean_dist=mean(abs(distanceToTSS))) %>%
  ungroup() %>%
  mutate(logmindist=log2(min_dist+1))

# why 30kb cutoff
distbygene_allDE <- distbygene  %>% 
  filter(!change=="ns") %>%
  mutate(change=factor(change,levels=c("down","up")))

print("We need to justify why we picked a cutoff of 30kb.")
print("From a genecentric perspective, we want to include the peak regions that most likely have a regulating function on the gene.")

print("With a cutoff of 30kb, how many genes DONT have at least one peak within that range?")
tbl <- table(distbygene_allDE$min_dist > 30000)
tbl[2]/(tbl[1]+tbl[2])

print("How many genes do we lose of both sets by using that cutoff?")
print("In the upregulated fraction:")
table( (distbygene %>% filter(change=="up"))$min_dist > 30000)
print("In the downregulated fraction:")
table( (distbygene %>% filter(change=="down"))$min_dist > 30000)

print("Min and mean dist for the genes with log2FC >", opt$log2fcthresh)
distbygene %>%
  filter(change=="up") %>%
  summarise_all(mean) %>%
  print()
print("Min and mean dist for the genes with log2FC <", opt$log2fcthresh )
distbygene %>%
  filter(change=="down") %>%
  summarise_all(mean) %>%
  print()

print("How many peaks per UPregulated gene:")
summitAnno_df_expr  %>% 
  filter(change=="up")%>%
  filter(abs(distanceToTSS)<30000) %>%
  group_by(SYMBOL) %>%
  summarise(count=n()) %>%
  pull(count) %>% 
  mean()
print("How many peaks per DOWNregulated gene:")
summitAnno_df_expr  %>% 
  filter(change=="down")%>%
  filter(abs(distanceToTSS)<30000) %>%
  group_by(SYMBOL) %>%
  summarise(count=n()) %>%
  pull(count) %>% 
  mean()

print("The distances between the peaks mapping to the same gene.")
print("returns NA if only one 1 peak is annotated to the gene - those are excluded")
print("For upregulated genes:")
summitAnno_df_expr  %>% 
  filter(change=="up")%>%
  filter(abs(distanceToTSS)<30000) %>%
  group_by(SYMBOL) %>%
  summarise(meanpeakdist = mean(dist(distanceToTSS))) %>% # 
  filter(!is.na(meanpeakdist)) %>%
  pull(meanpeakdist) %>%
  mean()
print("For downregulated genes:")
summitAnno_df_expr  %>% 
  filter(change=="down")%>%
  filter(abs(distanceToTSS)<30000) %>%
  group_by(SYMBOL) %>%
  summarise(meanpeakdist = mean(dist(distanceToTSS))) %>% 
  filter(!is.na(meanpeakdist)) %>%
  pull(meanpeakdist) %>%
  mean()

#--------------------------------------
#- permutations
#--------------------------------------

# Difference in means
groupdiff <- diff(tapply(distbygene_allDE$min_dist, distbygene_allDE$change, mean))
print("The mean minimum distance is smaller for the upregulated set")
print(paste("The group difference is: ",groupdiff))
print("Permutation test to see if this difference between the groups is meaningful")

#Permutation test
permutation.test <- function(group, outcome, n, reference){
  distribution=c()
  result=0
  for(i in 1:n){
    distribution[i]=diff(by(outcome, sample(group, length(group), FALSE), mean))
  }
  result=sum(abs(distribution) >= abs(groupdiff))/(n)
  return(list(result, distribution, groupdiff))
}

permtest_res <- permutation.test(distbygene_allDE$change, distbygene_allDE$min_dist, 100000, groupdiff)

#--------------------------------------
#- export objects
#--------------------------------------

#---------------------------------
# --- export results of the permutation test
saveRDS(permtest_res,
        file=paste0(opt$outdir,"permtest_res.rds"))

#---------------------------------
# --- export up and downregulated summitfraction for deeptools

table(ChIPseq_ranges$directionchange)
dir.create(paste0(opt$outdir,"peaks_annot2DEgenes_30kb_log2FC0.58/"))
export.bed(ChIPseq_ranges %>% filter(directionchange == "up") %>% filter(abs(distanceToTSS)<30000) ,
           con=paste0(opt$outdir,"peaks_annot2DEgenes_30kb_log2FC0.58/UP_summit_unmerged.bed"))
export.bed(ChIPseq_ranges %>% filter(directionchange == "down") %>% filter(abs(distanceToTSS)<30000) ,
           con=paste0(opt$outdir,"peaks_annot2DEgenes_30kb_log2FC0.58/DOWN_summit_unmerged.bed"))

#-------------------------------
## export objects to run memes afterwards

saveRDS(ChIPseq_ranges,
        file=paste0(opt$outdir,"../memes_bioc/ChIPseq_summit_Granges.rds"))

saveRDS(meme_db_expressed,
        file=paste0(opt$outdir,"../memes_bioc/meme_db_4sUexpressed.rds"))

#-------------------------------
## export objects for ggplot figures
saveRDS(summitAnno,
        file=paste0(opt$outdir,"summitAnno.rds"))
saveRDS(summitAnno_expr,
        file=paste0(opt$outdir,"summitAnno_expr.rds"))
saveRDS(summitAnno_df_expr,
        file=paste0(opt$outdir,"summitAnno_df_expr.rds"))

sink()
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--tfactivity"),
              type="character",
              help="TF activity, computed using macrophage specific TSS"),
  make_option(c("--expr"),
              type="character",
              help="Path to file with normalized counts, aggregated per mgi symbol"),
  make_option(c("--difffootprint"),
              type="character",
              help="Path to txt file with differential statistics from footprinting analysis"),
  make_option(c("--memedb_expressed"),
              type="character",
              help="Path to rds file of memedb motifs filtered for those expressed"),
  make_option(c("--heatmap"),
              type="character",
              help="Path to deeptools heatmap of motif of interest"),
  make_option(c("--chipms"),
              type="character",
              help="Path to xlsx file with statistics on GR-ChIPMS analysis")
  )

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(universalmotif, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "white", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=10, family = "ArialMT", colour="black"),
             title=element_text(size=8, family="ArialMT", colour="black"),
             panel.grid.major = element_blank(),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=8, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"),
             legend.key.size = unit(8, 'points'), #change legend key size
             legend.key.height = unit(8, 'points'), #change legend key height
             legend.key.width = unit(8, 'points'), #change legend key width
             legend.text = element_text(size=8, family="ArialMT", colour="black")
)

#-------------------------------------------------------------------------------
# Load input files
#-------------------------------------------------------------------------------

meme_db_expressed <- readRDS(opt$memedb_expressed)
expr <- read.delim(opt$expr)
TFA <- read.delim(opt$tfactivity)
footprint <- read.table(opt$difffootprint, header=TRUE)

#-------------------------------------------------------------------------------
# Differential footprints
#-------------------------------------------------------------------------------

footprint <- footprint %>% 
  mutate(motif_name = stringr::str_split_fixed(Motif, "\\.",3)[,3],
         Protection_score_diff = Protection_Score_DexLPS - Protection_Score_LPS,
         categories = case_when(grepl("NR3C", motif_name, ignore.case = TRUE) | motif_name=="Ar" | motif_name=="Nr2F6" ~ "NR",
                                  grepl("CREB", motif_name, ignore.case = TRUE) | motif_name=="Atf1"| motif_name=="CREM" ~ "CREB",
                                  grepl("KLF", motif_name, ignore.case = TRUE)  ~ "KLF",
                                  grepl("ATF", motif_name, ignore.case = TRUE) ~ "AP-1",
                                  grepl("JDP", motif_name, ignore.case = TRUE) ~ "AP-1",
                                  grepl("JUN", motif_name, ignore.case = TRUE) ~ "AP-1",
                                  grepl("IRF", motif_name, ignore.case = TRUE) ~ "IRF",
                                  TRUE ~ "Other"),
         padj = p.adjust(P_values, method = "fdr")
         )

# filter on those that we tested in the GLMs
# even if we do, FDR correction kills almost all significance
#footprint_ftr <- footprint %>% 
#  filter(motifnames %in% meme_db_expressed$altname) %>%
#  mutate( padj = p.adjust(P_values, method = "fdr"))


#should we additionally filter on the protection score or not? If we argue for transient binding, we might not want to
table(footprint %>% filter(Num>100 & P_values < 0.05) %>% dplyr::pull(categories))

gg_difffootprint <- ggplot()+
  geom_point(data = footprint %>% filter(Num>100 ), 
             aes(x=Num, y=-log10(P_values)), colour="grey") +
  geom_point(data = footprint %>% filter(Num>100 & P_values < 0.05), 
             aes(x=Num, y=-log10(P_values), colour=categories))+
  ggrepel::geom_label_repel(data = footprint %>% filter(Num>100 & P_values < 0.05 & categories=="Other") ,
                          aes(x=Num, y=-log10(P_values), label=motif_name, colour=categories), size=2.5, min.segment.length = 0,
                          position = ggrepel::position_nudge_repel(x=8000, y=0.1), 
                          label.padding = 0.1, box.padding = 0.1, show.legend = FALSE)+
  scale_colour_manual(name="Motif family",
                      values=c("NR"="firebrick",
                               "AP-1"="dodgerblue",
                               "CREB"="purple",
                               "IRF"="seagreen",
                               "KLF"="deeppink",
                               "Other"="black"))+
  ylim(c(0,3))

gg_difffootprint
#footprint %>% filter(Num>100 & Protection_Score_DexLPS>1) %>% arrange(P_values) %>% View()
#footprint %>% arrange(desc(abs(Protection_score_diff))) %>% head(20)

# requires poppler-cpp system installation
#magick::image_read_pdf(here("../mac_atacseq/results/current/footprints/DexLPSvLPS_diff_footprint/Lineplots/MA1127.1.FOSB::JUN.pdf"))


gg_placeholder <- ggplot() + 
  theme(plot.margin = margin(t=0, l=0, r=0, b=0, unit = "cm"),
        axis.line = element_blank())

#-------------------------------------------------------------------------------
# Expression levels of STATs
#-------------------------------------------------------------------------------

expr_long <- expr %>% 
  tibble::rownames_to_column(var="mgi_symbol") %>%
  tidyr::pivot_longer(cols=-c(mgi_symbol), # everything except mgi_symbol column
                      names_to="sample") %>%
  tidyr::extract(
    "sample", c("condition","rep","type"), regex = "(.*)([0-9])_([^_]+)$") %>%
  mutate(condition=factor(condition, 
                          levels=c("V", "LPS", "LPS_Dex"),
                          labels=c("Veh", "LPS", "DexLPS")))

genes_OI <- c("Stat1","Stat2","Stat3","Stat4","Stat5a","Stat5b","Stat6","Tcf7","Pou2f1","Rel","Nfkb1","Meis1","Nr3c1")

gg_expr <- 
  ggplot(expr_long %>% filter(mgi_symbol %in% genes_OI) %>%
           mutate(across(mgi_symbol, factor, levels=genes_OI)) )+
  geom_abline(slope=0, intercept = 0, colour="grey")+
  #ggplot(expr_long %>% filter(mgi_symbol %in% c("Stat2","Stat3","Tcf7","Pou2f1","Rel","Nfkb1","Meis1","Nr3c1")))+
  geom_boxplot(aes(x=condition, y=log2(value)))+
  geom_point(aes(x=condition, y=log2(value)))+
  facet_wrap(~mgi_symbol, ncol=7)+
  labs( y="log2 (FPKM)")+
  theme(axis.text.x = element_text(angle=30, hjust=1))

gg_expr

#-------------------------------------------------------------------------------
# TF activities
#-------------------------------------------------------------------------------

TFA_long <- as.data.frame(TFA) %>% 
  tibble::rownames_to_column( "TF") %>% 
  tidyr::pivot_longer(cols=2:(ncol(TFA)+1),
                      names_to="sample",
                      values_to="tfactivity") %>%
  tidyr::extract(
    "sample", c("condition","rep","type"), regex = "(.*)([0-9])_([^_]+)$") %>%
  mutate(condition=factor(condition, 
                          levels=c("V", "LPS", "LPS_Dex"),
                          labels=c("Veh", "LPS", "DexLPS")))

gg_TFA_all <- ggplot(TFA_long) +
  geom_boxplot(aes(x=condition, y=tfactivity))+
  facet_wrap(~TF, scales = "free", ncol=6)

ggsave(here("./results/current/tfactivity/TFA_all.png"), gg_TFA_all,
       width=190, height = 250, units="mm")

gg_tfa <- ggplot(TFA_long %>% filter(TF %in% c("NR3C1","STAT2","STAT3","RELA","JUN","JUNB","JUND","FOS","FOSL"))) +
  geom_boxplot(aes(x=condition, y=tfactivity))+
  geom_point(aes(x=condition, y=tfactivity))+
  labs( y = "TF activity")+
  theme(axis.text.x = element_text(angle=45, hjust=1))+
  facet_wrap(~TF, scales = "free")

#-------------------------------------------------------------------------------
# ChIP-MS data
#-------------------------------------------------------------------------------

chipMS <- openxlsx::read.xlsx( opt$chipms )
# save original column names to know what is what
orig_cnames <- colnames(chipMS)
# make them valid for R
colnames(chipMS) <- make.names(colnames(chipMS))
#orig_cnames
#colnames(chipMS)

genes_OI <- c("Rela","Rel","Junb","Nfkb1","Nr3c1","Meis1","Stat1","Stat2","Stat3","Stat4","Stat5b;Stat5a","Stat6")

gg_chipMS <- ggplot(chipMS, aes(x=Test.statistic ,y=X.Log.t.test.p.value ))+
  geom_point(colour="grey")+
  geom_abline(slope=0, intercept = 0, colour="grey")+
  geom_point(data=chipMS %>% filter(X.Log.t.test.p.value > 1.3),
             colour="black")+
  geom_point(data=chipMS %>% filter(Gene.names %in% genes_OI), 
             colour="blue", size=2)+
  ggrepel::geom_label_repel(data=chipMS %>% filter(Gene.names %in% genes_OI), 
                            aes( label=Gene.names ), size=2, nudge_x = 0.5, nudge_y = 0.2)+
  geom_hline(yintercept=1.3, linetype=2)+
  labs(x="Test statistic - wtGR vs wtIgG",
       y="-log(p) - wtGR vs wtIgG")
gg_chipMS

#-------------------------------------------------------------------------------
# deeptools at STAT
#-------------------------------------------------------------------------------

#deeptools <- png::readPNG( opt$heatmap )

#gg_deeptools <- ggplot() + 
#  ggpubr::background_image(deeptools) +
#  # so it doesn't get squished
#  #coord_fixed()+
#  # This ensures that the image leaves some space at the edges
#  theme(plot.margin = margin(t=0, l=0, r=0, b=0, unit = "cm"),
#        axis.line = element_blank())
# --> moved to supplements

#-------------------------------------------------------------------------------
# STAT motifs
#-------------------------------------------------------------------------------

gg_statmotifs <-
  meme_db_expressed %>%
  filter( grepl("STAT", stringr::str_to_upper(altname)) ) %>%
  mutate(name = paste(stringr::str_to_upper(altname), "(", name, ")")) %>%
  to_list() %>% 
  view_motifs()

gg_statmotifs

ggsave(here("./results/current/Figures/Suppl_Figure_statmotifs.pdf"), gg_statmotifs,
       width=180, height=200, units="mm",
       bg="white")

#------------------------------------------------------------------------------------
#------ plot aggregated figure
#------------------------------------------------------------------------------------

#gg_c1 <-  ggpubr::ggarrange(gg_expr, gg_tfa, 
#                            labels = c("A","B"),
#                            ncol = 1, nrow = 2, heights = c(1,1))

left <- ggpubr::ggarrange(gg_expr, gg_difffootprint, 
                          labels = c("A","C"),
                          ncol = 1, nrow=2, heights = c(1,1))

right <- ggpubr::ggarrange(gg_chipMS, gg_placeholder,
                                labels = c("B","D"),
                                ncol = 1, nrow=2, heights = c(2,1))


full_panel <- ggpubr::ggarrange(left, right, 
                            labels = c(NA,NA),
                            ncol = 2, nrow=1, widths = c(1,0.7))
full_panel


ggsave(here("./results/current/Figures/Figure_stats.png"), full_panel,
       width=190, height=120, units="mm",
       bg="white")

ggsave(here("./results/current/Figures/Figure_stats.pdf"), full_panel,
       width=190, height=120, units="mm",
       bg="white")
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--auc"),
              type="character",
              help="Path to rds file with auc results of all models"),
  make_option(c("--dirname_featurematrizes"),
              type="character",
              help="directory that the unscaled featurematrizes were saved in"),
  make_option(c("--dirname_models"),
              type="character",
              help="directory that the trained models were saved in"),
  make_option(c("--outfig"),
              type="character",
              help="Path to output Figure")
)

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(glmnet, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=8, family = "ArialMT", colour="black"),
             title=element_text(size=10, family="ArialMT", colour="black"),
             panel.grid.major = element_blank(),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=8, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"),
             legend.key.size = unit(8, 'points'), #change legend key size
             legend.key.height = unit(8, 'points'), #change legend key height
             legend.key.width = unit(8, 'points'), #change legend key width
             legend.text = element_text(size=8, family="ArialMT", colour="black")
)

# compare ROC curves for statistical significance
# which ones?
# let's start with the best performing one and our reference model

# what is the name of the best performing model?
AUC_metrics <- readRDS ( opt$auc ) 
bestmodel <- AUC_metrics %>% filter(net_test == max(AUC_metrics$net_test)) %>% rownames()
AUC_metrics[bestmodel,"net_train"]
# what is the performance of the best model on the training set?
#-----------------------------------------

# 0 write function that takes model and featurematrix as input and returns ROC object as output
not_all_na <- function(x) any(!is.na(x))
get_roc_object <- function(path_performance_rds, path_featurematrix_unscaled_rds){

  # 1. load cv.fit of model
  performance<- readRDS( path_performance_rds )
  cvfit_net <- performance[[4]]

  # 2. load testset of model
  motifdata <- readRDS( path_featurematrix_unscaled_rds )
  motifdata_scaled <- motifdata %>% 
    mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector)))%>%
    dplyr::select(where(not_all_na))
  motifdata_tranval_idx <- motifdata_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))

  features_train <- motifdata_scaled[ motifdata_tranval_idx, -c(1,2,3)] %>% as.matrix()
  features_test <- motifdata_scaled[ -motifdata_tranval_idx, -c(1,2,3)] %>% as.matrix()
  targets_train <- motifdata_scaled[ motifdata_tranval_idx, ] %>% pull(label) %>% as.numeric(levels(.))[.] %>% as.matrix()
  targets_test <- motifdata_scaled[ -motifdata_tranval_idx, ] %>% pull(label) %>% as.numeric(levels(.))[.] %>% as.matrix()

  # 3. Predict and return ROC
  targets_net.prob <- predict(cvfit_net,
                              type="response",
                              newx = features_test,
                              s = 'lambda.min')

  roc_object <- pROC::roc(as.factor(targets_test),targets_net.prob[,1], direction = "<")
  return(roc_object)

}

roc_reference <- get_roc_object ( paste0( opt$dirname_models, "prox.rds"),
                                  paste0( opt$dirname_featurematrizes, "prox.rds") )

roc_bestmodel <- get_roc_object ( paste0( opt$dirname_models, bestmodel,".rds"),
                                  paste0( opt$dirname_featurematrizes, bestmodel,".rds") )

# 4. Compare for pROC
# Should we compute the p value comparing our reference to all others and see how many others it beats?
#res <- pROC::roc.test( roc_reference, roc_bestmodel, method="delong", alternative="greater")
#res

#-------------------------------------------------------------------------------
#  comparison with reference model (proximity based)
#-------------------------------------------------------------------------------

# initialize a dataframe that will save the name of the model, the pvalue and whether the referene was better
all_pairwise_wprox <- data.frame(
  pvalues=numeric())

for (modelname in rownames(AUC_metrics) ) {
  # skip the prox model since this is what we compare to
  if (modelname=="prox"){next}
  print(modelname)
  roc_model <- get_roc_object ( paste0( opt$dirname_models, modelname,".rds"),
                                paste0( opt$dirname_featurematrizes, modelname,".rds") )
  roc_test_res <- pROC::roc.test( roc_reference, roc_model, method="delong", alternative="greater") 

  new_metrics <- data.frame(
    p.values=roc_test_res$p.value)

  all_pairwise_wprox <- rbind(all_pairwise_wprox,
                              new_metrics ) %>%
    magrittr::set_rownames(c(rownames(all_pairwise_wprox), modelname))
}

all_pairwise_wprox$input_is_summitregion <- grepl("motifcounts_summitregion*",rownames(all_pairwise_wprox))

storey_wprox <- qvalue::qvalue(all_pairwise_wprox$p.values,  lambda=seq(0.05, 0.8, 0.05), fdr.level = 0.05)
storey_wprox
print("Pi0 computed by Storey's method for comparison with reference model:")
print(storey_wprox$pi0)

# plot all p values to estimate where the histogram "levels out" and set this as lambda in Storey's q value
gg_storey_wprox <-
  ggplot(all_pairwise_wprox)+
  geom_histogram(aes(p.values,group=input_is_summitregion,fill=input_is_summitregion), bins=40 )+
  scale_fill_manual("",
                    labels = c("active regions", "GR summitregions"),
                    breaks = c("FALSE", "TRUE"),
                    values = c("chocolate4", "purple")) +
  scale_colour_manual("",
                      labels = c("active regions", "GR summitregions"),
                      breaks = c("FALSE", "TRUE"),
                      values = c("chocolate4", "purple")) +
  labs(x="p value",
       y="count")+
  theme(legend.position = c(0.7, 0.8))
gg_storey_wprox

table(all_pairwise_wprox$p.values<=0.05, all_pairwise_wprox$input_is_summitregion)
table(storey_wprox$significant)
#-------------------------------------------------------------------------------
# comparison with best performing model
#-------------------------------------------------------------------------------

# initialize a dataframe that will save the name of the model, the pvalue and whether the referene was better
all_pairwise_wbest <- data.frame(pvalues=numeric())

for (modelname in rownames(AUC_metrics) ) {
  # skip the bestmodel since this is what we compare to
  if (modelname==bestmodel){
    print("Skipping self") 
    next}
  print(modelname)
  roc_model <- get_roc_object ( paste0(opt$dirname_models, modelname,".rds"),
                                paste0( opt$dirname_featurematrizes, modelname,".rds") )
  roc_test_res <- pROC::roc.test( roc_bestmodel, roc_model, method="delong", alternative="greater") 

  new_metrics <- data.frame(p.values=roc_test_res$p.value)

  all_pairwise_wbest <- rbind(all_pairwise_wbest,
                              new_metrics ) %>%
    magrittr::set_rownames(c(rownames(all_pairwise_wbest), modelname))
}

all_pairwise_wbest$input_is_summitregion <- grepl("motifcounts_summitregion*",rownames(all_pairwise_wbest))


storey_wbest <- qvalue::qvalue(all_pairwise_wbest$p.values,  lambda=seq(0.05, 0.35, 0.05))
storey_wbest
print("Pi0 computed by Storey's method for comparison with best model:")
print(storey_wbest$pi0)

# plot all p values to estimate where the histogram "levels out" and set this as lambda in Storey's q value
gg_storey_wbest <-
  ggplot(all_pairwise_wbest)+
  geom_histogram(aes(p.values,group=input_is_summitregion,fill=input_is_summitregion), bins=40 )+
  scale_fill_manual("",
                    labels = c("active regions", "GR summitregions"),
                    breaks = c("FALSE", "TRUE"),
                    values = c("chocolate4", "purple")) +
  scale_colour_manual("",
                      labels = c("active regions", "GR summitregions"),
                      breaks = c("FALSE", "TRUE"),
                      values = c("chocolate4", "purple")) +
  labs(x="p value",
       y="count")+
  theme(legend.position = c(0.7, 0.8))
gg_storey_wbest

#-------------------------------------------------------------------------------
# bivariate models with motifs of interest
#-------------------------------------------------------------------------------
# Load in featurematrix, scale it and fit model with out motifs of interest in bivariate model

motifdata <- readRDS( paste0(opt$dirname_featurematrizes, "prox.rds" ))
motifdata_scaled <- motifdata %>% 
  mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector)))
motifdata_tranval_idx <- motifdata_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))

features_train <- motifdata_scaled[ motifdata_tranval_idx, -c(1,2,3)] %>% as.matrix()
features_test <- motifdata_scaled[ -motifdata_tranval_idx, -c(1,2,3)] %>% as.matrix()
targets_train <- motifdata_scaled[ motifdata_tranval_idx, ] %>% pull(label) %>% as.numeric(levels(.))[.] %>% as.matrix()
targets_test <- motifdata_scaled[ -motifdata_tranval_idx, ] %>% pull(label) %>% as.numeric(levels(.))[.] %>% as.matrix()

model_coefficients <- data.frame(motifname = character(),
                                 intercept = numeric(),
                                 coefficient = numeric(),
                                 pvalue = numeric() )

for (motif in c("MEIS1","NFKB1","REL","POU2F1","TCF7","STAT3")){
  glm_res <- glm(targets_train ~ features_train[,c(motif)], family="binomial")
  new_model <- data.frame(motifname=motif,
                          intercept= glm_res$coefficients[1],
                          coefficient = glm_res$coefficients[2],
                          pvalue = coef(summary(glm_res))[2,4],
                          row.names = NULL)
  model_coefficients <- rbind( model_coefficients, new_model )
}


gg_bivariate <- ggplot(data=model_coefficients)+
  geom_point(aes(coefficient, -log10(pvalue)))+
  ggrepel::geom_label_repel(aes(coefficient, -log10(pvalue), 
                                label=motifname), size=2)+
  coord_cartesian(ylim=c(0,max(-log10(model_coefficients$pvalue))),
                  xlim=c(min(model_coefficients$coefficient),-0.1))+
  geom_hline(aes(yintercept=-log10(0.05)), linetype="dashed" )

#-------------------------------------------------------------------------------
# model performance on training set
#-------------------------------------------------------------------------------
melted_AUC_metrics <- AUC_metrics %>%
  reshape::melt(., measure.vars=c("net_train","net_test"))

#remove the proximity based model and add it in shape of a reference line instead
prox_reference_train <- melted_AUC_metrics %>% filter(variable=="net_train") %>% filter(onlymax=="prox") %>% pull(value) %>% as.numeric()
gg_AUC_train <- ggplot(melted_AUC_metrics %>% filter(variable=="net_train") %>% filter(onlymax!="prox"))+
  geom_bar(aes(x=weight, y=value, fill=condition, alpha=onlymax), 
           colour="black", size=0.5, width=0.9, 
           stat="identity",
           position=position_dodge())+
  geom_hline(aes(yintercept=prox_reference_train, linetype="reference"), colour="purple")+
  scale_linetype_manual(name="", values = c(2))+
  facet_grid( cols = vars(sepPromEnh,excludepromoters),
              rows= vars(motifdata),
              labeller = labeller(
                motifdata=c("motifcounts_abcregion"="active regions",
                            "motifcounts_summitregion"="GR summitregions"),
                excludepromoters=c("FALSE"="excl.prom: none",
                                   "onlyNONself"="excl.prom: nonself",
                                   "all"="excl.prom: all"),
                sepPromEnh=c("TRUE"="sep prom and enh",
                             "FALSE"= "aggr prom and enh")
              )
  )+
  scale_fill_manual(
    values=c("#339966","#0066CC", "orange"),
    breaks=c("dexlps","lps", "DexLPS-LPS"),
    labels=c("DexLPS","LPS", "\u0394 DexLPS-LPS")
  )+
  scale_alpha_manual(
    values=c(1,0.5),
    breaks=c("FALSE","TRUE"),
    labels=c("1-to-many", "1-to-1")
  )+
  labs(x="Weight features during aggregation",
       y="AUC",
       alpha="mapping"
  )+
  theme(
    legend.position = "bottom")

#-------------------------------------------------------------------------------
# arrange and save figure
#-------------------------------------------------------------------------------

gg_placeholder <- ggplot() + 
  theme(plot.margin = margin(t=0, l=0, r=0, b=0, unit = "cm"),
        axis.line = element_blank())

#A in this panel will be tha training performance

gg_c1 <- ggpubr::ggarrange(gg_storey_wbest, gg_storey_wprox, 
                           labels = c("B","C"),
                           ncol = 1, nrow = 2)
gg_c2 <- ggpubr::ggarrange(gg_bivariate, gg_placeholder, 
                           labels = c("D",NA),
                           ncol = 1, nrow = 2,
                           heights = c(1.5,1))
gg_r2 <-  ggpubr::ggarrange(gg_c1, gg_c2, 
                         labels = c(NA, NA),
                         ncol = 2, nrow = 1)

gg <-  ggpubr::ggarrange(gg_AUC_train, gg_r2, 
                         labels = c("A", NA),
                         ncol = 1, nrow = 2,heights = c(1,1))
gg
ggsave( opt$outfig, gg,
       width=190, height=200, units="mm",
       bg="white")
# also save it as pdf
ggsave( gsub(".png",".pdf",opt$outfig), gg,
        width=190, height=200, units="mm",
        bg="white")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--fimo"),
              type="character",
              help="Path to fimo rds file that should be subsetted"),
  make_option(c("--summit_granges"),
              type="character",
              help="Path to summit granges file that we use to narrow down fimo hits on summitregions"),
  make_option(c("--motif_altname"),
              type="character",
              help="Altname of motif that we filter the fimo results for (case sensitive!)"),
  make_option(c("--outfile"),
              type="character",
              help="Path to subsetted output bed file")
)
opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(rtracklayer, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(GenomicRanges, warn.conflicts=F, quietly=T))

fimo_results <- readRDS ( opt$fimo )
ChIPseq_summit_Granges <- readRDS( opt$summit_granges )

# Take 100bp windows around ChIP-seq summits
summit_flank_100bp <- ChIPseq_summit_Granges %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 100) 

# narrow the hits of the motif of interest down to the immediate summit region
motifhits <- fimo_results %>% 
  filter(motif_alt_id==opt$motif_altname) %>% 
  filter_by_overlaps(summit_flank_100bp) 

print(paste0("We found " , length(motifhits), " motifhits for ", opt$motif_altname))

export.bed(motifhits, opt$outfile )
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("-g", "--genekey"),
              type="character",
              help="Path to biomart derived genekey"),
  make_option(c("-e", "--expression"),
              type="character",
              help="Path to TPM expression matrix")
)

suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))

opt <- parse_args(OptionParser(option_list=option_list))

tpm_counts <- as.matrix(read.table(
  opt$expression,
  quote = "\"", 
  header=TRUE, 
  row.names = 1 ))


geneKey_GRCm38.p6 <- read.table(
  opt$genekey,
  header=TRUE,
  sep="\t")

tpm_counts_ext <- merge(as.data.frame(tpm_counts),
                        geneKey_GRCm38.p6, 
                        by.x="row.names", 
                        by.y="ensembl_gene_id", 
                        all.x=TRUE)


# compute the mean per condition
tpm_counts_ext <-
  tpm_counts_ext %>% 
  rowwise() %>%
  mutate(mean_dexlps=mean(c(LPS_Dex1_nascent, LPS_Dex2_nascent, LPS_Dex3_nascent))) %>%
  mutate(mean_lps=mean(c(LPS1_nascent, LPS2_nascent, LPS3_nascent ))) %>%
  mutate(mean_veh=mean(c(V1_nascent, V2_nascent )))


write.table(tpm_counts_ext[,c("Row.names","mean_veh")],
            file="results/current/abcmodel/expression/Veh_tpm.tsv",
            quote = FALSE,
            row.names = FALSE,
            col.names = FALSE,
            sep="\t")

write.table(tpm_counts_ext[,c("Row.names","mean_lps")],
            file="results/current/abcmodel/expression/LPS_tpm.tsv",
            quote = FALSE,
            row.names = FALSE,
            col.names = FALSE,
            sep="\t")

write.table(tpm_counts_ext[,c("Row.names","mean_dexlps")],
            file="results/current/abcmodel/expression/DexLPS_tpm.tsv",
            quote = FALSE,
            row.names = FALSE,
            col.names = FALSE,
            sep="\t")
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--ctss_pool1"), 
              type="character",
              help="Path for ctss file from FANTOM5 of pool 1"),
  make_option(c("--ctss_pool2"), 
              type="character",
              help="Path for ctss file from FANTOM5 of pool 2"),
  make_option(c("--liftoverchain"), 
              type="character",
              help="Path to liftover chain file for mm9 to mm10"),
  make_option(c("--gencode_mm9_geneanno"), 
              type="character",
              help="Path to genomic reference file for mm9"),
  make_option(c("--gencode_mm10_geneanno"), 
              type="character",
              help="GENCODE genomic reference for assembly mm10, prefiltered for gene entries"),
  make_option(c("--outdir"), 
              type="character",
              help="Output directory")
)
opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(BSgenome.Mmusculus.UCSC.mm9, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ChIPseeker, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(CAGEr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(rtracklayer, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(GenomicRanges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(org.Mm.eg.db, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(TxDb.Mmusculus.UCSC.mm10.knownGene, warn.conflicts=F, quietly=T))

outdir <- here(opt$outdir)

# Workflow is based on the CAGEr vignette
# https://www.bioconductor.org/packages/release/bioc/vignettes/CAGEr/inst/doc/CAGEexp.html


#----------------------   Import CAGE samples from BMDMs
#------------------------------------------------------------------------------------

# get URL for public samples, download and read necessariy columns into ctss file (see snakemake workflow)
# We want to import bone-marrow derived macrophage samples through CAGEr.
# After looking at list of available datasets we can decide what samples best fit our needs.
# Let's see what samples are available through FANTOM5
#data(FANTOM5mouseSamples)
#head(FANTOM5mouseSamples)
# The FANTOM5 dataframe holds descriptions of the samples and the url where they can be retrieved.
# There's an easy way to import samples that match a certain term into a CAGEset object.
#mac_samples <- FANTOM5mouseSamples[grep("macrophage, bone marrow derived",
#                                        FANTOM5mouseSamples[,"description"]),]

print("NOTE: reference genome for the public CAGE files is mm9!")

ce <- CAGEr::CAGEexp( genomeName = "BSgenome.Mmusculus.UCSC.mm9",
                      inputFiles = c(opt$ctss_pool1 ,opt$ctss_pool2),
                      inputFilesType = "ctss",
                      sampleLabels   = c("pool1","pool2")
)
# To actually read in the data into the object we use getCTSS() function, that will add an experiment called tagCountMatrix to the CAGEexp object.
ce <- CAGEr::getCTSS(ce)
ce

#------------------------------------------------------------------------------------
#----------------------   QC
#------------------------------------------------------------------------------------

ncbim37_anno <- rtracklayer::import.gff(opt$gencode_mm9_geneanno)

ce <- annotateCTSS(ce, ncbim37_anno)
colData(ce)[,c("librarySizes", "promoter", "exon", "intron", "unknown")]
plotAnnot(ce, "counts")

corr.m <- plotCorrelation2( ce, samples = "all"
                            , tagCountThreshold = 1, applyThresholdBoth = FALSE
                            , method = "pearson")

#------------------------------------------------------------------------------------
#----------------------   Get read clusters
#------------------------------------------------------------------------------------

print("Merging samples")
#Now we can merge them
ce <- mergeSamples(ce, mergeIndex = c(1,1), 
                   mergedSampleLabels = c("BMDM"))

# redo annotation since this gets reset during merging
ce <- annotateCTSS(ce, ncbim37_anno)

print("The total library size is:")
print(librarySizes(ce))

# Check if data follows a power law distribution
plotReverseCumulatives(ce, fitInRange = c(5, 3000), onePlot = TRUE)

print("Normalizing reads")
# Since we don't really care about making comparisons between different population we could prob just skip the normalization
# The fit range is chosen from the plot. We take the alpha from the ref distribution and set T to a million to get the tag count per million (TPM)
ce <- normalizeTagCount(ce, method = "powerLaw", fitInRange = c(5, 3000), alpha = 1.15, T = 1*10^6)
#mac_CAGEset@tagCountMatrix

print("Cluster the tags")
# After normalization we can cluster the tags.
# Clustering, only seems to work with the CAGEset object (due to some problems with the IRanges column)
# From the CAGEr vignette:
# "Transcription start sites are found in the promoter region of a gene and reflect the transcriptional activity of that promoter (Figure 5). TSSs in the close proximity of each other give rise to a functionally equivalent set of transcripts and are likely regulated by the same promoter elements. Thus, TSSs can be spatially clustered into larger transcriptional units, called tag clusters (TCs) that correspond to individual promoters. CAGEr supports three methods for spatial clustering of TSSs along the genome, two ab initio methods driven by the data itself, as well as assigning TSSs to predefined genomic regions:"

ce <- clusterCTSS(ce,
           threshold=1,
           thresholdIsTpm = TRUE,
           nrPassThreshold = 1,
           method="distclu",
           maxDist=20,
           removeSingletons = TRUE,
           keepSingletonsAbove = 3)

# Let's have a look what the result looks like
head(tagClustersGR(ce, sample = "BMDM"))

# calculate cumulative distribution for every tag cluster in each of the samples
ce <- cumulativeCTSSdistribution(ce, clusters = "tagClusters", useMulticore = T)
# determine the positions of selected quantiles
ce <- quantilePositions(ce, clusters = "tagClusters", qLow = 0.1, qUp = 0.9)

# How many tagclusters do we have in total?
length(tagClustersGR(ce, sample = "BMDM"))

# histogram of interquantile width
plotInterquantileWidth(ce, clusters = "tagClusters", tpmThreshold = 3, qLow = 0.1, qUp = 0.9)

print("Retrieving clusters as GenomicRanges")
clusters_gr <- tagClustersGR(ce, sample="BMDM")

#------------------------------------------------------------------------------------
#----------------------   Liftover coordinates to mm10
#------------------------------------------------------------------------------------

print("Liftover to mm10")

# * Now we can lift over the intervals to mm10
# * Annotate them with peakanno
# * pick the most highly expressed one for each gene

liftover <- function(peaks_gr_mm9){ #input is a GenomicRanges object in mm9 coordinates
  #lift peak locations from mm9 to mm10
  chain <- rtracklayer::import.chain(opt$liftoverchain)
  on.exit( close( file(opt$liftoverchain)) )

  peaks_gr_mm10 <- rtracklayer::liftOver(peaks_gr_mm9, chain)
  peaks_gr_mm10 <- GenomicRanges::GRanges(unlist(peaks_gr_mm10))

  return(peaks_gr_mm10)
}

mac_cage_mm10 <- liftover( clusters_gr )
ggplot(as.data.frame(mac_cage_mm10), aes(x=width)) +
  geom_histogram(bins = 100)

# Liftover coordinates of dominant_ctss
dominant_ctss <- liftover( 
  GRanges(
    seqnames = seqnames(clusters_gr), 
    ranges = IRanges(start = clusters_gr$dominant_ctss,
                     end = clusters_gr$dominant_ctss),
    score=clusters_gr$score)
)

#------------------------------------------------------------------------------------
#-----------------   Annotate TSS clusters to reference gene coordinates
#------------------------------------------------------------------------------------
print("Annotate TSS coordinates")
# Use coordinates of the dominant ctss downstream

mac_cage_anno <- ChIPseeker::annotatePeak(dominant_ctss, 
                                          tssRegion=c(-1000, 1000), #more stringent than default
                                          level = "gene",
                                          TxDb=TxDb.Mmusculus.UCSC.mm10.knownGene, 
                                          annoDb = "org.Mm.eg.db")

# For those that are reasonably close to a TSS,
# check for each gene, which position has the highest score.

mac_cage_maxscore <- as.data.frame(mac_cage_anno) %>% 
  filter(abs(distanceToTSS)<=30000) %>%
  mutate(SYMBOL=as.factor(SYMBOL)) %>%
  filter(SYMBOL!="") %>%
  group_by(SYMBOL)%>%
  filter(score == max(score))%>%
  filter(distanceToTSS == min(distanceToTSS )) # for tied score, use shorter distance

nrow(mac_cage_maxscore)

ggplot(mac_cage_maxscore, aes(x=distanceToTSS)) +
  geom_histogram(bins = 100)

#------------------------------------------------------------------------------------
#----------   retrieve gene coordinates and promoterregion from reference
#------------------------------------------------------------------------------------

gencode_mm10_geneanno <- rtracklayer::import.gff(opt$gencode_mm10_geneanno)
genecoords <- as.data.frame(gencode_mm10_geneanno) %>%
  dplyr::select("seqnames","start","end","strand","gene_id") %>%
  mutate(score=0) %>%
  dplyr::mutate(gene_id=gsub("\\.[0-9]*$","",gene_id)) %>%
  dplyr::filter(!"gene_id"=="")%>%
  dplyr::select("seqnames","start","end","gene_id","score","strand")


gencode_mm10_promoterregions <- promoters(gencode_mm10_geneanno)
gencode_mm10_promoterregions <- as.data.frame(gencode_mm10_promoterregions) %>%
  dplyr::select("seqnames","start","end","strand","gene_id") %>%
  mutate(score=0) %>%
  dplyr::mutate(gene_id=gsub("\\.[0-9]*$","",gene_id)) %>%
  dplyr::filter(!"gene_id"=="")%>%
  dplyr::select("seqnames","start","end","gene_id","score","strand")

#------------------------------------------------------------------------------------
#-----------------   export files
#------------------------------------------------------------------------------------

write.table(genecoords, 
            file = paste0(outdir,"reference_genecoords.bed"),
            sep="\t", 
            col.names = FALSE,
            quote=FALSE,
            row.names = FALSE)

write.table(gencode_mm10_promoterregions, 
            file = paste0(outdir,"reference_promoterregions.bed"),
            sep="\t", 
            col.names = FALSE,
            quote=FALSE,
            row.names = FALSE)


rtracklayer::export.bed(as.data.frame(mac_cage_mm10),
                        paste0(outdir, "mac_cage_tssclusterregions.bed"),
                        format="bed")

rtracklayer::export.bed(as.data.frame(dominant_ctss),
                        paste0(outdir, "mac_cage_dominant_ctss.bed"),
                        format="bed")

rtracklayer::export.bed(mac_cage_maxscore,
                        paste0(outdir,"mac_cage_maxscore.bed"),
                        format="bed")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--summit_granges"),
              type="character",
              help="Path to rds file of summits in granges format with directionschange and distancetoTSS as additional metadata columns"),
  make_option(c("--memedb_expressed"),
              type="character",
              help="Path to memedb file filtered for motifs where TFs are expressed in 4sU"))

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(memes, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(universalmotif, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(GenomicRanges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(BSgenome.Mmusculus.UCSC.mm10, warn.conflicts=F, quietly=T))

#-------------------------------
## Import reference for sequence
#-------------------------------
mm.genome <- BSgenome.Mmusculus.UCSC.mm10

#-------------------------------
## read in prepared data
#-------------------------------

ChIPseq_summit_Granges <- readRDS(opt$summit_granges)

# Take 100bp windows around ChIP-seq summits
summit_flank_100bp <- ChIPseq_summit_Granges %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 100) 

# Take 100bp windows around ChIP-seq summits
summit_flank_1000bp <- ChIPseq_summit_Granges %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 1000) 

meme_db_expressed <- readRDS(opt$memedb_expressed)


# to_list() converts the database back from data.frame format to a standard `universalmotif` object.
options(meme_db = to_list(meme_db_expressed, extrainfo = FALSE))

# where is meme installed 
my_memepath="~/software/meme/bin/"
check_meme_install(meme_path=my_memepath)

summit_flank_100bp_seq <- summit_flank_100bp %>%
  get_sequence(mm.genome)

summit_flank_1000bp_seq <- summit_flank_1000bp %>%
  get_sequence(mm.genome)


#-------------------------------
## run fimo
#-------------------------------

fimo_results <-
  runFimo(summit_flank_1000bp_seq,
          meme_db_expressed,
          meme_path=my_memepath)

saveRDS (fimo_results, here("results/current/memes_bioc/fimo_1000bp/fimo.rds") )

print("Finished running fimo")
print("Analysis DONE")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--ABC_all"), 
              type="character",
              help="path to abc results of dexlps condition"),
  make_option(c("--memedb_expressed"),
              type="character",
              help="Path to memedb file filtered for motifs where TFs are expressed in 4sU"),
  make_option(c("--output"),
              type="character",
              help="fimo results file")
  )

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(memes, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(universalmotif, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(GenomicRanges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(BSgenome.Mmusculus.UCSC.mm10, warn.conflicts=F, quietly=T))

#-------------------------------
## Import reference for sequence
#-------------------------------
mm.genome <- BSgenome.Mmusculus.UCSC.mm10

#-------------------------------
## read in prepared data
#-------------------------------
ABC_all <- read.delim(opt$ABC_all) %>% plyranges::as_granges(., seqnames=chr)

# no need to run fimo a bunch of times on the same enhancers regions, just because they are listed more than once (with different ABCscores)
ABC_unique <- unique(ABC_all)

meme_db_expressed <- readRDS(opt$memedb_expressed)

# to_list() converts the database back from data.frame format to a standard `universalmotif` object.
options(meme_db = to_list(meme_db_expressed, extrainfo = FALSE))

# where is meme installed 
my_memepath="~/software/meme/bin/"
check_meme_install(meme_path=my_memepath)

#-------------------------------
## get sequences
#-------------------------------

enhancer_seq <- ABC_unique %>%
  get_sequence(mm.genome)

#-------------------------------
## run fimo
#-------------------------------

# conda activate py_3
# perlbrew use perl-5.34.0
# nohup Rscript memes_runanalyses_ABCenhancerregions.r & (from within the script directory)

fimo_results <-
  runFimo(enhancer_seq,
          meme_db_expressed,
          meme_path=my_memepath)

print("Finished running fimo")

saveRDS (fimo_results, opt$output)

print("Done saving results")
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--summit_granges"),
              type="character",
              help="Path to rds file of summits in granges format with directionschange and distancetoTSS as additional metadata columns"),
  make_option(c("--memedb_expressed"),
              type="character",
              help="Path to memedb file filtered for motifs where TFs are expressed in 4sU"))

opt <- parse_args(OptionParser(option_list=option_list))

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(memes, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(universalmotif, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(GenomicRanges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(BSgenome.Mmusculus.UCSC.mm10, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))

#-------------------------------
## Import reference for sequence
#-------------------------------
mm.genome <- BSgenome.Mmusculus.UCSC.mm10

#-------------------------------
## read in prepared data
#-------------------------------

ChIPseq_summit_Granges <- readRDS(opt$summit_granges)

# Take 100bp windows around ChIP-seq summits
summit_flank_100bp <- ChIPseq_summit_Granges %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 100) 

# Take 100bp windows around ChIP-seq summits
summit_flank_1000bp <- ChIPseq_summit_Granges %>% 
  plyranges::anchor_center() %>% 
  plyranges::mutate(width = 1000) 

meme_db_expressed <- readRDS(opt$memedb_expressed)

# to_list() converts the database back from data.frame format to a standard `universalmotif` object.
options(meme_db = to_list(meme_db_expressed, extrainfo = FALSE))

# where is meme installed 
my_memepath="~/software/meme/bin/"
check_meme_install(meme_path=my_memepath)

#-------------------------------
# define inputs
#-------------------------------

summit_flank_100bp_seq <- summit_flank_100bp %>%
  get_sequence(mm.genome)

summit_flank_1000bp_seq <- summit_flank_1000bp %>%
  get_sequence(mm.genome)

summit_flank_seq_bydirchange <- summit_flank_100bp %>%
  # remove unchanged ones and only compare "up" vs "down"
  filter(directionchange !="ns")%>%
  # Get a list of chip peaks belonging to each set
  split(mcols(.)$directionchange) %>%
  # look up the DNA sequence of each peak within each group
  get_sequence(mm.genome)

#-------------------------------
## up vs downregulation
# run by directionchange to discover consensus motif separately
#-------------------------------

#-------------------------------
# STREME
#-------------------------------

print("Start running streme for 100bp")

stremeout_100bp_down <-  here("results/current/memes_bioc/streme_100bp_down/streme.xml")
if (!file.exists( stremeout_100bp_down )){
  runStreme(summit_flank_seq_bydirchange[["down"]], control="shuffle", objfun="de",
            meme_path="~/software/meme/bin/", silent=FALSE,
            outdir = dirname(stremeout_100bp_down))
}

stremeout_100bp_up <- here("results/current/memes_bioc/streme_100bp_up/streme.xml")
if (!file.exists( stremeout_100bp_up )){
  runStreme(summit_flank_seq_bydirchange[["up"]], control="shuffle", objfun="de",
            meme_path="~/software/meme/bin/",
            outdir = dirname(stremeout_100bp_up))
}

print("Finished running streme for up- and down-regions")


#-------------------------------
# DREME
#-------------------------------

dremeout_100bp_down <- here("results/current/memes_bioc/dreme_100bp_down/dreme.xml")
if (!file.exists(dremeout_100bp_down)){
  runDreme(summit_flank_seq_bydirchange[["down"]], "shuffle",
           meme_path="~/software/meme/bin/",
           outdir = dirname(dremeout_100bp_down))
  }

dremeout_100bp_up <- here("results/current/memes_bioc/dreme_100bp_up/dreme.xml")
if (!file.exists(dremeout_100bp_up)){
  runDreme(summit_flank_seq_bydirchange[["up"]], "shuffle",
           meme_path="~/software/meme/bin/",
           outdir = dirname(dremeout_100bp_up))
  }

print("Done running DREME")

#-------------------------------
## run ame - discriminative mode
#-------------------------------

# enriched in upregulated with "down" as control
ame_discr_up <- here("results/current/memes_bioc/ame_discr_up/ame.tsv")
if (!file.exists( ame_discr_up )){
  runAme(summit_flank_seq_bydirchange, control = "down",
         meme_path=my_memepath,
         outdir=dirname(ame_discr_up))
}
# enriched in downregulated with "up" as control
ame_discr_down <- here("results/current/memes_bioc/ame_discr_down/ame.tsv")
if (!file.exists(ame_discr_down)){
  runAme(summit_flank_seq_bydirchange, control = "up",
         meme_path=my_memepath,
         outdir=dirname(ame_discr_down))
}

print("Finished running ame in discriminative mode for direction of expressionchange")


#-------------------------------
## all summits
#-------------------------------

## run streme to discover consensus motif
#-------------------------------
#print("Starting streme 1000bp")
#stremeout_1000bp <- here("results/current/memes_bioc/streme_1000bp/streme.xml")
#if (!file.exists( stremeout_1000bp )){
#  runStreme(summit_flank_1000bp_seq, control="shuffle",
#            meme_path="~/software/meme/bin/",
#            outdir = dirname(stremeout_1000bp) )
#}

print("Starting streme 100bp for all summits")
stremeout_100bp <- here("results/current/memes_bioc/streme_100bp/streme.xml")
if (!file.exists( stremeout_100bp )){
  runStreme(summit_flank_100bp_seq, control="shuffle",
            meme_path="~/software/meme/bin/",
            outdir = dirname(stremeout_100bp) )
}
print("Finished running streme for 100bp summit regions")

# Option objfun="cd" does not seem to get passed on to streme
#print("Starting streme 1000bp with central enrichment")
#stremeout_cd_1000bp <- here("results/current/memes_bioc/streme_cd_1000bp/streme.xml")
#if (!file.exists( stremeout_cd_1000bp )){
#  runStreme(summit_flank_1000bp_seq[1:100], objfun="cd", control=NA,
#            meme_path="~/software/meme/bin/",
#            outdir = dirname(stremeout_cd_1000bp) )
#}
#print("Finished running streme for 1000bp summit regions")

print("Analysis DONE")
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c( "--contrast_DexLPSvLPS"),
              type="character",
              help="Path to annotated tsv file of DeSeq2 contrast of DexLPS vs LPS"),
  make_option(c("--assignment_summit_prox"),
              type="character",
              help="Path to rds file of proximity based assignment of peak summits to genes"),
  make_option(c("--assignment_summits_abcregion_dexlps"),
              type="character",
              help="Path to rds file of assignment of peak summits within abcregions to genes (in DexLPS condition)"),
  make_option(c("--assignment_summits_abcregion_lps"),
              type="character",
              help="Path to rds file of assignment of peak summits within abcregions to genes (in LPS condition)"),
  make_option(c("--assignment_abcregion_dexlps"),
              type="character",
              help="Path to rds file of assignment of abcregions to genes (in DexLPS condition)"),
  make_option(c( "--assignment_abcregion_lps"),
              type="character",
              help="Path to rds file of assignment of abcregions to genes (in LPS condition)"),
  make_option(c("--motifcounts_summitregion"),
              type="character",
              help="Path to rds file of fimo motifcounts within summitregions"),
  make_option(c("--motifcounts_abcregion_dexlps"),
              type="character",
              help="Path to rds file of fimo motifcounts within ABC regions (in DexLPS condition)"),
  make_option(c("--motifcounts_abcregion_lps"),
              type="character",
              help="Path to rds file of fimo motifcounts within ABC regions (in LPS condition)"),
  make_option(c("--model_coefs_joint"),
              type="character",
              help="Path to rds file with model coefficients of joint models"),
  make_option(c("--model_coefs_sep"),
              type="character",
              help="Path to rds file with model coefficients of models tha include enhancers and promoters separately"),
  make_option(c( "--featuredir"),
              type="character",
              help="Path to directory with unscales featurematrizes"),
  make_option(c( "--outfile"),
              type="character",
              help="Path to output file with metrics")
)

opt <- parse_args(OptionParser(option_list=option_list))

dir.create(opt$featuredir)

#change default for stringAsFactors
options(stringsAsFactors = FALSE)

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plyranges, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(org.Mm.eg.db, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(DESeq2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ComplexHeatmap, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))

#set defaults for ggplot2 figures
theme_update(panel.background = element_rect(fill = "transparent", colour = NA),
             plot.background = element_rect(fill = "transparent", colour = NA),
             legend.background = element_rect(fill = "transparent", colour = NA),
             legend.key = element_rect(fill = "transparent", colour = NA),
             text=element_text(size=6, family = "ArialMT", colour="black"),
             title=element_text(size=8, family="ArialMT", colour="black"),
             panel.grid.major = element_line(colour="grey", size=0.2),
             panel.grid.minor = element_blank(),
             axis.text = element_text(size=6, family="ArialMT", colour="black"),
             axis.line = element_line(colour="black"),
             axis.ticks = element_line(colour="black"),
             legend.key.size = unit(6, 'points'), #change legend key size
             legend.key.height = unit(6, 'points'), #change legend key height
             legend.key.width = unit(6, 'points'), #change legend key width
             legend.text = element_text(size=6, family="ArialMT", colour="black"))

set.seed(12345)

#-------------------------------
## read in  data
#-------------------------------

contrast_DexLPSvLPS <- read.delim(opt$contrast_DexLPSvLPS)

for (optname in names(opt)[2:11]){ #except for the featuredir
  print(paste0("Loading ", optname))
  assign(optname, readRDS( opt[[optname]] ))
}

#--------------------------------------------
## ---- function definitions
#--------------------------------------------

coerce_coef2df <- function(model_coef){
  model_coef <- as.matrix(model_coef)
  model_coef <- as.data.frame(model_coef)
  model_coef$names <- rownames(model_coef)
  colnames(model_coef) <- c("estimates", "names")
  return(model_coef)
}

#------------function will------------:
# * merge the motifdata with gene assignments and 
# * then merge the gene expression changes,
# * filter for DE genes and aggregate per gene
#--------------------------------------
merge_motifdata_with_assignments <- function( motifcounts, assignments, contrast, 
                                              maxonly=FALSE, excludepromoters=FALSE, weightby=FALSE, sepPromEnh=FALSE){

  # check if we should use all abc assignments, or only the max one of each peakID
  if(maxonly==TRUE){
    assignments <- assignments %>% group_by(name) %>% filter(abcscore==max(abcscore)) %>% distinct()
  } else{
    assignments <- assignments
  }

  if(excludepromoters=="all"){
    assignments <- assignments %>% filter(!class=="promoter")
  } else if (excludepromoters=="onlyNONself"){
    assignments <- assignments %>% filter(!c(class=="promoter" & isSelfPromoter=="False"))
  } else{
    assignments <- assignments
  }

  motifdf <- merge(motifcounts, assignments, 
                   by.x="name", by.y="name")

  motifdf <- motifdf %>% relocate(c(anno))

  # merge the expression change
  # use mgi_symbol for prox based, otherwise ensemblID
  # We DONT set all.x=TRUE because we don't care about predicting gene that aren't even expressed or that we don't have a clear label for
  if(maxonly=="prox"){
    motifdf <- merge(motifdf, contrast, 
                     by.x="anno", by.y="mgi_symbol")
  } else {
    motifdf <- merge(motifdf, contrast, 
                     by.x="anno", by.y="Row.names")
  }

  #recode the logFC and padj into a label (optionally through command line arguments)
  motifdf <- motifdf %>% 
    mutate(label=case_when(log2FoldChange>0.58 & padj < 0.05 ~ "up",
                           log2FoldChange<(-0.58) & padj < 0.05 ~ "down",
                           TRUE ~ "no_change")) %>%
    filter(label!="no_change") %>%
    mutate(label=factor(label,
                        levels=c("down","up"),
                        labels=c(0,1))) %>%
    relocate(label)

  # chr 2, 3 and 4 (20%) were used as the tuning set for hyperparameter tuning. 
  # Regions from chromosomes 1, 8 and 9 (20%) were used as the test set for performance evaluation 
  # The remaining regions were used for model training.

  #------aggregate over gene SYMBOL
  if ("abcscore" %in% colnames(motifdf)) { # loop for ABC based assignments

    if (weightby=="abcscore"){
      unselect_col <- "abcnumerator"
    } else if(weightby=="abcnumerator") {
      unselect_col <- "abcscore"
    } else{
      unselect_col <- c("abcscore","abcnumerator")
    }

    if (sepPromEnh==TRUE){
      motifdf_aggr <-
        motifdf %>% 
        dplyr::select(!c(unselect_col,"name","baseMean","log2FoldChange","lfcSE","stat","pvalue","padj","gene_biotype","mgi_symbol")) %>%
        { if(weightby!=FALSE) mutate(.,across(where(is.numeric), ~ (.x * get(weightby)))) else .} %>% # weight features by score
        dplyr::select(!any_of(as.character(weightby))) %>% # then we can drop the score since it will be nonsensical after the aggregation anyways
        group_by(label,seqnames,anno,class) %>%
        dplyr::summarise(across( where(is.numeric), .fns=sum )) %>% # sum up genewise feature counts
        ungroup()

      # From here we need to cast the motifcounts for the promoterregions, so that in the end we have one row per gene (instead of 1-2)
      motifdf_aggr <- motifdf_aggr %>% tidyr::pivot_wider(id_cols=c(label,seqnames,anno), 
                                                          names_from=class, 
                                                          values_from = !c(label,seqnames,anno, class),
                                                          values_fill = 0)
    } else {
      motifdf_aggr <-
        motifdf %>% 
        dplyr::select(!c(unselect_col,"name","baseMean","log2FoldChange","lfcSE","stat","pvalue","padj","gene_biotype","mgi_symbol")) %>%
        { if(weightby!=FALSE) mutate(., across(where(is.numeric), ~ (.x * get(weightby)))) else .} %>% # weight features by score
        dplyr::select(!any_of(as.character(weightby))) %>% # then we can drop the score since it will be nonsensical after the aggregation anyways
        group_by(label,seqnames,anno) %>%
        dplyr::summarise(across( where(is.numeric), .fns=sum )) %>% # sum up genewise feature counts
        ungroup()
    }


  } else { # loop for prox based assignments
    motifdf_aggr <-
      motifdf %>% 
      dplyr::select(!c("name","baseMean","log2FoldChange","lfcSE","stat","pvalue","padj","gene_biotype")) %>% 
      group_by(label,seqnames,anno) %>%
      dplyr::summarise(across( where(is.numeric), .fns=sum )) %>% # sum up genewise feature counts
      ungroup()
  }

  return(motifdf_aggr)

}

get_feature_and_label_metrics <- function(motifdf, trainvalidx, genenames){

  targets_train <- motifdf[ trainvalidx, ] %>% pull(label) %>% as.numeric(levels(.))[.] %>% as.matrix()
  targets_test <- motifdf[ -trainvalidx, ] %>% pull(label) %>% as.numeric(levels(.))[.] %>% as.matrix()

  metrics = data.frame(
    n_input_features = ncol( motifdf[ , -c(1,2,3)]),# first three columns are labels, chromosome and gene annotation
    n_neg_inst_train = table(targets_train)[['0']],
    n_pos_inst_train = table(targets_train)[['1']],
    n_neg_inst_test = table(targets_test)[['0']],
    n_pos_inst_test = table(targets_test)[['1']]
  )

  return(metrics)
}

#------------------------------------------------
## initialize object to gather all metrics
#------------------------------------------------
all_metrics=data.frame(
  n_input_features=numeric(),
  n_neg_inst_train=numeric(),
  n_pos_inst_train=numeric(),
  n_neg_inst_test=numeric(),
  n_pos_inst_test=numeric()
)
#------------------------------------------------
## run proximity based
#------------------------------------------------

#---------------------- 
# This is independent of the ABC results (no need to loop through different assignment variations)

print("Getting metrics of prox-based model")
my_rdsfile <- paste0(opt$featuredir,"prox.rds")
if(!file.exists(my_rdsfile)){

  motifdata_aggr_prox <- merge_motifdata_with_assignments(motifcounts_summitregion,
                                                     assignment_summit_prox,
                                                     contrast_DexLPSvLPS,
                                                     maxonly="prox",
                                                     excludepromoters=FALSE,
                                                     weightby = FALSE,
                                                     sepPromEnh = FALSE)

  saveRDS(motifdata_aggr_prox,file=my_rdsfile)
} else{
  motifdata_aggr_prox <- readRDS(my_rdsfile)
}

motifdata_aggr_prox_scaled <- motifdata_aggr_prox %>% mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector)))
motifdata_aggr_prox_tranval_idx <- motifdata_aggr_prox_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))
metrics_prox <- get_feature_and_label_metrics (motifdata_aggr_prox_scaled, motifdata_aggr_prox_tranval_idx, genenames=genenames)

all_metrics <- rbind(all_metrics,
                     "prox"=metrics_prox)


#---------------------- 

not_all_na <- function(x) any(!is.na(x))

for (motifdata in c("motifcounts_abcregion","motifcounts_summitregion")){
  for(excludepromoters in c(FALSE,"all","onlyNONself")){
    for (onlymax in c(TRUE,FALSE)){
      for (sepPromEnh in c(TRUE,FALSE)){
        for (weight in c(FALSE, "abcscore")){

          # set assignments fitting for the input data
          if(motifdata=="motifcounts_abcregion"){
            assignment_dexlps <- assignment_abcregion_dexlps
            assignment_lps <- assignment_abcregion_lps
            motifcounts_dexlps <- motifcounts_abcregion_dexlps
            motifcounts_lps <- motifcounts_abcregion_lps
          } else if (motifdata=="motifcounts_summitregion" ){
            # in this case the motifcounts for the 2 conditions are the same, but there assignments differ
            assignment_dexlps <- assignment_summits_abcregion_dexlps
            assignment_lps <- assignment_summits_abcregion_lps
            motifcounts_dexlps <- motifcounts_summitregion
            motifcounts_lps <- motifcounts_summitregion
          } else {break}

          #-----------------------DEXLPS------------------------------
          modelname <- paste(motifdata,"condition_dexlps_exclprom",excludepromoters,"onlymax",onlymax,"sepPromEnh",sepPromEnh,"weight",weight, sep="_")
          print(modelname)

          my_rdsfile <- here( paste0(opt$featuredir, modelname,".rds"))
          if(!file.exists(my_rdsfile)){
            featurematrix_dexlps <- merge_motifdata_with_assignments(motifcounts_dexlps,
                                                                   assignment_dexlps,
                                                                   contrast_DexLPSvLPS,
                                                                   weightby=weight, 
                                                                   maxonly=onlymax, 
                                                                   excludepromoters=excludepromoters, 
                                                                   sepPromEnh=sepPromEnh)

            saveRDS(featurematrix_dexlps, my_rdsfile)
          } else{
            featurematrix_dexlps <- readRDS(my_rdsfile)
          }
          # remove columns that are NA after scaling
          featurematrix_dexlps_scaled <- featurematrix_dexlps %>%
            mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector))) %>%
            dplyr::select(where(not_all_na))
          motifdata_aggr_tranval_idx <- featurematrix_dexlps_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))
          new_metric <- get_feature_and_label_metrics (featurematrix_dexlps_scaled, motifdata_aggr_tranval_idx, genenames=genenames)

          all_metrics <- rbind(all_metrics,
                               new_metric)%>%
            magrittr::set_rownames(c(rownames(all_metrics),modelname))

          #--------------------------LPS---------------------------
          modelname <- paste(motifdata,"condition_lps_exclprom",excludepromoters,"onlymax",onlymax,"sepPromEnh",sepPromEnh,"weight",weight, sep="_")
          print(modelname)

          my_rdsfile <- here(paste0(opt$featuredir, modelname,".rds"))
          if(!file.exists(my_rdsfile)){
            featurematrix_lps <- merge_motifdata_with_assignments(motifcounts_lps,
                                                                assignment_lps,
                                                                contrast_DexLPSvLPS,
                                                                weightby=weight, 
                                                                maxonly=onlymax, 
                                                                excludepromoters=excludepromoters, 
                                                                sepPromEnh=sepPromEnh)

            saveRDS(featurematrix_lps,file=my_rdsfile)
          } else{
            featurematrix_lps <- readRDS(my_rdsfile)
          }
          featurematrix_lps_scaled <- featurematrix_lps %>% 
            mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector))) %>%
            dplyr::select(where(not_all_na))
          motifdata_aggr_tranval_idx <- featurematrix_lps_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))
          new_metric <- get_feature_and_label_metrics (featurematrix_lps_scaled, motifdata_aggr_tranval_idx, genenames=genenames)

          all_metrics <- rbind(all_metrics,
                               new_metric)%>%
            magrittr::set_rownames(c(rownames(all_metrics),modelname))

          #-----------------------DIFFERENCE------------------------------

          modelname <- paste(motifdata,"condition_DexLPS-LPS_exclprom",excludepromoters,"onlymax",onlymax,"sepPromEnh",sepPromEnh,"weight",weight, sep="_")
          print(modelname)
          my_rdsfile <- here(paste0(opt$featuredir, modelname,".rds"))
          if(!file.exists(my_rdsfile)){
            # they contain the same motifs, but not the same genes.
            # doublecheck that all columnnames are identical
            table(colnames(featurematrix_dexlps) == colnames(featurematrix_lps))

            #  motifcounts missing in one condition should be set to 0 
            merged_featurematrix <- merge(featurematrix_dexlps,
                                        featurematrix_lps, 
                                        by=c("anno","label","seqnames"),
                                        all=TRUE)
            # replace missing counts in one of the conditions with 0
            merged_featurematrix[is.na(merged_featurematrix)] <- 0

            # use dataframe suffix to grab respective columns
            featurematrix_diff <- 
              merged_featurematrix[grep(".x$",colnames(merged_featurematrix))] - 
              merged_featurematrix[grep(".y$",colnames(merged_featurematrix))] 
            # tidy up column names
            colnames(featurematrix_diff) <- gsub(".x$","", colnames(featurematrix_diff))

            # add first 3 columns back after computing the difference of the counts
            featurematrix_diff <- cbind(merged_featurematrix[1:3],featurematrix_diff)

            saveRDS(featurematrix_diff,file=my_rdsfile)
          } else{
            featurematrix_diff <- readRDS(my_rdsfile)
          }
          featurematrix_diff_scaled <- featurematrix_diff %>% 
            mutate(., across(where(is.numeric), ~(scale(.) %>% as.vector))) %>%
            dplyr::select(where(not_all_na))
          # run GLM and look at performance  
          featurematrix_diff_tranval_idx <- featurematrix_diff_scaled %>% with(which(seqnames!="chr1" & seqnames!="chr8" & seqnames!="chr9"))
          new_metric <- get_feature_and_label_metrics (featurematrix_diff_scaled, featurematrix_diff_tranval_idx, genenames=genenames)

          all_metrics <- rbind(all_metrics,
                               new_metric)%>%
            magrittr::set_rownames(c(rownames(all_metrics),modelname))


        }
      }
    }
  }
}

all_metrics <- all_metrics %>%
  mutate(ratio_pos_inst_train = n_pos_inst_train/(n_pos_inst_train+n_neg_inst_train),
         ratio_pos_inst_test = n_pos_inst_test/(n_pos_inst_test+n_neg_inst_test)
         )

# let'S add the number of non-zero coefficients to this
model_coefs_joint <- readRDS( opt$model_coefs_joint )
model_coefs_sep <- readRDS( opt$model_coefs_sep )

nonzero_columentries <- rbind ( colSums(model_coefs_joint != 0, na.rm=TRUE) %>% as.data.frame(),
                            colSums(model_coefs_sep != 0, na.rm=TRUE) %>% as.data.frame() )
colnames(nonzero_columentries) <- "n_sel_features_inclintercept"

all_metrics <- merge(all_metrics, nonzero_columentries, by="row.names") %>% 
  relocate(n_sel_features_inclintercept, .after = n_input_features )


# parse feature engineering choices from modelname and add them as variables
all_metrics <- all_metrics %>%
  mutate(condition = case_when(grepl("condition_lps", Row.names) ~ "LPS",
                              grepl("condition_DexLPS-LPS", Row.names) ~ "Dex+LPS - LPS",
                              grepl("condition_dexlps", Row.names) ~ "Dex+LPS"),
         input_region = case_when(grepl("motifcounts_summitregion", Row.names) ~ "GR summitregions",
                                  grepl("motifcounts_abcregion", Row.names) ~ "active regions"),
         excludepromoters = case_when(grepl("exclprom_all", Row.names) ~ "all",
                                      grepl("exclprom_onlyNONself", Row.names) ~ "nonself",
                                      grepl("exclprom_FALSE", Row.names) ~ "none"),
         mapping = case_when(grepl("onlymax_FALSE", Row.names) ~ "1-to-many (ABC-based)",
                             grepl("onlymax_TRUE", Row.names) ~ "1-to-1 (ABC-based)"),
         weight = case_when(grepl("weight_abcscore", Row.names) ~ "abcscore",
                             grepl("weight_FALSE", Row.names) ~ "none"),
         prom_and_enh_features = case_when(grepl("sepPromEnh_TRUE", Row.names) ~ "separate",
                                      grepl("sepPromEnh_FALSE", Row.names) ~ "aggregate")

         )
# manually update choices for the reference model
all_metrics <- all_metrics %>%
  rows_update( tibble(Row.names = "prox", 
                      condition="Dex+LPS",
                      input_region="GR summitregions",
                      mapping="1-to-1 (proximity-based)",
                      weight="none"), 
               by = "Row.names")

summary(all_metrics)

summary(all_metrics$ratio_pos_inst_train-all_metrics$ratio_pos_inst_test)

write.table(all_metrics,
            file=opt$outfile,
            quote=FALSE, sep="\t", row.names = FALSE, col.names = TRUE )
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
set -eo pipefail

# for the input samples
indir_ctrl=$1
indir_samples=$2
outdir=$3

ln -s "$(realpath $indir_ctrl/GAR0517/fastq/GAR0517_BC7FEMANXX_AGTCAA_L007_R1_001.fastq.gz)" $outdir/input_rep1_R1.fastq.gz
ln -s "$(realpath $indir_ctrl/GAR0517/fastq/GAR0517_BC7FEMANXX_AGTCAA_L007_R2_001.fastq.gz)" $outdir/input_rep1_R2.fastq.gz
ln -s "$(realpath $indir_ctrl/Sample_MUC9117/MUC9117_R1_merged.fastq.gz)" $outdir/input_rep2_R1.fastq.gz
ln -s "$(realpath $indir_ctrl/Sample_MUC9117/MUC9117_R2_merged.fastq.gz)" $outdir/input_rep2_R2.fastq.gz
ln -s "$(realpath $indir_ctrl/Sample_MUC9118/MUC9118_R1_merged.fastq.gz)" $outdir/input_rep3_R1.fastq.gz
ln -s "$(realpath $indir_ctrl/Sample_MUC9118/MUC9118_R2_merged.fastq.gz)" $outdir/input_rep3_R2.fastq.gz
ln -s "$(realpath $indir_ctrl/Sample_GAR1531/GAR1531_S13_L002_R1_001.fastq.gz)" $outdir/input_rep4_R1.fastq.gz
ln -s "$(realpath $indir_ctrl/Sample_GAR1531/GAR1531_S13_L002_R2_001.fastq.gz)" $outdir/input_rep4_R2.fastq.gz

# for the GR 2020 GR samples
ln -s "$(realpath $indir_samples/Sample_MUC20387/MUC20387_S6_R1_001.fastq.gz)" $outdir/DexLPS_chipseq_GR_rep1_R1.fastq.gz
ln -s "$(realpath $indir_samples/Sample_MUC20387/MUC20387_S6_R2_001.fastq.gz)" $outdir/DexLPS_chipseq_GR_rep1_R2.fastq.gz
ln -s "$(realpath $indir_samples/Sample_MUC20388/MUC20388_S7_R1_001.fastq.gz)" $outdir/DexLPS_chipseq_GR_rep2_R1.fastq.gz
ln -s "$(realpath $indir_samples/Sample_MUC20388/MUC20388_S7_R2_001.fastq.gz)" $outdir/DexLPS_chipseq_GR_rep2_R2.fastq.gz
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
set -eo pipefail

# for the input samples
indir=$1
outdir=$2

ln -s "$(realpath $indir/GAR0814_S7_L002_R1_001.fastq.gz)" $outdir/LPS_histone_H3K27ac_rep1_R1.fastq.gz
ln -s "$(realpath $indir/GAR0814_S7_L002_R2_001.fastq.gz)" $outdir/LPS_histone_H3K27ac_rep1_R2.fastq.gz
ln -s "$(realpath $indir/GAR0815_S8_L002_R1_001.fastq.gz)" $outdir/LPS_histone_H3K27ac_rep2_R1.fastq.gz
ln -s "$(realpath $indir/GAR0815_S8_L002_R2_001.fastq.gz)" $outdir/LPS_histone_H3K27ac_rep2_R2.fastq.gz
ln -s "$(realpath $indir/GAR0816_S9_L002_R1_001.fastq.gz)" $outdir/DexLPS_histone_H3K27ac_rep1_R1.fastq.gz
ln -s "$(realpath $indir/GAR0816_S9_L002_R2_001.fastq.gz)" $outdir/DexLPS_histone_H3K27ac_rep1_R2.fastq.gz
ln -s "$(realpath $indir/GAR0823_S10_L002_R1_001.fastq.gz)" $outdir/DexLPS_histone_H3K27ac_rep2_R1.fastq.gz
ln -s "$(realpath $indir/GAR0823_S10_L002_R2_001.fastq.gz)" $outdir/DexLPS_histone_H3K27ac_rep2_R2.fastq.gz
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
suppressPackageStartupMessages(library(optparse, warn.conflicts=F, quietly=T))

option_list <- list(
  make_option(c("--gene_annot"),
              type="character",
              help="Path to gencode annotation used to retrieve promoter regions"),
  make_option(c("--binding_sites_remap"),
              type="character",
              help="Path to peaks from the 2022 mouse remap release filtered for macrophages"),
  make_option(c("--rna_nascent_fpkm"),
              type="character",
              help="Path to normalized expression counts of nascent samples"),
  make_option(c("--genekey"),
              type="character",
              help="Path to genekey used to map ensembl geneIDs to mgi symbols"),
  make_option(c("--cage"),
              type="character",
              help="Path to bed file with location of max score within each cage read cluster"),
  make_option(c("--outdir"),
              type="character",
              help="Path to output directory")
)

opt <- parse_args(OptionParser(option_list=option_list))

dir.create( opt$outdir )
# created the first time executing
ftfbs_tss_annot_rds <- paste0( opt$outdir, "tfbs_tss2000u200d_annot.rds")
ftfbs_tssCAGE_annot_rds <- paste0( opt$outdir, "tfbs_tssCAGE2000u200d_annot.rds")

suppressPackageStartupMessages(library(here, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(dplyr, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(ggplot2, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(plsgenomics, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(data.table, warn.conflicts=F, quietly=T))
suppressPackageStartupMessages(library(GenomicRanges, warn.conflicts=F, quietly=T))

# ------------------------------------------------------------------------------
print("Get TFBS to TSS assignments.")
# ------------------------------------------------------------------------------

# MAC specific TSS
mac_spec_tss <- rtracklayer::import.bed(opt$cage)
mac_spec_tss <- mac_spec_tss %>% 
  filter(!duplicated(mac_spec_tss$SYMBOL)) %>%
  plyranges::as_granges()

load_gene_annotation <- function(gene_annot) {

  # load gene annotation
  ga <- fread(gene_annot)

  # file format is: chr origin type start stop U strand U add_info
  colnames(ga) <- c("chr", "origin", "type", "start", "stop", "score", "strand",
                    "frame", "info")
  # extract ranges
  ra <- with(ga, GRanges(chr, IRanges(start, stop), strand))

  # extract the additional attributes and merge with ranges object
  attrs <- strsplit(ga$info, ";")
  gene_id <- sapply(attrs, function(x) { sapply(strsplit(x[grepl("gene_id",x)], " "), "[[", 2) })
  gene_name <- sapply(attrs, function(x) { sapply(strsplit(x[grepl("gene_name",x)], " "), "[[", 3) })
  gene_biotype <- sapply(attrs, function(x) { sapply(strsplit(x[grepl("gene_type",x)], " "), "[[", 3) })

  # remove any lingering quotes
  gene_id <- gsub("\"", "", gene_id)
  gene_name <- gsub("\"", "", gene_name)
  gene_biotype <- gsub("\"", "", gene_biotype)

  # add to ranges object
  names(ra) <- gene_id
  ra$SYMBOL <- gene_name
  ra$BIOTYPE <- gene_biotype

  # finally, filter out 'misc_RNA' types and unusual chromosomes
  ra <- ra[ra$BIOTYPE != "misc_RNA"]
  ra <- keepStandardChromosomes(ra)

  return(ra)
}

annotate_tfbs_to_tss <- function(binding_sites_remap,
                                 tss) {

  # get the TFBS regions from remap
  tfbs = rtracklayer::import(binding_sites_remap)

  ann = t(matrix(unlist(strsplit(values(tfbs)[,"name"], ",", fixed=T)), nrow=3))

  colnames(ann) = c("geo_id", "TF", "condition")

  values(tfbs) = DataFrame(name=values(tfbs)[,"name"],
                           data.frame(ann, stringsAsFactors=F))


  # create an annotation matrix for the TSS
  chip = paste(values(tfbs)[,"TF"], values(tfbs)[,"condition"], sep=".")
  chip_exp = unique(chip)

  tfbs_ann = sapply(chip_exp, function(x) overlapsAny(tss,
                                                      tfbs[chip == x]))
  rownames(tfbs_ann) = names(tss)

  return(tfbs_ann)
}

# TSS only from ref
#------------------
ga <- load_gene_annotation(opt$gene_annot)
tss <- promoters(ga, 2000, 200)
names(tss) <- tss$SYMBOL

tfbs_annot <- annotate_tfbs_to_tss(opt$binding_sites_remap, tss)
saveRDS(tfbs_annot, file=ftfbs_tss_annot_rds)

# TSS from CAGE and only from ref where we have none
#------------------

ga_noCAGE <- ga %>% filter(!SYMBOL %in% mac_spec_tss$SYMBOL)
# add info on those genes where we don't have mac specific TSS
tss_wCAGE <- c(mac_spec_tss,ga_noCAGE)
tss_wCAGE <- promoters(tss_wCAGE, 2000, 200)
names(tss_wCAGE) <- tss_wCAGE$SYMBOL
tfbs_annot_CAGE <- annotate_tfbs_to_tss(opt$binding_sites_remap, tss_wCAGE)
saveRDS(tfbs_annot_CAGE, file=ftfbs_tssCAGE_annot_rds)

# ------------------------------------------------------------------------------
print("Read in expression data.")
# ------------------------------------------------------------------------------

expr_fpkm <- read.table(opt$rna_nascent_fpkm, header=TRUE)
expr_fpkm_nototal <- expr_fpkm [ !grepl('total|Total', colnames(expr_fpkm))]

# ------------------------------------------------------------------------------
print("Get ensembl to MGI mapping")
# ------------------------------------------------------------------------------

geneKey <- read.delim(opt$genekey)

# ------------------------------------------------------------------------------
print("Change gene annotation from Ensembl to MGI")
# ------------------------------------------------------------------------------

expr <- merge(expr_fpkm_nototal, geneKey[,c("ensembl_gene_id", "mgi_symbol")],
              by.x='Geneid', by.y='ensembl_gene_id')

expr <- expr %>% filter(mgi_symbol!="")

# summarize the expression values for those mgi symbols that have multiple entries
expr <- expr %>% 
  group_by(mgi_symbol) %>% 
  summarise(across(2:(ncol(expr)-1), mean)) %>%
  tibble::column_to_rownames("mgi_symbol")

write.table(expr, file=paste0( opt$outdir,"FPKMcounts_mgiaggr.tsv"),
            row.names = TRUE,
            col.names = TRUE,
            sep = "\t",
            quote = FALSE)

# ------------------------------------------------------------------------------
print("Define annotation and data subsets.")
# ------------------------------------------------------------------------------
tfs <- unique(sapply(strsplit(colnames(tfbs_annot), "\\."), "[[", 1))

# one TF might have the same target measured more than once -> summarize
tss_annot_summarized <- sapply(tfs, function(tf) {
  rowSums(tfbs_annot[,grepl(paste0(tf, "\\."), colnames(tfbs_annot)), drop=F])
})

# get TFs and their targets (which targets are expressed)
targets <- intersect(rownames(tfbs_annot), rownames(expr))
# we skip the filtering step for TFS that are expressed, and work with all of them for now
# (partially because the genenames and TF protein names might not even match and we'll look at the results in more detail afterwards anyways)
#tf_sub <- tfs[tfs %in% rownames(expr)]

# get the annotation and data subsets
annot_sub <- tss_annot_summarized[targets,,drop=F]
#annot_sub <- annot_sub[, tf_sub]
data_sub <- expr[targets,]


# ------------------------------------------------------------------------------
print("Estimating TFAs using PLS/SIMPLS and substituting.")
# ------------------------------------------------------------------------------
TFA <- plsgenomics::TFA.estimate(annot_sub, data_sub)$TFA

rownames(TFA) <- colnames(annot_sub)
colnames(TFA) <- colnames(data_sub)


# ------------------------------------------------------------------------------
print("Saving results.")
# ------------------------------------------------------------------------------
write.table(file=paste0( opt$outdir, "TFA_4sU.tsv"), TFA,
            sep="\t", quote=FALSE, col.names = TRUE, row.names = TRUE)

# ------------------------------------------------------------------------------
print("Same steps with CAGE specific data")
# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------
print("Define annotation and data subsets.")
# ------------------------------------------------------------------------------
tfs_CAGE <- unique(sapply(strsplit(colnames(tfbs_annot_CAGE), "\\."), "[[", 1))

# one TF might have the same target measured more than once -> summarize
tss_CAGE_annot_summarized <- sapply(tfs_CAGE, function(tf) {
  rowSums(tfbs_annot_CAGE[,grepl(paste0(tf, "\\."), colnames(tfbs_annot_CAGE)), drop=F])
})

# get TFs and their targets (which targets are expressed)
targets_CAGE <- intersect(rownames(tfbs_annot_CAGE), rownames(expr))
# we skip the filtering step for TFS that are expressed, and work with all of them for now
# (partially because the genenames and TF protein names might not even match and we'll look at the results in more detail afterwards anyways)
#tf_sub <- tfs[tfs %in% rownames(expr)]

# get the annotation and data subsets
annot_CAGE_sub <- tss_CAGE_annot_summarized[targets_CAGE,,drop=F]
#annot_sub <- annot_sub[, tf_sub]
data_sub_CAGE <- expr[targets_CAGE,]


# ------------------------------------------------------------------------------
print("Estimating TFAs using PLS/SIMPLS and substituting.")
# ------------------------------------------------------------------------------
TFA_CAGE <- plsgenomics::TFA.estimate(annot_CAGE_sub, data_sub_CAGE)$TFA

rownames(TFA_CAGE) <- colnames(annot_CAGE_sub)
colnames(TFA_CAGE) <- colnames(data_sub_CAGE)


# ------------------------------------------------------------------------------
print("Saving results.")
# ------------------------------------------------------------------------------
write.table(file=paste0( opt$outdir, "TFA_4sU_CAGE.tsv"), TFA_CAGE,
            sep="\t", quote=FALSE, col.names = TRUE, row.names = TRUE)
21
22
23
24
25
26
27
28
shell:
    """
    mkdir -p {params.outdir} && \
    wget {params.link1} -P {params.outdir} && \
    zcat {params.temp_s1} | awk '{{print $1,$2,$6,$5}}' OFS='\t' - > {output.s1} && \
    wget {params.link2} -P {params.outdir} && \
    zcat {params.temp_s2} | awk '{{print $1,$2,$6,$5}}' OFS='\t' - > {output.s2}
    """
50
51
52
53
54
55
56
shell:
    """
    mkdir -p {params.outdir} && \
    Rscript src/scripts/get_TSS_from_cage.r --ctss_pool1 {input.ctss_pool1} --ctss_pool2 {input.ctss_pool2} \
    --liftoverchain {input.liftoverchain} --gencode_mm9_geneanno {input.gencode_mm9_geneanno} \
    --gencode_mm10_geneanno {input.gencode_mm10_geneanno} --outdir {params.outdir}
    """
64
65
66
67
68
shell:
    """
    wget https://hicfiles.tc4ga.com/public/juicer/juicer_tools.1.9.9_jcuda.0.8.jar -P src/ &&
    ln -s juicer_tools.1.9.9_jcuda.0.8.jar  src/juicer_tools.jar
    """ 
80
81
82
83
84
85
86
87
88
shell:
  """
  mkdir -p {params.outdir} && \
  python src/scripts/abcmodel/juicebox_dump.py \
  --hic_file {input.hic} \
  --juicebox "java -jar src/juicer_tools.jar" \
  --outdir {params.outdir} \
  --chromosomes 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,X
  """
100
101
102
103
104
105
106
107
108
109
shell:
  """
  python src/scripts/abcmodel/compute_powerlaw_fit_from_hic.py \
  --hicDir {params.hicdir} \
  --outDir {params.outdir} \
  --maxWindow 1000000 \
  --minWindow 5000 \
  --resolution 5000 \
  --chr $(echo chr{{1..19}} chrX | tr ' ' ,)
  """
119
120
121
122
123
shell:
    """
    mkdir -p results/current/atacseq/macs2/ && \
    bedtools sort -faidx {input.chromsizes} -i {input.narrowpeak} > {output}
    """
132
133
shell:
    "samtools merge {output} {input}/*.bam"
142
143
shell:
    "cat {input.mac_cage_tssclusterregions} {input.ref_promoterregions} {input.summitintervals_GR_ChIPseq} > {output}"
161
162
163
164
165
166
167
168
169
170
171
shell:
    """
    python src/scripts/abcmodel/makeCandidateRegions.py \
    --narrowPeak {input.narrowpeak_sorted} \
    --bam {input.atac_bam} \
    --outDir {params.outdir} \
    --chrom_sizes {input.chromsizes} \
    --regions_blocklist {input.blacklist} \
    --regions_includelist {input.includeregions} \
    --nStrongestPeaks 150000
    """
188
189
190
191
192
shell:
    """
    mkdir -p "results/current/abcmodel/expression/" && \
    Rscript src/scripts/get_TPM_condition_expression.r -g {input.genekey} -e {input.tpm}
    """
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
shell:
    """
    python src/scripts/abcmodel/predict.py \
    --enhancers {input.enhancerlist} \
    --genes {input.genelist} \
    --HiCdir {params.hic_dir} \
    --chrom_sizes {input.chromsizes} \
    --hic_resolution {params.hic_res} \
    --scale_hic_using_powerlaw \
    --threshold .02 \
    --cellType {params.celltype} \
    --outdir {params.outdir} \
    --make_all_putative \
    --chromosomes $(echo chr{{1..19}} chrX | tr ' ' ,)
    """
273
274
275
276
shell:
    """
    zcat {input} |awk '{{if ($21>=0.02 && $21!="NaN") {{print}}}}' FS='\\t' OFS='\t' > {output}
    """
291
292
293
294
295
296
297
shell:
    """
    mkdir -p $(dirname {output}) && \
    perlbrew use perl-5.34.0 && \
    Rscript src/scripts/memes_runanalyses_ABCenhancerregions.r \
    --ABC_all {input.abc} --memedb_expressed {input.memedb} --output {output.rds_fimo}
    """
 9
10
11
12
13
shell:
    """
    mkdir -p $(dirname {output}) && \
    cat {input} > {output}
    """
38
39
40
41
42
shell:
    """
    mkdir -p {params.outdir} && \
    sh src/scripts/symlink_GR_2020.sh {params.indir_ctrl} {params.indir_samples} {params.outdir}
    """
66
67
68
69
70
shell:
    """
    mkdir -p {params.outdir} && \
    sh src/scripts/symlink_histone_samples.sh {params.indir} {params.outdir}
    """
87
88
89
90
91
shell:
    """
    mkdir -p {params.outdir} && \
    sh src/scripts/symlink_test.sh {params.indir} {params.outdir}
    """
107
108
109
110
111
shell:
    "mkdir -p results/current/ChIP/{wildcards.exp}/fastq/trimmed; \
    cutadapt -m {params.minimum_fragment_length} \
    -a AGATCGGAAGAGCACACGTCT \
    -o {output} {input.fastq}"
126
127
shell:
    "multiqc results/current/logs results/current/ChIP/H3K27ac/QC --outdir results/current/ChIP/H3K27ac --force"  
147
148
149
150
151
152
153
shell:
    "mkdir -p results/current/logs && \
    mkdir -p results/current/ChIP/{wildcards.exp}/bam && \
    gzip -cd {input[fastq]} | bowtie -S -p {params.nworkers} --chunkmbs 512 \
    -k {params.alignments_reported} -m {params.multialignments_allowed} \
    -v {params.mismatches_allowed} {params.index} - | \
    samtools view -F 4 -Sbo {output} -"
174
175
176
177
178
179
180
shell:
    "mkdir -p results/current/logs && \
    mkdir -p $(dirname {output}) && \
    bowtie -S -p {params.nworkers} --chunkmbs 512 \
    -k {params.alignments_reported} -m {params.multialignments_allowed} \
    -v {params.mismatches_allowed} {params.index} \
    -1 {input[fa1]} -2 {input[fa2]} | samtools view -F 4 -Sbo {output} -"
196
197
198
199
200
201
202
203
204
shell:
    """
    mkdir -p {params.tempdir} && \
    mkdir -p {params.outdir} && \
    macs2 callpeak -t {input.sample} -c {input.control}\
    --tempdir {params.tempdir} --qvalue 0.05 \
    --keep-dup all --bdg --SPMR \
    -g mm -f BAM --outdir {params.outdir} -n {params.name}
    """
215
216
217
218
219
220
221
222
223
shell:
    """
    mkdir -p {params.tempdir} && \
    mkdir -p {params.outdir} && \
    macs2 callpeak -t {input.sample} --broad \
    --tempdir {params.tempdir} --qvalue 0.05 \
    --keep-dup all --bdg --SPMR \
    -g mm -f BAM --outdir {params.outdir} -n {params.name}
    """
241
242
243
244
245
246
shell:
    "mkdir -p $(dirname {output[0]}) && \
    mkdir -p {params.tempdir} && \
    macs2 callpeak -t {input[0]} -c {input[1]} {input[2]} {input[3]} {input[4]}\
    --tempdir {params.tempdir} --pvalue 0.1 \
    --keep-dup 1 --bdg -g mm -f BAMPE --outdir {params.outdir} -n {params.name}"
256
257
258
shell:
    "mkdir -p $(dirname {output}) && \
    idr --samples {input} --input-file-type narrowPeak --rank signal.value --idr-threshold 0.05 --output-file {output} --plot"
269
270
shell:
    "samtools merge {output} {input[0]} {input[1]}"
281
282
283
284
285
286
287
288
shell:
    """
    cat {input.peaks1} {input.peaks2} | bedtools sort -i stdin | bedtools merge -i stdin > {output.peakuniverse} && \
    echo {input.bam1} > {output.counts} && \
    samtools view -c -L {output.peakuniverse} {input.bam1} >> {output.counts} && \
    echo {input.bam2} >> {output.counts} && \
    samtools view -c -L {output.peakuniverse} {input.bam2} >> {output.counts}
    """
299
300
301
302
303
304
305
306
shell:
    """
    cat {input.peaks1} {input.peaks2} | bedtools sort -i stdin | bedtools merge -i stdin > {output.peakuniverse} && \
    echo {input.bam1} > {output.counts} && \
    samtools view -c -L {output.peakuniverse} {input.bam1} >> {output.counts} && \
    echo {input.bam2} >> {output.counts} && \
    samtools view -c -L {output.peakuniverse} {input.bam2} >> {output.counts}
    """
15
16
17
18
19
shell:
    """
    Rscript src/scripts/DE_visualizations_4sU.r -n {input.norm} -a {input.metadata} --contrast {input.contrast} \
    --log2fcthresh {params.log2fcthresh} -o {params.outdir}
    """
36
37
38
39
40
41
shell:
    """
    Rscript src/scripts/figure_chipseq_prepdata.r --chipseq_bam {input.bam} --chipseq_summits {input.summits} \
    --nr3c1fullsitematches {input.nr3c1fullsitematches} --nr3c1halfsitematches {input.nr3c1halfsitematches} \
    -o {params.outdir}
    """
66
67
68
69
70
shell:
    """
    Rscript src/scripts/figure_proxanno_prepdata.r --log2fcthresh {params.log2fcthresh} --chipseq_summits {input.summits} --genekey {input.genekey} \
    --contrast_DexVSDexLPS {input.contrast} --meme_db_path {input.meme_db} --rna_nascent_fpkm {input.rna_nascent_fpkm} -o {params.outdir}
    """
85
86
87
88
89
90
shell:
    """
    Rscript src/scripts/figure_chipseq_plot.r --summitAnno {input.summitAnno} --chipseq_peaks {input.bed} --chipseq_summits {input.summits} \
    --nr3c1fullsitematches {input.nr3c1fullsitematches} --nr3c1halfsitematches {input.nr3c1halfsitematches} \
    --sm_summitranges {input.genomation_scorematrix} --streme {input.streme}
    """
110
111
112
113
114
115
shell:
    """
    Rscript src/scripts/figure_proxanno_plot.r --summitAnno_expr {input.summitAnno_expr} --summitAnno_df_expr {input.summitAnno_df_expr} \
    --permtest_res {input.permtest_res} --fimo_results {input.fimo_results} --chipseq_summit_granges {input.chipseq_summit_granges} \
    --deeptools {input.deeptools} --streme_100bp_up {input.streme_100bp_up} --streme_100bp_down {input.streme_100bp_down}
    """
128
129
130
131
132
shell:
    """
    Rscript src/scripts/abc_visualizations.r --ABC_DexLPS_all {input.ABC_DexLPS_all} --ABC_LPS_all {input.ABC_LPS_all} \
    --contrast_DexVSDexLPS {input.contrast_DexVSDexLPS} --chipseq_summits {input.chipseq_summits} --igv {input.igv}
    """
157
158
159
160
161
162
shell:
    """
    Rscript src/scripts/abc_predictions_prepdata.r --ABC_DexLPS_all {input.ABC_DexLPS_all} --ABC_LPS_all {input.ABC_LPS_all} \
    --fimo_results_dexlps {input.fimo_results_dexlps} --fimo_results_lps {input.fimo_results_lps} \
    --fimo_results_summitregion {input.fimo_results_summitregion} --chipseq_ranges {input.chipseq_ranges} --outdir {params.outdir}
    """
186
187
188
189
190
191
192
shell:
    """
    Rscript src/scripts/abc_predictions.r --contrast_DexLPSvLPS {input.contrast_DexLPSvLPS} \
    --assignment_summit_prox {input.assignment_summit_prox} --assignment_summits_abcregion_dexlps {input.assignment_summits_abcregion_dexlps} --assignment_summits_abcregion_lps {input.assignment_summits_abcregion_lps} \
    --assignment_abcregion_dexlps {input.assignment_abcregion_dexlps} --assignment_abcregion_lps {input.assignment_abcregion_lps} \
    --motifcounts_summitregion {input.motifcounts_summitregion} --motifcounts_abcregion_dexlps {input.motifcounts_abcregion_dexlps} --motifcounts_abcregion_lps {input.motifcounts_abcregion_lps} --outdir {params.outdir}
    """
207
208
209
210
211
212
shell:
    """
    Rscript src/scripts/figure_GLMs.r --model_coefs_joint {input.model_coefs_joint} \
    --model_coefs_sep {input.model_coefs_sep} --auc {input.auc} \
    --motifcounts_summitregion {input.motifcounts_summitregion} --raw_counts {input.raw_counts}
    """
225
226
227
228
229
230
shell:
    """
    Rscript src/scripts/figure_supplemental_GLMs.r --auc {input.auc_metrics} \
    --dirname_featurematrizes {params.dirname_featurematrizes} \
    --dirname_models {params.dirname_models} --outfig {output.png}
    """
247
248
249
250
251
252
shell:
    """
    Rscript src/scripts/tf_activity_4sU.r --gene_annot {input.gene_annot} \
    --binding_sites_remap {input.binding_sites_remap} --rna_nascent_fpkm {input.rna_nascent_fpkm} \
    --genekey {input.genekey} --cage {input.cage} --outdir {params.outdir}
    """
268
269
270
271
272
shell:
    """
    Rscript src/scripts/figure_stats.r --tfactivity {input.tfactivity} --expr {input.expr} --difffootprint {input.difffootprint} \
    --memedb_expressed {input.memedb_expressed} --heatmap {input.heatmap} --chipms {input.chipms}
    """
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
shell:
    """
    Rscript src/scripts/quantify_features_and_label_distribution.r --contrast_DexLPSvLPS {input.contrast_DexLPSvLPS} \
    --assignment_summit_prox {input.assignment_summit_prox} \
    --assignment_summits_abcregion_dexlps {input.assignment_summits_abcregion_dexlps} \
    --assignment_summits_abcregion_lps {input.assignment_summits_abcregion_lps} \
    --assignment_abcregion_dexlps {input.assignment_abcregion_dexlps} \
    --assignment_abcregion_lps {input.assignment_abcregion_lps} \
    --motifcounts_summitregion {input.motifcounts_summitregion} \
    --motifcounts_abcregion_dexlps {input.motifcounts_abcregion_dexlps} \
    --motifcounts_abcregion_lps {input.motifcounts_abcregion_lps} \
    --model_coefs_joint {input.model_coefs_joint} \
    --model_coefs_sep {input.model_coefs_sep} \
    --featuredir {params.featuredir} --outfile {output}
    """  
37
38
39
40
41
shell:
    """
    mkdir -p {params.outdir} && \
    Rscript src/scripts/DE_analysis_4sU.r -c {input.counts} -a {input.metadata} -k 100 -o {params.outdir}
    """
61
62
63
64
65
66
shell:
    """
    Rscript src/scripts/custom_bw_libnorm.r \
    --bw_DexLPS_h3k27ac {input.bw_DexLPS_h3k27ac} --bw_LPS_h3k27ac {input.bw_LPS_h3k27ac} --counts_h3k27ac {input.counts_h3k27ac} \
    --bw_DexLPS_atac {input.bw_DexLPS_atac} --bw_LPS_atac {input.bw_LPS_atac} --counts_atac {input.counts_atac} --gtf {input.gtf}
    """
76
77
78
79
shell:
    """
    bigwigCompare --bigwig1 {input.bw1} --bigwig2 {input.bw2} -p 4 -o {output}
    """
89
90
91
92
shell:
    """
    bigwigCompare --bigwig1 {input.bw1} --bigwig2 {input.bw2} -p 4 -o {output}
    """
115
116
117
118
119
120
121
122
shell:
    """
    mkdir -p results/current/memes_bioc/ && \
    perlbrew use perl-5.34.0 && \
    Rscript src/scripts/memes_runanalyses.r \
    --summit_granges {input.summit_granges} --memedb_expressed {input.memedb_expressed} && \
    touch {output.done}
    """
135
136
137
138
139
140
141
shell:
    """
    mkdir -p $(dirname {output}) && \
    perlbrew use perl-5.34.0 && \
    Rscript src/scripts/memes_fimo_runanalyses.r \
    --summit_granges {input.summit_granges} --memedb_expressed {input.memedb_expressed}
    """
154
155
156
157
158
159
shell:
    """
    mkdir -p "results/current/integration/deeptools" &&
    computeMatrix reference-point --referencePoint center -b 1000 -a 1000 -bs 50 -R {input.tUP} {input.tDOWN} \
    -S {input.chipseq} {input.atac_diff} {input.h3k27ac_diff} -o {output}
    """
168
169
170
171
172
173
174
175
176
177
shell:
    """
    plotHeatmap -m {input} \
    --sortRegions descend --refPointLabel summit \
    --samplesLabel chipseq_DexLPS atac_diff h3k27ac_diff \
    --colorMap Greens RdYlBu_r RdYlBu_r \
    --zMin 0 -2 -2  --zMax 0.8 1.8 1.8 \
    --regionsLabel "regions of upregulated genes" "regions of downregulated genes" \
    -out {output}
    """
186
187
188
189
190
191
192
193
194
195
shell:
    """
    plotHeatmap -m {input} \
    --sortRegions descend --refPointLabel summit \
    --samplesLabel chipseq_DexLPS atac_diff h3k27ac_diff \
    --colorMap Greens RdYlBu_r RdYlBu_r \
    --zMin 0 -2 -2  --zMax 0.8 1.8 1.8 \
    --regionsLabel "regions of upregulated genes" "regions of downregulated genes" \
    -out {output}
    """
205
206
207
208
209
shell:
    """
    Rscript src/scripts/filter_fimo_for_motif.r --fimo {input.fimo} --summit_granges {input.summit_granges} \
    --motif_altname {wildcards.motif_altname}
    """
224
225
226
227
228
229
shell:
    """
    mkdir -p $(dirname {output}) && \
    computeMatrix reference-point --referencePoint center -b 500 -a 500 -bs 2 -R {input.targets} \
    -S {input.chipseq} {input.atac_dexlps} {input.atac_lps} {input.h3k27ac_dexlps} {input.h3k27ac_lps} -o {output}
    """
238
239
240
241
242
243
244
245
246
shell:
    """
    plotHeatmap -m {input} \
    --sortRegions descend --refPointLabel summit \
    --samplesLabel chipseq_DexLPS atac_dexlps atac_lps h3k27ac_dexlps h3k27ac_lps \
    --colorMap Greens RdYlBu_r RdYlBu_r RdYlBu_r RdYlBu_r \
    --zMin 0 0 0 0 0  --zMax 0.8 10 10 10 10  \
    -out {output}
    """
 9
10
11
shell:
    "mkdir -p {wildcards.path1}/QC; \
    fastqc -o {wildcards.path1}/QC -f fastq {input}"
24
25
26
27
shell:
    "mkdir -p results/current/tmp && \
    samtools sort {input.bam} -T results/current/tmp/ --threads {threads} | \
    bedtools intersect -v -abam stdin -b {input.blacklist} > {output}"
35
36
37
shell:
    "mkdir -p {wildcards.path1}/stats && \
    picard MarkDuplicates INPUT={input} OUTPUT={output.bam} REMOVE_DUPLICATES=true METRICS_FILE={output.metric} VALIDATION_STRINGENCY=LENIENT PROGRAM_RECORD_ID='null'"
47
48
49
shell:
    "bamCoverage -b {input.bam} --normalizeUsing None \
    --binSize 1 -p {params.processors} --outFileName {output[0]}" 
59
60
61
shell:
    "bamCoverage -b {input.bam} --normalizeUsing None --filterRNAstrand forward \
    --binSize 1 -p {params.processors} --outFileName {output[0]}" 
71
72
73
shell:
    "bamCoverage -b {input.bam} --normalizeUsing None --filterRNAstrand reverse \
    --binSize 1 -p {params.processors} --outFileName {output[0]}" 
 96
 97
 98
 99
100
101
102
103
    shell:
        "bamCoverage -b {input.bam} --normalizeUsing CPM \
        --binSize 1 -p {params.processors} --outFileName {output[0]}" # normalization: CPM: Counts Per Million mapped reads

# generate bed files from IDR peaks for motif analysis
rule generate_bed_from_idr:
    input:
        "{path1}/idr/{path2}_idr0-05"
107
108
shell:
    "cut -f 1,2,3,4,5 {input} > {output}"
117
118
shell:
    "sort -k8,8nr {input} > {output}"
126
127
shell:
    "awk '{{print $1,$2+$10,$2+$10+1,$4,$5}}' FS='\\t' OFS='\t' {input} > {output}"
137
138
139
140
shell:
    "mkdir -p results/current/genomesize/; \
    samtools faidx {input[fa]} && \
    cut -f1,2 {input[fa]}.fai > {output[chromsizes]}"
147
148
shell:
    "awk '{{print $1,0,$2}}' FS='\\t' OFS='\t' {input} > {output}"
158
159
160
161
162
shell:
    """
    bedtools slop -i {input[summit]} -g {input[chromsizes]} -b {wildcards.slop} | \
    sort -k1,1 -k2,2n - > {output[bed]}
    """
171
172
173
174
shell:
    """
    bedtools merge -i {input.bed} -c 4 -o collapse -delim "|" > {output.bed}
    """
183
184
shell:
    "samtools index {input} && mv {input}.bai {output}"
ShowHide 75 more snippets with no or duplicated tags.

Login to post a comment if you would like to share your experience with this workflow.

Do you know this workflow well? If so, you can request seller status , and start supporting this workflow.

Free

Related Workflows

cellranger-snakemake-gke
snakemake workflow to run cellranger on a given bucket using gke.
A Snakemake workflow for running cellranger on a given bucket using Google Kubernetes Engine. The usage of this workflow ...