#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
#define pb push_back
using namespace std;
const string s[][3]=
{
    {
        "...",
        "...",
        "..."
    },
    {
        "...",
        ".O.",
        "..."
    },
    {
        "..O",
        "...",
        "O.."
    }
    ,
    {
        "..O",
        ".O.",
        "O.."
    }
    ,
    {
        "O.O",
        "...",
        "O.O"
    }
    ,
    {
        "O.O",
        ".O.",
        "O.O"
    },
    {
        "O.O",
        "O.O",
        "O.O"
    }

};
const string t[][3]=
{
    {
        "...",
        "...",
        "..."
    },
    {
        "...",
        ".O.",
        "..."
    },
    {
        "O..",
        "...",
        "..O"
    }
    ,
    {
        "O..",
        ".O.",
        "..O"
    }
    ,
    {
        "O.O",
        "...",
        "O.O"
    }
    ,
    {
        "O.O",
        ".O.",
        "O.O"
    },
    {
        "OOO",
        "...",
        "OOO"
    }

};
int a[300][300];
int n,m;
char st[300][300];
const long long mod=1000000007;
long long dp[400];
int b[400],c[400];
bool can()
{
    if (n&1)return 0;
    int i;
    for (i=0;i<n;i++)
    {
        if ((b[i]&1)==0)return 0;
    }
    return 1;
}
long long dp1[400];
long long gao()
{
    long long res=0;
    int i,j,k;
    memset(dp1,0,sizeof(dp1));
    dp1[0]=1;
    for (i=1;i<=n;i++)
    {
        if ((b[i-1]&2)&&(c[i-1]&2))
        {
            dp1[i]+=dp1[i-1];
            dp1[i]%=mod;
        }
        if (i-2>=0)
        {
            if ((b[i-2]&1)&&(b[i-1]&1)&&(c[i-2]&1)&&(c[i-1]&1))
            {
                dp1[i]+=dp1[i-2];
                dp1[i]%=mod;
            }
        }
    }
    int x=1;
    x&=can();
    memcpy(b,c,sizeof(b));
    x&=can();
    dp1[n]-=x;
    dp1[n]=(dp1[n]%mod+mod)%mod;
    return dp1[n];
}
int main()
{
    int i,j,k,l;
    string ss[4];
    cin>>n>>m;
    for (i=0;i<n;i++)
    {
        cin>>ss[0];
        for (j=0;j<3;j++)cin>>ss[j];
        for (j=0;j<3;j++)
        {
            string st="";
            for (k=0;k<4*m+1;k++)
            {
                if (ss[j][k]!='#')st+=ss[j][k];
            }
            ss[j]=st;
        }
        for (k=0;k<m;k++)
        {
            string tt[4];
            tt[0]=ss[0].substr(k*3,3);
            tt[1]=ss[1].substr(k*3,3);
            tt[2]=ss[2].substr(k*3,3);
            int tp=0;
            for (l=0;l<7;l++)
            {
                if (s[l][0]==tt[0]&&s[l][1]==tt[1]&&s[l][2]==tt[2])
                {
                    tp|=1;
                }
            }
            for (l=0;l<7;l++)
            {
                if (t[l][0]==tt[0]&&t[l][1]==tt[1]&&t[l][2]==tt[2])
                {
                    tp|=2;
                }
            }
            a[i][k]=tp;
        }
    }
    cin>>ss[0];
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    for (i=1;i<=m;i++)
    {
        if (i-2>=0)
        {
            for (j=0;j<n;j++)
            {
                b[j]=a[j][i-2];
            }
            for (j=0;j<n;j++)
            {
                c[j]=a[j][i-1];
            }
            dp[i]+=dp[i-2]*gao();
            dp[i]%=mod;
        }
        if (i-1>=0)
        {
            for (j=0;j<n;j++)
            {
                b[j]=a[j][i-1];
            }
            if (can())
            {
                dp[i]+=dp[i-1];
                dp[i]%=mod;
            }
        }
    }
    cout<<dp[m]<<endl;
    return 0;
}


#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
#define pb push_back
using namespace std;
const string s[][3]=
{
    {
        "...",
        "...",
        "..."
    },
    {
        "...",
        ".O.",
        "..."
    },
    {
        "..O",
        "...",
        "O.."
    }
    ,
    {
        "..O",
        ".O.",
        "O.."
    }
    ,
    {
        "O.O",
        "...",
        "O.O"
    }
    ,
    {
        "O.O",
        ".O.",
        "O.O"
    },
    {
        "O.O",
        "O.O",
        "O.O"
    }

};
const string t[][3]=
{
    {
        "...",
        "...",
        "..."
    },
    {
        "...",
        ".O.",
        "..."
    },
    {
        "O..",
        "...",
        "..O"
    }
    ,
    {
        "O..",
        ".O.",
        "..O"
    }
    ,
    {
        "O.O",
        "...",
        "O.O"
    }
    ,
    {
        "O.O",
        ".O.",
        "O.O"
    },
    {
        "OOO",
        "...",
        "OOO"
    }

};
int a[300][300];
int n,m;
char st[300][300];
const long long mod=1000000007;
long long dp[400];
int b[400],c[400];
bool can()
{
    int i;
    for (i=0;i<n;i++)
    {
        if ((b[i]&1)==0)return 0;
    }
    return 1;
}
long long dp1[400];
long long gao()
{
    long long res=0;
    int i,j,k;
    memset(dp1,0,sizeof(dp1));
    dp1[0]=1;
    for (i=1;i<=n;i++)
    {
        if ((b[i-1]&2)&&(c[i-1]&2))
        {
            dp1[i]+=dp1[i-1];
            dp1[i]%=mod;
        }
        if (i-2>=0)
        {
            if ((b[i-2]&1)&&(b[i-1]&1)&&(c[i-2]&1)&&(c[i-1]&1))
            {
                dp1[i]+=dp1[i-2];
                dp1[i]%=mod;
            }
        }
    }
    int x=1;
    x&=can();
    memcpy(b,c,sizeof(b));
    x&=can();
    dp1[n]-=x;
    dp1[n]=(dp1[n]%mod+mod)%mod;
    return dp1[n];
}
int main()
{
    int i,j,k,l;
    string ss[4];
    cin>>n>>m;
    for (i=0;i<n;i++)
    {
        cin>>ss[0];
        for (j=0;j<3;j++)cin>>ss[j];
        for (j=0;j<3;j++)
        {
            string st="";
            for (k=0;k<4*m+1;k++)
            {
                if (ss[j][k]!='#')st+=ss[j][k];
            }
            ss[j]=st;
        }
        for (k=0;k<m;k++)
        {
            string tt[4];
            tt[0]=ss[0].substr(k*3,3);
            tt[1]=ss[1].substr(k*3,3);
            tt[2]=ss[2].substr(k*3,3);
            int tp=0;
            for (l=0;l<7;l++)
            {
                if (s[l][0]==tt[0]&&s[l][1]==tt[1]&&s[l][2]==tt[2])
                {
                    tp|=1;
                }
            }
            for (l=0;l<7;l++)
            {
                if (t[l][0]==tt[0]&&t[l][1]==tt[1]&&t[l][2]==tt[2])
                {
                    tp|=2;
                }
            }
            a[i][k]=tp;
        }
    }
    cin>>ss[0];
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    for (i=1;i<=m;i++)
    {
        if (i-2>=0)
        {
            for (j=0;j<n;j++)
            {
                b[j]=a[j][i-2];
            }
            for (j=0;j<n;j++)
            {
                c[j]=a[j][i-1];
            }
            dp[i]+=dp[i-2]*gao();
            dp[i]%=mod;
        }
        if (i-1>=0)
        {
            for (j=0;j<n;j++)
            {
                b[j]=a[j][i-1];
            }
            if (can())
            {
                dp[i]+=dp[i-1];
            }
        }
    }
    cout<<dp[m]<<endl;
    return 0;
}


#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
#define pb push_back
using namespace std;
const string s[][3]=
{
    {
        "...",
        "...",
        "..."
    },
    {
        "...",
        ".O.",
        "..."
    },
    {
        "..O",
        "...",
        "O.."
    }
    ,
    {
        "..O",
        ".O.",
        "O.."
    }
    ,
    {
        "O.O",
        "...",
        "O.O"
    }
    ,
    {
        "O.O",
        ".O.",
        "O.O"
    },
    {
        "O.O",
        "O.O",
        "O.O"
    }

};
const string t[][3]=
{
    {
        "...",
        "...",
        "..."
    },
    {
        "...",
        ".O.",
        "..."
    },
    {
        "O..",
        "...",
        "..O"
    }
    ,
    {
        "O..",
        ".O.",
        "..O"
    }
    ,
    {
        "O.O",
        "...",
        "O.O"
    }
    ,
    {
        "O.O",
        ".O.",
        "O.O"
    },
    {
        "OOO",
        "...",
        "OOO"
    }

};
int a[300][300];
int n,m;
char st[300][300];
const long long mod=1000000007;
long long dp[400];
int b[400],c[400];
bool can()
{
    if (n&1)return 0;
    int i;
    for (i=0;i<n;i++)
    {
        if ((b[i]&1)==0)return 0;
    }
    return 1;
}
long long dp1[400];
long long gao()
{
    long long res=0;
    int i,j,k;
    memset(dp1,0,sizeof(dp1));
    dp1[0]=1;
    for (i=1;i<=n;i++)
    {
        if ((b[i-1]&2)&&(c[i-1]&2))
        {
            dp1[i]+=dp1[i-1];
            dp1[i]%=mod;
        }
        if (i-2>=0)
        {
            if ((b[i-2]&1)&&(b[i-1]&1)&&(c[i-2]&1)&&(c[i-1]&1))
            {
                dp1[i]+=dp1[i-2];
                dp1[i]%=mod;
            }
        }
    }
    int x=1;
    x&=can();
    memcpy(b,c,sizeof(b));
    x&=can();
    dp1[n]-=x;
    dp1[n]=(dp1[n]%mod+mod)%mod;
    return dp1[n];
}
int main()
{
    int i,j,k,l;
    string ss[4];
    cin>>n>>m;
    for (i=0;i<n;i++)
    {
        cin>>ss[0];
        for (j=0;j<3;j++)cin>>ss[j];
        for (j=0;j<3;j++)
        {
            string st="";
            for (k=0;k<4*m+1;k++)
            {
                if (ss[j][k]!='#')st+=ss[j][k];
            }
            ss[j]=st;
        }
        for (k=0;k<m;k++)
        {
            string tt[4];
            tt[0]=ss[0].substr(k*3,3);
            tt[1]=ss[1].substr(k*3,3);
            tt[2]=ss[2].substr(k*3,3);
            int tp=0;
            for (l=0;l<7;l++)
            {
                if (s[l][0]==tt[0]&&s[l][1]==tt[1]&&s[l][2]==tt[2])
                {
                    tp|=1;
                }
            }
            for (l=0;l<7;l++)
            {
                if (t[l][0]==tt[0]&&t[l][1]==tt[1]&&t[l][2]==tt[2])
                {
                    tp|=2;
                }
            }
            a[i][k]=tp;
        }
    }
    cin>>ss[0];
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    for (i=1;i<=m;i++)
    {
        if (i-2>=0)
        {
            for (j=0;j<n;j++)
            {
                b[j]=a[j][i-2];
            }
            for (j=0;j<n;j++)
            {
                c[j]=a[j][i-1];
            }
            dp[i]+=dp[i-2]*gao();
            dp[i]%=mod;
        }
        if (i-1>=0)
        {
            for (j=0;j<n;j++)
            {
                b[j]=a[j][i-1];
            }
            if (can())
            {
                dp[i]+=dp[i-1];
            }
        }
    }
    cout<<dp[m]<<endl;
    return 0;
}


#include <cstdio>
using namespace std;
#include <iostream>
#include <string>

const int MAXN = 500;
const long long MOD = 1000 * 1000 * 1000 + 7;

int n, m;
bool canV[MAXN][MAXN];
bool canH[MAXN][MAXN];

string vert[3][7] = {
{"...", "...", "..O", "..O", "O.O", "O.O", "O.O"},
{"...", ".O.", "...", ".O.", "...", ".O.", "O.O"},
{"...", "...", "O..", "O..", "O.O", "O.O", "O.O"}
};

string hor[3][7] = {
{"...", "...", "O..", "O..", "O.O", "O.O", "OOO"},
{"...", ".O.", "...", ".O.", "...", ".O.", "..."},
{"...", "...", "..O", "..O", "O.O", "O.O", "OOO"},
};

void readRow(int row) {
	string empty;
	cin >> empty;
	string s[3];
	for (int i = 0; i < 3; ++i)
		cin >> s[i];
	for (int i = 0; i < m; ++i) {
		for (int digit = 0; digit <= 6; ++digit) {
			bool ok = true;
			for (int p = 0; p < 3; ++p)
				for (int q = 0; q < 3; ++q)
					if (vert[p][digit][q] != s[p][i * 4 + q + 1])
						ok = false;
			if (ok) canV[row][i] = true;
		}
		for (int digit = 0; digit <= 6; ++digit) {
			bool ok = true;
			for (int p = 0; p < 3; ++p)
				for (int q = 0; q < 3; ++q)
					if (hor[p][digit][q] != s[p][i * 4 + q + 1])
						ok = false;
			if (ok) canH[row][i] = true;
		}
	}
}

void init() {
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		readRow(i);
	}
}

long long ans[MAXN];

void solve() {
	for (int i = 0; i < MAXN; ++i) ans[i] = 0;
	ans[0] = 1;
	for (int col = 0; col < m; ++col) {
		bool can_all_v = true;
		for (int i = 0; i < n; ++i) if (!canV[i][col]) can_all_v = false;
		if (can_all_v && (n % 2 == 0)) {
			ans[col + 1] = (ans[col + 1] + ans[col]) % MOD;
		}
		if (col == m - 1)
			continue;
		//some of them are horisontal. Subtract one variant if have to!
		for (int i = 0; i < n; ++i) if (!canV[i][col + 1]) can_all_v = false;
		long long tmp[MAXN];
		for (int i = 0; i <= n; ++i) tmp[i] = 0;
		tmp[0] = 1;
		for (int i = 0; i < n; ++i) {
			if (canH[i][col] && canH[i][col + 1]) tmp[i + 1] = (tmp[i + 1] + tmp[i]) % MOD;
			if (i == n - 1) continue;
			if (canV[i][col] && canV[i][col + 1] && canV[i + 1][col] && canV[i + 1][col + 1])
				tmp[i + 2] = (tmp[i + 2] + tmp[i]) % MOD;
		}
		long long mn = tmp[n];
		if (can_all_v) {
			mn -= 1;
			if (mn < 0) mn += MOD;
		}
//		cerr << "mn = " << mn << endl;
		ans[col + 2] = (ans[col + 2] + mn * ans[col]) % MOD;
	}
//	for (int i = 0; i <= m; ++i) cout << ans[i] << " ";
//	cout << endl;
	cout << ans[m] << endl;
}

