--{-# LANGUAGE OverloadedStrings #-}
--{-# LANGUAGE OverloadedLists   #-}
{-# LANGUAGE BangPatterns      #-} --引数に!
{-# LANGUAGE MultiWayIf        #-}
{-# LANGUAGE TupleSections     #-}

import Data.Bits
import Data.Maybe (fromJust)
import Data.List
import Data.Array  --変数衝突
import Data.Array.Unboxed
import Data.Array.MArray
import Data.Array.ST
import Data.Graph
--import Data.Vector as V　--変数衝突
import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.Vector.Unboxed as V
import Control.Monad
import Control.Monad.State
import Control.Monad.ST
import Debug.Trace

type Elem = Int
type SegT s = STUArray s Int Elem

{-
セグ木について
sup2によりnを２の冪にする
配列をdp[1]~[n] 変数はi'
セグ木をsegT[1]~[2*n-1] 変数はi
添え字iに対して、親ノードはi`div`2、子ノードは2*i,2*i+1
高さは (floor logBase 2 (fromIntegral i))+1
それぞれPは一点、Rは範囲の操作
-}

--nを超える最小の２の冪
sup2 :: Int -> Int
sup2 n = 2^(ceiling $ logBase 2 (fromIntegral n :: Double) :: Int)

newSegT :: MArray a e m => Int -> e -> m (a Int e)
newSegT n e = newArray (1,2*n-1) e

buildSegT :: Elem -> Int -> (Elem -> Elem -> Elem) -> [Elem] -> ST s (SegT s)
buildSegT e n f ls = do
  segT <- newSegT n e
  forM_ (zip [n..2*n-1] ls) $ \(i,e) -> writeArray segT i e
  sub segT 1
  return segT
  where
    sub :: SegT s -> Int -> ST s Elem
    sub segT' i | i >= n = readArray segT' i
                | otherwise = do
                  l <- sub segT' (2*i)
                  r <- sub segT' (2*i+1)
                  writeArray segT' i $ mod' (f l r)
                  return $ mod' (f l r)

readRSegT :: SegT s -> (Elem -> Elem -> Elem) -> (Int,Int) -> Int -> ST s Elem
readRSegT segT f (left,right) n = sub segT (1,n) 1
  where
    sub :: SegT s -> (Int,Int) -> Int -> ST s Elem
    sub segT' (l,r) i
      | r < left || right < l = return 0 --単位元
      | left <= l && r <= right = readArray segT' i
      | otherwise  = do
        let mid = (l+r)`div`2
        high <- sub segT' (mid+1,r) (2*i+1)
        low  <- sub segT' (l,mid) (2*i)
        return $ mod' $ f high low


dp_i :: Int -> [Elem] -> [Char] -> ST s Elem
dp_i n ls [] = return $ sum ls
dp_i n ls (c:s) = do
  segT <- buildSegT 0 (sup2 n) (+) ls
  ls' <- if c == '<'
    then forM [1..n-1] $ \i -> readRSegT segT (+) (1,i) (sup2 n)
    else forM [1..n-1] $ \i -> readRSegT segT (+) (i+1,n) (sup2 n)
  traceShowM ls'
  dp_i (n-1) ls' s

solve :: Int -> String -> ST s Elem
solve n s = dp_i n ((take n $ repeat 1)++(repeat 0)) s

readBInt :: B.ByteString -> Int
readBInt = fst . fromJust . B.readInt

main0 :: B.ByteString -> Int
main0 cont =
   let remLines0 = map B.words (B.lines cont)
       [n']:remLines1 = remLines0
       n = readBInt n'
       [line2]:remLines2 = remLines1
       s = B.unpack line2
   in mod' $ runST $ solve n s

main :: IO ()
main = print . main0 =<< B.getContents

mod' :: Int -> Int
mod' n = if n < 1000000007 then n else mod n 1000000007
