以下某些代码可能至少需要 JMP 15 才能支持 XML 导入。 它还使用了对未来需要调整的显示框树的深刻理解。
@datanaut问计算等高线内的面积. 我走了三条路试图弄清楚这一点。 首先,设置代码:
dt = Open( "$sample_data/big class.jmp", invisible );
magenta = RGB Color( 1, 0, 1 );// pure magenta
cp = dt << Contour Plot(
X( :weight, :height ),
Y( :age ),
Show Boundary( 0 ),
Show Data Points( 0 ),
Fill Areas( 1 ),
Label Contours( 0 ),
Transform( "Range Normalized" ),
Color Theme( "White to Black" ),
Show Boundary( 0 ),
Specify Contours( Min( 12.5 ), Max( 16.5 ), N( 9 ) ),
SendToReport( Dispatch( {}, "Contour Plot Graph", FrameBox, {Frame Size( 623, 512 ), Background Color( magenta )} ) )
);
ymin = (Report( cp )[axisbox( 1 )] << getscript)["Min"];
ymax = (Report( cp )[axisbox( 1 )] << getscript)["Max"];
xmin = (Report( cp )[axisbox( 2 )] << getscript)["Min"];
xmax = (Report( cp )[axisbox( 2 )] << getscript)["Max"];
Show( xmin, xmax, ymin, ymax );
cp << minimizewindow( 1 );
Gray contours on magenta background.Gray contours on magenta background.Gray contours on magenta background.Gray contours on magenta background.洋红色背景上的灰色轮廓。
第一条路很短。 我发现等高线图有一条消息给 <
路径二是计算像素,可能类似于@gzmorgan0方法。 它有效,但有一些缺陷,您可以在上图中看到这些缺陷。 我故意制作了难看的洋红色背景,这样我就可以轻松地寻找灰色像素。 但如果你仔细观察,你会看到一些洋红色从区域之间渗漏出来。 无赖! 工作中的抗锯齿! 通常,在白色背景上,您几乎不会注意到,但颜色之间的灰度过渡仍然存在。
Zoomed in, the darker regions are still anti-aliased against white.Zoomed in, the darker regions are still anti-aliased against white.Zoomed in, the darker regions are still anti-aliased against white.Zoomed in, the darker regions are still anti-aliased against white.放大后,较暗的区域仍然针对白色进行抗锯齿处理。
不管怎样,下面的代码试图将洋红色像素放入附近的灰色区域。 也许它可以平衡地让任何一方犯错。 没有洋红色,一切都将是灰色阴影,代码将无法看到需要做出决定。 (这似乎在 JMP 14 和 15 上运行。)
pixels = (Report( cp )[framebox( 1 )] << getimage) << getpixels;
// trim non magenta edges. not sure why there are extra pixels...
For( ileft = 1, ileft < N Cols( pixels ), iLeft += 1,
If( pixels[N Rows( pixels ) / 2, ileft] == magenta,
Break()
)
);
For( iright = N Cols( pixels ), iright > ileft, iright -= 1,
If( pixels[N Rows( pixels ) / 2, iright] == magenta,
Break()
)
);
For( itop = 1, itop < N Rows( pixels ), itop += 1,
If( pixels[itop, N Cols( pixels ) / 2] == magenta,
Break()
)
);
For( ibottom = N Rows( pixels ), ibottom > itop, ibottom -= 1,
If( pixels[ibottom, N Cols( pixels ) / 2] == magenta,
Break()
)
);
If( ileft > 10 | itop > 10 | iright < N Cols( pixels ) - 10 | ibottom < N Rows( pixels ) - 10,
Throw( "trimming error" )
);
pixels = pixels[itop :: ibottom, ileft :: iright];
colorCounts = [=> 0];
spiral = [-1 -1, -1 0, -1 1, 0 1, 1 1, 1 0, 1 -1, 0 -1, -2 -2, -2 -1, -2 0, -2 1, -2 2, -1 2, 0 2, 1 2, 2 2, 2 1, 2 0, 2 -1, 2 -2, 1 -2, 0 -2, -1 -2];
grays = [=> ];
For( i = 0, i <= 255, i += 1,
grays[RGB Color( i / 255, i / 255, i / 255 )] = i
);
temp = pixels;
For( i = 1, i <= N Items( pixels ), i += 1,
// pixels that are not magenta and not gray, but are antialiased values...
// force them to the gray of a near pixel
If( pixels[i] != magenta,
{r, g, b} = Color To RGB( pixels[i] );
If( (r != g & r == b),
rowidx = Floor( (i - 1) / N Cols( pixels ) ) + 1; // nc is the number of columns in the 2D pixmat
colidx = Mod( (i - 1), N Cols( pixels ) ) + 1; // rowlocs and collocs are 2D indexes (1-based)
For( j = 1, j <= N Rows( spiral ), j += 1,
// if this has an array out of bounds, make sure there is magenta pad all around
color = pixels[rowidx + spiral[j, 1], colidx + spiral[j, 2]];
If( grays << Contains( color ),
temp[i] = color;
Break();
);
);
);
);
colorCounts[temp[i]] += 1;
);
pixels = temp;
totalpixels = Sum( colorCounts << getvalues );
If( totalpixels != N Rows( pixels ) * N Cols( pixels ),
Throw( "error counting pixels" )
);
areaPerPixel = 1;//((ymax - ymin) * (xmax - xmin)) / totalpixels;
New Window( "Check polygons are inside the magenta area", New Image( pixels ) );
pixelcount = 0;
For( ii = 0, ii <= 255, ii += 1,
i = ii / 255;
If( colorcounts[RGB Color( i, i, i )] > 0,
thisarea = colorcounts[RGB Color( i, i, i )] * areaPerPixel;
Write( "\!ngray=", If( i == 0, "black", i == 1, "white", Char( i, 7, 3 ) ), " \!tarea=", Char( thisarea, 5 ) );
pixelcount += colorcounts[RGB Color( i, i, i )];
pixels[Loc( pixels == RGB Color( i, i, i ) )] = RGB Color( 0, 1, 0 );
);
);
thisarea = colorcounts[magenta] * areaPerPixel;
Write( "\!nmagenta \!tarea=", Char( thisarea, 7, 3 ) );
pixelcount += colorcounts[magenta];
pixels[Loc( pixels == magenta )] = RGB Color( 0, 1, 0 );
New Window( "Check polygons are inside the magenta area", New Image( pixels ) );
Write( "\!nidentified \!tarea=", Char( pixelcount * areaPerPixel, 7, 3 ) );
Write( "\!nall graph \!tarea=", Char( totalpixels * areaPerPixel, 7, 3 ) );
Write( "\!noverlooked \!tarea=", Char( (totalpixels - pixelcount) * areaPerPixel, 7, 3 ) );这是清理后的图像
The interior magenta pixels are converted to a nearby gray.The interior magenta pixels are converted to a nearby gray.The interior magenta pixels are converted to a nearby gray.The interior magenta pixels are converted to a nearby gray.内部洋红色像素被转换为附近的灰色。
仍然存在一些破烂,但可能会在其他地方得到平衡:
Those pixels will be counted wrong.Those pixels will be counted wrong.Those pixels will be counted wrong.Those pixels will be counted wrong.这些像素将被计算错误。
结果是日志窗口中的一个表。
灰=黑 面积=2598
灰色=0.098 面积=2973
灰色=0.200 面积=3781
灰色=0.302 面积=5003
灰色=0.400 面积=8528
灰色=0.502 面积=12535
灰色=0.600 面积=11081
灰色=0.702 面积=8382
灰色=0.800 面积=12718
灰色=0.902 面积=13074
洋红色区域=238302
识别区域=318975
所有图形面积=318976
被忽视的面积=1.000
被忽略的像素是右上角几乎纯品红色的像素。 没有试图进一步追踪它。
如果可以的话,路径三可能是最好的;它取决于 JMP 以相同方式编写 SVG 文件,并且也可能取决于此特定示例。 答案与第二次尝试非常相似,应该更正确。 (这取决于 JMP 15 中的功能。)理解 SVG 路径的关键:矩阵的第 3 列对于段的结尾是负的;开始/结束数组定位路径矩阵中的段。
(Report( cp )[framebox( 1 )]) << savepicture( "$temp/deletemeGraph.svg" );
(Report( cp )[framebox( 2 )]) << savepicture( "$temp/deletemeLegend.svg" );
Rename File( "$temp/deletemeGraph.svg", "deletemeGraph.xml" );
Rename File( "$temp/deletemeLegend.svg", "deletemeLegend.xml" );
dtSVGGraph = Open(
"C:\Users\v1\AppData\Local\Temp\deletemeGraph.xml",
XML Settings( Stack( 1 ), Row( "/svg/g/g/g/g/g/path/@d" ), Row( "/svg/g/g/g/g/path/@d" ),
Col( "/svg/g/g/g/g/g/@fill", Column Name( "color" ), Fill( "Use Once" ), Type( "Character" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/g/g/g/g/g/path/@d", Column Name( "path" ), Fill( "Use Once" ), Type( "Character" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/@width", Column Name( "width" ), Fill( "Use Once" ), Type( "Table Variable" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/@height", Column Name( "height" ), Fill( "Use Once" ), Type( "Table Variable" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/g/@fill", Column Name( "colorAlternate" ), Fill( "-", "/svg/g" ), Type( "Character" ), Format( {"Best"} ), Modeling Type( "Continuous" ) ),
Col( "/svg/g/g/g/g/path/@d", Column Name( "path" ), Fill( "Use Once" ), Type( "Character" ), Format( {"Best"} ), Modeling Type( "Continuous" ) ) ),
XML Wizard( 0 )
);
For( i = 1, i <= N Rows( dtSVGGraph ), i += 1,
If( dtSVGGraph:color[i] == "",
dtSVGGraph:color[i] = dtSVGGraph:colorAlternate[i]
)
);
dtSVGGraph << deletecolumns( {colorAlternate} );
dtSVGLegend = Open(
"C:\Users\v1\AppData\Local\Temp\deletemeLegend.xml",
XML Settings(
Stack( 1 ),
Row( "/svg/g/g/g/g/g/text" ),
Row( "/svg/g/g/g/g/text" ),
Col( "/svg/g/g/g/g/g/@fill", Column Name( "color" ), Fill( "Use Once" ), Type( "Character" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/g/g/g/g/g/text", Column Name( "text" ), Fill( "Use Once" ), Type( "Character" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/g/g/g/g/text", Column Name( "textAlternate" ), Fill( "Use Once" ), Type( "Character" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/g/g/g/g/g/rect/@y", Column Name( "y" ), Fill( "Use Once" ), Type( "Numeric" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/g/g/g/g/rect/@y", Column Name( "y" ), Fill( "Use Once" ), Type( "Numeric" ), Format( {"Best", 15} ), Modeling Type( "Continuous" ) ),
Col( "/svg/g/@fill", Column Name( "colorAlternate" ), Fill( "-", "/svg/g" ), Type( "Character" ), Format( {"Best"} ), Modeling Type( "Continuous" ) ) ),
XML Wizard( 0 )
);
dtSVGLegend << selectwhere( Is Missing( y ) );
dtSVGLegend << deleterows;
For( i = 1, i <= N Rows( dtSVGLegend ), i += 1,
If( dtSVGLegend:color[i] == "",
dtSVGLegend:color[i] = dtSVGLegend:colorAlternate[i]
);
If( dtSVGLegend:text[i] == "",
dtSVGLegend:text[i] = dtSVGLegend:textAlternate[i]
);
);
dtSVGLegend << deletecolumns( {textAlternate, y, colorAlternate} );
//dtSVGGraph<<SORT></SORT>日志输出与上次相反...
这些是每种颜色的像素数:
#E6E6E6 < 12.5 13026.06075
#CCCCCC < 13.0 12648.7232
#B3B3B3 < 13.5 8322.47330000002
#999999 < 14.0 10780.35015
#808080 < 14.5 12529.58585
#666666 < 15.0 8507.05305
#4D4D4D < 15.5 4961.26459999998
#333333 < 16.0 3712.89360000002
#191919 < 16.5 2922.03675000001
#000000 >= 16.5 2535.49285
------ 灰色像素总数 ------
总计 79945.9341
表示图形框架大小的两种方法...
帧 318976 像素
这是 xaxis 长度 * yaxis 长度的乘积:
帧 3150 数据^2
您可以使用帧的像素与数据 ^2 的比率来转换每种颜色的像素数。
像素计数包括小数,因为它们被计算为 SVG 文件用来制作图形的一堆小多边形的面积。 由于 SVG 是 XML 的变体,我使用 XML 向导生成 XML 设置来读取这两个 SVG 文件。 其中一个 SVG 文件保存自 frame(1),图形,另一个保存自 frame(2),图例。 日志输出标有从 SVG 文件中提取的图例文本。 在 JMP 15 中,图例位于第二帧中。 JMP 16 似乎正在改变;如果您小心地删除与图例相关的位,它仍然可以工作,没有标签。