# TmCalculator: A Comprehensive Tool for Melting Temperature Calculations

#### Junhui Li

#### 2026-03-19

# Introduction

The TmCalculator package provides comprehensive options for calculating melting temperatures (Tm) of DNA/RNA sequences. This vignette demonstrates the package’s functionality, including:

- Basic sequence input and Tm calculation with Wallace rule method
- Genomic coordinate input and Tm calculation with nearest neighbor method
- FASTA file input and Tm calculation with nearest neighbor method
- Complementary sequence input and Tm calculation with nearest neighbor method
- DNA genome melting temperature map visualization
- An overview of R shiny application

## Installation

    # Install required packages
    suppressMessages({
      library(BiocManager)
      BiocManager::install(c("Biostrings", "BSgenome", "BSgenome.Hsapiens.UCSC.hg38"))
    })
    install.packages("TmCalculator")
    pak::pkg_install("Gviz")
    pak::pkg_install("JunhuiLi1017/TmCalculator@dev")

# Basic Usage

## Simple Sequence Input with Wallace rule method

    # Calculate Tm for simple sequences
    seqs <- c("ATGCGCGAAAT", "GCTAGCTAGCT")
    names(seqs) <- c("chr1:1-11:+:seq1", "chr2:1-11:+:seq2")
    result <- tm_calculate(seqs, method = "tm_wallace")
    print(result)
    #> $tm
    #> GRanges object with 2 ranges and 3 metadata columns:
    #>     seqnames    ranges strand |    sequence  complement        Tm
    #>        <Rle> <IRanges>  <Rle> | <character> <character> <numeric>
    #>   1     chr1      1-11      + | ATGCGCGAAAT TACGCGCTTTA        32
    #>   2     chr2      1-11      + | GCTAGCTAGCT CGATCGATCGA        34
    #>   -------
    #>   seqinfo: 2 sequences from an unspecified genome; no seqlengths

## Genomic Coordinate Input with nearest neighbor method

### In this example, we calculate the melting temperature of the sequences in the hg38 genome with nearest neighbor method. The coordinates should be in the format of “chr:start-end:+:genome_name:seq_name”

    # Example with genomic coordinates
    coords <- c(
      "chr1:1898000-1898050:+:BSgenome.Hsapiens.UCSC.hg38:seq1",
      "chr2:2563000-2563050:-:BSgenome.Hsapiens.UCSC.hg38:seq2"
    )
    result <- tm_calculate(coords)
    result
    #> $tm
    #> GRanges object with 2 ranges and 4 metadata columns:
    #>        seqnames          ranges strand |               sequence
    #>           <Rle>       <IRanges>  <Rle> |            <character>
    #>   seq1     chr1 1898000-1898050      + | AAAAACCCCACAAACCTCCC..
    #>   seq2     chr2 2563000-2563050      - | GCAGCCTTTTGAGGAGCCCA..
    #>                        genome             complement        Tm
    #>                   <character>            <character> <numeric>
    #>   seq1 BSgenome.Hsapiens.UC.. TTTTTGGGGTGTTTGGAGGG..   66.2586
    #>   seq2 BSgenome.Hsapiens.UC.. CGTCGGAAAACTCCTCGGGT..   78.8140
    #>   -------
    #>   seqinfo: 2 sequences from an unspecified genome; no seqlengths