int main() {
	init();
//	for (int i = 0; i < n; ++i) {
//		for (int j = 0; j < m; ++j) cout << canV[i][j];
//		cout << endl;
//	}
	solve();
	return 0;
}


#include <cstdio>
using namespace std;
#include <iostream>
#include <string>

const int MAXN = 500;
const long long MOD = 1000 * 1000 * 1000 + 7;

int n, m;
bool canV[MAXN][MAXN];
bool canH[MAXN][MAXN];

string vert[3][7] = {
{"...", "...", "..O", "..O", "O.O", "O.O", "O.O"},
{"...", ".O.", "...", ".O.", "...", ".O.", "O.O"},
{"...", "...", "O..", "O..", "O.O", "O.O", "O.O"}
};

string hor[3][7] = {
{"...", "...", "O..", "O..", "O.O", "O.O", "OOO"},
{"...", ".O.", "...", ".O.", "...", ".O.", "..."},
{"...", "...", "..O", "..O", "O.O", "O.O", "OOO"},
};

void readRow(int row) {
	string empty;
	cin >> empty;
	string s[3];
	for (int i = 0; i < 3; ++i)
		cin >> s[i];
	for (int i = 0; i < m; ++i) {
		for (int digit = 0; digit <= 6; ++digit) {
			bool ok = true;
			for (int p = 0; p < 3; ++p)
				for (int q = 0; q < 3; ++q)
					if (vert[p][digit][q] != s[p][i * 4 + q + 1])
						ok = false;
			if (ok) canV[row][i] = true;
		}
		for (int digit = 0; digit <= 6; ++digit) {
			bool ok = true;
			for (int p = 0; p < 3; ++p)
				for (int q = 0; q < 3; ++q)
					if (hor[p][digit][q] != s[p][i * 4 + q + 1])
						ok = false;
			if (ok) canH[row][i] = true;
		}
	}
}

void init() {
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		readRow(i);
	}
}

long long ans[MAXN];

void solve() {
	for (int i = 0; i < MAXN; ++i) ans[i] = 0;
	ans[0] = 1;
	for (int col = 0; col < m; ++col) {
		bool can_all_v = (n % 2 == 0);
		for (int i = 0; i < n; ++i) if (!canV[i][col]) can_all_v = false;
		if (can_all_v) {
			ans[col + 1] = (ans[col + 1] + ans[col]) % MOD;
		}
		if (col == m - 1)
			continue;
		//some of them are horisontal. Subtract one variant if have to!
		for (int i = 0; i < n; ++i) if (!canV[i][col + 1]) can_all_v = false;
		long long tmp[MAXN];
		for (int i = 0; i <= n; ++i) tmp[i] = 0;
		tmp[0] = 1;
		for (int i = 0; i < n; ++i) {
			if (canH[i][col] && canH[i][col + 1]) tmp[i + 1] = (tmp[i + 1] + tmp[i]) % MOD;
			if (i == n - 1) continue;
			if (canV[i][col] && canV[i][col + 1] && canV[i + 1][col] && canV[i + 1][col + 1])
				tmp[i + 2] = (tmp[i + 2] + tmp[i]) % MOD;
		}
		long long mn = tmp[n];
		if (can_all_v) {
			mn -= 1;
			if (mn < 0) mn += MOD;
		}
//		cerr << "mn = " << mn << endl;
		ans[col + 2] = (ans[col + 2] + mn * ans[col]) % MOD;
	}
//	for (int i = 0; i <= m; ++i) cout << ans[i] << " ";
//	cout << endl;
	cout << ans[m] << endl;
}

int main() {
	init();
//	for (int i = 0; i < n; ++i) {
//		for (int j = 0; j < m; ++j) cout << canV[i][j];
//		cout << endl;
//	}
	solve();
	return 0;
}


#include <iostream>
#include <string>
#include <vector>
using namespace std;

typedef long long ll;

const int Maxd = 7;
const int Maxn = 255;
const int mod = 1000000007;

vector <string> pic[2][Maxd];
int n, m;
string B[4 * Maxn];
bool v[Maxn][Maxn], h[Maxn][Maxn];
int best[2][Maxn];

void Prepare()
{
     pic[0][0].push_back("..."); pic[0][0].push_back("..."); pic[0][0].push_back("...");
     pic[0][1].push_back("..."); pic[0][1].push_back(".O."); pic[0][1].push_back("...");
     pic[0][2].push_back("..O"); pic[0][2].push_back("..."); pic[0][2].push_back("O..");
     pic[0][3].push_back("..O"); pic[0][3].push_back(".O."); pic[0][3].push_back("O..");
     pic[0][4].push_back("O.O"); pic[0][4].push_back("..."); pic[0][4].push_back("O.O");
     pic[0][5].push_back("O.O"); pic[0][5].push_back(".O."); pic[0][5].push_back("O.O");
     pic[0][6].push_back("O.O"); pic[0][6].push_back("O.O"); pic[0][6].push_back("O.O");
     pic[1][0] = pic[0][0]; pic[1][1] = pic[0][1];
     pic[1][2].push_back("O.."); pic[1][2].push_back("..."); pic[1][2].push_back("..O");
     pic[1][3].push_back("O.."); pic[1][3].push_back(".O."); pic[1][3].push_back("..O");
     pic[1][4] = pic[0][4]; pic[1][5] = pic[0][5];
     pic[1][6].push_back("OOO"); pic[1][6].push_back("..."); pic[1][6].push_back("OOO");
}

bool checkPic(int wh, const vector <string> &V)
{
     for (int i = 0; i < Maxd; i++)
        if (V == pic[wh][i]) return true;
     return false;
}

void getBoard()
{
    std::ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 0; i <= 4 * n; i++)
       cin >> B[i];
    for (int i = 0; i < n; i++)
       for (int j = 0; j < m; j++) {
           vector <string> tmp;
           for (int l = 1; l <= 3; l++)
              tmp.push_back(B[4 * i + l].substr(4 * j + 1, 3));
           v[i][j] = checkPic(0, tmp); h[i][j] = checkPic(1, tmp);
       }
}

int checkVer(int col)
{
    if (n % 2) return 0;
    for (int i = 0; i < n; i++)
       if (!v[i][col]) return 0;
    return 1;
}

int getWays(int col)
{
    int curbest[2][Maxn] = {0};
    curbest[0][n - 1] = v[n - 1][col] && v[n - 1][col + 1];
    curbest[1][n - 1] = h[n - 1][col] && h[n - 1][col + 1];
    for (int i = n - 2; i >= 0; i--) {
        curbest[0][i] = (v[i][col] && v[i][col + 1]) * curbest[1][i + 1];
        curbest[1][i] = (h[i][col] && h[i][col + 1]) * curbest[1][i + 1] +
                        (v[i][col] && v[i][col + 1]) * curbest[0][i + 1];
        curbest[1][i] %= mod;
    }
    int res = curbest[1][0];
    if (checkVer(col) && checkVer(col + 1)) res--;
    if (res < 0) res += mod;
    return res;
}

int main()
{
    Prepare();
    getBoard();
    best[0][m - 1] = checkVer(m - 1); best[1][m - 1] = 0;
    if (m == 1) cout << best[0][m - 1] + best[1][m - 1] << endl;
    else {
         best[0][m - 2] = checkVer(m - 2) * (best[0][m - 1] + best[1][m - 1]);
         best[1][m - 2] = getWays(m - 2);
         for (int j = m - 3; j >= 0; j--) {
             best[0][j] = checkVer(j) * (best[0][j + 1] + best[1][j + 1]) % mod;
             best[1][j] = ll(getWays(j)) * ll((best[0][j + 2] + best[1][j + 2])) % ll(mod);
         }
         cout << (best[0][0] + best[1][0]) % mod << endl;
    }
    return 0;
}


#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;

#define PB push_back
#define MP make_pair

const double pi = 3.1415926535;
const double eps = 1e-6;

const int mod = 1000000007;
map <string, int> hash;
string S;
int n, m, one[300], a[300][300];
long long two[300], g[300], f[300];
char c, st[1200][1200];
void save(string a, int b)
{
    hash[a] = b;
}
int main()
{
    save(".........", 3);
    save("....O....", 3);
    save("O.......O", 1);
    save("..O...O..", 2);
    save("O...O...O", 1);
    save("..O.O.O..", 2);
    save("O.O...O.O", 3);
    save("O.O.O.O.O", 3);
    save("OOO...OOO", 1);
    save("O.OO.OO.O", 2);
    scanf("%d%d\n", &n, &m);
    for (int i = 0; i < n * 4; i++)
        gets(st[i]);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            S = "";
            for (int x = 1; x < 4; x++)
                for (int y = 1; y < 4; y++)
                        S += st[(i - 1) * 4 + x][(j - 1) * 4 + y];
            a[i][j] = hash[S];
        }
    }
    for (int i = 1; i <= m; i++) {
        one[i] = 1;
        for (int j = 1; j <= n; j++)
            if (!(a[j][i] & 2))
                one[i] = 0;
        if (n & 1)
            one[i] = 0;
    }
    for (int i = 2; i <= m; i++) {
        g[0] = 1;
        for (int j = 1; j <= n; j++) {
            g[j] = 0;
            if ((a[j][i - 1] & 1) && (a[j][i] & 1))
                g[j] = (g[j] + g[j - 1]) % mod;
            if (j >= 2) {
                if ((a[j - 1][i - 1] & 2) && (a[j - 1][i] & 2))
                if ((a[j][i - 1] & 2) && (a[j][i] & 2))
                    g[j] = (g[j] + g[j - 2]) % mod;
            }
        }
        two[i] = g[n];
        if (one[i] && one[i - 1])
            two[i]--;
    }
    f[0] = 1;
    for (int i = 1; i <= m; i++) {
        f[i] = f[i] + f[i - 1] * one[i];
        if (i >= 2)
            f[i] = f[i] + f[i - 2] * two[i];
        f[i] %= 1000000007;
    }
    printf("%d\n", (int)f[m]);
}


#include <bits/stdc++.h>

#define FOR(i,a,b) for(int i=(a),_b=(b); i<=_b; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b); i>=_b; i--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; i++)
#define FORN(i,a,b) for(int i=(a),_b=(b);i<_b;i++)
#define DOWN(i,a,b) for(int i=a,_b=(b);i>=_b;i--)
#define SET(a,v) memset(a,v,sizeof(a))
#define sqr(x) ((x)*(x))
#define ll long long
#define F first
#define S second
#define PB push_back
#define MP make_pair

#define DEBUG(x) cout << #x << " = "; cout << x << endl;
#define PR(a,n) cout << #a << " = "; FOR(_,1,n) cout << a[_] << ' '; cout << endl;
#define PR0(a,n) cout << #a << " = "; REP(_,n) cout << a[_] << ' '; cout << endl;
using namespace std;

//Buffer reading
int INP,AM,REACHEOF;
const int BUFSIZE = (1<<12) + 17;
char BUF[BUFSIZE+1], *inp=BUF;
#define GETCHAR(INP) { \
    if(!*inp && !REACHEOF) { \
        memset(BUF,0,sizeof BUF);\
        int inpzzz = fread(BUF,1,BUFSIZE,stdin);\
        if (inpzzz != BUFSIZE) REACHEOF = true;\
        inp=BUF; \
    } \
    INP=*inp++; \
}
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define GN(j) { \
    AM=0;\
    GETCHAR(INP); while(!DIG(INP) && INP!='-') GETCHAR(INP);\
    if (INP=='-') {AM=1;GETCHAR(INP);} \
    j=INP-'0'; GETCHAR(INP); \
    while(DIG(INP)){j=10*j+(INP-'0');GETCHAR(INP);} \
    if (AM) j=-j;\
}
//End of buffer reading

const int MN = 1011;
const int MOD = (int) (1e9 + 7);

int m, n;
char s[MN][MN];
int a[MN][MN];

long long f[MN], cnt[MN][MN];

void solve() {
    memset(cnt, 0, sizeof cnt);
    memset(f, 0, sizeof f);

    f[0] = 1;
    FOR(j,1,n) {
        // All vertical
        bool check = m % 2 == 0;
        FOR(i,1,m) if (a[i][j] == 2) check = false;

        if (check) f[j] = f[j-1]; // Put all vertical at column j
        else f[j] = 0;

        if (j >= 2) {
            cnt[m+1][j] = 1;
            FORD(i,m,1) {
                cnt[i][j] = 0;
                if (a[i][j] != 1 && a[i][j-1] != 1) {
                    cnt[i][j] = (cnt[i][j] + cnt[i+1][j]) % MOD;
                }
                if (i <= m-1
                        && a[i  ][j] != 2 && a[i  ][j-1] != 2
                        && a[i+1][j] != 2 && a[i+1][j-1] != 2) {
                    cnt[i][j] = (cnt[i][j] + cnt[i+2][j]) % MOD;
                }
            }

            FOR(i,1,m) { // First horizontal at i
                if ((i-1) % 2 == 0 && a[i][j] != 1 && a[i][j-1] != 1) {
                    f[j] = (f[j] + f[j-2] * cnt[i+1][j]) % MOD;
                }
                if (a[i][j] == 2 || a[i][j-1] == 2) break;
            }
        }
    }
}

int main() {
    while (scanf("%d%d\n", &m, &n) == 2) {
        FOR(i,1,4*m+1) {
            scanf("%s\n", &s[i][1]);
        }
        for(int i = 1, r = 2; i <= m; ++i, r += 4) {
            for(int j = 1, c = 2; j <= n; ++j, c += 4) {
                int cnt = 0;
                FOR(u,r,r+2) FOR(v,c,c+2)
                    if (s[u][v] == 'O')
                        ++cnt;
                if (cnt == 0 || cnt == 1 || cnt == 4 || cnt == 5) {
                    a[i][j] = 3;
                }
                else if (cnt == 2 || cnt == 3) {
                    if (s[r][c] == 'O')
                        a[i][j] = 2;
                    else a[i][j] = 1;
                }
                else {
                    if (s[r+1][c] == 'O')
                        a[i][j] = 1;
                    else a[i][j] = 2;
                }
            }
        }
        // FOR(i,1,m) { PR(a[i], n); }

        solve();
        cout << f[n] << endl;
    }
    return 0;
}


