CONCERTDR provides a complete pipeline for drug repurposing using the Connectivity Map (CMap) L1000 database. The core idea is signature matching: given a disease differential-expression signature (a ranked list of up- and down-regulated genes), CONCERTDR scores every perturbation in CMap and returns those whose transcriptional effect most strongly reverses the disease pattern.
This vignette demonstrates two complementary use cases using a bundled AML-relevant example dataset (163 genes × 496 signatures):
trt_cp)
perturbations against an AML disease signature to identify candidate drugs.trt_oe) and
CRISPR knockout (trt_xpr) perturbations against the same signature to
nominate therapeutic gene targets.All code in this vignette runs without any external downloads using the data
bundled in inst/extdata/.
library(CONCERTDR)
The package ships with a real CMap subset in inst/extdata/:
| File | Description |
|---|---|
example_signature.txt |
Manually curated AML/BCR-ABL-themed demonstration query |
example_reference_df.csv |
163 genes × 496 CMap signatures (Level 5 z-scores) |
example_siginfo.txt |
Metadata for the 496 signatures |
example_geneinfo.txt |
CMap annotations for the 163 genes |
example_compoundinfo.txt |
CMap compound, mechanism-of-action, and target annotations |
The four CMap-derived files can be regenerated from the LINCS2020 source files
with inst/scripts/make_example_data.R. The script records the source URLs,
selection manifest, extraction procedure, and rounding used for the compact
example. example_signature.txt is not a CMap measurement: it is a
deterministic, manually curated query used to exercise both reversal-scoring
directions. Its values should not be interpreted as estimates from a patient
cohort or as biological validation of the example rankings.
sig_file <- system.file("extdata", "example_signature.txt",
package = "CONCERTDR")
ref_file <- system.file("extdata", "example_reference_df.csv",
package = "CONCERTDR")
sig_info_file <- system.file("extdata", "example_siginfo.txt",
package = "CONCERTDR")
comp_info_file <- system.file("extdata", "example_compoundinfo.txt",
package = "CONCERTDR")
# Load the reference matrix
reference_df <- read.csv(ref_file, row.names = 1, check.names = FALSE)
reference_df$gene_symbol <- rownames(reference_df)
cat("Reference matrix:", nrow(reference_df), "genes ×",
ncol(reference_df) - 1, "signatures\n")
#> Reference matrix: 163 genes × 496 signatures
The example signature is an AML/BCR-ABL-themed set of genes with illustrative positive and negative weights. It demonstrates the reversal criterion: a perturbation that suppresses the positively weighted genes and activates the negatively weighted genes receives a negative connectivity score.
signature <- read.delim(sig_file)
cat("Up-regulated genes: ", sum(signature$log2FC > 0), "\n")
#> Up-regulated genes: 30
cat("Down-regulated genes:", sum(signature$log2FC < 0), "\n")
#> Down-regulated genes: 27
head(signature[order(-abs(signature$log2FC)), ], 10)
#> Gene log2FC
#> 1 MYC 3.0
#> 2 TP53 -3.0
#> 3 MYCN 2.9
#> 4 RB1 -2.9
#> 5 CCND1 2.8
#> 6 CDKN1A -2.8
#> 7 CCND2 2.7
#> 8 CDKN1B -2.7
#> 9 CDK2 2.6
#> 10 CDKN2A -2.6
The bundled siginfo covers both small-molecule (trt_cp) and gene perturbation
(trt_oe, trt_xpr) signatures in four well-represented CMap cell lines.
siginfo <- read.delim(sig_info_file, stringsAsFactors = FALSE)
cat("Total signatures:", nrow(siginfo), "\n")
#> Total signatures: 496
table(Type = siginfo$pert_type, Cell = siginfo$cell_iname)
#> Cell
#> Type A375 A549 HEPG2 PC3
#> trt_cp 106 109 65 116
#> trt_oe 23 26 0 12
#> trt_xpr 10 20 0 9
We first subset the siginfo to trt_cp only, then build a reference matrix
containing just those signatures. This keeps the scoring fast and the results
interpretable.
cp_siginfo <- subset_siginfo_beta(
siginfo_file = sig_info_file,
interactive = FALSE,
filters = list(pert_type = "trt_cp"),
verbose = FALSE,
show_preview = FALSE
)
cat("Compound signatures:", nrow(cp_siginfo), "\n")
#> Compound signatures: 396
table(cp_siginfo$cell_iname)
#>
#> A375 A549 HEPG2 PC3
#> 106 109 65 116
Rather than re-reading from GCTX (which would require the full CMap download), we subset the in-memory reference matrix to keep only the compound signatures identified above.
cp_sig_ids <- cp_siginfo$sig_id
cp_ref <- reference_df[, c("gene_symbol",
intersect(cp_sig_ids, colnames(reference_df))),
drop = FALSE]
cat("Compound reference:", nrow(cp_ref), "genes ×",
ncol(cp_ref) - 1, "signatures\n")
#> Compound reference: 163 genes × 396 signatures
results_cp <- process_signature_with_df(
signature_file = sig_file,
reference_df = cp_ref,
methods = c("xsum", "ks"),
topN = 30,
permutations = 100,
save_files = FALSE
)
print(results_cp)
#> CMap Signature Matching Results
#> ===============================
#>
#> Signature file: /private/tmp/RtmpQJXIGo/Rinst409d540a8288/CONCERTDR/extdata/example_signature.txt
#> Analysis completed: 2026-09-08 16:45:52
#> Time taken: 0.11 minutes
#>
#> Methods used:
#> - xsum: 396 results
#> - ks: 396 results
#>
#> Gene coverage:
#> Up-regulated: 30/30 genes (100.0%)
#> Down-regulated: 27/27 genes (100.0%)
#>
#> Top compounds across all methods:
#> 1. PBIOA018_HEPG2_24H:O07 (method: xsum, score: 43.8400, p-value: 0.0300)
#> 2. PCLB003_HEPG2_24H:BRD-A52530684-003-01-7:10 (method: xsum, score: 35.0200, p-value: 0.0500)
#> 3. REP.B003_A375_24H:P02 (method: xsum, score: 28.3500, p-value: 0.0200)
#> 4. CPC011_A549_24H:BRD-K82109576-065-20-2:10 (method: xsum, score: 26.8100, p-value: 0.0200)
#> 5. CRCGN004_PC3_24H:BRD-K74793820-001-01-2:10 (method: xsum, score: 23.8800, p-value: 0.0000)
#>
#> Use the following to explore the results:
#> - $results: List of result data frames for each method
#> - $summary: Summary of top hits across all methods
#> - $gene_data: Original signature gene data
#> - $settings: Analysis settings and metadata
#> - $common_genes: Genes found in the reference data
#>
#> Example: result_obj$results$ks to view KS score results
A negative score means the drug reverses the disease signature — the standard criterion for a candidate repurposing hit. BCR-ABL inhibitors such as imatinib and dasatinib should rank near the top against this AML signature.
xsum_cp <- results_cp$results$xsum
top_cp <- head(xsum_cp[order(xsum_cp$Score), ], 20)
top_cp[, c("compound", "Score", "pValue", "pAdjValue")]
#> compound
#> CPC005_A375_24H:BRD-K81418486:10 CPC005_A375_24H:BRD-K81418486:10
#> REP.A015_PC3_24H:P14 REP.A015_PC3_24H:P14
#> ERG021_PC3_24H:BRD-K02130563:10 ERG021_PC3_24H:BRD-K02130563:10
#> CPC005_A375_6H:BRD-A18419789-001-01-4:10 CPC005_A375_6H:BRD-A18419789-001-01-4:10
#> PBIOA013_PC3_24H:C21 PBIOA013_PC3_24H:C21
#> PBIOA022_A375_24H:H15 PBIOA022_A375_24H:H15
#> ASG002_PC3_24H:D10 ASG002_PC3_24H:D10
#> PBIOA015_A549_24H:O19 PBIOA015_A549_24H:O19
#> BRAF001_A375_24H:BRD-K81418486-001-15-2:10 BRAF001_A375_24H:BRD-K81418486-001-15-2:10
#> REP.A015_PC3_24H:P16 REP.A015_PC3_24H:P16
#> REP.A015_PC3_24H:P15 REP.A015_PC3_24H:P15
#> ASG003_A549_24H:P01 ASG003_A549_24H:P01
#> LKCP001_A549_24H:D22 LKCP001_A549_24H:D22
#> REP.A015_PC3_24H:P17 REP.A015_PC3_24H:P17
#> PBIOA022_HEPG2_24H:H13 PBIOA022_HEPG2_24H:H13
#> CPC011_A375_6H:BRD-K37798499-001-13-2:10 CPC011_A375_6H:BRD-K37798499-001-13-2:10
#> PBIOA013_A375_24H:O07 PBIOA013_A375_24H:O07
#> LKCP001_A549_24H:D23 LKCP001_A549_24H:D23
#> PBIOA013_PC3_24H:G18 PBIOA013_PC3_24H:G18
#> PBIOA022_HEPG2_24H:H15 PBIOA022_HEPG2_24H:H15
#> Score pValue pAdjValue
#> CPC005_A375_24H:BRD-K81418486:10 -77.30 0.00 0.00000000
#> REP.A015_PC3_24H:P14 -71.50 0.00 0.00000000
#> ERG021_PC3_24H:BRD-K02130563:10 -69.80 0.00 0.00000000
#> CPC005_A375_6H:BRD-A18419789-001-01-4:10 -69.02 0.02 0.07401869
#> PBIOA013_PC3_24H:C21 -63.64 0.00 0.00000000
#> PBIOA022_A375_24H:H15 -63.57 0.01 0.04771084
#> ASG002_PC3_24H:D10 -59.24 0.01 0.04771084
#> PBIOA015_A549_24H:O19 -58.41 0.00 0.00000000
#> BRAF001_A375_24H:BRD-K81418486-001-15-2:10 -56.56 0.00 0.00000000
#> REP.A015_PC3_24H:P16 -55.30 0.00 0.00000000
#> REP.A015_PC3_24H:P15 -55.03 0.00 0.00000000
#> ASG003_A549_24H:P01 -52.93 0.00 0.00000000
#> LKCP001_A549_24H:D22 -52.88 0.03 0.09737705
#> REP.A015_PC3_24H:P17 -52.80 0.00 0.00000000
#> PBIOA022_HEPG2_24H:H13 -52.70 0.01 0.04771084
#> CPC011_A375_6H:BRD-K37798499-001-13-2:10 -49.79 0.01 0.04771084
#> PBIOA013_A375_24H:O07 -49.68 0.01 0.04771084
#> LKCP001_A549_24H:D23 -49.61 0.04 0.11395683
#> PBIOA013_PC3_24H:G18 -48.93 0.03 0.09737705
#> PBIOA022_HEPG2_24H:H15 -47.80 0.02 0.07401869
plot(results_cp, method = "xsum", plot_type = "scores", top_n = 20)
plot(results_cp, method = "xsum", plot_type = "volcano")
annotate_drug_results() joins the scoring output with siginfo and
compoundinfo to add drug names, mechanism of action, targets, and clinical
phase.
compinfo <- read.delim(comp_info_file, stringsAsFactors = FALSE)
views_cp <- annotate_drug_results(
results_df = xsum_cp,
sig_info_file = cp_siginfo,
comp_info_file = compinfo,
write_outputs = FALSE,
verbose = FALSE
)
# Drug-level summary: one row per compound, best score across all contexts
head(views_cp$wetlab_drug_view[,
c("perturbation_name", "Score", "effect_direction", "moa", "target")
], 15)
#> perturbation_name Score
#> 37 vorinostat -77.30
#> 30 romidepsin -71.50
#> 11 panobinostat -69.80
#> 3 etoposide -69.02
#> 41 bortezomib -63.64
#> 16 midostaurin -58.41
#> 20 etoposide -49.79
#> 35 entinostat -47.20
#> 42 doxorubicin -43.82
#> 17 pacritinib -43.51
#> 32 cytarabine -42.64
#> 45 bosutinib -41.44
#> 18 cytarabine -39.82
#> 28 methotrexate -37.58
#> 25 palbociclib -34.51
#> effect_direction
#> 37 Reversal (potentially therapeutic)
#> 30 Reversal (potentially therapeutic)
#> 11 Reversal (potentially therapeutic)
#> 3 Reversal (potentially therapeutic)
#> 41 Mimic/Aggravating; Reversal (potentially therapeutic)
#> 16 Reversal (potentially therapeutic)
#> 20 Reversal (potentially therapeutic)
#> 35 Mimic/Aggravating; Reversal (potentially therapeutic)
#> 42 Mimic/Aggravating; Reversal (potentially therapeutic)
#> 17 Mimic/Aggravating; Reversal (potentially therapeutic)
#> 32 Reversal (potentially therapeutic)
#> 45 Mimic/Aggravating; Reversal (potentially therapeutic)
#> 18 Reversal (potentially therapeutic)
#> 28 Reversal (potentially therapeutic)
#> 25 Reversal (potentially therapeutic)
#> moa target
#> 37 HDAC inhibitor HDAC6
#> 30 HDAC inhibitor HDAC1
#> 11 HDAC inhibitor HDAC1
#> 3 Topoisomerase inhibitor TOP2A
#> 41 Proteasome inhibitor PSMB1
#> 16 KIT inhibitor FLT3
#> 20 Topoisomerase inhibitor TOP2A
#> 35 HDAC inhibitor HDAC1
#> 42 Topoisomerase inhibitor TOP2A
#> 17 JAK inhibitor FLT3
#> 32 Ribonucleotide reductase inhibitor POLA1
#> 45 Src inhibitor ABL1
#> 18 Ribonucleotide reductase inhibitor POLA1
#> 28 Dihydrofolate reductase inhibitor DHFR
#> 25 CDK inhibitor CDK4
# How many cell-line contexts did each top drug appear in?
head(views_cp$drug_context_summary[,
c("perturbation_name", "best_score", "n_contexts", "n_cell_lines", "moa_status")
], 10)
#> perturbation_name best_score n_contexts n_cell_lines moa_status
#> 297 vorinostat -77.30 16 4 Known
#> 50 panobinostat -69.80 16 4 Known
#> 344 bortezomib -63.64 16 4 Known
#> 93 midostaurin -58.41 16 4 Known
#> 261 entinostat -47.20 16 4 Known
#> 301 nilotinib -30.04 16 4 Known
#> 164 dasatinib -26.34 16 4 Known
#> 279 decitabine -17.38 16 4 Known
#> 143 buparlisib -22.97 15 4 Known
#> 333 navitoclax -21.13 15 4 Known
The barcode heatmap shows the z-score profile of the top-scoring perturbations across the signature genes. Genes are arranged left-to-right as down-regulated → up-regulated in the disease; a drug that reverses the signature appears as warm colours on the left and cool colours on the right.
z_cp <- extract_signature_zscores(
results_df = views_cp$tech_view_all,
signature_file = sig_file,
reference_df = cp_ref,
max_genes = 50, # top-50 up-regulated + top-50 down-regulated
split_direction = TRUE,
max_perts = 50,
verbose = FALSE
)
cat("Heatmap matrix:", nrow(z_cp$z_plot), "perturbations ×",
ncol(z_cp$z_plot), "genes\n")
#> Heatmap matrix: 50 perturbations × 57 genes
if (requireNamespace("ComplexHeatmap", quietly = TRUE) &&
requireNamespace("circlize", quietly = TRUE)) {
plot_signature_direction_tile_barcode(
precomputed = z_cp,
cluster_rows = TRUE,
show_row_dendrogram = TRUE,
cluster_cols = FALSE,
verbose = FALSE
)
} else {
message("Install ComplexHeatmap and circlize for heatmap rendering:\n",
" BiocManager::install('ComplexHeatmap')\n",
" install.packages('circlize')")
}
Setting split_direction = TRUE divides the plot into two panels: genes with
positive log2FC (up-regulated in the disease) on the left, and genes with
negative log2FC (down-regulated) on the right. Both panels share the same
perturbation row order, determined by hierarchical clustering of the full
gene matrix, so patterns on each side can be compared directly.
if (requireNamespace("ComplexHeatmap", quietly = TRUE) &&
requireNamespace("circlize", quietly = TRUE)) {
plot_signature_direction_tile_barcode(
precomputed = z_cp,
split_direction = TRUE, # up-regulated panel (left) | down-regulated panel (right)
gap_width = 6, # mm gap between the two panels
cluster_rows = TRUE,
show_row_dendrogram = TRUE,
cluster_cols = FALSE,
verbose = FALSE
)
}
Gene overexpression and CRISPR knockout perturbations in CMap can identify which genes, when modulated, produce a transcriptional effect similar to a beneficial drug. This nominates candidate therapeutic targets independently of any existing compound library.
ge_siginfo <- subset_siginfo_beta(
siginfo_file = sig_info_file,
interactive = FALSE,
filters = list(pert_type = c("trt_oe", "trt_xpr")),
verbose = FALSE,
show_preview = FALSE
)
cat("Gene perturbation signatures:", nrow(ge_siginfo), "\n")
#> Gene perturbation signatures: 100
table(Type = ge_siginfo$pert_type, Cell = ge_siginfo$cell_iname)
#> Cell
#> Type A375 A549 PC3
#> trt_oe 23 26 12
#> trt_xpr 10 20 9
ge_sig_ids <- ge_siginfo$sig_id
ge_ref <- reference_df[, c("gene_symbol",
intersect(ge_sig_ids, colnames(reference_df))),
drop = FALSE]
cat("Gene perturbation reference:", nrow(ge_ref), "genes ×",
ncol(ge_ref) - 1, "signatures\n")
#> Gene perturbation reference: 163 genes × 100 signatures
results_ge <- process_signature_with_df(
signature_file = sig_file,
reference_df = ge_ref,
methods = c("xsum", "ks"),
topN = 50,
permutations = 100,
save_files = FALSE
)
print(results_ge)
#> CMap Signature Matching Results
#> ===============================
#>
#> Signature file: /private/tmp/RtmpQJXIGo/Rinst409d540a8288/CONCERTDR/extdata/example_signature.txt
#> Analysis completed: 2026-09-08 16:46:09
#> Time taken: 0.03 minutes
#>
#> Methods used:
#> - xsum: 100 results
#> - ks: 100 results
#>
#> Gene coverage:
#> Up-regulated: 30/30 genes (100.0%)
#> Down-regulated: 27/27 genes (100.0%)
#>
#> Top compounds across all methods:
#> 1. TA.OE012_A549_96H:BRDN0000553495:-666 (method: xsum, score: 21.5200, p-value: 0.0700)
#> 2. TA.OE014_A549_96H:BRDN0000553488:-666 (method: xsum, score: 18.8300, p-value: 0.0200)
#> 3. TA.OE002_A375_72H:CCSBBROAD304_00526:-666 (method: xsum, score: 16.9500, p-value: 0.0000)
#> 4. XPRJJ001_A375_96H:BRDN0001057046:-666 (method: xsum, score: 16.2300, p-value: 0.0000)
#> 5. TA.OE007_A549_96H:BRDN0000465016:-666 (method: xsum, score: 14.9800, p-value: 0.0500)
#>
#> Use the following to explore the results:
#> - $results: List of result data frames for each method
#> - $summary: Summary of top hits across all methods
#> - $gene_data: Original signature gene data
#> - $settings: Analysis settings and metadata
#> - $common_genes: Genes found in the reference data
#>
#> Example: result_obj$results$ks to view KS score results
Negative-scoring gene perturbations are those whose expression effect reverses the AML signature. An overexpression hit (trt_oe) suggests that activating that gene is therapeutic; a knockout hit (trt_xpr) suggests that silencing it is therapeutic.
xsum_ge <- results_ge$results$xsum
top_ge <- head(xsum_ge[order(xsum_ge$Score), ], 20)
top_ge[, c("compound", "Score", "pValue", "pAdjValue")]
#> compound
#> XPR016_PC3.311B_96H:J12 XPR016_PC3.311B_96H:J12
#> TA.OE003_PC3_72H:BRDN0000464908:-666 TA.OE003_PC3_72H:BRDN0000464908:-666
#> XPR008_PC3.311B_96H:G11 XPR008_PC3.311B_96H:G11
#> XPR016_A375.311_96H:J12 XPR016_A375.311_96H:J12
#> XPR033_A549.311_96H:C10 XPR033_A549.311_96H:C10
#> XPR026_A375.311_96H:L06 XPR026_A375.311_96H:L06
#> XPR025_PC3.311B_96H:L11 XPR025_PC3.311B_96H:L11
#> TA.OE003_A375_72H:CCSBBROAD304_00282:-666 TA.OE003_A375_72H:CCSBBROAD304_00282:-666
#> TA.OE007_A549_96H:BRDN0000464992:-666 TA.OE007_A549_96H:BRDN0000464992:-666
#> TA.OE002_A375_72H:BRDN0000465013:-666 TA.OE002_A375_72H:BRDN0000465013:-666
#> XPR025_A549.311_96H:L11 XPR025_A549.311_96H:L11
#> TA.OE007_A549_96H:CCSBBROAD304_00282:-666 TA.OE007_A549_96H:CCSBBROAD304_00282:-666
#> OEC001_A375_96H:CCSBBROAD304_01093:-666 OEC001_A375_96H:CCSBBROAD304_01093:-666
#> OEB001_A375_96H:BRDN0000399136:-666 OEB001_A375_96H:BRDN0000399136:-666
#> TA.OE012_A549_96H:BRDN0000561657:-666 TA.OE012_A549_96H:BRDN0000561657:-666
#> TA.OE002_PC3_72H:CCSBBROAD304_06179:-666 TA.OE002_PC3_72H:CCSBBROAD304_06179:-666
#> TA.OE007_A549_96H:BRDN0000465013:-666 TA.OE007_A549_96H:BRDN0000465013:-666
#> XPR042_A549.311_96H:K24 XPR042_A549.311_96H:K24
#> XPR026_A549.311_96H:L06 XPR026_A549.311_96H:L06
#> XPR008_PC3.311B_96H:O23 XPR008_PC3.311B_96H:O23
#> Score pValue pAdjValue
#> XPR016_PC3.311B_96H:J12 -30.52 0.00 0.0000000
#> TA.OE003_PC3_72H:BRDN0000464908:-666 -29.90 0.00 0.0000000
#> XPR008_PC3.311B_96H:G11 -22.50 0.03 0.2500000
#> XPR016_A375.311_96H:J12 -22.02 0.00 0.0000000
#> XPR033_A549.311_96H:C10 -19.11 0.03 0.2500000
#> XPR026_A375.311_96H:L06 -19.01 0.00 0.0000000
#> XPR025_PC3.311B_96H:L11 -18.29 0.00 0.0000000
#> TA.OE003_A375_72H:CCSBBROAD304_00282:-666 -17.41 0.13 0.4642857
#> TA.OE007_A549_96H:BRDN0000464992:-666 -14.63 0.07 0.3684211
#> TA.OE002_A375_72H:BRDN0000465013:-666 -13.59 0.13 0.4642857
#> XPR025_A549.311_96H:L11 -13.36 0.05 0.3333333
#> TA.OE007_A549_96H:CCSBBROAD304_00282:-666 -13.28 0.34 0.6250000
#> OEC001_A375_96H:CCSBBROAD304_01093:-666 -11.67 0.35 0.6250000
#> OEB001_A375_96H:BRDN0000399136:-666 -10.81 0.15 0.4687500
#> TA.OE012_A549_96H:BRDN0000561657:-666 -10.19 0.20 0.5263158
#> TA.OE002_PC3_72H:CCSBBROAD304_06179:-666 -9.81 0.06 0.3684211
#> TA.OE007_A549_96H:BRDN0000465013:-666 -9.57 0.15 0.4687500
#> XPR042_A549.311_96H:K24 -8.39 0.14 0.4687500
#> XPR026_A549.311_96H:L06 -8.26 0.02 0.2222222
#> XPR008_PC3.311B_96H:O23 -8.06 0.12 0.4615385
plot(results_ge, method = "xsum", plot_type = "scores", top_n = 20)
views_ge <- annotate_drug_results(
results_df = xsum_ge,
sig_info_file = ge_siginfo,
comp_info_file = compinfo, # compinfo may not cover gene perts; that is expected
write_outputs = FALSE,
verbose = FALSE
)
# Gene-focused view: perturbation name, mode (OE vs XPR), score
head(views_ge$wetlab_gene_view[,
c("perturbation_name", "mode", "Score", "effect_direction", "cell_line")
], 15)
#> perturbation_name mode Score effect_direction cell_line
#> 71 CDK4 XPR -30.52 Reversal (potentially therapeutic) PC3.311B
#> 13 TP53 OE -29.90 Reversal (potentially therapeutic) PC3
#> 59 AKT1 XPR -22.50 Reversal (potentially therapeutic) PC3.311B
#> 70 CDK4 XPR -22.02 Reversal (potentially therapeutic) A375.311
#> 72 CDK4 XPR -19.11 Reversal (potentially therapeutic) A549.311
#> 64 MTOR XPR -19.01 Reversal (potentially therapeutic) A375.311
#> 68 CDK4 XPR -18.29 Reversal (potentially therapeutic) PC3.311B
#> 89 CDKN1A OE -17.41 Reversal (potentially therapeutic) A375
#> 17 AKT1 OE -14.63 Reversal (potentially therapeutic) A549
#> 20 AKT1 OE -13.59 Reversal (potentially therapeutic) A375
#> 67 CDK4 XPR -13.36 Reversal (potentially therapeutic) A549.311
#> 90 CDKN1A OE -13.28 Reversal (potentially therapeutic) A549
#> 93 NFKBIA OE -11.67 Reversal (potentially therapeutic) A375
#> 2 GATA2 OE -10.81 Reversal (potentially therapeutic) A375
#> 47 PTEN OE -10.19 Reversal (potentially therapeutic) A549
z_ge <- extract_signature_zscores(
results_df = views_ge$tech_view_all,
signature_file = sig_file,
reference_df = ge_ref,
max_genes = 50,
split_direction = TRUE,
max_perts = 50,
verbose = FALSE
)
if (requireNamespace("ComplexHeatmap", quietly = TRUE) &&
requireNamespace("circlize", quietly = TRUE)) {
plot_signature_direction_tile_barcode(
precomputed = z_ge,
cluster_rows = TRUE,
show_row_dendrogram = TRUE,
cluster_cols = FALSE,
verbose = FALSE
)
}
if (requireNamespace("ComplexHeatmap", quietly = TRUE) &&
requireNamespace("circlize", quietly = TRUE)) {
plot_signature_direction_tile_barcode(
precomputed = z_ge,
split_direction = TRUE,
gap_width = 6,
cluster_rows = TRUE,
cluster_cols = FALSE,
verbose = FALSE
)
}
# Top 10 compounds vs top 10 gene perturbations by XSum score
top10_cp <- head(xsum_cp[order(xsum_cp$Score), "Score", drop = FALSE], 10)
top10_ge <- head(xsum_ge[order(xsum_ge$Score), "Score", drop = FALSE], 10)
cat("Score range — compounds: ",
round(range(top10_cp$Score), 3), "\n")
#> Score range — compounds: -77.3 -55.3
cat("Score range — gene perturbations:",
round(range(top10_ge$Score), 3), "\n")
#> Score range — gene perturbations: -30.52 -13.59
The two use cases are complementary: compound hits suggest drugs that could be repositioned immediately, while gene perturbation hits suggest mechanistic targets that could guide future drug discovery or combination strategies.
CONCERTDR overlaps with
signatureSearch and
cmapR, but the packages operate at
different levels of the workflow:
| Package | Primary scope | When it is a good fit |
|---|---|---|
| CONCERTDR | An opinionated end-to-end drug-repurposing workflow: filter CMap contexts, extract reference profiles, run KS/GSEA/XCos/XSum/Zhang matching, annotate hits, and create wet-lab-oriented tables and heatmaps. | When the goal is to move from a disease signature and CMap files to ranked, annotated drug or gene-perturbation candidates with a compact API. |
| signatureSearch | A broader gene-expression-signature search and functional-enrichment framework, with preprocessed CMap/LINCS reference resources supplied through signatureSearchData and ExperimentHub. |
When scalable searches against packaged reference databases, custom databases, or downstream functional enrichment are central to the analysis. |
| cmapR | General infrastructure for parsing, manipulating, and writing CMap formats such as GCT/GCTX matrices and gene-set collections. | When low-level CMap data access and format manipulation are needed without an opinionated repurposing and result-annotation pipeline. |
The packages can also be complementary. For example, cmapR can prepare or
inspect CMap objects before a CONCERTDR analysis, while signatureSearch is a
useful alternative when its database abstractions and functional-enrichment
tools are preferred.
For a real analysis, replace the bundled reference_df with a matrix built
from the full CMap GCTX. Set file paths once at the top of your script:
data_dir <- "/path/to/cmap_data"
options(
CONCERTDR.data_dir = data_dir,
CONCERTDR.gctx_file = file.path(data_dir, "level5_beta_trt_cp_n720216x12328.gctx"),
CONCERTDR.siginfo_file = file.path(data_dir, "siginfo_beta.txt"),
CONCERTDR.geneinfo_file = file.path(data_dir, "geneinfo_beta.txt"),
CONCERTDR.compoundinfo_file = file.path(data_dir, "compoundinfo_beta.txt")
)
# Step 1: filter siginfo
cp_siginfo <- subset_siginfo_beta(
getOption("CONCERTDR.siginfo_file"),
interactive = FALSE,
filters = list(
pert_type = "trt_cp",
pert_itime = c("6 h", "24 h"),
cell_iname = c("K562", "HL60", "THP1", "JURKAT", "U937", "NB4")
)
)
# Step 2: build reference matrix from GCTX
reference_df <- extract_cmap_data_from_siginfo(
siginfo_file = cp_siginfo,
geneinfo_file = getOption("CONCERTDR.geneinfo_file"),
gctx_file = getOption("CONCERTDR.gctx_file"),
filter_quality = FALSE,
landmark = TRUE
)
# Steps 3–7: identical to the vignette above — just replace cp_ref with
# reference_df and use larger topN / permutations for real-scale analysis:
# topN = 400, permutations = 1000
sessionInfo()
#> R version 4.6.1 Patched (2026-06-24 r90190)
#> Platform: x86_64-apple-darwin20
#> Running under: macOS Ventura 13.7.8
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.6-x86_64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.6-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
#>
#> locale:
#> [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: America/New_York
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] CONCERTDR_0.99.2 BiocStyle_2.41.0
#>
#> loaded via a namespace (and not attached):
#> [1] sass_0.4.10 generics_0.1.4 shape_1.4.6.1
#> [4] digest_0.6.39 magrittr_2.0.5 evaluate_1.0.5
#> [7] grid_4.6.1 RColorBrewer_1.1-3 bookdown_0.48
#> [10] iterators_1.0.14 circlize_0.4.18 fastmap_1.2.0
#> [13] foreach_1.5.2 doParallel_1.0.17 jsonlite_2.0.0
#> [16] GlobalOptions_0.1.4 tinytex_0.60 BiocManager_1.30.27
#> [19] ComplexHeatmap_2.29.0 scales_1.4.0 codetools_0.2-20
#> [22] jquerylib_0.1.4 cli_3.6.6 crayon_1.5.3
#> [25] rlang_1.3.0 withr_3.0.3 cachem_1.1.0
#> [28] yaml_2.3.12 otel_0.2.0 tools_4.6.1
#> [31] parallel_4.6.1 dplyr_1.2.1 colorspace_2.1-3
#> [34] Rhdf5lib_2.1.0 ggplot2_4.0.3 BiocGenerics_0.59.12
#> [37] GetoptLong_1.1.1 vctrs_0.7.3 R6_2.6.1
#> [40] png_0.1-9 stats4_4.6.1 matrixStats_1.5.0
#> [43] lifecycle_1.0.5 rhdf5_2.57.12 magick_2.9.1
#> [46] S4Vectors_0.51.9 IRanges_2.47.5 clue_0.3-68
#> [49] cluster_2.1.8.3 pkgconfig_2.0.3 pillar_1.11.1
#> [52] bslib_0.12.0 gtable_0.3.6 data.table_1.18.6.1
#> [55] glue_1.8.1 Rcpp_1.1.2 xfun_0.60
#> [58] tibble_3.3.1 tidyselect_1.2.1 knitr_1.52
#> [61] dichromat_2.0-1 rhdf5filters_1.25.4 rjson_0.2.23
#> [64] farver_2.1.2 htmltools_0.5.9 rmarkdown_2.32
#> [67] labeling_0.4.3 Cairo_1.7-0 compiler_4.6.1
#> [70] S7_0.2.2