次のコードの一部では、少なくとも XML インポートをサポートするために JMP 15 が必要です。 また、将来的に調整が必要になるディスプレイボックス ツリーの深い理解も使用しています。
@datanaut尋ねた輪郭内の領域を計算する. 私はこれを理解しようとして3つの道をたどりました。 まず、セットアップ コード:
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.マゼンタの背景に灰色の輪郭。
パス 1 は非常に短かった。 コンター プロットに <
パス 2 は、おそらく次のように、ピクセルをカウントしていました。 @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
見過ごされているピクセルは、右上隅にあるほぼ純粋なマゼンタ ピクセルです。 それ以上追跡しようとはしませんでした。
パス 3 は、うまく機能させることができれば、おそらく最良の方法です。これは、同じ方法で SVG ファイルを作成する JMP に依存しており、この特定の例にも依存している可能性があります。 答えは 2 回目の試行と非常に似ており、より正確なはずです。 (これは 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
グラフのフレームのサイズを表す 2 つの方法...
フレーム 318976 ピクセル
これは、x 軸の長さ * y 軸の長さの積です。
フレーム 3150 データ^2
フレームのデータ ^2 に対するピクセルの比率を使用して、各色のピクセル数を変換できます。
ピクセル数には小数が含まれます。これは、SVG ファイルがグラフを作成するために使用する一連の小さなポリゴンの面積として計算されるためです。 SVG は XML のバリエーションであるため、XML ウィザードを使用して XML 設定を生成し、2 つの SVG ファイルを読み取りました。 SVG ファイルの 1 つは frame(1) のグラフから保存され、もう 1 つは frame(2) の凡例から保存されました。 ログ出力には、SVG ファイルから抽出された凡例テキストのラベルが付けられます。 JMP 15 では、凡例は 2 番目のフレームにあります。 これは JMP 16 では変更されているようです。凡例に関連するビットを慎重に削除しても、ラベルがなくても機能します。