#include <bits/stdc++.h>

#define FOR(i,a,b) for(int i=(a),_b=(b); i<=_b; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b); i>=_b; i--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; i++)
#define FORN(i,a,b) for(int i=(a),_b=(b);i<_b;i++)
#define DOWN(i,a,b) for(int i=a,_b=(b);i>=_b;i--)
#define SET(a,v) memset(a,v,sizeof(a))
#define sqr(x) ((x)*(x))
#define ll long long
#define F first
#define S second
#define PB push_back
#define MP make_pair

#define DEBUG(x) cout << #x << " = "; cout << x << endl;
#define PR(a,n) cout << #a << " = "; FOR(_,1,n) cout << a[_] << ' '; cout << endl;
#define PR0(a,n) cout << #a << " = "; REP(_,n) cout << a[_] << ' '; cout << endl;
using namespace std;

//Buffer reading
int INP,AM,REACHEOF;
const int BUFSIZE = (1<<12) + 17;
char BUF[BUFSIZE+1], *inp=BUF;
#define GETCHAR(INP) { \
    if(!*inp && !REACHEOF) { \
        memset(BUF,0,sizeof BUF);\
        int inpzzz = fread(BUF,1,BUFSIZE,stdin);\
        if (inpzzz != BUFSIZE) REACHEOF = true;\
        inp=BUF; \
    } \
    INP=*inp++; \
}
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define GN(j) { \
    AM=0;\
    GETCHAR(INP); while(!DIG(INP) && INP!='-') GETCHAR(INP);\
    if (INP=='-') {AM=1;GETCHAR(INP);} \
    j=INP-'0'; GETCHAR(INP); \
    while(DIG(INP)){j=10*j+(INP-'0');GETCHAR(INP);} \
    if (AM) j=-j;\
}
//End of buffer reading

const int MN = 1011;
const int MOD = (int) (1e9 + 7);

int m, n;
char s[MN][MN];
int a[MN][MN];

long long f[MN], cnt[MN][MN];

void solve() {
    memset(cnt, 0, sizeof cnt);
    memset(f, 0, sizeof f);

    f[0] = 1;
    FOR(j,1,n) {
        // All vertical
        bool check = m % 2 == 0;
        FOR(i,1,m) if (a[i][j] == 2) check = false;

        if (check) f[j] = 1;
        else f[j] = 0;

        if (j >= 2) {
            cnt[m+1][j] = 1;
            FORD(i,m,1) {
                cnt[i][j] = 0;
                if (a[i][j] != 1 && a[i][j-1] != 1) {
                    cnt[i][j] = (cnt[i][j] + cnt[i+1][j]) % MOD;
                }
                if (i <= m-1
                        && a[i  ][j] != 2 && a[i  ][j-1] != 2
                        && a[i+1][j] != 2 && a[i+1][j-1] != 2) {
                    cnt[i][j] = (cnt[i][j] + cnt[i+2][j]) % MOD;
                }
            }

            FOR(i,1,m) { // First horizontal at i
                if ((i-1) % 2 == 0 && a[i][j] != 1 && a[i][j-1] != 1) {
                    f[j] = (f[j] + f[j-2] * cnt[i+1][j]) % MOD;
                }
                if (a[i][j] == 2 || a[i][j-1] == 2) break;
            }
        }
    }
}

int main() {
    while (scanf("%d%d\n", &m, &n) == 2) {
        FOR(i,1,4*m+1) {
            scanf("%s\n", &s[i][1]);
        }
        for(int i = 1, r = 2; i <= m; ++i, r += 4) {
            for(int j = 1, c = 2; j <= n; ++j, c += 4) {
                int cnt = 0;
                FOR(u,r,r+2) FOR(v,c,c+2)
                    if (s[u][v] == 'O')
                        ++cnt;
                if (cnt == 0 || cnt == 1 || cnt == 4 || cnt == 5) {
                    a[i][j] = 3;
                }
                else if (cnt == 2 || cnt == 3) {
                    if (s[r][c] == 'O')
                        a[i][j] = 2;
                    else a[i][j] = 1;
                }
                else {
                    if (s[r+1][c] == 'O')
                        a[i][j] = 1;
                    else a[i][j] = 2;
                }
            }
        }
        // FOR(i,1,m) { PR(a[i], n); }

        solve();
        cout << f[n] << endl;
    }
    return 0;
}


#include <bits/stdc++.h>

#define FOR(i,a,b) for(int i=(a),_b=(b); i<=_b; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b); i>=_b; i--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; i++)
#define FORN(i,a,b) for(int i=(a),_b=(b);i<_b;i++)
#define DOWN(i,a,b) for(int i=a,_b=(b);i>=_b;i--)
#define SET(a,v) memset(a,v,sizeof(a))
#define sqr(x) ((x)*(x))
#define ll long long
#define F first
#define S second
#define PB push_back
#define MP make_pair

#define DEBUG(x) cout << #x << " = "; cout << x << endl;
#define PR(a,n) cout << #a << " = "; FOR(_,1,n) cout << a[_] << ' '; cout << endl;
#define PR0(a,n) cout << #a << " = "; REP(_,n) cout << a[_] << ' '; cout << endl;
using namespace std;

//Buffer reading
int INP,AM,REACHEOF;
const int BUFSIZE = (1<<12) + 17;
char BUF[BUFSIZE+1], *inp=BUF;
#define GETCHAR(INP) { \
    if(!*inp && !REACHEOF) { \
        memset(BUF,0,sizeof BUF);\
        int inpzzz = fread(BUF,1,BUFSIZE,stdin);\
        if (inpzzz != BUFSIZE) REACHEOF = true;\
        inp=BUF; \
    } \
    INP=*inp++; \
}
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define GN(j) { \
    AM=0;\
    GETCHAR(INP); while(!DIG(INP) && INP!='-') GETCHAR(INP);\
    if (INP=='-') {AM=1;GETCHAR(INP);} \
    j=INP-'0'; GETCHAR(INP); \
    while(DIG(INP)){j=10*j+(INP-'0');GETCHAR(INP);} \
    if (AM) j=-j;\
}
//End of buffer reading

const int MN = 1011;
const int MOD = (int) (1e9 + 7);

int m, n;
char s[MN][MN];
int a[MN][MN];

long long f[MN], cnt[MN][MN];

void solve() {
    memset(cnt, 0, sizeof cnt);
    memset(f, 0, sizeof f);

    f[0] = 1;
    FOR(j,1,n) {
        // All vertical
        bool check = m % 2 == 0;
        FOR(i,1,m) if (a[i][j] == 2) check = false;

        if (check) f[j] = f[j-1]; // Put all vertical at column j
        else f[j] = 0;

        if (j >= 2) {
            cnt[m+1][j] = 1;
            FORD(i,m,1) {
                cnt[i][j] = 0;
                if (a[i][j] != 1 && a[i][j-1] != 1) {
                    cnt[i][j] = (cnt[i][j] + cnt[i+1][j]) % MOD;
                }
                if (i <= m-1
                        && a[i  ][j] != 2 && a[i  ][j-1] != 2
                        && a[i+1][j] != 2 && a[i+1][j-1] != 2) {
                    cnt[i][j] = (cnt[i][j] + cnt[i+2][j]) % MOD;
                }
            }

            FOR(i,1,m) { // First horizontal at i
                if ((i-1) % 2 == 0 && a[i][j] != 1 && a[i][j-1] != 1) {
                    f[j] = (f[j] + f[j-2] * cnt[i+1][j]) % MOD;
                }
                if (a[i][j] == 2 || a[i][j-1] == 2) break;
            }
        }
    }
}

int main() {
    while (scanf("%d%d\n", &m, &n) == 2) {
        FOR(i,1,4*m+1) {
            scanf("%s\n", &s[i][1]);
        }
        for(int i = 1, r = 2; i <= m; ++i, r += 4) {
            for(int j = 1, c = 2; j <= n; ++j, c += 4) {
                int cnt = 0;
                FOR(u,r,r+2) FOR(v,c,c+2)
                    if (s[u][v] == 'O')
                        ++cnt;
                if (cnt == 0 || cnt == 1 || cnt == 4 || cnt == 5) {
                    a[i][j] = 3;
                }
                else if (cnt == 2 || cnt == 3) {
                    if (s[r][c] == 'O')
                        a[i][j] = 2;
                    else a[i][j] = 1;
                }
                else {
                    if (s[r+1][c] == 'O')
                        a[i][j] = 1;
                    else a[i][j] = 2;
                }
            }
        }
        // FOR(i,1,m) { PR(a[i], n); }

        solve();
        PR(f, n);
        cout << f[n] << endl;
    }
    return 0;
}


#include <bits/stdc++.h>

#define FOR(i,a,b) for(int i=(a),_b=(b); i<=_b; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b); i>=_b; i--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; i++)
#define FORN(i,a,b) for(int i=(a),_b=(b);i<_b;i++)
#define DOWN(i,a,b) for(int i=a,_b=(b);i>=_b;i--)
#define SET(a,v) memset(a,v,sizeof(a))
#define sqr(x) ((x)*(x))
#define ll long long
#define F first
#define S second
#define PB push_back
#define MP make_pair

#define DEBUG(x) cout << #x << " = "; cout << x << endl;
#define PR(a,n) cout << #a << " = "; FOR(_,1,n) cout << a[_] << ' '; cout << endl;
#define PR0(a,n) cout << #a << " = "; REP(_,n) cout << a[_] << ' '; cout << endl;
using namespace std;

//Buffer reading
int INP,AM,REACHEOF;
const int BUFSIZE = (1<<12) + 17;
char BUF[BUFSIZE+1], *inp=BUF;
#define GETCHAR(INP) { \
    if(!*inp && !REACHEOF) { \
        memset(BUF,0,sizeof BUF);\
        int inpzzz = fread(BUF,1,BUFSIZE,stdin);\
        if (inpzzz != BUFSIZE) REACHEOF = true;\
        inp=BUF; \
    } \
    INP=*inp++; \
}
#define DIG(a) (((a)>='0')&&((a)<='9'))
#define GN(j) { \
    AM=0;\
    GETCHAR(INP); while(!DIG(INP) && INP!='-') GETCHAR(INP);\
    if (INP=='-') {AM=1;GETCHAR(INP);} \
    j=INP-'0'; GETCHAR(INP); \
    while(DIG(INP)){j=10*j+(INP-'0');GETCHAR(INP);} \
    if (AM) j=-j;\
}
//End of buffer reading

const int MN = 1011;
const int MOD = (int) (1e9 + 7);

int m, n;
char s[MN][MN];
int a[MN][MN];

long long f[MN], cnt[MN][MN];

void solve() {
    memset(cnt, 0, sizeof cnt);
    memset(f, 0, sizeof f);

    f[0] = 1;
    FOR(j,1,n) {
        // All vertical
        bool check = m % 2 == 0;
        FOR(i,1,m) if (a[i][j] == 2) check = false;

        if (check) f[j] = 1; // Put all vertical at column j
        else f[j] = 0;

        if (j >= 2) {
            cnt[m+1][j] = 1;
            FORD(i,m,1) {
                cnt[i][j] = 0;
                if (a[i][j] != 1 && a[i][j-1] != 1) {
                    cnt[i][j] = (cnt[i][j] + cnt[i+1][j]) % MOD;
                }
                if (i <= m-1
                        && a[i  ][j] != 2 && a[i  ][j-1] != 2
                        && a[i+1][j] != 2 && a[i+1][j-1] != 2) {
                    cnt[i][j] = (cnt[i][j] + cnt[i+2][j]) % MOD;
                }
            }

            FOR(i,1,m) { // First horizontal at i
                bool ok = true;
                FOR(ii,1,i-1) {
                    if (a[ii][j-1] == 2 || a[ii][j] == 2) {
                        ok = false;
                        break;
                    }
                }
                if (!ok) break;
                if ((i-1) % 2 == 0 && a[i][j] != 1 && a[i][j-1] != 1) {
                    f[j] = (f[j] + f[j-2] * cnt[i+1][j]) % MOD;
                }
            }
        }
    }
}

