Einige der folgenden Codes benötigen wahrscheinlich mindestens JMP 15 für die Unterstützung des XML-Imports. Es nutzt auch ein tiefes Verständnis des Displaybox-Baums, der in Zukunft Anpassungen erfordern wird.
@datanaut fragte Bereiche innerhalb von Konturen berechnen . Ich bin drei Wege gegangen, um das herauszufinden. Zuerst der Setup-Code:
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.Graue Konturen auf magentafarbenem Hintergrund.
Weg eins war sehr kurz. Ich habe festgestellt, dass das Konturdiagramm eine Meldung zum Speichern von Konturen enthält. Es erstellt eine Datentabelle, aber die Konturbeschreibungen bilden keine sauberen Schleifen.
Pfad zwei zählte Pixel, wahrscheinlich ähnlich wie @gzmorgan0 sich nähern. Es funktioniert, hat aber einige Mängel, die Sie im Bild oben angedeutet sehen können. Ich habe den Hintergrund absichtlich so hässlich magentafarben gemacht, damit ich leicht nach grauen Pixeln suchen kann. Aber wenn Sie genau hinsehen, können Sie sehen, wie etwas Magenta zwischen den Regionen durchsickert. Schade! Anti-Aliasing bei der Arbeit! Normalerweise würden Sie auf einem weißen Hintergrund fast nichts bemerken, aber der Graustufenübergang zwischen den Farben ist immer noch vorhanden.
Zoomed in, the darker regions are still anti-aliased against white.Beim Vergrößern werden die dunkleren Bereiche immer noch gegen Weiß geglättet.
Wie auch immer, der folgende Code versucht, die magentafarbenen Pixel in einem nahe gelegenen grauen Bereich zu platzieren. Vielleicht macht es einen ausgewogenen Job, Fehler auf beiden Seiten zu machen. Ohne das Magenta wären alles Graustufen und der Code könnte nicht erkennen, dass eine Entscheidung erforderlich ist. (Dies scheint auf JMP 14 und 15 zu laufen.)
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 ) );Hier ist das bereinigte Bild
The interior magenta pixels are converted to a nearby gray.Die inneren Magenta-Pixel werden in ein nahes Grau umgewandelt.
Es gibt immer noch eine gewisse Unschärfe, die jedoch an anderer Stelle ausgeglichen werden könnte:
Those pixels will be counted wrong.Diese Pixel werden falsch gezählt.
Das Ergebnis ist eine Tabelle im Protokollfenster.
grau=schwarzer Bereich=2598
grau=0,098 Fläche=2973
grau=0,200 Fläche=3781
grau=0,302 Fläche=5003
grau=0,400 Fläche=8528
grau=0,502 Fläche=12535
grau=0,600 Fläche=11081
grau=0,702 Fläche=8382
grau=0,800 Fläche=12718
grau=0,902 Fläche=13074
Magenta-Bereich = 238302
identifizierter Bereich = 318975
alle Diagrammbereiche = 318976
übersehene Fläche=1.000
Das übersehene Pixel ist ein nahezu reines Magenta-Pixel in der oberen rechten Ecke. Habe nicht versucht, es weiter aufzuspüren.
Weg drei ist wahrscheinlich der beste, wenn Sie es zum Laufen bringen können; es hängt davon ab, ob JMP eine SVG-Datei auf die gleiche Weise schreibt, und kann auch von diesem speziellen Beispiel abhängig sein. Die Antworten sind dem zweiten Versuch sehr ähnlich und sollten korrekter sein. (Dies hängt von den Funktionen in JMP 15 ab.) Schlüssel zum Verständnis des SVG-Pfads: Spalte 3 der Matrix ist für das Ende eines Segments negativ; die Start/End-Arrays lokalisieren die Segmente in der Pfadmatrix.
(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>Die Protokollausgabe ist seit dem letzten Mal umgekehrt ...
Dies sind Pixelzahlen für jede Farbe:
#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
------ Summe der grauen Pixel --------
insgesamt 79945,9341
Zwei Möglichkeiten, die Größe des Diagrammrahmens darzustellen ...
Rahmen 318976 Pixel
Dies ist das Produkt aus x-Achsenlänge * y-Achsenlänge:
Frame 3150-Daten^2
Sie können das Verhältnis von Pixeln zu Daten^2 des Frames verwenden, um die Pixelanzahl für jede Farbe umzuwandeln.
Die Pixelanzahl enthält Dezimalzahlen, da sie als Flächen einer Reihe kleiner Polygone berechnet werden, die die SVG-Datei zum Erstellen des Diagramms verwendet. Da SVG eine Variation von XML ist, habe ich den XML-Assistenten verwendet, um die XML-Einstellungen zum Lesen der beiden SVG-Dateien zu generieren. Eine der SVG-Dateien wurde aus Frame(1), dem Diagramm, und die andere aus Frame(2), der Legende, gespeichert. Die Protokollausgabe wird mit dem Legendentext beschriftet, der aus der SVG-Datei gezogen wird. In JMP 15 befindet sich die Legende in einem zweiten Frame. Das scheint sich für JMP 16 zu ändern; Wenn Sie die legendenbezogenen Bits vorsichtig entfernen, funktioniert es immer noch ohne die Etiketten.