// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

#define ll long long

int n, m; ll paths, mod = 1e9+7, memo[1002][1002];

char c[1002][1002];

ll fix_mod(ll x){

	return (mod + x % mod) % mod;

}

ll solve(int i, int j){

    if(c[i][j] == '#' || i >= n || j >= m) return 0;

    if(i == n-1 && j == m-1) return 1;

    if(memo[i][j] != -1) return memo[i][j];

    paths = fix_mod(solve(i, j+1) + solve(i+1, j));

    return memo[i][j] = paths;

}

int main()

{



    cin>> n>> m;

    for(int i = 0; i < n; i++){

        for(int j = 0; j < m; j++){

            cin>> c[i][j];

        }

    }

    memset(memo, -1, sizeof memo);

    cout<< solve(0, 0);

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.8342449957678395x):
#include <iostream>

#include <string>

#include <vector>

#include <algorithm>

#include<bits/stdc++.h>

#define ll long long

using namespace std;



int root(int arr[],int i){

    while(arr[i]!=i){

         arr[i]=arr[arr[i]];

        i=arr[i];

    }

    return i;

}

void Union(int arr[],int Size[],int a,int b){

int rootA=root(arr,a);

int rootB=root(arr,b);

if(Size[rootA]<Size[rootB]){

    arr[rootA]=arr[rootB];

    Size[rootB]+=Size[rootA];

}else{

arr[rootB]=arr[rootA];

Size[rootA]+=Size[rootB];

}

}

bool findRoot(int a,int b,int arr[]){

 if(root(arr,a)==root(arr,b))return true;

 else return false;

}

 vector<vector<int> >adj(105);

bool nCyc=false;

/*void dijkstra(int v,long long dis[]){

dis[v]=0;

multiset<pair<int,int> >s;

s.insert({0,v});

while(!s.empty()){

    pair<int,int>p= *s.begin();

    s.erase(s.begin());

    int x=p.second;

  if(vis[x])continue;

    vis[x]=1;

    for(int i=0;i<adj[x].size();i++){

        int e=adj[x][i].first,w=adj[x][i].second;

      //  cout<<dis[e]<<" "<<dis[x]+w<<endl;

        if(dis[e]>dis[x]+w){

            dis[e]=dis[x]+w;

            s.insert(make_pair(dis[e],e));

        }

    }

}

}*/

/*void bfs(int s){

    queue<int>q;

    q.push(s);

    while(!q.empty()){

        int v=q.front();

        q.pop();

        for(int i=0;i<adj[v].size();i++){

            if(!vis[adj[v][i]]){

                 q.push(adj[v][i]);

                 vis[adj[v][i]]=1;

            }

        }

    }

}*/

int vis[55][55];

int dx[4]={1,-1,0,0};

int dy[4]={0,0,1,-1};

/*bool isVal(int i,int j){

      if(i<0 || j<0 || j>=m || i>=n)return false;

      return true;

}*/

/*void dfs(int i,int j) {



    if(!isVal(i,j) || vis[i][j] || arr[i][j]=='#')return;

      vis[i][j]=1;

	  if(arr[i][j]=='G'){

	  check++;

	  }

	  if(arr[i][j]=='B'){

        b=1;

        return;

	  }

	for(int k=0;k<4;k++){

     int pos1=i+dx[k],pos2=j+dy[k];

   //  cout<<pos1<<" "<<pos2<<endl;

     if( isVal(pos1,pos2) && (arr[pos1][pos2]=='#'))continue;

               dfs(pos1,pos2);

	}

}

void dfs2(int i,int j){

 if(isVal(i,j)==false || arr[i][j]!='.')return;

  arr[i][j]='#';

}*/

/*

double prim(int x){

    priority_queue<pair<double,int>,vector<pair<double,int> >,greater<pair<double,int> > >q;

    double min_cost=0.0;

    pair<double,int>p;

     q.push(make_pair(0.0,x));

     while(!q.empty()){

      p=q.top();

      q.pop();

      x=p.second;

      if(vis[x])continue;

      min_cost+=p.first;

      vis[x]=1;

      for(int i=0;i<adj[x].size();i++){

         int y=adj[x][i].second;

         if(!vis[y]){

            q.push(adj[x][i]);

        }

      }

     }

   return min_cost;

}*/

int n,m;

char arr[1005][1005];

int dp[1005][1005];

int solve(int i,int j){

    if(arr[i][j]=='#' || i==n || j==m)return 0;

    if(i==n-1 && j==m-1)return 1;

    if(dp[i][j]!=-1)return dp[i][j];

    int ans=solve(i,j+1)%1000000007;

    ans+=solve(i+1,j)%1000000007;

    return dp[i][j]=ans%1000000007;

}

int freq[200005],check[100005];

int main()

{

    cin>>n>>m;

    memset(dp,-1,sizeof dp);

    for(int i=0;i<n;i++)

        for(int j=0;j<m;j++)

           cin>>arr[i][j];

    cout<<solve(0,0);

return 0;

}