int main() {
    while (scanf("%d%d\n", &m, &n) == 2) {
        FOR(i,1,4*m+1) {
            scanf("%s\n", &s[i][1]);
        }
        for(int i = 1, r = 2; i <= m; ++i, r += 4) {
            for(int j = 1, c = 2; j <= n; ++j, c += 4) {
                int cnt = 0;
                FOR(u,r,r+2) FOR(v,c,c+2)
                    if (s[u][v] == 'O')
                        ++cnt;
                if (cnt == 0 || cnt == 1 || cnt == 4 || cnt == 5) {
                    a[i][j] = 3;
                }
                else if (cnt == 2 || cnt == 3) {
                    if (s[r][c] == 'O')
                        a[i][j] = 2;
                    else a[i][j] = 1;
                }
                else {
                    if (s[r+1][c] == 'O')
                        a[i][j] = 1;
                    else a[i][j] = 2;
                }
            }
        }
        // FOR(i,1,m) { PR(a[i], n); }

        solve();
        cout << f[n] << endl;
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>

using namespace std;

typedef long long ll;

const int maxN= 300;
const int mod = 1000*1000*1000 + 7;

char type[maxN][maxN], mat[maxN][maxN];
int n,m;
int dp[maxN], tdp[maxN];

inline char check (int row, int col){
    int ret=0;

    for (int i=0;i<=2;i++)
        for (int j=0;j<=2;j++)
            ret+= (mat[row+i][col+j]=='O');

    if (ret==0 || ret==1 || ret==4 || ret==5)
        return '?';

    if (ret==2 || ret==3)
        return (mat[row][col]=='O') ? 'h' : 'v';

    return (mat[row][col+1]=='O') ? 'h' : 'v';
}
/******************************************/
inline void setGrid(){
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            type[i][j]= check(4*i-3, 4*j-3);
}
/*****************************************/
inline bool ok (int col){
    for (int i=1;i<=n;i++) if (type[i][col]=='h')
        return false;
    return n%2==0;
}
/*****************************************/
inline int solve (int col, int s, int e){
    if (e<=s)
        return 1;

    tdp[s-1]= 1;
    tdp[s]  = (type[s][col]=='?' && type[s][col-1]=='?');

    for (int i=s+1; i<e ;i++){
        tdp[i]=0;
        if (type[i][col]=='?' && type[i][col-1]=='?')
            tdp[i]= tdp[i-1];

        tdp[i]= (tdp[i] + tdp[i-2])%mod;
    }

    return tdp[e-1];
}
/*****************************************/
inline void setDyn (){
    dp[1]= ok(1);

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

        if (ok(j) && (!ok(j-1)))
            dp[j]= dp[j-1];

        bool flag= false;
        for (int i=1;i<=n;i++) if ((type[i][j]=='h' && type[i][j-1]=='v') || (type[i][j]=='v' && type[i][j-1]=='h')){
            flag= true; break;
        }

        if (flag)
            continue;

        vector <int> Q;

        Q.push_back (1);
        for (int i=1;i<=n;i++) if (type[i][j]=='h' || type[i][j-1]=='h'){
            Q.push_back (i);
        }
        Q.push_back (n+1);

        ll tmp=1;
        for (int i=1;i<(int)Q.size();i++)
            tmp= (tmp * solve (j,Q[i-1],Q[i]))%mod;

        dp[j]= (dp[j] + tmp)%mod;

    }
}
/*****************************************/
int main(){
    scanf ("%d%d", &n, &m);
    for (int i=0;i<4*n+1;i++)
        scanf ("%s", mat[i]);

    setGrid();
    setDyn ();

    printf ("%d\n", dp[m]);

    return 0;
}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <algorithm>
#include <cstring>

using namespace std;

#define REP(a,b) for(int (a)=0;a<(int)b;a++)
#define FOR(a,b,c) for(int (a)=b;a<(int)c;a++)
#define REPR(a,b) for(int (a)=b;a>=0;a--)
#define MP(A,B) pair<long long, long long>(A,B)
#define PB push_back
#define S(a) scanf("%d",&a)
#define SCH(a) scanf("%s",a)
#define foreach(a,b) for(__typeof(b).begin() a  = b.begin(); a != b.end();a++)

int arr[250][250];

// 0 -> Down
// 1 -> Left
// 2 -> both
int val[250][250];

char ch[4][5*250];

int A[7]={0,16,68,84,325,341,365};
int B[7]={0,16,257,273,325,341,455};

bool vertical[250];
long long dp[250][250];
long long sol[250];

long long MOD = 1000000007;

int N;
int M;

bool CanL(int y, int x)
{
	return val[y][x]==1 || val[y][x]==2;
}

bool CanH(int y, int x)
{
	return val[y][x]==0 || val[y][x]==2;
}

long long Calc(int y, int x)
{
	if(y==N)
	{
		return 1;
	}
	else if(dp[y][x]==-1)
	{
		dp[y][x]=0;

		// one horizontal line
		if(CanL(y,x) && CanL(y,x+1))
		{
			dp[y][x]+=Calc(y+1,x);
		}

		// two vertical lines
		if(y+1<N && CanH(y,x) && CanH(y+1,x) && CanH(y,x+1) && CanH(y+1,x+1) )
		{
			dp[y][x]+=Calc(y+2,x);
		}

		dp[y][x]%=MOD;
	}

	return dp[y][x];
}

int main()
{
	S(N);S(M);
	REP(n,N)
	{
		REP(m,4)
		{
			scanf("%s",ch[m]);
			if(N==4 && M==4)
			{
				cout<<ch[m]<<endl;
			}
		}

		for(int m=0;m<M;m++)
		{
			int k=1+m*4;
			int num=1;
			arr[n][m]=0;
			for(int a=0;a<3;a++)
			{
				for(int b=0;b<3;b++)
				{
					arr[n][m]+=(ch[1+a][k+b]=='O'?1:0)*num;
					num*=2;
				}
			}

			//cout<<arr[n][m]<<endl;

			bool x[]={false,false};
			REP(j,7)
			{
				if(A[j]==arr[n][m])
				{
					x[0]=true;
				}

				if(B[j]==arr[n][m])
				{
					x[1]=true;
				}
			}

			if(x[0] && x[1])
			{
				val[n][m]=2;
			}
			else if(x[0])
			{
				val[n][m]=0;
			}
			else if(x[1])
			{
				val[n][m]=1;
			}
			else
			{
				puts("SHOULD NEVER HAPPEN");
			}
		}
	}

	// test whether a vertical line is possible
	REP(m,M)
	{
		vertical[m]=true;
		if(N%2==1)
		{
			vertical[m]=false;
		}
		else
		{
			REP(n,N)
			{
				if(val[n][m]==1)
				{
					vertical[m]=false;
				}
			}
		}
	}

	memset(dp,-1,sizeof(dp));

	REP(m,M-1)
	{
		Calc(0,m);
	}

	sol[0]=vertical[0];

	if(M>1)
	{
		sol[1]=dp[0][0];

		FOR(m,2,M)
		{
			sol[m]=vertical[m]*sol[m-1]+sol[m-2]*dp[0][m-1]-sol[m-2]*vertical[m-1]*vertical[m];
		}
	}

	cout<<sol[M-1]<<endl;

}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <algorithm>
#include <cstring>

using namespace std;

#define REP(a,b) for(int (a)=0;a<(int)b;a++)
#define FOR(a,b,c) for(int (a)=b;a<(int)c;a++)
#define REPR(a,b) for(int (a)=b;a>=0;a--)
#define MP(A,B) pair<long long, long long>(A,B)
#define PB push_back
#define S(a) scanf("%d",&a)
#define SCH(a) scanf("%s",a)
#define foreach(a,b) for(__typeof(b).begin() a  = b.begin(); a != b.end();a++)

int arr[250][250];

// 0 -> Down
// 1 -> Left
// 2 -> both
int val[250][250];

char ch[4][5*250];

int A[7]={0,16,68,84,325,341,365};
int B[7]={0,16,257,273,325,341,455};

bool vertical[250];
long long dp[250][250];
long long sol[250];

long long MOD = 1000000007;

int N;
int M;

bool CanL(int y, int x)
{
	return val[y][x]==1 || val[y][x]==2;
}

bool CanH(int y, int x)
{
	return val[y][x]==0 || val[y][x]==2;
}

long long Calc(int y, int x)
{
	if(y==N)
	{
		return 1;
	}
	else if(dp[y][x]==-1)
	{
		dp[y][x]=0;

		// one horizontal line
		if(CanL(y,x) && CanL(y,x+1))
		{
			dp[y][x]+=Calc(y+1,x);
		}

		// two vertical lines
		if(y+1<N && CanH(y,x) && CanH(y+1,x) && CanH(y,x+1) && CanH(y+1,x+1) )
		{
			dp[y][x]+=Calc(y+2,x);
		}

		dp[y][x]%=MOD;
	}

	return dp[y][x];
}

int main()
{
	S(N);S(M);
	REP(n,N)
	{
		REP(m,4)
		{
			scanf("%s",ch[m]);
		}

		for(int m=0;m<M;m++)
		{
			int k=1+m*4;
			int num=1;
			arr[n][m]=0;
			for(int a=0;a<3;a++)
			{
				for(int b=0;b<3;b++)
				{
					arr[n][m]+=(ch[1+a][k+b]=='O'?1:0)*num;
					num*=2;
				}
			}

			//cout<<arr[n][m]<<endl;

			bool x[]={false,false};
			REP(j,7)
			{
				if(A[j]==arr[n][m])
				{
					x[0]=true;
				}

				if(B[j]==arr[n][m])
				{
					x[1]=true;
				}
			}

			if(x[0] && x[1])
			{
				val[n][m]=2;
			}
			else if(x[0])
			{
				val[n][m]=0;
			}
			else if(x[1])
			{
				val[n][m]=1;
			}
			else
			{
				puts("SHOULD NEVER HAPPEN");
			}
		}
	}

	// test whether a vertical line is possible
	REP(m,M)
	{
		vertical[m]=true;
		if(N%2==1)
		{
			vertical[m]=false;
		}
		else
		{
			REP(n,N)
			{
				if(val[n][m]==1)
				{
					vertical[m]=false;
				}
			}
		}
	}

	memset(dp,-1,sizeof(dp));

	REP(m,M-1)
	{
		Calc(0,m);
	}

	sol[0]=vertical[0];

	if(M>1)
	{
		sol[1]=dp[0][0];

		FOR(m,2,M)
		{
			sol[m]=vertical[m]*sol[m-1]+sol[m-2]*dp[0][m-1]-sol[m-2]*vertical[m-1]*vertical[m];

			sol[m]=(sol[m]+MOD)%MOD;
		}
	}

	cout<<sol[M-1]<<endl;

}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <algorithm>
#include <cstring>

using namespace std;

#define REP(a,b) for(int (a)=0;a<(int)b;a++)
#define FOR(a,b,c) for(int (a)=b;a<(int)c;a++)
#define REPR(a,b) for(int (a)=b;a>=0;a--)
#define MP(A,B) pair<long long, long long>(A,B)
#define PB push_back
#define S(a) scanf("%d",&a)
#define SCH(a) scanf("%s",a)
#define foreach(a,b) for(__typeof(b).begin() a  = b.begin(); a != b.end();a++)

int arr[250][250];

// 0 -> Down
// 1 -> Left
// 2 -> both
int val[250][250];

char ch[4][5*250];

int A[7]={0,16,68,84,325,341,365};
int B[7]={0,16,257,273,325,341,455};

bool vertical[250];
long long dp[250][250];
long long sol[250];

long long MOD = 1000000007;

int N;
int M;

bool CanL(int y, int x)
{
	return val[y][x]==1 || val[y][x]==2;
}

bool CanH(int y, int x)
{
	return val[y][x]==0 || val[y][x]==2;
}

long long Calc(int y, int x)
{
	if(y==N)
	{
		return 1;
	}
	else if(dp[y][x]==-1)
	{
		dp[y][x]=0;

		// one horizontal line
		if(CanL(y,x) && CanL(y,x+1))
		{
			dp[y][x]+=Calc(y+1,x);
		}

		// two vertical lines
		if(y+1<N && CanH(y,x) && CanH(y+1,x) && CanH(y,x+1) && CanH(y+1,x+1) )
		{
			dp[y][x]+=Calc(y+2,x);
		}

		dp[y][x]%=MOD;
	}

	return dp[y][x];
}

int main()
{
	S(N);S(M);
	REP(n,N)
	{
		REP(m,4)
		{
			scanf("%s",ch[m]);
		}

		for(int m=0;m<M;m++)
		{
			int k=1+m*4;
			int num=1;
			arr[n][m]=0;
			for(int a=0;a<3;a++)
			{
				for(int b=0;b<3;b++)
				{
					arr[n][m]+=(ch[1+a][k+b]=='O'?1:0)*num;
					num*=2;
				}
			}

			//cout<<arr[n][m]<<endl;

			bool x[]={false,false};
			REP(j,7)
			{
				if(A[j]==arr[n][m])
				{
					x[0]=true;
				}

				if(B[j]==arr[n][m])
				{
					x[1]=true;
				}
			}

			if(x[0] && x[1])
			{
				val[n][m]=2;
			}
			else if(x[0])
			{
				val[n][m]=0;
			}
			else if(x[1])
			{
				val[n][m]=1;
			}
			else
			{
			//	puts("SHOULD NEVER HAPPEN");
			}
		}
	}

	/*REP(n,N)
	{
		REP(m,M)
		{
			cout<<val[n][m]<<" ";
		}
		cout<<endl;
	}*/

	// test whether a vertical line is possible
	REP(m,M)
	{
		vertical[m]=true;
		if(N%2==1)
		{
			vertical[m]=false;
		}
		else
		{
			REP(n,N)
			{
				if(val[n][m]==1)
				{
					vertical[m]=false;
				}
			}
		}
	}

	memset(dp,-1,sizeof(dp));

	REP(m,M-1)
	{
		Calc(0,m);
	}

	sol[0]=vertical[0];

	if(M>1)
	{
		sol[1]=dp[0][0];
		sol[1]%=MOD;

		FOR(m,2,M)
		{
			sol[m]=vertical[m]*sol[m-1]+sol[m-2]*dp[0][m-1]-sol[m-2]*vertical[m-1]*vertical[m];
			sol[m]=(sol[m]+M)%M;
		}
	}

	cout<<sol[M-1]<<endl;

}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <algorithm>
#include <cstring>

using namespace std;

#define REP(a,b) for(int (a)=0;a<(int)b;a++)
#define FOR(a,b,c) for(int (a)=b;a<(int)c;a++)
#define REPR(a,b) for(int (a)=b;a>=0;a--)
#define MP(A,B) pair<long long, long long>(A,B)
#define PB push_back
#define S(a) scanf("%d",&a)
#define SCH(a) scanf("%s",a)
#define foreach(a,b) for(__typeof(b).begin() a  = b.begin(); a != b.end();a++)

int arr[250][250];

// 0 -> Down
// 1 -> Left
// 2 -> both
int val[250][250];

char ch[4][5*250];

int A[7]={0,16,68,84,325,341,365};
int B[7]={0,16,257,273,325,341,455};

bool vertical[250];
long long dp[250][250];
long long sol[250];

long long MOD = 1000000007;

int N;
int M;

bool CanL(int y, int x)
{
	return val[y][x]==1 || val[y][x]==2;
}

bool CanH(int y, int x)
{
	return val[y][x]==0 || val[y][x]==2;
}

long long Calc(int y, int x)
{
	if(y==N)
	{
		return 1;
	}
	else if(dp[y][x]==-1)
	{
		dp[y][x]=0;

		// one horizontal line
		if(CanL(y,x) && CanL(y,x+1))
		{
			dp[y][x]+=Calc(y+1,x);
		}

		// two vertical lines
		if(y+1<N && CanH(y,x) && CanH(y+1,x) && CanH(y,x+1) && CanH(y+1,x+1) )
		{
			dp[y][x]+=Calc(y+2,x);
		}

		dp[y][x]%=MOD;
	}

	return dp[y][x];
}

int main()
{
	S(N);S(M);
	REP(n,N)
	{
		REP(m,4)
		{
			scanf("%s",ch[m]);
		}

		for(int m=0;m<M;m++)
		{
			int k=1+m*4;
			int num=1;
			arr[n][m]=0;
			for(int a=0;a<3;a++)
			{
				for(int b=0;b<3;b++)
				{
					arr[n][m]+=(ch[1+a][k+b]=='O'?1:0)*num;
					num*=2;
				}
			}

			//cout<<arr[n][m]<<endl;

			bool x[]={false,false};
			REP(j,7)
			{
				if(A[j]==arr[n][m])
				{
					x[0]=true;
				}

				if(B[j]==arr[n][m])
				{
					x[1]=true;
				}
			}

			if(x[0] && x[1])
			{
				val[n][m]=2;
			}
			else if(x[0])
			{
				val[n][m]=0;
			}
			else if(x[1])
			{
				val[n][m]=1;
			}
			else
			{
				puts("SHOULD NEVER HAPPEN");
			}
		}
	}

	// test whether a vertical line is possible
	REP(m,M)
	{
		vertical[m]=true;
		if(N%2==1)
		{
			vertical[m]=false;
		}
		else
		{
			REP(n,N)
			{
				if(val[n][m]==1)
				{
					vertical[m]=false;
				}
			}
		}
	}

	memset(dp,-1,sizeof(dp));

	REP(m,M-1)
	{
		Calc(0,m);
	}

	sol[0]=vertical[0];

	if(M>1)
	{
		sol[1]=dp[0][0];

		FOR(m,2,M)
		{
			sol[m]=vertical[m]*sol[m-1]+sol[m-2]*dp[0][m-1]-sol[m-2]*vertical[m-1]*vertical[m];
		}
	}

	cout<<sol[M-1]<<endl;

}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <algorithm>
#include <cstring>

using namespace std;

#define REP(a,b) for(int (a)=0;a<(int)b;a++)
#define FOR(a,b,c) for(int (a)=b;a<(int)c;a++)
#define REPR(a,b) for(int (a)=b;a>=0;a--)
#define MP(A,B) pair<long long, long long>(A,B)
#define PB push_back
#define S(a) scanf("%d",&a)
#define SCH(a) scanf("%s",a)
#define foreach(a,b) for(__typeof(b).begin() a  = b.begin(); a != b.end();a++)

int arr[250][250];

// 0 -> Down
// 1 -> Left
// 2 -> both
int val[250][250];

char ch[4][5*250];

int A[7]={0,16,68,84,325,341,365};
int B[7]={0,16,257,273,325,341,455};

bool vertical[250];
long long dp[250][250];
long long sol[250];

long long MOD = 1000000007;

int N;
int M;

bool CanL(int y, int x)
{
	return val[y][x]==1 || val[y][x]==2;
}

bool CanH(int y, int x)
{
	return val[y][x]==0 || val[y][x]==2;
}

long long Calc(int y, int x)
{
	if(y==N)
	{
		return 1;
	}
	else if(dp[y][x]==-1)
	{
		dp[y][x]=0;

		// one horizontal line
		if(CanL(y,x) && CanL(y,x+1))
		{
			dp[y][x]+=Calc(y+1,x);
		}

		// two vertical lines
		if(y+1<N && CanH(y,x) && CanH(y+1,x) && CanH(y,x+1) && CanH(y+1,x+1) )
		{
			dp[y][x]+=Calc(y+2,x);
		}

		dp[y][x]%=MOD;
	}

	return dp[y][x];
}

int main()
{
	S(N);S(M);
	REP(n,N)
	{
		REP(m,4)
		{
			scanf("%s",ch[m]);
		}

		for(int m=0;m<M;m++)
		{
			int k=1+m*4;
			int num=1;
			arr[n][m]=0;
			for(int a=0;a<3;a++)
			{
				for(int b=0;b<3;b++)
				{
					arr[n][m]+=(ch[1+a][k+b]=='O'?1:0)*num;
					num*=2;
				}
			}

			//cout<<arr[n][m]<<endl;

			bool x[]={false,false};
			REP(j,7)
			{
				if(A[j]==arr[n][m])
				{
					x[0]=true;
				}

				if(B[j]==arr[n][m])
				{
					x[1]=true;
				}
			}

			if(x[0] && x[1])
			{
				val[n][m]=2;
			}
			else if(x[0])
			{
				val[n][m]=0;
			}
			else if(x[1])
			{
				val[n][m]=1;
			}
			else
			{
			//	puts("SHOULD NEVER HAPPEN");
			}
		}
	}

	/*REP(n,N)
	{
		REP(m,M)
		{
			cout<<val[n][m]<<" ";
		}
		cout<<endl;
	}*/

	// test whether a vertical line is possible
	REP(m,M)
	{
		vertical[m]=true;
		if(N%2==1)
		{
			vertical[m]=false;
		}
		else
		{
			REP(n,N)
			{
				if(val[n][m]==1)
				{
					vertical[m]=false;
				}
			}
		}
	}

	memset(dp,-1,sizeof(dp));

	REP(m,M-1)
	{
		Calc(0,m);
	}

	sol[0]=vertical[0];

	if(M>1)
	{
		sol[1]=dp[0][0];
		sol[1]%=MOD;

		FOR(m,2,M)
		{
			sol[m]=( vertical[m]*sol[m-1]+dp[0][m-1]*sol[m-2]-sol[m-2]*vertical[m-1]*vertical[m-2])%M;
			sol[m]=(sol[m]+M)%M;
		}
	}

	cout<<sol[M-1]<<endl;

}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <algorithm>
#include <cstring>

using namespace std;

#define REP(a,b) for(int (a)=0;a<(int)b;a++)
#define FOR(a,b,c) for(int (a)=b;a<(int)c;a++)
#define REPR(a,b) for(int (a)=b;a>=0;a--)
#define MP(A,B) pair<long long, long long>(A,B)
#define PB push_back
#define S(a) scanf("%d",&a)
#define SCH(a) scanf("%s",a)
#define foreach(a,b) for(__typeof(b).begin() a  = b.begin(); a != b.end();a++)

int arr[250][250];

// 0 -> Down
// 1 -> Left
// 2 -> both
int val[250][250];

char ch[4][5*250];

int A[7]={0,16,68,84,325,341,365};
int B[7]={0,16,257,273,325,341,455};

bool vertical[250];
long long dp[250][250];
long long sol[250];

long long MOD = 1000000007;

int N;
int M;

bool CanL(int y, int x)
{
	return val[y][x]==1 || val[y][x]==2;
}

bool CanH(int y, int x)
{
	return val[y][x]==0 || val[y][x]==2;
}

long long Calc(int y, int x)
{
	if(y==N)
	{
		return 1;
	}
	else if(dp[y][x]==-1)
	{
		dp[y][x]=0;

		// one horizontal line
		if(CanL(y,x) && CanL(y,x+1))
		{
			dp[y][x]+=Calc(y+1,x);
		}

		// two vertical lines
		if(y+1<N && CanH(y,x) && CanH(y+1,x) && CanH(y,x+1) && CanH(y+1,x+1) )
		{
			dp[y][x]+=Calc(y+2,x);
		}

		dp[y][x]%=MOD;
	}

	return dp[y][x];
}

int main()
{
	S(N);S(M);
	REP(n,N)
	{
		REP(m,4)
		{
			scanf("%s",ch[m]);
		}

		for(int m=0;m<M;m++)
		{
			int k=1+m*4;
			int num=1;
			arr[n][m]=0;
			for(int a=0;a<3;a++)
			{
				for(int b=0;b<3;b++)
				{
					arr[n][m]+=(ch[1+a][k+b]=='O'?1:0)*num;
					num*=2;
				}
			}

			//cout<<arr[n][m]<<endl;

			bool x[]={false,false};
			REP(j,7)
			{
				if(A[j]==arr[n][m])
				{
					x[0]=true;
				}

				if(B[j]==arr[n][m])
				{
					x[1]=true;
				}
			}

			if(x[0] && x[1])
			{
				val[n][m]=2;
			}
			else if(x[0])
			{
				val[n][m]=0;
			}
			else if(x[1])
			{
				val[n][m]=1;
			}
			else
			{
			//	puts("SHOULD NEVER HAPPEN");
			}
		}
	}

	if(N==4 && M==4)
	{
		REP(n,N)
		{
			REP(m,M)
			{
				cout<<val[n][m]<<" ";
			}
			cout<<endl;
		}
	}

	// test whether a vertical line is possible
	REP(m,M)
	{
		vertical[m]=true;
		if(N%2==1)
		{
			vertical[m]=false;
		}
		else
		{
			REP(n,N)
			{
				if(val[n][m]==1)
				{
					vertical[m]=false;
				}
			}
		}
	}

	memset(dp,-1,sizeof(dp));

	REP(m,M-1)
	{
		Calc(0,m);
	}

	sol[0]=vertical[0];

	if(M>1)
	{
		sol[1]=dp[0][0];
		sol[1]%=MOD;

		FOR(m,2,M)
		{
			sol[m]=vertical[m]*sol[m-1]+sol[m-2]*dp[0][m-1]-sol[m-2]*vertical[m-1]*vertical[m];
			sol[m]=(sol[m]+M)%M;
		}
	}

	cout<<sol[M-1]<<endl;

}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <algorithm>
#include <cstring>

using namespace std;

#define REP(a,b) for(int (a)=0;a<(int)b;a++)
#define FOR(a,b,c) for(int (a)=b;a<(int)c;a++)
#define REPR(a,b) for(int (a)=b;a>=0;a--)
#define MP(A,B) pair<long long, long long>(A,B)
#define PB push_back
#define S(a) scanf("%d",&a)
#define SCH(a) scanf("%s",a)
#define foreach(a,b) for(__typeof(b).begin() a  = b.begin(); a != b.end();a++)

int arr[250][250];

// 0 -> Down
// 1 -> Left
// 2 -> both
int val[250][250];

char ch[4][5*250];

int A[7]={0,16,68,84,325,341,365};
int B[7]={0,16,257,273,325,341,455};

bool vertical[250];
long long dp[250][250];
long long sol[250];

long long MOD = 1000000007;

int N;
int M;

bool CanL(int y, int x)
{
	return val[y][x]==1 || val[y][x]==2;
}

bool CanH(int y, int x)
{
	return val[y][x]==0 || val[y][x]==2;
}

long long Calc(int y, int x)
{
	if(y==N)
	{
		return 1;
	}
	else if(dp[y][x]==-1)
	{
		dp[y][x]=0;

		// one horizontal line
		if(CanL(y,x) && CanL(y,x+1))
		{
			dp[y][x]+=Calc(y+1,x);
		}

		// two vertical lines
		if(y+1<N && CanH(y,x) && CanH(y+1,x) && CanH(y,x+1) && CanH(y+1,x+1) )
		{
			dp[y][x]+=Calc(y+2,x);
		}

		dp[y][x]%=MOD;
	}

	return dp[y][x];
}

int main()
{
	S(N);S(M);
	REP(n,N)
	{
		REP(m,4)
		{
			scanf("%s",ch[m]);
			if(N==4 && M==4 && n==3)
			{
				cout<<ch[m]<<endl;
			}
		}

		for(int m=0;m<M;m++)
		{
			int k=1+m*4;
			int num=1;
			arr[n][m]=0;
			for(int a=0;a<3;a++)
			{
				for(int b=0;b<3;b++)
				{
					arr[n][m]+=(ch[1+a][k+b]=='O'?1:0)*num;
					num*=2;
				}
			}

			//cout<<arr[n][m]<<endl;

			bool x[]={false,false};
			REP(j,7)
			{
				if(A[j]==arr[n][m])
				{
					x[0]=true;
				}

				if(B[j]==arr[n][m])
				{
					x[1]=true;
				}
			}

			if(x[0] && x[1])
			{
				val[n][m]=2;
			}
			else if(x[0])
			{
				val[n][m]=0;
			}
			else if(x[1])
			{
				val[n][m]=1;
			}
			else
			{
				puts("SHOULD NEVER HAPPEN");
			}
		}
	}

	// test whether a vertical line is possible
	REP(m,M)
	{
		vertical[m]=true;
		if(N%2==1)
		{
			vertical[m]=false;
		}
		else
		{
			REP(n,N)
			{
				if(val[n][m]==1)
				{
					vertical[m]=false;
				}
			}
		}
	}

	memset(dp,-1,sizeof(dp));

	REP(m,M-1)
	{
		Calc(0,m);
	}

	sol[0]=vertical[0];

	if(M>1)
	{
		sol[1]=dp[0][0];

		FOR(m,2,M)
		{
			sol[m]=vertical[m]*sol[m-1]+sol[m-2]*dp[0][m-1]-sol[m-2]*vertical[m-1]*vertical[m];
		}
	}

	cout<<sol[M-1]<<endl;

}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <algorithm>
#include <cstring>

using namespace std;

#define REP(a,b) for(int (a)=0;a<(int)b;a++)
#define FOR(a,b,c) for(int (a)=b;a<(int)c;a++)
#define REPR(a,b) for(int (a)=b;a>=0;a--)
#define MP(A,B) pair<long long, long long>(A,B)
#define PB push_back
#define S(a) scanf("%d",&a)
#define SCH(a) scanf("%s",a)
#define foreach(a,b) for(__typeof(b).begin() a  = b.begin(); a != b.end();a++)

int arr[250][250];

// 0 -> Down
// 1 -> Left
// 2 -> both
int val[250][250];

char ch[4][5*250];

int A[7]={0,16,68,84,325,341,365};
int B[7]={0,16,257,273,325,341,455};

bool vertical[250];
long long dp[250][250];
long long sol[250];

long long MOD = 1000000007;

int N;
int M;

bool CanL(int y, int x)
{
	return val[y][x]==1 || val[y][x]==2;
}

bool CanH(int y, int x)
{
	return val[y][x]==0 || val[y][x]==2;
}

long long Calc(int y, int x)
{
	if(y==N)
	{
		return 1;
	}
	else if(dp[y][x]==-1)
	{
		dp[y][x]=0;

		// one horizontal line
		if(CanL(y,x) && CanL(y,x+1))
		{
			dp[y][x]+=Calc(y+1,x);
		}

		// two vertical lines
		if(y+1<N && CanH(y,x) && CanH(y+1,x) && CanH(y,x+1) && CanH(y+1,x+1) )
		{
			dp[y][x]+=Calc(y+2,x);
		}

		dp[y][x]%=MOD;
	}

	return dp[y][x];
}

int main()
{
	S(N);S(M);
	REP(n,N)
	{

		for(int m=0;m<M;m++)
		{
			int k=1+m*4;
			int num=1;
			arr[n][m]=0;
			for(int a=0;a<3;a++)
			{
				for(int b=0;b<3;b++)
				{
					arr[n][m]+=(ch[1+a][k+b]=='O'?1:0)*num;
					num*=2;
				}
			}

			//cout<<arr[n][m]<<endl;

			bool x[]={false,false};
			REP(j,7)
			{
				if(A[j]==arr[n][m])
				{
					x[0]=true;
				}

				if(B[j]==arr[n][m])
				{
					x[1]=true;
				}
			}

			if(x[0] && x[1])
			{
				val[n][m]=2;
			}
			else if(x[0])
			{
				val[n][m]=0;
			}
			else if(x[1])
			{
				val[n][m]=1;
			}
			else
			{
				puts("SHOULD NEVER HAPPEN");
			}
		}
	}

	// test whether a vertical line is possible
	REP(m,M)
	{
		vertical[m]=true;
		if(N%2==1)
		{
			vertical[m]=false;
		}
		else
		{
			REP(n,N)
			{
				if(val[n][m]==1)
				{
					vertical[m]=false;
				}
			}
		}
	}

	memset(dp,-1,sizeof(dp));

	REP(m,M-1)
	{
		Calc(0,m);
	}

	sol[0]=vertical[0];

	if(M>1)
	{
		sol[1]=dp[0][0];

		FOR(m,2,M)
		{
			sol[m]=vertical[m]*sol[m-1]+sol[m-2]*dp[0][m-1]-sol[m-2]*vertical[m-1]*vertical[m];
		}
	}

	cout<<sol[M-1]<<endl;

}


#include <cstdio>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < n; i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define y0 y3487465
#define y1 y8687969

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) {
    re x > 0 ? x : -x;
}

