Matrix 在Mathematica中将坐标系转换为矩阵

Matrix 在Mathematica中将坐标系转换为矩阵,matrix,count,wolfram-mathematica,coordinates,transform,Matrix,Count,Wolfram Mathematica,Coordinates,Transform,在回答编程问题之前,我认为我需要提供一点背景知识,说明我正在做什么,以便于理解我的问题: 我记录下眼睛的运动,同时向受试者展示一些图案。通过实验,我随后展示了这些图案的一些对称变换 我得到的是固定坐标和持续时间列表: {fix1X,fix1Y,fix1Dn},{fix2X,fix2Y,fix2Dn},{fixNX,fixNY,fixNDn} 其中: -fix1X是第一次固定的X坐标 -fix1Y是第一次固定的Y坐标 -fix1D是固定的持续时间(以毫秒为单位) 请考虑:< /强> Fram

在回答编程问题之前,我认为我需要提供一点背景知识,说明我正在做什么,以便于理解我的问题:

我记录下眼睛的运动,同时向受试者展示一些图案。通过实验,我随后展示了这些图案的一些对称变换

我得到的是固定坐标和持续时间列表:

{fix1X,fix1Y,fix1Dn},{fix2X,fix2Y,fix2Dn},{fixNX,fixNY,fixNDn}

其中:

-fix1X是第一次固定的X坐标

-fix1Y是第一次固定的Y坐标

-fix1D是固定的持续时间(以毫秒为单位)

<强>请考虑:< /强>

FrameWidth  = 31.36;
scrHeightCM = 30;
scrWidthCM  = 40;
FrameXYs    = {{4.32, 3.23}, {35.68, 26.75}};  (* {{Xmin,Ymin},{Xmax,Ymax}} *)
下面是1个显示器的固定画面(屏幕上显示3s刺激时的受试者固定画面)

我想做什么:

FrameWidth  = 31.36;
scrHeightCM = 30;
scrWidthCM  = 40;
FrameXYs    = {{4.32, 3.23}, {35.68, 26.75}};  (* {{Xmin,Ymin},{Xmax,Ymax}} *)
我想将刺激帧空间“离散化”为簇:

下面是不同簇(2,4,16,64)的视觉表示(用PPT完成)

表示发生固定的簇的彩色部分:

有了这个,我想

-计算每个群集中的固定数量

-计算每个集群中观察到的存在/计数或持续时间

矩阵形式很容易让我通过减法比较不同的显示固定

因此,问题(s)

-如何创建一种灵活的机制来将刺激帧划分为簇。

-将固定点映射到这些簇上,获得一个矩形矩阵,其中填充0或每个矩阵单元的固定点计数或总固定持续时间。

我觉得这个问题可能不清楚,将对其进行编辑,以澄清任何需要的内容。 另外,您是否认为这应该在两个单独的问题中提出,我很乐意这样做


很多人会提前感谢您提供的任何帮助。

您可以做以下事情:

createMatrix[list_, frameXYs_, partitX_, partitY_, fun_] :=
 Module[{matrix},
  (*init return matrix*)
  matrix = Array[0 &, {partitX, partitY}];
  (matrix[[
    IntegerPart@Rescale[#[[1]], {frameXYs[[1, 1]], frameXYs[[2, 1]]}, {1,partitX}],
    IntegerPart@Rescale[#[[2]], {frameXYs[[1, 2]], frameXYs[[2, 2]]}, {1,partitY}]
         ]] += fun[#[[3]]]) & /@ list;

  Return@(matrix[[1 ;; -2, 1 ;; -2]]);]
其中
fun
是列表第三维的计数函数

因此,如果要计算发生次数,请执行以下操作:

fix = {{20.14, 15.22, 774.}, {20.26, 15.37, 518.}, {25.65, 16.22, 200.}, 
       {28.15, 11.06, 176.}, {25.25, 13.38, 154.}, {24.78, 15.74, 161.}, 
       {24.23, 16.58, 121.}, {20.06, 13.22, 124.}, {24.91, 15.8,  273.}, 
       {24.32, 12.83, 119.}, {20.06, 12.14, 366.}, {25.64, 18.22, 236.}, 
       {24.37, 19.2, 177.},  {21.02, 16.4, 217.},  {20.63, 15.75, 406.}};
FrameXYs = {{4.32, 3.23}, {35.68, 26.75}};

cm = createMatrix[fix, FrameXYs, 10, 10, 1 &]
MatrixPlot@cm
MatrixForm@cm

如果你想把注视时间加起来

cm = createMatrix[fix, FrameXYs, 10, 10, # &]
MatrixPlot@cm
MatrixForm@cm

编辑

对索引进行一些调整,对代码进行一些修饰,一个更清晰的示例:

createMatrix[list_, frameXYs_, partit : {partitX_, partitY_}, fun_] :=
 Module[{matrix, g},
  (*Define rescale function*)
  g[i_, l_] := IntegerPart@
                   Rescale[l[[i]], (Transpose@frameXYs)[[i]], {1, partit[[i]]}];
  (*Init return matrix*)
  matrix = Array[0 &, {partitX + 1, partitY + 1}];
  (matrix[[g[1, #], g[2, #]]] += fun[#[[3]]]) & /@ list;
  Return@(matrix[[1 ;; -2, 1 ;; -2]]);]


要实现你的目标,必须做几件事。首先,给定一个除法计数,我们必须对二维空间进行除法。其次,使用除法计数,我们需要一种灵活的方法将固定点分组到适当的位置。最后,我们生成您需要的任何统计数据

至于除法计数,内置函数几乎可以满足您的需要。比如说,

(* The second parameter is the upper limit for the number of factors returned *)
FactorInteger[35,2] == {{5,1}, {7,1}}
FactorInteger[64,2] == {{2,6}}
不幸的是,您只能指定返回的因子数的上限,因此我们必须稍微修改输出

Clear[divisionCount]
divisionCount[c_Integer?(Positive[#] && (# == 2 || ! PrimeQ[#]) &)] :=
With[{res = FactorInteger[c, 2]},
 Power @@@ If[ 
     Length[res] == 2, 
     res // Reverse,
     With[
       {q = Quotient[res[[1, 2]], 2], r = Mod[res[[1, 2]], 2], 
        b = res[[1, 1]]},
       {{b, q + r}, {b, q}}
     ]
 ]
] 
这做了两件事,将
{b,m}}
替换为
{b,m/2+m mod 2},{b,m/2}
,其中
/
表示整数除法(即有余数),并通过将
{b,m}.}
转换为
{b^m..}
。这给

divisionCount[32] == {8, 4}
divisionCount[64] == {8, 8}.
事实证明,在这一点上,我们可以通过最小的额外工作获得固定计数,如下所示

BinCounts[fix[[All,;;2]], (* stripping duration from tuples *)
  {xmin, xmax, (xmax - xmin)/#1,
  {ymin, ymax, (ymax - ymin)/#2]& @@ divisionCount[ divs ]
Clear[makeDivisions]
makeDivisions[
 {xmin_, xmax_, xdivs_Integer?Positive}, {ymin_, ymax_, ydivs_Integer?Positive}] :=
   Partition[#,2,1]& /@ {
     (xmax - xmin)*Range[0, xdivs]/xdivs + xmin,
     (ymax - ymin)*Range[0, ydivs]/ydivs + ymin
   }

makeDivisions[
       {xmin_, xmax_}, {ymin_, ymax_}, 
       divs_Integer?(Positive[#] && (# == 2 || ! PrimeQ[#]) &)] :=
 makeDivisions[{xmin, xmax, #1}, {ymin, ymax, #2}] & @@ divisionCount[divs]
其中需要提供
x
y
的范围以及分区数。然而,这并没有它可能的那么灵活。相反,我们将利用

有效使用
SelectEquivalents
的关键是创建良好的分类功能。要做到这一点,我们需要自己确定划分,如下所示

BinCounts[fix[[All,;;2]], (* stripping duration from tuples *)
  {xmin, xmax, (xmax - xmin)/#1,
  {ymin, ymax, (ymax - ymin)/#2]& @@ divisionCount[ divs ]
Clear[makeDivisions]
makeDivisions[
 {xmin_, xmax_, xdivs_Integer?Positive}, {ymin_, ymax_, ydivs_Integer?Positive}] :=
   Partition[#,2,1]& /@ {
     (xmax - xmin)*Range[0, xdivs]/xdivs + xmin,
     (ymax - ymin)*Range[0, ydivs]/ydivs + ymin
   }

makeDivisions[
       {xmin_, xmax_}, {ymin_, ymax_}, 
       divs_Integer?(Positive[#] && (# == 2 || ! PrimeQ[#]) &)] :=
 makeDivisions[{xmin, xmax, #1}, {ymin, ymax, #2}] & @@ divisionCount[divs]
在哪里

(我可能会使用,但它并不总是返回您请求的分割数。)
makeDivisions
返回两个列表,其中每个列表中的每个项都是一个最小-最大对,我们可以使用它们来确定一个点是否落在bin中

因为我们在一个正方形格子上,我们需要测试我们刚刚确定的所有极限对。我会用下面的方法

Clear[inBinQ, categorize]
inBinQ[{xmin_,xmax_}, {ymin_, ymax_}, {x_,y_}]:= 
   (xmin <= x < xmax) && (ymin <= y < ymax)

categorize[{xmin_, xmax_}, {ymin_, ymax_}, divs_][val : {x_, y_, t_}] := 
 With[{bins = makeDivisions[{xmin, xmax}, {ymin, ymax}, divs]}, 
  Outer[inBinQ[#1, #2, {x, y}] &, bins[[1]], bins[[2]], 1]] //Transpose
注意,y坐标与绘图相反,低值位于数组的开头。要“修复”此问题,
分类中反转
垃圾箱[[2]]
。另外,在将结果提供给
MatrixPlot
之前,您需要删除
转置
,因为它希望结果以未转换的形式出现

使用

我们得到

{{
  {{0, 0, 0}, {0, 1, 0}}, {774., 518., 161., 121., 273., 177., 217., 406.}
 }, 
 {
  {{0, 0, 0}, {0, 0, 1}}, {200., 236.}
 }, 
 {
  {{0, 0, 1}, {0, 0, 0}}, {176., 154.}
 }, 
 {
  {{0, 1, 0}, {0, 0, 0}}, {124., 119., 366.}
 }}}
其中,每个子列表中的第一项是bin的矩阵表示,第二项是属于该bin的点列表。要确定每个箱子中有多少个

Plus @@ (Times @@@ ({#1, Length[#2]} & @@@ %)) ==
 {{0, 3, 2}, {0, 8, 2}}
或者,时间

Plus @@ (Times @@@ ({#1, Total[#2]} & @@@ %)) ==
 {{0, 609., 330.}, {0, 2647., 436.}}

编辑:如您所见,要获得所需的定影统计信息,您只需替换
长度
总计
。例如,您可能需要平均(
Mean
)花费的时间,而不仅仅是总时间。

根据您正在执行的计算和数据的精度,您可能需要更软的方法。考虑使用图像重采样。这里有一种可能的方法。这里有明显的模糊性,但同样,这可能是可取的

fix = {{20.14, 15.22, 774.}, {20.26, 15.37, 518.}, {25.65, 16.22, 
    200.}, {28.15, 11.06, 176.}, {25.25, 13.38, 154.}, {24.78, 15.74, 
    161.}, {24.23, 16.58, 121.}, {20.06, 13.22, 124.}, {24.91, 15.8, 
    273.}, {24.32, 12.83, 119.}, {20.06, 12.14, 366.}, {25.64, 18.22, 
    236.}, {24.37, 19.2, 177.}, {21.02, 16.4, 217.}, {20.63, 15.75, 
    406.}};
FrameXYs = {{4.32, 3.23}, {35.68, 26.75}};

Graphics[{AbsolutePointSize@Sqrt@#3, Point[{#, #2}]} & @@@ fix, 
 BaseStyle -> Opacity[0.3], PlotRange -> Transpose@FrameXYs,
 PlotRangePadding -> None, ImageSize -> {400, 400}]

ImageResize[%, {16, 16}];

Show[ImageAdjust@%, ImageSize -> {400, 400}]


由于上述情况显然无济于事,这里是一个建设性的尝试。 这是我对belisarius的完美解决方案的看法。我觉得有点干净

createMatrix[list_, {{x1_, y1_}, {x2_, y2_}}, par:{pX_, pY_}, fun_] :=
 Module[{matrix, quant},
    matrix = 0 ~ConstantArray~ par;
    quant = IntegerPart@Rescale@## &;
    (matrix[[
         quant[#1, {x1, x2}, {1, pX}],
         quant[#2, {y1, y2}, {1, pY}]
           ]] += fun[#3] &) @@@ list;
    Drop[matrix, -1, -1]
 ]

注意,语法略有不同:量化分区x和y在列表中给出。我觉得这与其他函数更加一致,例如
数组

不同的细分有多大?它们是整数像素数吗?您的示例显示了1:2:4:8细分。我们是否应该得出结论,要求的细分都是2的幂?为什么在第一个示例中,您将屏幕水平分割而不是垂直分割?这是否意味着细分应该在地平线上独立完成
fix = {{20.14, 15.22, 774.}, {20.26, 15.37, 518.}, {25.65, 16.22, 
    200.}, {28.15, 11.06, 176.}, {25.25, 13.38, 154.}, {24.78, 15.74, 
    161.}, {24.23, 16.58, 121.}, {20.06, 13.22, 124.}, {24.91, 15.8, 
    273.}, {24.32, 12.83, 119.}, {20.06, 12.14, 366.}, {25.64, 18.22, 
    236.}, {24.37, 19.2, 177.}, {21.02, 16.4, 217.}, {20.63, 15.75, 
    406.}};
FrameXYs = {{4.32, 3.23}, {35.68, 26.75}};

Graphics[{AbsolutePointSize@Sqrt@#3, Point[{#, #2}]} & @@@ fix, 
 BaseStyle -> Opacity[0.3], PlotRange -> Transpose@FrameXYs,
 PlotRangePadding -> None, ImageSize -> {400, 400}]

ImageResize[%, {16, 16}];

Show[ImageAdjust@%, ImageSize -> {400, 400}]
createMatrix[list_, {{x1_, y1_}, {x2_, y2_}}, par:{pX_, pY_}, fun_] :=
 Module[{matrix, quant},
    matrix = 0 ~ConstantArray~ par;
    quant = IntegerPart@Rescale@## &;
    (matrix[[
         quant[#1, {x1, x2}, {1, pX}],
         quant[#2, {y1, y2}, {1, pY}]
           ]] += fun[#3] &) @@@ list;
    Drop[matrix, -1, -1]
 ]