### The options of the nearest neighbor method are:

    result$tm$Options
    #> $Ambiguous
    #> [1] FALSE
    #>
    #> $Shift
    #> [1] 0
    #>
    #> $`Thermodynamic NN values`
    #> [1] "DNA_NN_SantaLucia_2004: SantaLucia J (2004) <doi:10.1146/annurev.biophys.32.110601.141800>"
    #>
    #> $`Thermodynamic values for terminal mismatches`
    #> [1] "DNA_TMM_Bommarito_2000: Bommarito S (2000)  <doi:10.1093/nar/28.9.1929>"
    #>
    #> $`Thermodynamic values for internal mismatches`
    #> [1] "DNA_IMM_Peyret_1999: Peyret N (1999) <doi:10.1021/bi9825091> & Allawi H T (1997) <doi:10.1021/bi962590c> & Santalucia N (2005) <doi:10.1093/nar/gki918>"
    #>
    #> $`Thermodynamic values for dangling ends`
    #> [1] "DNA_DE_Bommarito_2000: Bommarito S (2000) <doi:10.1093/nar/28.9.1929>"
    #>
    #> $`Concentration of the higher concentrated strand`
    #> [1] 25
    #>
    #> $`Concentration of the lower concentrated strand`
    #> [1] 25
    #>
    #> $`Sequence self-complementary`
    #> [1] FALSE
    #>
    #> $Na
    #> [1] 50
    #>
    #> $K
    #> [1] 0
    #>
    #> $Tris
    #> [1] 0
    #>
    #> $Mg
    #> [1] 0
    #>
    #> $dNTPs
    #> [1] 0
    #>
    #> $`Salt correction method`
    #> [1] "Schildkraut2010"
    #>
    #> $`Percent of DMSO`
    #> [1] 0
    #>
    #> $`Formamide concentration`
    #> [1] 0
    #>
    #> $`Coeffecient of Tm decreases per percent DMSO`
    #> [1] 0.75
    #>
    #> $`Method for formamide concentration`
    #> [1] "percent"
    #>
    #> $`Coefficient of Tm decrease per percent formamide`
    #> [1] 0.65

## FASTA File Processing

### In this example, we calculate the melting temperature of the sequences in the fasta file with nearest neighbor method.

    # Process sequences from a FASTA file
    fasta_file <- system.file("extdata", "example1.fasta", package = "TmCalculator")
    result_fa <- tm_calculate(fasta_file)
    result_fa
    #> $tm
    #> GRanges object with 3 ranges and 3 metadata columns:
    #>     seqnames            ranges strand |               sequence
    #>        <Rle>         <IRanges>  <Rle> |            <character>
    #>   1    chr22 13209021-13209099      + | ATGCGATCGATCGATCGATC..
    #>   2     chr1              1-76      * | GCAACGACGACGACGACGAC..
    #>   3    chr14       13200-13222      * | GCGATCGATCGATCGATCGA..
    #>                 complement        Tm
    #>                <character> <numeric>
    #>   1 TACGCTAGCTAGCTAGCTAG..   69.1147
    #>   2 CGTTGCTGCTGCTGCTGCTG..   71.1160
    #>   3 CGCTAGCTAGCTAGCTAGCT..   50.7169
    #>   -------
    #>   seqinfo: 3 sequences from an unspecified genome; no seqlengths

## Complementary Sequence with a mismatch

### In this example, we calculate the melting temperature of the complementary sequences with nearest neighbor method. there is a mismatch between the two sequences.

GCTAGCCGA[C]AATGGGCAGATAGTAGAAA CGATCGGCT[A]TTACCCGTCTATCATCTTT

    # Example with provided complementary sequences
    seqs <- c("GCTAGCCGACAATGGGCAGATAGTAGAAA")
    comp_seqs <- c("CGATCGGCTATTACCCGTCTATCATCTTT")
    result <- tm_calculate(input_seq=seqs,complement_seq=comp_seqs, method="tm_nn")
    result
    #> $tm
    #> GRanges object with 1 range and 3 metadata columns:
    #>     seqnames    ranges strand |               sequence             complement
    #>        <Rle> <IRanges>  <Rle> |            <character>            <character>
    #>   1     chr1      1-29      * | GCTAGCCGACAATGGGCAGA.. CGATCGGCTATTACCCGTCT..
    #>            Tm
    #>     <numeric>
    #>   1   54.2609
    #>   -------
    #>   seqinfo: 1 sequence from an unspecified genome; no seqlengths

## Complementary Sequence with a dangling end and a mismatch

