Scores full DNA sequences using a Position Weight Matrix (PWM) over a specified
region of interest (ROI). The ROI is defined by start_pos and end_pos
(1-based, inclusive), with optional extension controlled by extend.
All reported positions are on the full input sequence.
Usage
gseq.pwm(
seqs,
pssm,
mode = c("lse", "max", "pos", "count"),
bidirect = TRUE,
strand = 1L,
score.thresh = NULL,
start_pos = NULL,
end_pos = NULL,
extend = FALSE,
spat.factor = NULL,
spat.bin = 1L,
spat.min = NULL,
spat.max = NULL,
return_strand = FALSE,
skip_gaps = TRUE,
gap_chars = c("-", "."),
neutral_chars = character(0),
neutral_chars_policy = c("average", "log_quarter", "na"),
prior = 0.01
)Arguments
- seqs
character vector of DNA sequences (A/C/G/T/N; case-insensitive)
- pssm
numeric matrix or data frame with columns named A, C, G, T (additional columns are allowed and will be ignored). Each row holds the probabilities or counts of the four bases at one motif position; log-odds matrices,
NAvalues and rows summing to 0 are rejected.- mode
character; one of "lse", "max", "pos", or "count"
- bidirect
logical; if TRUE, scans both strands (default: TRUE)
- strand
integer;
1for the forward strand,-1for the reverse (default:1). Used only whenbidirect = FALSE, and required there -0is refused, since exactly one strand is read and0cannot name it. Underbidirect = TRUEboth strands are read and this is ignored.- score.thresh
single number; windows scoring at or above this value are counted. Required when
mode="count"and ignored otherwise. PWM scores are log-likelihoods, so the usable range depends on the PSSM, the prior and any spatial weights - calibrate withmode="max"before choosing one.- start_pos
integer or NULL; 1-based inclusive start of ROI (default: 1)
- end_pos
integer or NULL; 1-based inclusive end of ROI (default: sequence length)
- extend
logical or integer; if TRUE, a motif anchored in the ROI may run up to w - 1 bases past its end (w being the motif length), so boundary-anchored motifs keep their full context; anchors must still start inside the ROI. If FALSE (default), only windows fully contained in the ROI are scored. An integer is the number of bases a window may run past
end_pos: TRUE is w - 1 and FALSE is 0. An integer above w - 1 also scores windows that start afterend_pos.- spat.factor
numeric vector; spatial weighting factors (optional)
- spat.bin
integer; bin size for spatial weighting
- spat.min
numeric; 1-based position, counted from
start_pos, where the scanning window starts; spatial bins are counted from it (optional)- spat.max
numeric; 1-based position, counted from
start_pos, where the scanning window ends: only windows ending at or before it are scored (optional)- return_strand
logical; if TRUE and
mode="pos", returns data.frame withposandstrandcolumns- skip_gaps
logical; if TRUE, treat gap characters as holes and skip them while scanning. Windows are w consecutive non-gap bases (default: TRUE)
- gap_chars
character vector; which characters count as gaps (default: c("-", "."))
- neutral_chars
character vector; characters to score as unknown bases, by
neutral_chars_policy, instead of leaving their windows out. Default: none, so a window holdingNor any other non-ACGT character is not scored, as in the PWM virtual tracks. Pass e.g.c("N", "n", "*")to score them.- neutral_chars_policy
character string; how to score the characters listed in
neutral_chars. One of"average"(the column's mean log-probability),"log_quarter"(alwayslog(1/4)), or"na"(return NA when one is in the scanning window). Has no effect whenneutral_charsis empty.- prior
numeric; pseudocount added to frequencies (default: 0.01). Set to 0 for no pseudocounts.
Value
Numeric vector (for "lse"/"max"/"count" modes), integer vector (for "pos" mode),
or data.frame with pos and strand columns (for "pos" mode with
return_strand=TRUE). A sequence whose windows are all unscorable (for example
all N) gives 0 for "count", as pwm.count does. A sequence
or ROI with no window at all (shorter than the motif), or an NA sequence, gives
NA in every mode, "count" included, as the PWM virtual tracks give for an
interval without an anchor.
Details
This function scores DNA sequences directly without requiring a genomics database.
For detailed documentation on PWM scoring modes, parameters, and spatial weighting,
see gvtrack.create (functions "pwm", "pwm.max", "pwm.max.pos", "pwm.count").
The ROI (region of interest) is defined by start_pos and end_pos. As in the
PWM virtual tracks, a window on either strand is anchored at its first (leftmost) base,
which must not lie before start_pos. extend sets how many bases past
end_pos a window may run (w - 1 with TRUE, so every anchor in the ROI is scored),
never past the end of the sequence.
When skip_gaps=TRUE, characters specified in gap_chars are treated as gaps.
Windows are defined as w consecutive non-gap bases, and extend counts non-gap
bases. All positions (pos) are reported
as 1-based indices on the original full sequence (including gaps). start_pos and
end_pos are interpreted as physical coordinates on the full sequence.
By default a window holding N or any other character that is not A, C, G or T (in
either case) is not scored on either strand: it is left out, exactly as the pwm,
pwm.max, pwm.max.pos and pwm.count virtual tracks leave it out, and a
sequence with no scorable window gives -Inf for "lse" and "max",
NA for "pos" and 0 for "count". Characters listed in
neutral_chars are instead scored as unknown bases, the same on both strands, as
neutral_chars_policy says.
Under bidirect = TRUE the forward and reverse-complement matches are
two readings of the same window, and every mode but "pos" combines
them at each window by log-sum-exp, after any spatial weights are applied:
"lse" then log-sum-exps those unions across the windows, "max"
takes the largest of them, and "count" thresholds each one once, so a
window is at most a single hit however well its reverse complement matches it.
That is the same union the pwm, pwm.max and pwm.count
virtual tracks take, and over the same windows, with the default neutral_chars, on a
sequence read from the genome (which holds no gap characters), gseq.pwm() agrees with
them to the precision the two share - the virtual tracks accumulate in single
precision and gseq.pwm() in double, so expect agreement to about
1e-5 relative, not to the last bit. mode = "pos" instead takes
the better of the two strands, because it has to name one - what the
pwm.max.pos virtual track does - so "max" and "pos" can
select different windows, and the value from "max" is not necessarily
the score at the position from "pos". The asymmetry is the pwm family's own
(pwm.max combines the strands, pwm.max.pos does not) and is
mirrored here rather than fixed on one side. With bidirect = FALSE
only the strand named by strand is read and there is nothing to
combine.
See also
gvtrack.create for detailed PWM parameter documentation
Examples
if (FALSE) { # \dontrun{
# Create a PSSM (position-specific scoring matrix) with frequency values
pssm <- matrix(
c(
0.7, 0.1, 0.1, 0.1, # Position 1: mostly A
0.1, 0.7, 0.1, 0.1, # Position 2: mostly C
0.1, 0.1, 0.7, 0.1, # Position 3: mostly G
0.1, 0.1, 0.1, 0.7 # Position 4: mostly T
),
ncol = 4, byrow = TRUE
)
colnames(pssm) <- c("A", "C", "G", "T")
# Example sequences
seqs <- c("ACGTACGTACGT", "GGGGACGTCCCC", "TTTTTTTTTTT")
# Score sequences using log-sum-exp (default mode)
gseq.pwm(seqs, pssm, mode = "lse")
# Get maximum score
gseq.pwm(seqs, pssm, mode = "max")
# Find position of best match
gseq.pwm(seqs, pssm, mode = "pos")
# Find position with strand information
gseq.pwm(seqs, pssm, mode = "pos", bidirect = TRUE, return_strand = TRUE)
# Count matches above threshold. score.thresh is mandatory in "count" mode
# and has no default: PWM scores are log-likelihoods, so calibrate it
# against the score range of your own PSSM.
range(gseq.pwm(seqs, pssm, mode = "max"))
gseq.pwm(seqs, pssm, mode = "count", score.thresh = -3)
# Score only a region of interest
gseq.pwm(seqs, pssm, mode = "max", start_pos = 3, end_pos = 10)
# Also score motifs that start in the region and end past it
gseq.pwm(seqs, pssm, mode = "count", score.thresh = -3, start_pos = 5, end_pos = 8, extend = TRUE)
# Spatial weighting example: higher weight in the center
spatial_weights <- c(0.5, 1.0, 2.0, 1.0, 0.5)
gseq.pwm(seqs, pssm,
mode = "lse",
spat.factor = spatial_weights,
spat.bin = 2
)
} # }