use std::str::FromStr;
use std::io::*;
use std::collections::*;
use std::mem::*;

pub fn main() {
    let i = stdin();
    let mut o = Vec::new();
    run(&mut i.lock(), &mut o);
    stdout().write_all(&o).unwrap();
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Edge {
    p: (usize, usize),
    d: usize,
}

fn run<R: BufRead, W: Write>(i: &mut R, o: &mut W) {
    let mut i = AtRead::from(i);
    let (n, m) = i.read2::<usize, usize>();
    let (s, t) = i.read2::<usize, usize>();
    let (s, t) = (s - 1, t - 1);
    let mut es = Vec::new();
    for _ in 0..m {
        let (u, v, d) = i.read3::<usize, usize, usize>();
        let (u, v, d) = (u - 1, v - 1, d);
        es.push(Edge { p: (u, v), d: d });
    }
    writeln!(o, "{}", solve(n, s, t, es)).unwrap();
}
fn solve(n: usize, s: usize, g: usize, es: Vec<Edge>) -> usize {
    let mut ds = vec![Vec::new(); n];
    for e in es {
        ds[e.p.0].push((e.p.1, e.d));
        ds[e.p.1].push((e.p.0, e.d));
    }

    // 最短距離ルートの探索
    let mut t = vec![usize::max_value(); n]; // スタート地点からの距離
    t[s] = 0;

    let mut rs0 = vec![Vec::new(); n]; // rs[i]は点iからsへの最短距離でのリンク先
    let mut rs1 = vec![Vec::new(); n]; // rs[i]は点iからgへの最短距離でのリンク先
    let mut q = BTreeSet::new();
    q.insert((0, s));

    while let Some(&(t0, p0)) = q.iter().next() {
        q.remove(&(t0, p0));
        let t0 = t[p0];
        if t0 > t[g] {
            break;
        }
        for &(p1, d) in &ds[p0] {
            let t1_old = t[p1];
            let t1 = t0 + d;
            if t1 > t1_old {
                continue;
            }
            let r = &mut rs0[p1];
            if t1 < t1_old {
                r.clear();
                q.remove(&(t1_old, p1));
                q.insert((t1, p1));
                t[p1] = t1;
            }
            r.push(p0);
        }
    }
    let tg = t[g];
    if tg == usize::max_value() {
        return 0;
    }
    drop(ds);
    drop(q);

    // 中間地点の取得
    let mut ms0 = Vec::new(); // 中間地点リスト(sに近い点)
    let mut ms1 = Vec::new(); // 中間地点リスト(gに近い点)
    let mut vs = vec![false; n]; // 既に訪れた点はtrue
    let mut ps = Vec::new(); // 最短ルートまでに使用する点
    let mut q = Vec::new();
    q.push(g);
    vs[g] = true;
    while let Some(p1) = q.pop() {
        ps.push(p1);
        if t[p1] * 2 == tg {
            ms0.push(p1);
            ms1.push(p1);
        }
        for &p0 in &rs0[p1] {
            rs1[p0].push(p1);
            if t[p1] * 2 > tg && tg > t[p0] * 2 {
                ms0.push(p0);
                ms1.push(p1);
            }
            if vs[p0] {
                continue;
            }
            q.push(p0);
            vs[p0] = true;
        }
    }
    ps.sort_by_key(|&p| t[p]);

    // ルート数の計算
    let mod_val = 1000000007;

    let mut cs0 = vec![0; n];
    cs0[s] = 1;
    for &p1 in ps.iter().skip(1) {
        let mut c = 0;
        for &p0 in &rs0[p1] {
            c += cs0[p0];
        }
        cs0[p1] = c % mod_val;
    }

    let mut cs1 = vec![0; n];
    cs1[g] = 1;
    for &p0 in ps.iter().rev().skip(1) {
        let mut c = 0;
        for &p1 in &rs1[p0] {
            c += cs1[p1];
        }
        cs1[p0] = c % mod_val;
    }

    // 衝突パターン数の計算
    let mut sumc = 0;
    for i in 0..ms0.len() {
        let d0 = cs0[ms0[i]];
        let d1 = cs1[ms1[i]];
        let d0 = (d0 * d0) % mod_val;
        let d1 = (d1 * d1) % mod_val;

        sumc += d0 * d1;
        sumc %= mod_val;
    }
    let cs_all = cs0[g];
    (mod_val + cs_all * cs_all - sumc) % mod_val
}

struct AtRead<'a, R: BufRead + 'a> {
    r: &'a mut R,
    s: String,
}

macro_rules! fn_read {
        {$f:ident($($v:ident: $t:ident),*)} => {
            fn $f<$($t: FromStr),*>(&mut self) -> ($($t),*) {
                let i = &mut self.next().split(' ');
                $(
                    let $v = next(i);
                )*
                ($($v),*)
            }
        };
    }

impl<'a, R: BufRead + 'a> AtRead<'a, R> {
    fn from(r: &'a mut R) -> Self {
        AtRead {
            r: r,
            s: String::new(),
        }
    }
    fn next(&mut self) -> &str {
        self.s.clear();
        self.r.read_line(&mut self.s).unwrap();
        self.s.trim()
    }

    fn_read! { read2(v1: T1, v2: T2) }
    fn_read! { read3(v1: T1, v2: T2, v3: T3) }
}

fn next<'a, T: FromStr, I: std::iter::Iterator<Item = &'a str>>(i: &mut I) -> T {
    i.next().unwrap().parse().ok().unwrap()
}


Measured memory_bytes: 33004