/*
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 2e5 + 10, INF = 1LL * 1e9 * 1e9;
struct E{
    int u, v, val;
}edge[MAXN];
vector <int> adj[MAXN];
pair <int, int> p[MAXN][20];
bitset <MAXN> b;
int dis[MAXN], h[MAXN];
pair <int, int> lca(int a, int b) {
    pair <int, int> res = {};
    if (h[a] < h[b])
        swap(a, b);
    int delta = h[a] - h[b];
    int t = 0;
    for(;delta; delta >>= 1, ++t)
        if (delta & 1) {
            res.second = max(res.second, p[a][t].second);
            a = p[a][t].first;
        }
    t = 20 - 1;
    while(~(t--)) {
        if (p[a][t].first != p[b][t].first) {
            res.second = max(res.second, p[a][t].second);
            res.second = max(res.second, p[b][t].second);
            a = p[a][t].first;
            b = p[b][t].first;
        }
    }
    res.second =max(res.second, max(p[a][0].second, p[b][0].second));
    res.first = p[a][0].first;
    return res;
}//
int32_t main () {
    ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n, m, sum = 0;
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        cin >> edge[i].v >> edge[i].u >> edge[i].val;
        adj[edge[i].v].push_back(i);
        adj[edge[i].u].push_back(i);
    }
    set <pair <int, int>> s;
    for (int i = 1; i <= n; ++i)
        dis[i] = m;
    edge[m].val = INF;
    s.insert({0, 1});
    while(!s.empty()) {
        auto now = *s.begin();
        s.erase(now);
        int v = now.second, e = dis[v];
        p[v][0] = {edge[e].v + edge[e].u - v, now.first};
        sum += now.first;
        // cout << v << ' ' << sum << '\n';
        h[v] = h[p[v][0].first] + 1;
        for (int i = 1; i < 20; ++i)
            p[v][i] = {p[p[v][i - 1].first][i - 1].first, max(p[p[v][i - 1].first][i - 1].second, p[v][i - 1].second)};
        b[v] = true;
        for (auto i : adj[v])  { 
            int u = edge[i].v + edge[i].u - v;
            if (!b[u] && edge[dis[u]].val > edge[i].val) {
                s.erase({edge[dis[u]].val, u});
                dis[u] = i;
                s.insert({edge[dis[u]].val, u});
            }
        }
    }
    for (int i = 0; i < m; ++i) 
        cout << sum + edge[i].val - lca(edge[i].v, edge[i].u).second << '\n';
    return 0;
}
/*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 2e5 + 10, MAX = 2010, md = 1e9 + 7;
int dp[2 * MAX][2 * MAX], fact[4 * MAX], inv_fact[4 * MAX];
int combination(int k, int n) {
    if (k > n)
        return 0;
    return (fact[n] * inv_fact[k] % md) * inv_fact[n - k] % md;
}
int power(int n, int p) {
    int res = 1;
    for (;p; p >>= 1, n = n * n % md)
        if (p & 1)
            res = res * n % md;
    return res;
}
int a[MAXN], b[MAXN];
int32_t main () {
    fact[0] = 1;
    for (int i = 1; i < 4 * MAX; ++i)
        fact[i] = fact[i - 1] * i % md;
    inv_fact[4 * MAX - 1] = power(fact[4 * MAX - 1], md - 2);
    for (int i = 4 * MAX - 1; i; --i)
        inv_fact[i - 1] = inv_fact[i] * i % md;
    ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i)
        cin >> a[i] >> b[i];
    for (int i = 0; i < n; ++i)
        ++dp[MAX - a[i]][MAX - b[i]];
    for (int i = 0; i < 2 * MAX - 1; ++i)
        for (int j = 0; j < 2 * MAX - 1; ++j) {
            dp[i + 1][j] += dp[i][j];
            dp[i][j + 1] += dp[i][j];
            if (dp[i + 1][j] >= md)
                dp[i + 1][j] %= md;
            if (dp[i][j + 1] >= md)
                dp[i][j + 1] %= md;
        }
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        ans += (dp[MAX + a[i]][MAX + b[i]] + (md - 1) * combination(2 * a[i], 2 * b[i] + 2 * a[i])) % md;
        if (ans >= md)
            ans %= md;
    }
    cout << ans * power(2, md - 2) % md;
    return 0;
}

Measured memory_bytes: 129792