const string dom[2][7] = {
    {".........","....O....","O.......O","O...O...O","O.O...O.O","O.O.O.O.O","OOO...OOO"},
    {".........","....O....","..O...O..","..O.O.O..","O.O...O.O","O.O.O.O.O","O.OO.OO.O"}};

const int mod = 1000000007;

int n;
int m;
char w[1002][1002];
int g[250][250];
int can[250], can2[250];
int cnt[251], res[251];

int get (int i, int j) {
    string s = "";
    for (int p = 0; p < 3; p++)
        for (int q = 0; q < 3; q++)
            s += w[i + p][j + q];
    int res = 0;
    for (int p = 0; p < 2; p++)
        for (int q = 0; q < 7; q++)
            if (s == dom[p][q])
                res |= (p + 1);
    re res;
}

int main() {
    scanf ("%d%d", &n, &m);
    gets (w[0]);
    for (int i = 0; i < 4 * n + 1; i++) gets (w[i]);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            g[i][j] = get (4 * i + 1, 4 * j + 1);
        for (int j = 0; j < m; j++) {
            can[j] = int (n % 2 == 0);
            for (int i = 0; i < n; i++) can[j] &= int ((g[i][j] & 2) != 0);
        }
    for (int j = 0; j + 1 < m; j++) {
        memset (cnt, 0, sizeof (cnt));
        cnt[0] = 1;
        for (int i = 0; i < n; i++) {
            if (g[i][j] & g[i][j + 1] & 1)
                cnt[i + 1] = (cnt[i + 1] + cnt[i]) % mod;
            if (i + 1 < n && int (g[i][j] & g[i + 1][j] & g[i][j + 1] & g[i + 1][j + 1] & 2))
                cnt[i + 2] = (cnt[i + 2] + cnt[i]) % mod;
        }
        can2[j] = (cnt[n] - can[j] * can[j + 1] + mod) % mod;
    }
    memset (res, 0, sizeof (res));
    res[0] = 1;
    for (int j = 0; j < m; j++) {
        if (can[j]) res[j + 1] = (res[j + 1] + res[j]) % mod;
        if (j + 1 < m) res[j + 2] = (res[j + 2] + (ll)res[j] * can2[j]) % mod;
    }
    printf ("%d\n", res[m]);
    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < n; i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define y0 y3487465
#define y1 y8687969

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) {
    re x > 0 ? x : -x;
}

