#include <bits/stdc++.h>
using namespace std;
#define ff first
#define ss second
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define per(i, a, b) for(int i = b-1; i>=a ; i--)
#define trav(a, x) for(auto& a : x)
#define allin(a , x) for(auto a : x)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<ll> vl;
typedef vector<pii> vpi;
typedef pair<ll,ll> pll;
typedef vector<string> vs;
typedef vector<pll> vpl;
typedef vector<int> vi;
std::mt19937 rng((int) std::chrono::steady_clock::now().time_since_epoch().count());
#define endl '\n'
#define pb push_back
#define db(x) cerr << #x <<" == "<<x << endl;
#define db2(x,y) cerr<<#x <<" == "<<x<<", "<<#y<<" == "<<y<<endl;
#define db3(x,y,z) cerr << #x<<" == "<<x<<", "<<#y<<" == "<<y<<", "<<#z<<" == "<<z<<endl;
#define ms(v,x) memset(v,x,sizeof(v))
ll exp(ll b,ll e,ll m){
  b%=m;
  ll ans = 1;
  for (; e; b = b * b % m, e /= 2)
      if (e & 1) ans = ans * b % m;
  return ans;
}

const int N = 21;
vi g[N];
int vis[N];

vi order;
void dfs(int i){
  vis[i] = 1;
  order.pb(i);
  for(auto j : g[i])if(!vis[j])dfs(j);
}

int cor[N];

ll go(int p){
  if(p==sz(order))return 1;
  ll tot=0;
  vi cnt(4,0);
  for(auto to : g[order[p]]){
    cnt[cor[to]]++;
  }
  rep(j,1,4){
    if(cnt[j])continue;
    cor[order[p]] = j;
    tot+=go(p+1);
    cor[order[p]] = 0;
  }
  return tot;
}

ll solve(int i){
  order.clear();
  dfs(i);

  return go(0);
}

int32_t main(){
  ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
  int n,m;
  cin >> n >> m;

  ll ans = 1;
  rep(i,0,m){
    int a,b;
    cin>>a>>b;
    --a;--b;
    g[a].pb(b);
    g[b].pb(a);
  }
  rep(i,0,n){
    if(!vis[i]){
      ans = ans * solve(i);
    }
  }
  cout << ans << endl;

}
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <random>
#include <chrono>
 
using namespace std;
using namespace __gnu_pbds;
 
#define endl '\n'
 
typedef long long ll;
typedef pair<ll, ll> pii;
typedef tree<int,null_type,less<int>,rb_tree_tag, tree_order_statistics_node_update> indexed_set;
 
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const ll mod = 1e9 + 7;

ll mod_exp(ll a, ll b){
	if(b == 0)
		return 1ll;

	if(b % 2 == 0){
		ll t = mod_exp(a, b / 2) % mod;
		return t * t % mod;
	}
	return a * mod_exp(a, b - 1) % mod;
}

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
 
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);


	int n, m;
	cin >> n >> m;

	ll ans = 0, k = 0;
	vector<string> a(n);
	for(int i = 0; i < n; i++){
		cin >> a[i];
		for(int j = 0; j < m; j++)
			if(a[i][j] == '.')
				k++;
	}

	vector<vector<int>> u(n, vector<int>(m)), d(n, vector<int>(m));
	vector<vector<int>> l(n, vector<int>(m)), r(n, vector<int>(m));

	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			if(a[i][j] == '.'){
				if(j - 1 >= 0 && a[i][j - 1] == '.')
					l[i][j] = l[i][j - 1] + 1;
			}
		}

		for(int j = m - 1; j >= 0; j--){
			if(a[i][j] == '.'){
				if(j + 1 < m && a[i][j + 1] == '.')
					r[i][j] = r[i][j + 1] + 1;
			}
		}
	}

	for(int j = 0; j < m; j++){
		for(int i = 0; i < n; i++){
			if(a[i][j] == '.'){
				if(i - 1 >= 0 && a[i - 1][j] == '.')
					u[i][j] = u[i - 1][j] + 1;
			}
		}

		for(int i = n - 1; i >= 0; i--){
			if(a[i][j] == '.'){
				if(i + 1 < n && a[i + 1][j] == '.')
					d[i][j] = d[i + 1][j] + 1;
			}
		}
	}

	for(int i = 0; i < n; i++)
		for(int j = 0; j < m; j++){
			if(a[i][j] == '.'){
				ll cnt = 1 + u[i][j] + d[i][j] + l[i][j] + r[i][j];
				ll rem = k - cnt;
				ll ways = (mod_exp(2ll, cnt) + mod - 1) % mod;
				ways = (ways * mod_exp(2ll, rem)) % mod;
				ans = (ans + ways) % mod;
			}
		}

	cout << ans << endl;

	return 0;
}