in solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/ZplotStream.java [128:395]
public void open() throws IOException {
Map<String, Object> lets = streamContext.getLets();
Set<Map.Entry<String, Object>> entries = letParams.entrySet();
Map<String, Object> evaluated = new HashMap<>();
// Load up the StreamContext with the data created by the letParams.
int numTuples = -1;
int columns = 0;
boolean table = false;
boolean distribution = false;
boolean clusters = false;
boolean heat = false;
for (Map.Entry<String, Object> entry : entries) {
++columns;
String name = entry.getKey();
if (name.equals("table")) {
table = true;
} else if (name.equals("dist")) {
distribution = true;
} else if (name.equals("clusters")) {
clusters = true;
} else if (name.equals("heat")) {
heat = true;
}
Object o = entry.getValue();
if (o instanceof StreamEvaluator evaluator) {
Tuple eTuple = new Tuple(lets);
evaluator.setStreamContext(streamContext);
Object eo = evaluator.evaluate(eTuple);
if (eo instanceof List<?> l) {
if (numTuples == -1) {
numTuples = l.size();
} else {
if (l.size() != numTuples) {
throw new IOException(
"All lists provided to the zplot function must be the same length.");
}
}
evaluated.put(name, l);
} else if (eo instanceof Tuple) {
evaluated.put(name, eo);
} else {
evaluated.put(name, eo);
}
} else {
Object eval = lets.get(o);
if (eval instanceof List<?> l) {
if (numTuples == -1) {
numTuples = l.size();
} else {
if (l.size() != numTuples) {
throw new IOException(
"All lists provided to the zplot function must be the same length.");
}
}
evaluated.put(name, l);
} else if (eval instanceof Tuple) {
evaluated.put(name, eval);
} else if (eval instanceof Matrix) {
evaluated.put(name, eval);
}
}
}
if (columns > 1 && (table || distribution)) {
throw new IOException(
"If the table or dist parameter is set there can only be one parameter.");
}
// Load the values into tuples
List<Tuple> outTuples = new ArrayList<>();
if (!table && !distribution && !clusters && !heat) {
// Handle the vectors
for (int i = 0; i < numTuples; i++) {
Tuple tuple = new Tuple();
for (Map.Entry<String, Object> entry : evaluated.entrySet()) {
List<?> l = (List<?>) entry.getValue();
tuple.put(entry.getKey(), l.get(i));
}
outTuples.add(tuple);
}
// Generate the x-axis if the tuples contain y and not x
if (outTuples.get(0).getFields().containsKey("y")
&& !outTuples.get(0).getFields().containsKey("x")) {
int x = 0;
for (Tuple tuple : outTuples) {
tuple.put("x", x++);
}
}
} else if (clusters) {
Object o = evaluated.get("clusters");
if (o instanceof KmeansEvaluator.ClusterTuple ct) {
List<CentroidCluster<KmeansEvaluator.ClusterPoint>> cs = ct.getClusters();
int clusterNum = 0;
for (CentroidCluster<KmeansEvaluator.ClusterPoint> c : cs) {
clusterNum++;
List<KmeansEvaluator.ClusterPoint> points = c.getPoints();
for (KmeansEvaluator.ClusterPoint p : points) {
Tuple tuple = new Tuple();
tuple.put("x", p.getPoint()[0]);
tuple.put("y", p.getPoint()[1]);
tuple.put("cluster", "cluster" + clusterNum);
outTuples.add(tuple);
}
}
} else if (o instanceof DbscanEvaluator.ClusterTuple ct) {
List<Cluster<DbscanEvaluator.ClusterPoint>> cs = ct.getClusters();
int clusterNum = 0;
for (Cluster<DbscanEvaluator.ClusterPoint> c : cs) {
clusterNum++;
List<DbscanEvaluator.ClusterPoint> points = c.getPoints();
for (DbscanEvaluator.ClusterPoint p : points) {
Tuple tuple = new Tuple();
tuple.put("x", p.getPoint()[0]);
tuple.put("y", p.getPoint()[1]);
tuple.put("cluster", "cluster" + clusterNum);
outTuples.add(tuple);
}
}
}
} else if (distribution) {
Object o = evaluated.get("dist");
if (o instanceof RealDistribution realDistribution) {
List<SummaryStatistics> binStats = null;
if (realDistribution instanceof EmpiricalDistribution empiricalDistribution) {
binStats = empiricalDistribution.getBinStats();
} else {
double[] samples = realDistribution.sample(500000);
EmpiricalDistribution empiricalDistribution = new EmpiricalDistribution(32);
empiricalDistribution.load(samples);
binStats = empiricalDistribution.getBinStats();
}
double[] x = new double[binStats.size()];
double[] y = new double[binStats.size()];
for (int i = 0; i < binStats.size(); i++) {
x[i] = binStats.get(i).getMean();
y[i] = realDistribution.density(x[i]);
}
for (int i = 0; i < x.length; i++) {
Tuple tuple = new Tuple();
if (!Double.isNaN(x[i])) {
tuple.put("x", Precision.round(x[i], 2));
if (y[i] == Double.NEGATIVE_INFINITY || y[i] == Double.POSITIVE_INFINITY) {
tuple.put("y", 0);
} else {
tuple.put("y", y[i]);
}
outTuples.add(tuple);
}
}
} else if (o instanceof IntegerDistribution integerDistribution) {
int[] samples = integerDistribution.sample(50000);
Frequency frequency = new Frequency();
for (int i : samples) {
frequency.addValue(i);
}
Iterator<?> it = frequency.valuesIterator();
List<Long> values = new ArrayList<>();
while (it.hasNext()) {
values.add((Long) it.next());
}
int[] x = new int[values.size()];
double[] y = new double[values.size()];
for (int i = 0; i < values.size(); i++) {
x[i] = values.get(i).intValue();
y[i] = integerDistribution.probability(x[i]);
}
for (int i = 0; i < x.length; i++) {
Tuple tuple = new Tuple();
tuple.put("x", x[i]);
tuple.put("y", y[i]);
outTuples.add(tuple);
}
} else if (o instanceof List<?> list) {
if (list.get(0) instanceof Tuple) {
@SuppressWarnings({"unchecked"})
List<Tuple> tlist = (List<Tuple>) o;
Tuple tuple = tlist.get(0);
if (tuple.getFields().containsKey("N")) {
for (Tuple t : tlist) {
Tuple outtuple = new Tuple();
outtuple.put("x", Precision.round(((double) t.get("mean")), 2));
outtuple.put("y", t.get("prob"));
outTuples.add(outtuple);
}
} else if (tuple.getFields().containsKey("count")) {
for (Tuple t : tlist) {
Tuple outtuple = new Tuple();
outtuple.put("x", t.get("value"));
outtuple.put("y", t.get("pct"));
outTuples.add(outtuple);
}
}
}
}
} else if (table) {
// Handle the Tuple and List of Tuples
Object o = evaluated.get("table");
if (o instanceof Matrix m) {
List<String> rowLabels = m.getRowLabels();
List<String> colLabels = m.getColumnLabels();
double[][] data = m.getData();
for (int i = 0; i < data.length; i++) {
String rowLabel = null;
if (rowLabels != null) {
rowLabel = rowLabels.get(i);
} else {
rowLabel = Integer.toString(i);
}
Tuple tuple = new Tuple();
tuple.put("rowLabel", rowLabel);
double[] row = data[i];
for (int j = 0; j < row.length; j++) {
String colLabel = null;
if (colLabels != null) {
colLabel = colLabels.get(j);
} else {
colLabel = "col" + Integer.toString(j);
}
tuple.put(colLabel, data[i][j]);
}
outTuples.add(tuple);
}
}
} else if (heat) {
// Handle the Tuple and List of Tuples
Object o = evaluated.get("heat");
if (o instanceof Matrix m) {
List<String> rowLabels = m.getRowLabels();
List<String> colLabels = m.getColumnLabels();
double[][] data = m.getData();
for (int i = 0; i < data.length; i++) {
String rowLabel = null;
if (rowLabels != null) {
rowLabel = rowLabels.get(i);
} else {
rowLabel = "row" + pad(Integer.toString(i), data.length);
}
double[] row = data[i];
for (int j = 0; j < row.length; j++) {
Tuple tuple = new Tuple();
tuple.put("y", rowLabel);
String colLabel = null;
if (colLabels != null) {
colLabel = colLabels.get(j);
} else {
colLabel = "col" + pad(Integer.toString(j), row.length);
}
tuple.put("x", colLabel);
tuple.put("z", data[i][j]);
outTuples.add(tuple);
}
}
}
}
this.out = outTuples.iterator();
}