I've been working on this snippet:
public static final TermCriteria KMEANS_CRITERIA = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 10, 1.0);
private double getColours(Mat image) {
var labels = new MatOfFloat();
var reshape = new Mat();
image.convertTo(reshape, CvType.CV_32FC3);
reshape = reshape.reshape(1,1);
System.out.println("reshape = " + reshape.toString());
var centers = new Mat();
Core.kmeans(reshape, 3, labels, KMEANS_CRITERIA, 3, Core.KMEANS_RANDOM_CENTERS, centers);
}
The problem is, reshape = reshape.reshape(1,1); converts the image from CV_32FC3[X, Y] to CV_32FC1[X*Y] - it goes from 3 channels (R,G,B) to 1 channel.
I think this is the final problem to solve, in order to get the KMeans clustering working.
Anyone know how to fix this, so that I can get a final result of centers = CV_8UC3[3] (the 3 colour clusters)
I've learned something about Java3D and I wondered how to move around the Camera using keystrokes. I've found the KeyNavigatorBehavior and set it up, just there is no Key doing anything. How do I use this Behavior properly?
Here I got my method setting the Behavior:
protected BranchGroup buildViewBranch(Canvas3D c) {
BranchGroup viewBranch = new BranchGroup();
Transform3D viewXfm = new Transform3D();
viewXfm.set(new Vector3f(0.0f, 0.0f, 10.0f));
TransformGroup viewXfmGroup = new TransformGroup(viewXfm);
viewXfmGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
viewXfmGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
BoundingSphere movingBounds = new BoundingSphere(new Point3d(0.0, 0.0,0.0), 100.0);
BoundingLeaf boundLeaf = new BoundingLeaf(movingBounds);
ViewPlatform myViewPlatform = new ViewPlatform();
viewXfmGroup.addChild(boundLeaf);
PhysicalBody myBody = new PhysicalBody();
PhysicalEnvironment myEnvironment = new PhysicalEnvironment();
viewXfmGroup.addChild(myViewPlatform);
viewBranch.addChild(viewXfmGroup);
View myView = new View();
myView.addCanvas3D(c);
myView.attachViewPlatform(myViewPlatform);
myView.setPhysicalBody(myBody);
myView.setPhysicalEnvironment(myEnvironment);
KeyNavigatorBehavior keyNav = new KeyNavigatorBehavior(viewXfmGroup);
keyNav.setSchedulingBounds(movingBounds);
viewBranch.addChild(keyNav);
return viewBranch;
}
Here are the lines setting the VirtualUniverse:
group = new BranchGroup();
VirtualUniverse universe = new VirtualUniverse();
Locale locale = new Locale(universe);
locale.addBranchGraph(this.buildViewBranch(canvas));
locale.addBranchGraph(group);
I found the answer myself:
You have to activate KeyboardMouse (Alt + Shift + Num) and deactivate numlock:
Keys are: arrows + page up/down (also on the numlock)
I am unable to add a line on a second axis (right axis) on an existing chart. Is there a way to do this with the new implementation of Charts in POI 4.0.0/1?
Desired output will look like this (A simple excel chart with 2 axes):
. The associated data to that chart as an example:
Series 1/Axis1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Series 2/Axis2 = [200,300,400,500,600,700,800,900,1000]
Here is the code that I am trying so far in Java, it is mostly replicated from the LineChart.java example
//Initial code instantiates a document
XWPFDocument doc = new XWPFDocument();
...
// Generate Chart
// This was taken from the example https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java
XWPFChart prChart = doc.createChart();
//Values 1 on the Left Axis
//Values 2 on the Right Axis
String[] categories = dates.toArray(new String[dates.size()]);
BigDecimal[] values1 = prices1.toArray(new BigDecimal[prices1.size()]);
BigDecimal[] values2 = prices2.toArray(new BigDecimal[prices2.size()]);
XDDFChartAxis bottomAxis = prChart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setMajorTickMark(AxisTickMark.NONE);
XDDFValueAxis leftAxis = prChart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setMajorTickMark(AxisTickMark.OUT);
/*
* Is this made correctly?
*/
XDDFValueAxis rightAxis = prChart.createValueAxis(AxisPosition.RIGHT);
rightAxis.setCrosses(AxisCrosses.MAX);
rightAxis.setMajorTickMark(AxisTickMark.IN);
final int numOfPoints = categories.length;
final String categoryDataRange = prChart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
final String valuesDataRange = prChart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
final String valuesDataRange2 = prChart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1);
final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);
XDDFLineChartData line = (XDDFLineChartData) prChart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) line.addSeries(categoriesData, valuesData);
series1.setTitle("Price", null);
series1.setSmooth(true);
series1.setMarkerStyle(MarkerStyle.NONE);
solidLineSeries(series1, PresetColor.BLUE_VIOLET);
// Am I adding the rightAxis correctly here?
XDDFLineChartData line2 = (XDDFLineChartData) prChart.createData(ChartTypes.LINE, bottomAxis, rightAxis);
XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) line2.addSeries(categoriesData, valuesData2);
series2.setTitle("Index", null);
series2.setSmooth(true);
series2.setMarkerStyle(MarkerStyle.NONE);
solidLineSeries(series2, PresetColor.BLACK);
prChart.plot(line);
prChart.plot(line2); /// <- Does this add to the same plot correctly?
prChart.displayBlanksAs(DisplayBlanks.GAP);
Running this code doesn't produce any compile errors. But I do get errors when opening the document "Problem with its' contents."
I suppose I am not adding the 2nd line and 2nd axes correctly.
Is there a way to accomplish this?
Update w. Solution
Axel's solution below works perfectly. The additional info to know is exactly what was the issue.
I would also like to recognize the order in which you add to the plot, this will hopefully help others
Create first set of axis
Create first Line
Plot first Line
Create new Axis
Create 2nd line
Plot 2nd line
Update the axis ids!
When it comes to multiple different value axes in one chart, this is not fully implemented in XDDF until now. So we need correcting something using the low level ooxml-schemas-1.4 classes.
Needed knowledge:
In principle the series which shall be shown on second value axis are in a separate chart in the same plot area. So the series which shall be shown on second value axis needs it's own bottom axis too. But this bottom axis must be invisible.
Both the axes, the second bottom and the new right axis, must cross each other properly. This crossing apache poi does not properly until now. So we must correct here.
Because while adding to the chart, the apache poi code which adds the second line chart does not knows something about the already present line chart, it's IDs starts with 0 again. But this is wrong for an combined chart. So we need correct the id and order. It must not start with 0 again because there is a line series already in same plot area.
Complete example to be reproducible for others too:
import java.io.*;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
public class CreateWordXDDFChart {
public static void main(String[] args) throws Exception {
try (XWPFDocument document = new XWPFDocument()) {
// create the data
String[] categories = new String[]{"1","2","3","4","5","6","7","8","9"};
Double[] values1 = new Double[]{1d,2d,3d,4d,5d,6d,7d,8d,9d};
Double[] values2 = new Double[]{200d,300d,400d,500d,600d,700d,800d,900d,1000d};
// create the chart
XWPFChart chart = document.createChart(15*Units.EMU_PER_CENTIMETER, 10*Units.EMU_PER_CENTIMETER);
// create data sources
int numOfPoints = categories.length;
String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
String valuesDataRange1 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
XDDFNumericalDataSource<Double> valuesData1 = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange1, 1);
XDDFNumericalDataSource<Double> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);
// first line chart
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFChartData data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFChartData.Series series = data.addSeries(categoriesData, valuesData1);
chart.plot(data);
solidLineSeries(data, 0, PresetColor.BLUE);
// second line chart
// bottom axis must be there but must not be visible
bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setVisible(false);
XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
rightAxis.setCrosses(AxisCrosses.MAX);
// set correct cross axis
bottomAxis.crossAxis(rightAxis);
rightAxis.crossAxis(bottomAxis);
data = chart.createData(ChartTypes.LINE, bottomAxis, rightAxis);
series = data.addSeries(categoriesData, valuesData2);
chart.plot(data);
// correct the id and order, must not be 0 again because there is one line series already
chart.getCTChart().getPlotArea().getLineChartArray(1).getSerArray(0).getIdx().setVal(1);
chart.getCTChart().getPlotArea().getLineChartArray(1).getSerArray(0).getOrder().setVal(1);
solidLineSeries(data, 0, PresetColor.RED);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("CreateWordXDDFChart.docx")) {
document.write(fileOut);
}
}
}
private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFLineProperties line = new XDDFLineProperties();
line.setFillProperties(fill);
XDDFChartData.Series series = data.getSeries().get(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setLineProperties(line);
series.setShapeProperties(properties);
}
}
Good day. I'm building a simple pdf report using native PrintedPdfDocument class and I need to insert a text with hyperlink into a document. This is my simple implementation of pdf page.
PrintedPdfDocument document = new PrintedPdfDocument(context, attributes);
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(595, 842, 1).create();
PdfDocument.Page page = document.startPage(pageInfo);
Canvas c = page.getCanvas();
TextPaint p = new TextPaint();
Here a several ways I had tried but still no luck.
First way using a Canvas drawText() method. Result: "some link" without hyperlink.
c.drawText("<a href='https://example.com'>some link</a>", 30, 30, p);
Second way using SpannableString. Result: "some link".
String link = "https://example.com";
SpannableString s = new SpannableString("some link");
s.setSpan(new URLSpan(link), 0, link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
c.drawText(s.toString(), 30, 30, p);
Third way using StaticLayout. Result: blank space.
Spanned spanned = Html.fromHtml("<a href='https://example.com'>some link</a>", null, null);
StaticLayout l = new StaticLayout(spanned, p, 30, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
l.draw(c);
TextView do not draw anything to Canvas.
TextView tv = new TextView(context);
tv.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
tv.setText(Html.fromHtml("<a href='https://example.com'>some link</a>"));
tv.draw(c);
Maybe you better know how to deal with it?
I'm searching for a library or an example on how to implement in java a likelihood ratio test like in matlab.
I have two different vector of double values and want to receive a scalar value.
Every value correspond to a feature for my machine learning algorithm so one the first vector is the training pattern and the second one a test.
Could you please help me?
On matlab i just use division on two matrix like LR= test_matrix/training_matrix
I've tryied with apache mahout but i'm not sure i'm using it correctly.
Here the code:
FastByIDMap<FastByIDMap<Long>> timestamps = new FastByIDMap<>();
Collection<Preference> prefs = new ArrayList<>(2);
FastByIDMap<Collection<Preference>> data = new FastByIDMap<>(); //Preferecens for user0
Preference newPrefs = new GenericPreference(0, 0, (float) -0.5);
Preference pref = new GenericPreference(0, 1, 50);
Preference pref2 = new GenericPreference(0, 2, 51);
prefs.add(newPrefs);
prefs.add(pref);
prefs.add(pref2);
data.put(0, prefs);
Collection<Preference> prefs_1 = new ArrayList<>(2);
newPrefs = new GenericPreference(1, 0, (float) -0.5);
pref = new GenericPreference(1, 1, 50);
pref2 = new GenericPreference(1, 2, 51);
prefs_1.add(newPrefs);
prefs_1.add(pref);
prefs_1.add(pref2);
data.put(1, prefs_1);
GenericDataModel model = new GenericDataModel(GenericDataModel.toDataMap(data, true), timestamps);
FastByIDMap<PreferenceArray> us = model.getRawUserData();
System.out.println("us:"+ us.toString());
LogLikelihoodSimilarity l = new LogLikelihoodSimilarity(model);
System.out.println(l.userSimilarity(0, 1));
In this case, user similarity alwasy return 0.