package main

import (
  "bufio"
  "container/heap"
  "fmt"
  "os"
  "strconv"
  "strings"
)

const INF int64 = 100000000000000000
const MOD int64 = 1000000007

func main() {
  input := Input{bufio.NewReaderSize(os.Stdin,100)}
  n,m := input.Next2Ints()
  s,t := input.Next2Ints()
  s,t = s-1,t-1
  g := NewGraph(n)
  time := make(map[int]map[int]int64)
  for i:=0;i<n;i++ { time[i] = make(map[int]int64) }
  for i:=0;i<m;i++ {
    u,v,d := input.Next3Ints()
    g.Add(u-1,v-1,d)
    g.Add(v-1,u-1,d)
    time[u-1][v-1] = d
    time[v-1][u-1] = d
  }
  d := g.Dijkstra(s)
  var pq PriorityQueue
  heap.Init(&pq)
  for i:=0;i<n;i++ { heap.Push(&pq,&Edge{i,d[i]}) }
  idx := make([]int,n)
  for i:=0;i<n;i++ {
    s := heap.Pop(&pq).(*Edge)
    idx[i] = s.to
  }
  dp1 := make([]int64,n)
  dp2 := make([]int64,n)
  dp1[s] = 1
  for i:=0;i<n;i++ {
    for _,e := range g[idx[i]] {
      if d[idx[i]]+time[idx[i]][e.to] == d[e.to] {
        dp1[e.to] = (dp1[e.to]+dp1[idx[i]])%MOD
      }
    }
  }
  dp2[t] = 1
  for i:=n-1;i>-1;i-- {
    for _,e := range g[idx[i]] {
      if d[e.to]+time[e.to][idx[i]] == d[idx[i]] {
        dp2[e.to] = (dp2[e.to]+dp2[idx[i]])%MOD
      }
    }
  }
  dst := d[t]
  ans := (dp1[t]*dp1[t])%MOD
  for u:=0;u<n;u++ {
    if 2*d[u] == dst {
      x := (dp1[u]*dp1[u])%MOD
      y := (dp2[u]*dp2[u])%MOD
      ans = (ans+MOD-(x*y)%MOD)%MOD
    }
    for _,e := range g[u] {
      v := e.to
      if 2*d[u] < dst && 2*d[v] > dst && d[u]+time[u][v] == d[v] {
        x := (dp1[u]*dp1[u])%MOD
        y := (dp2[v]*dp2[v])%MOD
        ans = (ans+MOD-(x*y)%MOD)%MOD
      }
    }
  }
  fmt.Println(ans)
}

type Edge struct { to int;d int64 }
type PriorityQueue []*Edge
func(pq PriorityQueue) Len() int { return len(pq) }
func(pq PriorityQueue) Less(i,j int) bool { return pq[i].d < pq[j].d }
func(pq PriorityQueue) Swap(i,j int) { pq[i],pq[j] = pq[j],pq[i] }
func(pq *PriorityQueue) Push(x interface{}) {
  e := x.(*Edge)
  *pq = append(*pq,e)
}
func(pq *PriorityQueue) Pop() interface{} {
  old := *pq
  n := len(old)
  e := old[n-1]
  *pq = old[0:n-1]
  return e
}
type Graph [][]Edge
func NewGraph(n int) Graph { return make([][]Edge,n) }
func(g Graph) AddEdge(fm int,e Edge) { g[fm] = append(g[fm],e) }
func(g Graph) Add(fm,to int,d int64) { g.AddEdge(fm,Edge{to,d}) }
func(g Graph) Dijkstra(start int) []int64 {
  n := len(g)
  c := make([]int64,n)
  for i:=0;i<n;i++ { c[i] = INF }
  var pq PriorityQueue
  heap.Init(&pq)
  heap.Push(&pq,&Edge{start,0})
  c[start] = 0
  for pq.Len() > 0 {
    s := heap.Pop(&pq).(*Edge)
    if s.d > c[s.to] { continue }
    for _,e := range g[s.to] {
      if c[e.to] > s.d+e.d {
        c[e.to] = s.d+e.d
        heap.Push(&pq,&Edge{e.to,c[e.to]})
      }
    }
  }
  return c
}

type Input struct { reader *bufio.Reader }
func(i *Input) NextLine() string {
  var buffer []byte
  for {
    line,isPrefix,err := i.reader.ReadLine()
    if err != nil { panic(err) }
    buffer = append(buffer,line...)
    if !isPrefix { break }
  }
  return string(buffer)
}
func(i *Input) Next2Ints() (int,int) {
  s := strings.Fields(i.NextLine())
  x,_ := strconv.Atoi(s[0])
  y,_ := strconv.Atoi(s[1])
  return x,y
}
func(i *Input) Next3Ints() (int,int,int64) {
  s := strings.Fields(i.NextLine())
  x,_ := strconv.Atoi(s[0])
  y,_ := strconv.Atoi(s[1])
  z,_ := strconv.ParseInt(s[2],10,64)
  return x,y,z
}

Measured memory_bytes: 64000