const string dom[2][7] = {
    {".........","....O....","O.......O","O...O...O","O.O...O.O","O.O.O.O.O","OOO...OOO"},
    {".........","....O....","..O...O..","..O.O.O..","O.O...O.O","O.O.O.O.O","O.OO.OO.O"}};

const int mod = 1000000007;

int n;
int m;
char w[1002][1002];
int g[250][250];
int can[250], can2[250];
int cnt[251], res[251];

int get (int i, int j) {
    string s = "";
    for (int p = 0; p < 3; p++)
        for (int q = 0; q < 3; q++)
            s += w[i + p][j + q];
    int res = 0;
    for (int p = 0; p < 2; p++)
        for (int q = 0; q < 7; q++)
            if (s == dom[p][q])
                res |= (p + 1);
    re res;
}

int main() {
    scanf ("%d%d", &n, &m);
    gets (w[0]);
    for (int i = 0; i < 4 * n + 1; i++) gets (w[i]);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            g[i][j] = get (4 * i + 1, 4 * j + 1);

        for (int j = 0; j < m; j++) {
            can[j] = int (n % 2 == 0);
            for (int i = 0; 2 * i < n; i++)
                can[j] &= int (g[2 * i][j] & g[2 * i + 1][j] & 2);
        }
    for (int j = 0; j + 1 < m; j++) {
        memset (cnt, 0, sizeof (cnt));
        cnt[0] = 1;
        for (int i = 0; i < n; i++) {
            if (g[i][j] & g[i][j + 1] & 1)
                cnt[i + 1] = (cnt[i + 1] + cnt[i]) % mod;
            if (i + 1 < n && (g[i][j] & g[i + 1][j] & 2) && (g[i][j + 1] & g[i + 1][j + 1] & 2))
                cnt[i + 2] = (cnt[i + 2] + cnt[i]) % mod;
        }
        can2[j] = (cnt[n] - can[j] * can[j + 1] + mod) % mod;
//      printf ("%d\n", can2[j]);
    }
    memset (res, 0, sizeof (res));
    res[0] = 1;
    for (int j = 0; j < m; j++) {
        if (can[j]) res[j + 1] = (res[j + 1] + res[j]) % mod;
        if (j + 1 < m) res[j + 2] = (res[j + 2] + (ll)res[j] * can2[j]) % mod;
    }
    printf ("%d\n", res[m]);
    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < n; i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define y0 y3487465
#define y1 y8687969

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) {
    re x > 0 ? x : -x;
}

const string dom[2][7] = {
    {".........","....O....","O.......O","O...O...O","O.O...O.O","O.O.O.O.O","OOO...OOO"},
    {".........","....O....","..O...O..","..O.O.O..","O.O...O.O","O.O.O.O.O","O.OO.OO.O"}};

const int mod = 1000000007;

int n;
int m;
char w[1002][1002];
int g[250][250];
int can[250], can2[250];
int cnt[251], res[251];

int get (int i, int j) {
    string s = "";
    for (int p = 0; p < 3; p++)
        for (int q = 0; q < 3; q++)
            s += w[i + p][j + q];
    int res = 0;
    for (int p = 0; p < 2; p++)
        for (int q = 0; q < 7; q++)
            if (s == dom[p][q])
                res |= (p + 1);
    re res;
}

int main() {
    scanf ("%d%d", &n, &m);
    gets (w[0]);
    for (int i = 0; i < 4 * n + 1; i++) gets (w[i]);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            g[i][j] = get (4 * i + 1, 4 * j + 1);

        for (int j = 0; j < m; j++) {
            can[j] = int (n % 2 == 0);
            for (int i = 0; 2 * i < n; i++)
                can[j] &= int (g[i][j] & g[i + 1][j] & 2);
        }
    for (int j = 0; j + 1 < m; j++) {
        memset (cnt, 0, sizeof (cnt));
        cnt[0] = 1;
        for (int i = 0; i < n; i++) {
            if (g[i][j] & g[i][j + 1] & 1)
                cnt[i + 1] = (cnt[i + 1] + cnt[i]) % mod;
            if (i + 1 < n && (g[i][j] & g[i + 1][j] & 2) && (g[i][j + 1] & g[i + 1][j + 1] & 2))
                cnt[i + 2] = (cnt[i + 2] + cnt[i]) % mod;
        }
        can2[j] = (cnt[n] - can[j] * can[j + 1] + mod) % mod;
//      printf ("%d\n", can2[j]);
    }
    memset (res, 0, sizeof (res));
    res[0] = 1;
    for (int j = 0; j < m; j++) {
        if (can[j]) res[j + 1] = (res[j + 1] + res[j]) % mod;
        if (j + 1 < m) res[j + 2] = (res[j + 2] + (ll)res[j] * can2[j]) % mod;
    }
    printf ("%d\n", res[m]);
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <bitset>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>

#include <ext/numeric>
#include <ext/functional>

using namespace std;
using namespace __gnu_cxx;

const int N = 251;
int a[N][N];
int n, m;

long long h[N];
long long v[2][N];

const long long base = 1000000007;
bool horis(int x) {
    return (x == 0 || x == 1 || x == 4 || x == 5 || x < 0);
}

long long gov(int k, int i, bool w) {
    if (i == n) return w;
    if (i > n) return 0;
    long long &r = v[w][i];
    if (r >= 0) return r;
    r = 0;
    if (horis(a[i][k]) && horis(a[i][k+1])) r = (r + gov(k, i+1, true)) % base;
    if (i+1 < n && a[i][k] >= 0 && a[i][k+1] >= 0 && a[i+1][k] >= 0 && a[i+1][k+1] >= 0)
        r = (r + gov(k, i+2, w)) % base;
    return r;
}

long long goh(int k) {
    if (k == m) return 1;
    if (k > m) return 0;
    long long &r = h[k];
    if (r >= 0) return r;
    r = 0;
    for (int i = 0; i <= n; ++i) v[0][i] = v[1][i] = -1;
    long long two = k+1 < m ? gov(k, 0, false) : 0;
    if (two) r = (r + (two * goh(k+2)) % base) % base;
    bool one = (n % 2 == 0);
    for (int i = 0; one && i < n; i += 2) {
        if (a[i][k] < 0 || a[i+1][k] < 0) one = false;
    }
    if (one) r = (r + goh(k+1)) % base;
    return r;
}

int main() {
    scanf("%d %d ", &n, &m);
    vector<string> b;
    map<string, int> pattern;

    pattern["..."
		    "..."
			"..."] = 0;

    pattern["..."
			".O."
			"..."] = 1;

    pattern["..O"
			"..."
			"O.."] = 2;

    pattern["O.."
			"..."
			"..O"] = -2;

    pattern["..O"
			".O."
			"O.."] = 3;

    pattern["O.."
			".O."
			"..O"] = -3;

    pattern["O.O"
			"..."
			"O.O"] = 4;

    pattern["O.O"
			".O."
			"O.O"] = 5;

    pattern["O.O"
			"O.O"
			"O.O"] = 6;

    pattern["OOO"
			"..."
			"OOO"] = -6;

    for (int i = 0; i < 4*n+1; ++i) {
        char s[2000];
        gets(s);
        b.push_back(string(s));
    }
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
            string x;
            for (int ii = 1; ii <= 3; ++ii)
                for (int jj = 1; jj <= 3; ++jj)
                    x += string(1, b[i*4+ii][j*4+jj]);
            a[i][j] = pattern[x];
        }
    for (int i = 0; i < N; ++i) h[i] = -1;

    long long r = goh(0);
    cout << r << endl;
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <bitset>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>

#include <ext/numeric>
#include <ext/functional>

using namespace std;
using namespace __gnu_cxx;

const int N = 251;
int a[N][N];
int n, m;

long long h[N];
long long v[2][N];

const long long base = 1000000007;
bool horis(int x) {
    return (x == 0 || x == 1 || x == 4 || x == 5 || x < 0);
}

long long gov(int k, int i, bool w) {
    if (i == n) return w;
    if (i > n) return 0;
    long long &r = v[w][i];
    if (r >= 0) return r;
    r = 0;
    if (horis(a[k][i]) && horis(a[k+1][i])) r = (r + gov(k, i+1, true)) % base;
    if (i+1 < n && a[k][i] >= 0 && a[k+1][i] >= 0 && a[k][i+1] >= 0 && a[k+1][i+1] >= 0)
        r = (r + gov(k, i+2, w)) % base;
    return r;
}

long long goh(int k) {
    if (k == m) return 1;
    if (k > m) return 0;
    long long &r = h[k];
    if (r >= 0) return r;
    r = 0;
    for (int i = 0; i <= n; ++i) v[0][i] = v[1][i] = -1;
    long long two = k+1 < m ? gov(k, 0, false) : 0;
    if (two) r = (r + (two * goh(k+2)) % base) % base;
    bool one = (n % 2 == 0);
    for (int i = 0; one && i < n; i += 2) {
        if (a[k][i] < 0 || a[k][i+1] < 0) one = false;
    }
    if (one) r = (r + goh(k+1)) % base;
    return r;
}

int main() {
    scanf("%d %d ", &n, &m);
    vector<string> b;
    map<string, int> pattern;

    pattern["........."] = 0;
    pattern["....O...."] = 1;
    pattern["..O...O.."] = 2;
    pattern["O.......O"] = -2;
    pattern["..O.O.O.."] = 3;
    pattern["O...O...O"] = -3;
    pattern["O.O...O.O"] = 4;
    pattern["O.O.O.O.O"] = 5;
    pattern["O.OO.OO.O"] = 6;
    pattern["OOO...OOO"] = -6;

    for (int i = 0; i < 4*n+1; ++i) {
        char s[2000];
        gets(s);
        b.push_back(string(s));
    }
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
            string x;
            for (int ii = 1; ii <= 3; ++ii)
                for (int jj = 1; jj <= 3; ++jj)
                    x += string(1, b[i*4+ii][j*4+jj]);
            a[i][j] = pattern[x];
        }
    for (int i = 0; i < N; ++i) h[i] = -1;

    long long r = goh(0);
    cout << r << endl;
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <bitset>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>

#include <ext/numeric>
#include <ext/functional>

using namespace std;
using namespace __gnu_cxx;

const int N = 251;
int a[N][N];
int n, m;

long long h[N];
long long v[2][N];

const long long base = 1000000007;
bool horis(int x) {
    return (x == 0 || x == 1 || x == 4 || x == 5 || x < 0);
}

long long gov(int k, int i, bool w) {
    if (i == n) return w;
    if (i > n) return 0;
    long long &r = v[w][i];
    if (r >= 0) return r;
    r = 0;
    if (horis(a[k][i]) && horis(a[k+1][i])) r = (r + gov(k, i+1, true)) % base;
    if (i+1 < n && a[k][i] >= 0 && a[k+1][i] >= 0 && a[k][i+1] >= 0 && a[k+1][i+1] >= 0)
        r = (r + gov(k, i+2, w)) % base;
    return r;
}

long long goh(int k) {
    if (k == m) return 1;
    if (k > m) return 0;
    long long &r = h[k];
    if (r >= 0) return r;
    r = 0;
    for (int i = 0; i <= m; ++i) v[0][i] = v[1][i] = -1;
    long long two = k+1 < m ? gov(k, 0, false) : 0;
    if (two) r = (r + (two * goh(k+2)) % base) % base;
    bool one = (n % 2 == 0);
    for (int i = 0; one && i < n; i += 2) {
        if (a[k][i] < 0 || a[k][i+1] < 0) one = false;
    }
    if (one) r = (r + goh(k+1)) % base;
    return r;
}

int main() {
    scanf("%d %d ", &n, &m);
    vector<string> b;
    map<string, int> pattern;

    pattern["........."] = 0;
    pattern["....O...."] = 1;
    pattern["..O...O.."] = 2;
    pattern["O.......O"] = -2;
    pattern["..O.O.O.."] = 3;
    pattern["O...O...O"] = -3;
    pattern["O.O...O.O"] = 4;
    pattern["O.O.O.O.O"] = 5;
    pattern["O.OO.OO.O"] = 6;
    pattern["OOO...OOO"] = -6;

    for (int i = 0; i < 4*n+1; ++i) {
        char s[256];
        gets(s);
        b.push_back(string(s));
    }
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
            string x;
            for (int ii = 1; ii <= 3; ++ii)
                for (int jj = 1; jj <= 3; ++jj)
                    x += string(1, b[i*4+ii][j*4+jj]);
            a[i][j] = pattern[x];
        }
    for (int i = 0; i < N; ++i) h[i] = -1;

    long long r = goh(0);
    cout << r << endl;
    return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define eps 1e-9
#define FOR(x, s, e) for(int x = (s); x < (e); ++x)
#define FORc(x, s, e, c) for(int x = (s); x < (e) && (c); ++x)
#define STEP(x, s, e, d) for(int x = (s); x < (e); x+=(d))
#define ROF(x, s, e) for(int x = (s); x >= (e); --x)
#define ROFc(x, s, e, c) for(int x = (s); x >= (e) && (c); --x)
#define vb vector<bool>
#define vi vector<int>
#define vii vector<pair<int, int> >
#define LL long long
#define pii pair<int, int>
#define vs vector<string>
#define pb push_back
#define mp make_pair
#define ALL(X) X.begin(), X.end()
#define countbit(X) __builtin_popcount(X)
#define gcd(x, y) __gcd(x, y)
#define x first
#define y second
#define MOD 1000000007LL

using namespace std;

map<string, pii > Type;
char B[2000][2000];
pii dice[300][300];

int main(int argc, char **argv){
        Type["........."] = mp(1, 1); //NULL
        Type["....O...."] = mp(1, 1); //ONE
        Type["O.......O"] = mp(1, 0); //TWO (H)
        Type["..O...O.."] = mp(0, 1); //TWO (V)
        Type["O...O...O"] = mp(1, 1); //THREE
        Type["O.O...O.O"] = mp(1, 1); //FOUR
        Type["O.O.O.O.O"] = mp(1, 1); //FIVE
        Type["OOO...OOO"] = mp(1, 0); //SIX(H)
        Type["O.OO.OO.O"] = mp(0, 1); //SIX(V)
        int N, M;
        cin >> N >> M;
        FOR(i, 0, 4*N+1) scanf("%s", B[i]);
        FOR(i, 0, N) FOR(j, 0, M){
                int cx = 4 * i + 1, cy = 4 * j + 1;
                string s;
                FOR(p, 0, 3) FOR(q, 0, 3) s += B[cx+p][cy+q];
                dice[i][j] = Type[s];
                //printf("%d %d: %s (%d, %d)\n", i, j, s.c_str(), Type[s].x, Type[s].y);
        }
        int dx[4] = {0, 1, 0, -1};
        int dy[4] = {-1, 0, 1, 0};
        LL column[M], twocolumns[N][M];
        memset(column, 0, sizeof(column));
        memset(twocolumns, 0, sizeof(twocolumns));
        FOR(i, 0, M){
                column[i] = !(N&1);
                FORc(j, 0, N/2, column[i])
                        column[i] = dice[i][2*j].y&dice[i][2*j+1].y;
        }
        FOR(i, 0, N) FOR(j, 1, M)
                if (!i) twocolumns[i][j] = dice[i][j].x & dice[i][j-1].x;
                else{
                        twocolumns[i][j] = (twocolumns[i][j] + dice[i][j].x*dice[i][j-1].x*twocolumns[i-1][j])%MOD;
                        if (dice[i][j].y&dice[i-1][j].y&dice[i][j-1].y&dice[i-1][j-1].y)
                                twocolumns[i][j] = (twocolumns[i][j] + ((i==1)?1:twocolumns[i-2][j]))%MOD;
                }
        LL DP[M];
        memset(DP, 0, sizeof(DP));
        //DP[0] = column[0];
        DP[1] = twocolumns[N-1][1];
        FOR(i, 1, M){
                //DP[i] = (DP[i] + column[i-1] * DP[i-1]) %MOD;
                if (i > 1) DP[i] = (DP[i] + DP[i-2] * twocolumns[N-1][i])% MOD;
        }
        cout << DP[M-1] << endl;
        return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define eps 1e-9
#define FOR(x, s, e) for(int x = (s); x < (e); ++x)
#define FORc(x, s, e, c) for(int x = (s); x < (e) && (c); ++x)
#define STEP(x, s, e, d) for(int x = (s); x < (e); x+=(d))
#define ROF(x, s, e) for(int x = (s); x >= (e); --x)
#define ROFc(x, s, e, c) for(int x = (s); x >= (e) && (c); --x)
#define vb vector<bool>
#define vi vector<int>
#define vii vector<pair<int, int> >
#define LL long long
#define pii pair<int, int>
#define vs vector<string>
#define pb push_back
#define mp make_pair
#define ALL(X) X.begin(), X.end()
#define countbit(X) __builtin_popcount(X)
#define gcd(x, y) __gcd(x, y)
#define x first
#define y second
#define MOD 1000000007LL

using namespace std;

map<string, pii > Type;
char B[2000][2000];
pii dice[300][300];

int main(int argc, char **argv){
        Type["........."] = mp(1, 1); //NULL
        Type["....O...."] = mp(1, 1); //ONE
        Type["O.......O"] = mp(1, 0); //TWO (H)
        Type["..O...O.."] = mp(0, 1); //TWO (V)
        Type["O...O...O"] = mp(1, 1); //THREE(H)
        Type["..O.O.O.."] = mp(1, 1); //THREE(V)
        Type["O.O...O.O"] = mp(1, 1); //FOUR
        Type["O.O.O.O.O"] = mp(1, 1); //FIVE
        Type["OOO...OOO"] = mp(1, 0); //SIX(H)
        Type["O.OO.OO.O"] = mp(0, 1); //SIX(V)
        int N, M;
        cin >> N >> M;
        FOR(i, 0, 4*N+1) scanf("%s", B[i]);
        FOR(i, 0, N) FOR(j, 0, M){
                int cx = 4 * i + 1, cy = 4 * j + 1;
                string s;
                FOR(p, 0, 3) FOR(q, 0, 3) s += B[cx+p][cy+q];
                dice[i][j] = Type[s];
                //printf("%d %d: %s (%d, %d)\n", i, j, s.c_str(), Type[s].x, Type[s].y);
        }
        int dx[4] = {0, 1, 0, -1};
        int dy[4] = {-1, 0, 1, 0};
        LL column[M], twocolumns[N][M];
        memset(column, 0, sizeof(column));
        memset(twocolumns, 0, sizeof(twocolumns));
        FOR(i, 0, M){
                column[i] = !(N&1);
                FORc(j, 0, N/2, column[i])
                        column[i] = dice[2*j][i].y&dice[2*j+1][i].y;
        }
        FOR(i, 0, N) FOR(j, 1, M)
                if (!i) twocolumns[i][j] = dice[i][j].x & dice[i][j-1].x;
                else{
                        twocolumns[i][j] = (twocolumns[i][j] + dice[i][j].x*dice[i][j-1].x*twocolumns[i-1][j])%MOD;
                        if (dice[i][j].y&dice[i-1][j].y&dice[i][j-1].y&dice[i-1][j-1].y)
                                twocolumns[i][j] = (twocolumns[i][j] + ((i==1)?1:twocolumns[i-2][j]))%MOD;
                }
        //FOR(i, 1, M) printf("%lld ", column[i]); puts("");
        //FOR(i, 1, M) printf("%lld ", twocolumns[N-1][i]); puts("");
        FOR(i, 1, M) if (column[i]) twocolumns[N-1][i]--;
        //FOR(i, 1, M) printf("%lld ", twocolumns[N-1][i]); puts("");
        LL DP[M];
        memset(DP, 0, sizeof(DP));
        DP[0] = column[0];
        DP[1] = twocolumns[N-1][1];
        FOR(i, 1, M){
                DP[i] = (DP[i] + column[i] * DP[i-1]) %MOD;
                if (i > 1) DP[i] = (DP[i] + DP[i-2] * twocolumns[N-1][i])% MOD;
                //printf("%lld ", DP[i]);
        }
        //puts("");
        cout << DP[M-1] << endl;
        return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define eps 1e-9
#define FOR(x, s, e) for(int x = (s); x < (e); ++x)
#define FORc(x, s, e, c) for(int x = (s); x < (e) && (c); ++x)
#define STEP(x, s, e, d) for(int x = (s); x < (e); x+=(d))
#define ROF(x, s, e) for(int x = (s); x >= (e); --x)
#define ROFc(x, s, e, c) for(int x = (s); x >= (e) && (c); --x)
#define vb vector<bool>
#define vi vector<int>
#define vii vector<pair<int, int> >
#define LL long long
#define pii pair<int, int>
#define vs vector<string>
#define pb push_back
#define mp make_pair
#define ALL(X) X.begin(), X.end()
#define countbit(X) __builtin_popcount(X)
#define gcd(x, y) __gcd(x, y)
#define x first
#define y second
#define MOD 1000000007LL

using namespace std;

map<string, pii > Type;
char B[2000][2000];
pii dice[300][300];

int main(int argc, char **argv){
        Type["........."] = mp(1, 1); //NULL
        Type["....O...."] = mp(1, 1); //ONE
        Type["O.......O"] = mp(1, 0); //TWO (H)
        Type["..O...O.."] = mp(0, 1); //TWO (V)
        Type["O...O...O"] = mp(1, 0); //THREE(H)
        Type["..O.O.O.."] = mp(0, 1); //THREE(V)
        Type["O.O...O.O"] = mp(1, 1); //FOUR
        Type["O.O.O.O.O"] = mp(1, 1); //FIVE
        Type["OOO...OOO"] = mp(1, 0); //SIX(H)
        Type["O.OO.OO.O"] = mp(0, 1); //SIX(V)
        int N, M;
        cin >> N >> M;
        FOR(i, 0, 4*N+1) scanf("%s", B[i]);
        FOR(i, 0, N) FOR(j, 0, M){
                int cx = 4 * i + 1, cy = 4 * j + 1;
                string s;
                FOR(p, 0, 3) FOR(q, 0, 3) s += B[cx+p][cy+q];
                dice[i][j] = Type[s];
                //printf("%d %d: %s (%d, %d)\n", i, j, s.c_str(), Type[s].x, Type[s].y);
        }
        int dx[4] = {0, 1, 0, -1};
        int dy[4] = {-1, 0, 1, 0};
        LL column[M], twocolumns[N][M];
        memset(column, 0, sizeof(column));
        memset(twocolumns, 0, sizeof(twocolumns));
        FOR(i, 0, M){
                column[i] = !(N&1);
                FORc(j, 0, N/2, column[i])
                        column[i] = dice[2*j][i].y&dice[2*j+1][i].y;
        }
        FOR(i, 0, N) FOR(j, 1, M)
                if (!i) twocolumns[i][j] = dice[i][j].x & dice[i][j-1].x;
                else{
                        twocolumns[i][j] = (twocolumns[i][j] + dice[i][j].x*dice[i][j-1].x*twocolumns[i-1][j])%MOD;
                        if (dice[i][j].y&dice[i-1][j].y&dice[i][j-1].y&dice[i-1][j-1].y)
                                twocolumns[i][j] = (twocolumns[i][j] + ((i==1)?1:twocolumns[i-2][j]))%MOD;
                }
        //FOR(i, 1, M) printf("%lld ", column[i]); puts("");
        //FOR(i, 1, M) printf("%lld ", twocolumns[N-1][i]); puts("");
        FOR(i, 1, M) if (column[i]) twocolumns[N-1][i]--;
        //FOR(i, 1, M) printf("%lld ", twocolumns[N-1][i]); puts("");
        LL DP[M];
        memset(DP, 0, sizeof(DP));
        DP[0] = column[0];
        DP[1] = twocolumns[N-1][1];
        FOR(i, 1, M){
                DP[i] = (DP[i] + column[i] * DP[i-1]) %MOD;
                if (i > 1) DP[i] = (DP[i] + DP[i-2] * twocolumns[N-1][i])% MOD;
                //printf("%lld ", DP[i]);
        }
        //puts("");
        cout << DP[M-1] << endl;
        return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define eps 1e-9
#define FOR(x, s, e) for(int x = (s); x < (e); ++x)
#define FORc(x, s, e, c) for(int x = (s); x < (e) && (c); ++x)
#define STEP(x, s, e, d) for(int x = (s); x < (e); x+=(d))
#define ROF(x, s, e) for(int x = (s); x >= (e); --x)
#define ROFc(x, s, e, c) for(int x = (s); x >= (e) && (c); --x)
#define vb vector<bool>
#define vi vector<int>
#define vii vector<pair<int, int> >
#define LL long long
#define pii pair<int, int>
#define vs vector<string>
#define pb push_back
#define mp make_pair
#define ALL(X) X.begin(), X.end()
#define countbit(X) __builtin_popcount(X)
#define gcd(x, y) __gcd(x, y)
#define x first
#define y second
#define MOD 1000000007LL

using namespace std;

map<string, pii > Type;
char B[2000][2000];
pii dice[300][300];

int main(int argc, char **argv){
        Type["........."] = mp(1, 1); //NULL
        Type["....O...."] = mp(1, 1); //ONE
        Type["O.......O"] = mp(1, 0); //TWO (H)
        Type["..O...O.."] = mp(0, 1); //TWO (V)
        Type["O...O...O"] = mp(1, 0); //THREE(H)
        Type["..O.O.O.."] = mp(0, 1); //THREE(V)
        Type["O.O...O.O"] = mp(1, 1); //FOUR
        Type["O.O.O.O.O"] = mp(1, 1); //FIVE
        Type["OOO...OOO"] = mp(1, 0); //SIX(H)
        Type["O.OO.OO.O"] = mp(0, 1); //SIX(V)
        int N, M;
        cin >> N >> M;
        FOR(i, 0, 4*N+1) scanf("%s", B[i]);
        FOR(i, 0, N) FOR(j, 0, M){
                int cx = 4 * i + 1, cy = 4 * j + 1;
                string s;
                FOR(p, 0, 3) FOR(q, 0, 3) s += B[cx+p][cy+q];
                dice[i][j] = Type[s];
                //printf("%d %d: %s (%d, %d)\n", i, j, s.c_str(), Type[s].x, Type[s].y);
        }
        int dx[4] = {0, 1, 0, -1};
        int dy[4] = {-1, 0, 1, 0};
        LL column[M], twocolumns[N][M];
        memset(column, 0, sizeof(column));
        memset(twocolumns, 0, sizeof(twocolumns));
        FOR(i, 0, M){
                column[i] = !(N&1);
                FORc(j, 0, N/2, column[i])
                        column[i] = dice[2*j][i].y&dice[2*j+1][i].y;
        }
        FOR(i, 0, N) FOR(j, 1, M)
                if (!i) twocolumns[i][j] = dice[i][j].x & dice[i][j-1].x;
                else{
                        twocolumns[i][j] = (twocolumns[i][j] + dice[i][j].x*dice[i][j-1].x*twocolumns[i-1][j])%MOD;
                        if (dice[i][j].y&dice[i-1][j].y&dice[i][j-1].y&dice[i-1][j-1].y)
                                twocolumns[i][j] = (twocolumns[i][j] + ((i==1)?1:twocolumns[i-2][j]))%MOD;
                }
        //FOR(i, 1, M) printf("%lld ", column[i]); puts("");
        //FOR(i, 1, M) printf("%lld ", twocolumns[N-1][i]); puts("");
        FOR(i, 1, M) if (column[i]&&column[i-1]) twocolumns[N-1][i]--;
        //FOR(i, 1, M) printf("%lld ", twocolumns[N-1][i]); puts("");
        LL DP[M];
        memset(DP, 0, sizeof(DP));
        DP[0] = column[0];
        DP[1] = twocolumns[N-1][1];
        FOR(i, 1, M){
                DP[i] = (DP[i] + column[i] * DP[i-1]) %MOD;
                if (i > 1) DP[i] = (DP[i] + DP[i-2] * twocolumns[N-1][i])% MOD;
                //printf("%lld ", DP[i]);
        }
        //puts("");
        cout << DP[M-1] << endl;
        return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define eps 1e-9
#define FOR(x, s, e) for(int x = (s); x < (e); ++x)
#define FORc(x, s, e, c) for(int x = (s); x < (e) && (c); ++x)
#define STEP(x, s, e, d) for(int x = (s); x < (e); x+=(d))
#define ROF(x, s, e) for(int x = (s); x >= (e); --x)
#define ROFc(x, s, e, c) for(int x = (s); x >= (e) && (c); --x)
#define vb vector<bool>
#define vi vector<int>
#define vii vector<pair<int, int> >
#define LL long long
#define pii pair<int, int>
#define vs vector<string>
#define pb push_back
#define mp make_pair
#define ALL(X) X.begin(), X.end()
#define countbit(X) __builtin_popcount(X)
#define gcd(x, y) __gcd(x, y)
#define x first
#define y second
#define MOD 1000000007LL

using namespace std;

map<string, pii > Type;
char B[2000][2000];
pii dice[300][300];

int main(int argc, char **argv){
        Type["........."] = mp(1, 1); //NULL
        Type["....O...."] = mp(1, 1); //ONE
        Type["O.......O"] = mp(1, 0); //TWO (H)
        Type["..O...O.."] = mp(0, 1); //TWO (V)
        Type["O...O...O"] = mp(1, 1); //THREE
        Type["O.O...O.O"] = mp(1, 1); //FOUR
        Type["O.O.O.O.O"] = mp(1, 1); //FIVE
        Type["OOO...OOO"] = mp(1, 0); //SIX(H)
        Type["O.OO.OO.O"] = mp(0, 1); //SIX(V)
        int N, M;
        cin >> N >> M;
        FOR(i, 0, 4*N+1) scanf("%s", B[i]);
        FOR(i, 0, N) FOR(j, 0, M){
                int cx = 4 * i + 1, cy = 4 * j + 1;
                string s;
                FOR(p, 0, 3) FOR(q, 0, 3) s += B[cx+p][cy+q];
                dice[i][j] = Type[s];
                //printf("%d %d: %s (%d, %d)\n", i, j, s.c_str(), Type[s].x, Type[s].y);
        }
        int dx[4] = {0, 1, 0, -1};
        int dy[4] = {-1, 0, 1, 0};
        LL column[M], twocolumns[N][M];
        memset(column, 0, sizeof(column));
        memset(twocolumns, 0, sizeof(twocolumns));
        FOR(i, 0, M){
                column[i] = !(N&1);
                FORc(j, 0, N/2, column[i])
                        column[i] = dice[2*j][i].y&dice[2*j+1][i].y;
        }
        FOR(i, 0, N) FOR(j, 1, M)
                if (!i) twocolumns[i][j] = dice[i][j].x & dice[i][j-1].x;
                else{
                        twocolumns[i][j] = (twocolumns[i][j] + dice[i][j].x*dice[i][j-1].x*twocolumns[i-1][j])%MOD;
                        if (dice[i][j].y&dice[i-1][j].y&dice[i][j-1].y&dice[i-1][j-1].y)
                                twocolumns[i][j] = (twocolumns[i][j] + ((i==1)?1:twocolumns[i-2][j]))%MOD;
                }
        //FOR(i, 1, M) printf("%lld ", column[i]); puts("");
        //FOR(i, 1, M) printf("%lld ", twocolumns[N-1][i]); puts("");
        FOR(i, 1, M) if (column[i]) twocolumns[N-1][i]--;
        //FOR(i, 1, M) printf("%lld ", twocolumns[N-1][i]); puts("");
        LL DP[M];
        memset(DP, 0, sizeof(DP));
        DP[0] = column[0];
        DP[1] = twocolumns[N-1][1];
        FOR(i, 1, M){
                DP[i] = (DP[i] + column[i] * DP[i-1]) %MOD;
                if (i > 1) DP[i] = (DP[i] + DP[i-2] * twocolumns[N-1][i])% MOD;
                //printf("%lld ", DP[i]);
        }
        //puts("");
        cout << DP[M-1] << endl;
        return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <fstream>
#include <complex>

#define pb push_back
#define pf push_front
#define mp make_pair
#define REP(i, a, b)     for (int i = int(a); i <= int(b); i++)
#define SET(p) memset(p, -1, sizeof(p))
#define CLR(p) memset(p, 0, sizeof(p))
#define all(c) c.begin(), c.end()
#define tr(container, it) for(typeof(container.begin()) it=container.begin(); it!=container.end(); it++)
#define present(container, element) (container.find(element)!=container.end())
#define cpresent(container, element) (find(all(container), element)!=container.end())
#define sz(a) int((a).size())

using namespace std;

typedef long long ll;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<int> vi;
typedef vector<vi> vvi;

const double PI = 2.0*acos(0.0);
const double EPS = 1e-9;
const int MOD = 1000000007;
const int INF = 1000000000;
const ll LINF = 1000000000000000000LL;

vector<string> vs;
ii arr[260][260];
map<string, ii> mapa;
int n, m;
long long pdcol[260], pdrow[260];

void debug() {
    REP (i, 1, n) {
        REP (j, 1, m) printf("(%d,%d) ", arr[i][j].first, arr[i][j].second);
        puts("");
    }
}

void init() {
    mapa["........."]=mp(0, 3), mapa["....O...."]=mp(1, 3), mapa["..O...O.."]=mp(2, 1), mapa["O.......O"]=mp(2, 2), mapa["..O.O.O.."]=mp(3, 1);
    mapa["O...O...O"]=mp(3, 2), mapa["O.O...O.O"]=mp(4, 3), mapa["O.O.O.O.O"]=mp(5, 3), mapa["O.OO.OO.O"]=mp(6, 1), mapa["OOO...OOO"]=mp(6, 2);
    string str;
    cin>>n>>m;
    REP (i, 1, 4*n+1) cin>>str, vs.pb(str);
    REP (i, 1, n) REP (j, 1, m) {
        str="";
        REP (k, 1, 3) str+=vs[4*(i-1)+k].substr(4*(j-1)+1, 3);
        arr[i][j]=mapa[str];
    }
}

ll uni(int c) {
    if (n%2) return 0LL;
    ll ret=1LL;
    REP (i, 1, n) ret&=arr[i][c].second&1;
    return ret;
}

ll dupla(int c) {
    REP (i, 1, n) {
        pdrow[i]=1LL*(arr[i][c-1].second&2)/2LL*(arr[i][c].second&2)/2LL*pdrow[i-1];
        //cout<<i<<' '<<c<<' '<<pdrow[i]<<endl;
        if (i>1) pdrow[i]=(pdrow[i]+1LL*(arr[i-1][c-1].second&1)*(arr[i-1][c].second&1)*(arr[i][c-1].second&1)*(arr[i][c].second&1)*pdrow[i-2]%MOD)%MOD;
        //cout<<i<<' '<<c<<' '<<pdrow[i]<<endl;
    }
    pdrow[n]=(pdrow[n]-1LL*uni(c)*uni(c-1)+MOD)%MOD;
    return pdrow[n];
}

int main() {
    init(), pdcol[0]=pdrow[0]=1LL;
    //debug();
    REP (i, 1, m) {
        pdcol[i]=1LL*uni(i)*pdcol[i-1];
        if (i>1) pdcol[i]=(pdcol[i]+1LL*dupla(i)*pdcol[i-2]%MOD)%MOD;
        /*cout<<i<<' '<<uni(i)<<endl;
        cout<<i<<' '<<dupla(i)<<endl;
        cout<<i<<' '<<pdcol[i]<<endl;*/
    }
    cout<<pdcol[m]<<endl;
    return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <fstream>
#include <complex>

#define pb push_back
#define pf push_front
#define mp make_pair
#define REP(i, a, b)     for (int i = int(a); i <= int(b); i++)
#define SET(p) memset(p, -1, sizeof(p))
#define CLR(p) memset(p, 0, sizeof(p))
#define all(c) c.begin(), c.end()
#define tr(container, it) for(typeof(container.begin()) it=container.begin(); it!=container.end(); it++)
#define present(container, element) (container.find(element)!=container.end())
#define cpresent(container, element) (find(all(container), element)!=container.end())
#define sz(a) int((a).size())

using namespace std;

typedef long long ll;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<int> vi;
typedef vector<vi> vvi;

const double PI = 2.0*acos(0.0);
const double EPS = 1e-9;
const int MOD = 1000000009;
const int INF = 1000000000;
const ll LINF = 1000000000000000000LL;

vector<string> vs;
ii arr[260][260];
map<string, ii> mapa;
int n, m;
long long pdcol[260], pdrow[260];

void debug() {
    REP (i, 1, n) {
        REP (j, 1, m) printf("(%d,%d) ", arr[i][j].first, arr[i][j].second);
        puts("");
    }
}

void init() {
    mapa["........."]=mp(0, 3), mapa["....O...."]=mp(1, 3), mapa["..O...O.."]=mp(2, 1), mapa["O.......O"]=mp(2, 2), mapa["..O.O.O.."]=mp(3, 1);
    mapa["O...O...O"]=mp(3, 2), mapa["O.O...O.O"]=mp(4, 3), mapa["O.O.O.O.O"]=mp(5, 3), mapa["O.OO.OO.O"]=mp(6, 1), mapa["OOO...OOO"]=mp(6, 2);
    string str;
    cin>>n>>m;
    REP (i, 1, 4*n+1) cin>>str, vs.pb(str);
    REP (i, 1, n) REP (j, 1, m) {
        str="";
        REP (k, 1, 3) str+=vs[4*(i-1)+k].substr(4*(j-1)+1, 3);
        arr[i][j]=mapa[str];
    }
}

ll uni(int c) {
    if (n%2) return 0LL;
    ll ret=1LL;
    REP (i, 1, n) ret&=arr[i][c].second&1;
    return ret;
}

ll dupla(int c) {
    REP (i, 1, n) {
        pdrow[i]=1LL*(arr[i][c-1].second&2)/2LL*(arr[i][c-1].second&2)/2LL*pdrow[i-1];
        if (i>1) pdrow[i]=(pdrow[i]+1LL*(arr[i-1][c-1].second&1)*(arr[i-1][c].second&1)*(arr[i][c-1].second&1)*(arr[i][c].second&1)*pdrow[i-2]%MOD)%MOD;
        //cout<<i<<' '<<c<<' '<<pdrow[i]<<endl;
    }
    pdrow[n]=(pdrow[n]-1LL*uni(c)*uni(c-1)+MOD)%MOD;
    return pdrow[n];
}

int main() {
    init(), pdcol[0]=pdrow[0]=1LL;
    //debug();
    REP (i, 1, m) {
        pdcol[i]=1LL*uni(i)*pdcol[i-1];
        if (i>1) pdcol[i]=(pdcol[i]+1LL*dupla(i)*pdcol[i-2]%MOD)%MOD;
        //cout<<i<<' '<<uni(i)<<endl;
        //cout<<i<<' '<<dupla(i)<<endl;
        //cout<<i<<' '<<pdcol[i]<<endl;
    }
    cout<<pdcol[m]<<endl;
    return 0;
}