{-# LANGUAGE ScopedTypeVariables #-}
import Control.Applicative
import Control.Monad
import Control.Monad.State
import Control.DeepSeq
import Data.Array
import Data.Bits
import Data.Char
import Data.Functor.Identity
import Data.List
import Data.Ord
import Data.Maybe
import Data.Tree
import Data.Tuple
import qualified System.IO
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Sequence as Q
import qualified Data.ByteString.Char8 as B

main = do
  n <- getInt
  ps <- replicateM n getIntPair
  print $ solve ps

solve :: [(Z,Z)] -> Fp
solve ps = let
  amax = maximum $ map fst ps
  bmax = maximum $ map snd ps
  rect = ((-amax-1,-bmax-1),(amax,bmax))
  src = accumArray (+) 0 rect $ zip (map (\(a,b) -> (-a,-b)) ps) $ repeat (1::Z)
  dp = listArray rect $
    [if i == -amax-1 || j == -bmax-1 then 0 else
      (fint $ src!(i,j)) + dp!(i-1,j) + dp!(i,j-1)
    | (i,j) <- range rect
    ]
  x :: Fp  = sum $ map (dp !) ps
  fact n  = product $ map fint [1..n]
  f n m = fact (n+m) / (fact n * fact m)
  in  (x - sum [f (2*a) (2*b) | (a,b)<-ps]) / 2

 
type Z = Int
type Q = Rational
type R = Double
type S = String

fint :: (Integral a, Num b) => a -> b
fint = fromIntegral

getInt = fst . fromJust . B.readInt <$> B.getLine
getIntPair = (\[a,b]->(a,b)) <$> getInts
getInts = map (fst . fromJust . B.readInt) . B.words <$> B.getLine
getStr = B.unpack <$> B.getLine

yesNo :: Bool -> String
yesNo True = "YES"
yesNo False = "NO"

printList :: (Show a) => [a] -> IO ()
printList = putStrLn . unwords . map show

readLnList :: (Read a) => IO [a]
readLnList = map read . words <$> getLine


-----  Modulo
theMod = 10^9 + 7 :: Int  -- and assume 64 bits

newtype Fp = Fp Int  deriving (Eq)

instance Show Fp  where
  showsPrec p (Fp x) = showsPrec p x

instance Num Fp  where
  (Fp x) + (Fp y) = Fp ((x + y) `mod` theMod)
  (Fp x) - (Fp y) = Fp ((x - y) `mod` theMod)
  (Fp x) * (Fp y) = Fp ((x * y) `mod` theMod)
  negate (Fp x) = Fp ((negate x) `mod` theMod)
  abs _ = error "Fp: abs"
  signum _ = error "Fp: signum"
  fromInteger x = Fp (fromInteger (x `mod` toInteger theMod))

instance Fractional Fp  where
  recip (Fp x) = Fp ((fst . snd $ egcd x theMod) `mod` theMod)
  fromRational = undefined

egcd :: (Integral a) => a -> a -> (a,(a,a))
egcd a b = last $ zip (takeWhile (/= 0) r) $ zip s t
  where
    r = a : b : zipWith mod r (tail r)
    q = zipWith div r (tail r)
    s = 1 : 0 : zipWith (-) s (zipWith (*) q (tail s))
    t = 0 : 1 : zipWith (-) t (zipWith (*) q (tail t))

-----  Union-find
type UnionFindT v m a = StateT (M.Map v (UnionFindVal v)) m a
newtype UnionFindVal v = UnionFindVal v

runUnionFindT :: (Monad m) => UnionFindT v m a -> m a
runUnionFindT = flip evalStateT $ M.empty

runUnionFind = runIdentity . runUnionFindT

ufFresh :: (Monad m, Ord v) => v -> UnionFindT v m ()
ufFresh v = modify $ M.insert v (UnionFindVal v)

ufClass :: (Monad m, Ord v) => v -> UnionFindT v m v
ufClass v = do
  (UnionFindVal pv) <- gets (M.! v)
  if v == pv
    then return v
    else do
      c <- ufClass pv
      modify $ M.insert v (UnionFindVal c)
      return c

ufUnify v w = do
  cv <- ufClass v
  cw <- ufClass w
  modify $ M.insert cw (UnionFindVal cv)
  return $ cv /= cw

-- vi:expandtab:
