//这道题是矩阵树定理中:给出有向图和其中一个点,求以这个点为根的生成外向树个数
/*
 矩阵树定理:有向图有根树的情况
 去掉所有自环,主对角线上第i行第i列是i这个点的出度,剩下的是邻接矩阵取相反数。
 然后求的是删掉根节点所在行列式的余子式的行列式
 */

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
typedef long long ll;
using namespace std;

#define maxr 210
#define maxnode 40010
#define maxn 310
#define MOD 1000000007
#define LL long long

int T, r, c;
char Map[maxr][maxr]; //记录r行c列的字符

struct Graph //Graph有clear 和 AddEdge函数
{
    int n, m;
    int head[maxnode], nxt[maxnode], to[maxnode];
    Graph() {}

    void clear() //一开始的m为0(0条边),head都是0
    {
        m = 0;
        memset(head, 0, sizeof(head));
        return ;
    }

    void AddEdge(int a, int b) //添加边
    {
        //第++m条边,
        ++m;
        to[m] = b;         //第m条边的to是b
        nxt[m] = head[a];  //第m条边的nxt是head[a] -> 之后head[a]=m
        head[a] = m;       //a的head是m
        return ;
    }
} G;

int id(int i, int j)
{
    return (i - 1) * c + j;
}
int vis[40010];

bool dfs(int u)
{
    if(vis[u] == 2) return 0;
    if(vis[u]) return 1;
    vis[u] = 2;
    for(int e = G.head[u]; e; e = G.nxt[e])
    {
        if(dfs(G.to[e])==0)
        {
            return 0;
        }
    }
    vis[u] = 1;
    return 1;
}

int pre[40010]; //祖先函数(pre)

int find(int x)  //寻找x的祖先(并查集)
{
    if(x==pre[x]) return x;
    else return pre[x]=find(pre[x]);
}

int n, trid[40010];

int ID(int u)
{
    if(trid[u]!=0) return trid[u];
    else return trid[u]=++n;
}

int A[maxn][maxn], tA[maxn][maxn];

void MatAddEdge(int a, int b)
{
    if(a == b) return ;
    tA[a][a]++; tA[a][b]--;
    return ;
}

void elim(int *a, int *b, int tar)
{
    if(!b[tar]) return ;
    int rate = a[tar] / b[tar];
    for (int i=1;i<=n;i++)
    {
        a[i] = ((LL)a[i] - (LL)b[i] * rate % MOD + MOD) % MOD;
    }
    elim(b, a, tar);
    return ;
}

int solve()
{
    n--;
    int sgn = 1;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            if(A[i][j] < 0) A[i][j] += MOD;
        }
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=i+1;j<=n;j++)
        {
            if(A[j][i])
            {
                elim(A[i], A[j], i);
                if(!A[i][i])
                {
                    swap(A[i], A[j]);
                    sgn = -sgn;
                }
            }
        }
    }
    int sum = 1;
    for (int i=1;i<=n;i++)
    {
        sum = (LL)sum * A[i][i] % MOD;
    }
    return (sum * sgn + MOD) % MOD;
}

int main()
{
    cin >> T; //多少组样例
    while(T--)
    {
        cin >> r >> c; //r代表行数,c代表列数
        G.n = r * c + 1; //图表里面的 n=行数*列数+1

        /*初始化*/
        G.clear();
        for (int i=1;i<=G.n;i++) //每一个点的祖先都是自己
        {
            pre[i]=i;
        }
        /*进行图的更新*/
        for (int i=1;i<=r;i++) //输入r行,一行一个字符串
        {
            scanf("%s", Map[i] + 1); //想要以这种方法输入,必须是char数组的形式,不能是string的形式
        }
        for (int i=1;i<=r;i++) //遍历一共r行
        {
            for (int j=1;j<=c;j++) //遍历一共j行
            {
                if(Map[i][j] == 'D')//如果i不是最后一行,则D可以进行,否则就出去了
                {
                    int x=id(i,j);
                    int y;
                    if(i!=r) y=id(i+1,j);
                    else y=G.n;
                    G.AddEdge(x, y);
                    int u = find(x);
                    int v = find(y);
                    if(u != v) pre[v] = u;   //如果两者的祖先不相同,就进行合并
                }
                if(Map[i][j] == 'U')
                {
                    int x=id(i,j);
                    int y;
                    if(i!=1) y=id(i-1,j);
                    else y=G.n;
                    G.AddEdge(x, y);
                    int u=find(x);
                    int v=find(y);
                    if(u!=v) pre[v]=u;
                }
                if(Map[i][j] == 'R')
                {
                    G.AddEdge(id(i, j), j < c ? id(i, j + 1) : G.n);
                    int u = find(id(i, j)), v = find(j < c ? id(i, j + 1) : G.n);
                    if(u != v) pre[v] = u;
                }
                if(Map[i][j] == 'L')
                {
                    G.AddEdge(id(i, j), j > 1 ? id(i, j - 1) : G.n);
                    int u = find(id(i, j)), v = find(j > 1 ? id(i, j - 1) : G.n);
                    if(u != v) pre[v] = u;
                }
            }
        }
        memset(vis, 0, sizeof(vis));     //初始化vis函数
        bool ok = 1;

        for(int i=1;i<=G.n;i++)
        {
            if(vis[i]==0 && dfs(i)==0)
            {
                cout << "0" << endl;
                ok = 0;
                break;
            }
        }

        if(!ok) continue;

        memset(trid, 0, sizeof(trid)); n = 0;
        memset(tA, 0, sizeof(tA));
        for (int i=1;i<=r;i++)
        {
            for (int j=1;j<=c;j++)
            {
                if(Map[i][j]=='.')
                {
                    int u = find(id(i, j));
                    MatAddEdge(ID(u), ID(find(i < r ? id(i + 1, j) : G.n)));
                    MatAddEdge(ID(u), ID(find(i > 1 ? id(i - 1, j) : G.n)));
                    MatAddEdge(ID(u), ID(find(j < c ? id(i, j + 1) : G.n)));
                    MatAddEdge(ID(u), ID(find(j > 1 ? id(i, j - 1) : G.n)));
                }
            }
        }

        int ci = 0, cj = 0;
        for (int i=1;i<=n;i++)
        {
            if(i != ID(find(G.n)))
            {
                ci++;
                cj = 0;
                for (int j=1;j<=n;j++)
                {
                    if(j != ID(find(G.n)))
                    {
                        A[ci][++cj] = tA[i][j];
                    }
                }
            }
        }
        cout << solve() << endl;
    }
    return 0;
}