### In this example, we calculate the melting temperature of the complementary sequences with nearest neighbor method. there is a dangling end between the two sequences.

GCTAGCCGA[C]AATGGGCAGATAGTAGAAA GATCGGCT[A]TTACCCGTCTATCATCTTT

    seqs <- c("GCTAGCCGACAATGGGCAGATAGTAGAAA")
    comp_seqs <- c("GATCGGCTATTACCCGTCTATCATCTTT")
    result <- tm_calculate(input_seq=seqs,
                           complement_seq=comp_seqs,
                           method="tm_nn",
                           shift=-1)
    result
    #> $tm
    #> GRanges object with 1 range and 3 metadata columns:
    #>     seqnames    ranges strand |               sequence             complement
    #>        <Rle> <IRanges>  <Rle> |            <character>            <character>
    #>   1     chr1      1-29      * | GCTAGCCGACAATGGGCAGA.. GATCGGCTATTACCCGTCTA..
    #>            Tm
    #>     <numeric>
    #>   1   52.3654
    #>   -------
    #>   seqinfo: 1 sequence from an unspecified genome; no seqlengths

# Visualization of Tm values

    # Generate sample data with 150 sequences
    set.seed(123)

    # Generate 100 sequences for chr1
    chr1_starts <- sort(sample(1:249250621, 100))  # chr1 length in hg19
    chr1_lengths <- sample(50:200, 100, replace=TRUE)
    chr1_ends <- chr1_starts + chr1_lengths
    chr1_tms <- runif(100, min=60, max=80)

    # Generate 50 sequences for chr2
    chr2_starts <- sort(sample(1:243199373, 50))   # chr2 length in hg19
    chr2_lengths <- sample(50:200, 50, replace=TRUE)
    chr2_ends <- chr2_starts + chr2_lengths
    chr2_tms <- runif(50, min=60, max=80)

    # Create GRanges object
    tm_results <- GRanges(
      seqnames = Rle(c(rep("chr1", 100), rep("chr2", 50))),
      ranges = IRanges(
        start = c(chr1_starts, chr2_starts),
        end = c(chr1_ends, chr2_ends)
      ),
      strand = Rle(sample(c("+", "-"), 150, replace=TRUE)),
      Tm = c(chr1_tms, chr2_tms)
    )
    genome(seqinfo(tm_results)) <- "hg38"

    # Example usage by plot_tm_karyotype
    plot_tm_karyotype(tm_results, genome_assembly = "hg38")

    # Example usage by plot_tm_genome_tracks with custom settings (plot_type=4)
    plot_tm_karyotype(tm_results,
                      genome_assembly = "hg38",
                      plot_type = 4,
                      xaxis_cex = 0.5
                      )

    # Example usage by plot_tm_genome_tracks with default settings (plot_type=1)
    plot_tm_genome_tracks(tm_results, chromosome_to_plot = "chr1", genome_assembly = "hg38")

    # Create example GRanges object
    gr_tm <- GenomicRanges::GRanges(
      seqnames = c("chr1", "chr2", "chr1", "chr2", "chr1"),
      ranges = IRanges::IRanges(
        start = c(100, 200, 300, 400, 150),
        end = c(150, 250, 350, 450, 200)
      ),
      Tm = c(65.5, 68.2, 70.1, 63.8, 72.0)
    )

    # Plot with ideograms
    plot_tm_heatmap(gr_tm, genome_assembly = "hg19", plot_type = "karyogram")

    # Faceted plot by chromosome
    plot_tm_heatmap(gr_tm, genome_assembly = "hg19", plot_type = "faceted")

## launch the shiny application

    TmCalculatorShiny::TmCalculator_shiny()

# Conclusion

The TmCalculator package provides a comprehensive suite of tools for calculating and analyzing melting temperatures of DNA/RNA sequences. The visualization tools help in understanding the genomic context and comparing Tm values across different sequences.

For more information, please refer to the package documentation and examples.