Certains des codes suivants ont probablement besoin de JMP 15 pour la prise en charge de l'importation XML, au moins. Il utilise également une compréhension approfondie de l'arborescence de la boîte d'affichage qui nécessitera des ajustements à l'avenir.
@datanaut a demandé Calculer les zones à l'intérieur des contours . J'ai parcouru trois chemins pour essayer de comprendre cela. Tout d'abord, le code d'installation :
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.Contours gris sur fond magenta.
Le premier chemin était très court. J'ai découvert que le tracé de contour a un message pour <
Le chemin deux comptait les pixels, probablement similaire à @gzmorgan0 approcher. Cela fonctionne, mais présente quelques défauts que vous pouvez voir dans l'image ci-dessus. J'ai fait exprès pour l'arrière-plan cette vilaine teinte magenta afin de pouvoir facilement rechercher des pixels gris. Mais si vous regardez attentivement, vous pouvez voir du magenta s'infiltrer entre les régions. Dommage! L'anticrénelage au travail ! Normalement, sur un fond blanc, vous ne le remarqueriez presque pas, mais la transition des niveaux de gris entre les couleurs est toujours là.
Zoomed in, the darker regions are still anti-aliased against white.En zoomant, les régions les plus sombres sont toujours anti-crénelées contre le blanc.
Quoi qu'il en soit, le code ci-dessous tente de placer les pixels teintés de magenta dans une zone grise proche. Peut-être que cela fait un travail équilibré en faisant des erreurs de part et d'autre. Sans le magenta, tout serait en nuances de gris et le code ne serait pas en mesure de voir qu'une décision était nécessaire. (Cela semble fonctionner sur JMP 14 et 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 ) );Voici l'image nettoyée
The interior magenta pixels are converted to a nearby gray.Les pixels magenta intérieurs sont convertis en un gris proche.
Il y a encore des irrégularités, mais elles pourraient être compensées ailleurs :
Those pixels will be counted wrong.Ces pixels seront mal comptés.
Le résultat est un tableau dans la fenêtre du journal.
gris=zone noire=2598
gris=0,098 zone=2973
gris=0.200 zone=3781
gris=0,302 zone=5003
gris=0.400 zone=8528
gris=0,502 zone=12535
gris=0.600 zone=11081
gris=0,702 zone=8382
gris=0.800 zone=12718
gris=0,902 zone=13074
zone magenta=238302
zone identifiée=318975
toute la zone graphique = 318976
zone négligée=1.000
Le pixel négligé est un pixel magenta presque pur dans le coin supérieur droit. Je n'ai pas essayé de le retrouver plus loin.
La troisième voie est probablement la meilleure si vous pouvez la faire fonctionner ; cela dépend du fait que JMP écrit un fichier SVG de la même manière, et peut également dépendre de cet exemple particulier. Les réponses sont très similaires au deuxième essai et devraient être plus correctes. (Cela dépend des fonctionnalités de JMP 15.) Clé pour comprendre le chemin SVG : la colonne 3 de la matrice est négative pour la fin d'un segment ; les tableaux de début/fin localisent les segments dans la matrice de chemin.
(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>La sortie du journal est inversée depuis la dernière fois...
ce sont les nombres de pixels pour chaque couleur :
#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
------ total de pixels gris --------
total 79945.9341
Deux façons de représenter la taille du cadre du graphique...
cadre 318976 pixels
C'est le produit de la longueur de l'axe x * longueur de l'axe y :
trame 3150 données ^ 2
Vous pouvez utiliser le rapport pixels/données^2 de l'image pour convertir le nombre de pixels pour chaque couleur.
Le nombre de pixels comprend des décimales car ils sont calculés comme les aires d'un groupe de petits polygones que le fichier SVG utilise pour créer le graphique. Puisque SVG est une variation de XML, j'ai utilisé l'assistant XML pour générer les paramètres XML pour lire les deux fichiers SVG. L'un des fichiers SVG a été enregistré à partir de frame(1), le graphique, et l'autre a été enregistré à partir de frame(2), la légende. La sortie du journal est étiquetée avec le texte de la légende, extrait du fichier SVG. Dans JMP 15, la légende est dans un deuxième cadre. Cela semble changer pour JMP 16 ; si vous supprimez soigneusement les bits liés à la légende, cela fonctionne toujours, sans les étiquettes.