Sorting for reactor Flux - collections

I am not familiar with java Collection sorting and reactor Flux.
Now, I got a requirement is that user need to prioritize the publishing for some of items from a Flux.
e.g.
p1 = Person{name="p1", country="US", gender="male", age=20}
p2 = Person{name="p2", country="US", gender="female", age=20}
p3 = Person{name="p3", country="Russia", gender="male", age=40}
p4 = Person{name="p4", country="China", gender="female" age=30}
p5 = Person{name="p5", country="Japan", gender="female" age=25}
p6 = Person{name="p6", country="Japan", gender="male" age=40}
A Flux is built like below:
Flux.fromIterable(Stream.of(p1, p2, p3, p4, p5, p6))
Now, we need to prioritize the females from Japan and China, the rest of person will keep orginal order.
e.g.
p5 = Person{name="p5", country="Japan", gender="female" age=25}
p6 = Person{name="p6", country="Japan", gender="male" age=40}
p4 = Person{name="p4", country="China", gender="female" age=30}
p1 = Person{name="p1", country="US", gender="male", age=20}
p2 = Person{name="p2", country="US", gender="female", age=20}
p3 = Person{name="p3", country="Russia", gender="male", age=40}
How to sort the Flux?

You can use sort method.
Flux<Person> flux = Flux.fromIterable(List.of(p1, p2, p3, p4, p5, p6));
Flux<Person> result = flux.sort(Comparator
.comparing((Person p) -> !p.getCountry().equals("Japan"))
.thenComparing((Person p) -> !p.getCountry().equals("China"))
);
result.subscribe(val -> System.out.println(val.toString()));
Output:
Person(name=p5, country=Japan, gender=female, age=25)
Person(name=p6, country=Japan, gender=male, age=40)
Person(name=p4, country=China, gender=female, age=30)
Person(name=p1, country=US, gender=male, age=20)
Person(name=p2, country=US, gender=female, age=20)
Person(name=p3, country=Russia, gender=male, age=40)

I assume you have a potentially infinite Flux, so you can't just collect everything, sort it and emit again. This would throw out Flux#sort, which would just do that.
Obviously you can't sort a sequence you do not (fully) have. What you can do is
Use Flux#groupBy and generate GroupedFluxes for every priority.
You get one Flux, which will emit a Flux for every group (prio). You can then work on each prioFlux as you like.
For example you could merge them again using Flux#mergeComparing, prioritizing one Flux over the other (if both have values, take the first - otherwise take what is there).
Use Flux#buffer and work on smaller buffers. Sort those as usual and emit again. This could be a reasonable and simple solution.
Regards,
Martin

Related

Store plots in an array

I am trying to plot histograms of different columns of a dataframe in subplots.
plt_count = 1
for i = names(abalone)[2:end]
p[plt_count]=histogram(abalone[:,i])
plt_count += 1
end
plot(p, layout=(3,3), legend=false)
This is what I tried. But I can't come up with the right definition for the array p. How do I define p?
Improvements to the code will also be helpful.
If you don't care about the type stability, you can make Any type array.
ps = Array{Any}(nothing, 3)
ps[1] = plot([2,3,4])
ps[2] = plot([1,5])
ps[3] = plot([10,5,1,0])
#show typeof(ps)
plot(ps..., layout=(3,1))
If you want to create an array of Plot type specifically, one approach is to initialize an array with a dummy plot, then replace later.
ps = repeat([plot(1)], 3)
ps[1] = plot([2,3,4])
ps[2] = plot([1,5])
ps[3] = plot([10,5,1,0])
#show typeof(ps)
plot(ps..., layout=(3,1))

How to unterstand "children" in SciLab?

clc
x = [1:1:10];
y1 = x;
y2 = 2*x;
y3 = 3*x;
plot2d(x,y1);
plot2d(x,y2);
plot2d(x,y3)
gca().children(1).children(1).thickness = 2
gca().children(2).children(1).thickness = 7
gca().children(3).children(1).thickness = 4
I am new from Matlab to Scilab
Could someone tell me, how to unterstand children?
What means
gca().children ?
gca().children.children ?
gca().children.children(1) ?
gca().children(1).children ?
How can we know which attribute belong to children ?
e.g gca().children(1).children(1).color = ... // not exist
I am very confused now.. Thanks in Advance
Let's schematize the nested graphical object by their children properties.
We have
figure (f)
- axes (a)
- compound1 (c1)
- polyline (p1)
- compound2 (c2)
- polyline (p2)
- compound3 (c3)
- polyline (p3)
Since gca is a function lets do a = gca() because gca().children will raise an error because scilab doesn't understand that you're trying to access to the fields of its return value.
gca() returns the handles to the axes of the current figure :a.
a.children returns the array of handles of all the children of theses axes. : c1, c2, c3
a.children.children returns the array of handles of all the children of the above objects: p1, p2, p3
a.children.children(1) returns the first children of c1, c2, c3 : p1
a.children(1).children returns all the children of the first children of the current axes (c1). Since there only one : p1
To access the value of your entities
Either go for a temp variable :
a = gca();
idcolor=a.children(1).children(1).foreground // gives the color of a.c1.p1
or use get
// idcolor is an array , with idcolor(i) the color of pi
idcolor = get(get(get(gca(),'children'),'children'),'foreground')
FYI
gce() command returns the handle of the last object created. With plot2d its a compound so we need to get its children.
you could rewrite your program as
clc
x = [1:1:10];
y1 = x;
y2 = 2*x;
y3 = 3*x;
plot2d(x,y1);
e1 = get(gce(),'children');
plot2d(x,y2);
e2 = get(gce(),'children');
plot2d(x,y3)
e3 = get(gce(),'children');
e1.thickness = 2
e2.thickness = 7
e3.thickness = 4

Julia's equivalent of MATLAB's inpolygon()

Is there such function in Julia?
Desperately trying to migrate to Julia from MATLAB, but still finding myself dependent on it...
The GeometricalPredicates package has inpolygon: https://github.com/JuliaGeometry/GeometricalPredicates.jl
You could also investigate Luxor.jl:
using Luxor
p1 = Point(0, 0)
p2 = Point(10, 0)
p3 = Point(10, 10)
p4 = Point(0, 10)
isinside(Point(5, 5), [p1, p2, p3, p4]) # true
isinside(Point(15, 5), [p1, p2, p3, p4]) # false
But make sure to check for vertex and edge exceptions...
The PolygonOps package does point-in-polygon testing too.
It's more user-friendly, but possibly slower, than GeometricalPredicates.
(Hat tip: Julia forum.)

PyQtGraph sliding window acquires y offset

I'm trying to create an scrolling plot window with PyQtGraph. The plot itself has multiple axes. I used this as the basis of the multiple axes. I used this one as the base to do the scrolling bit.
My problem is that for my data, the scrolling plot seems to acquire an y-offset, increasing as time goes on. I also tried using the same data to display in an accumulating plot (though I really would rather to do a scrolling view) and it didn't acquire any y-offset.
This is what it looks at the end of my test sample - missing the effect of y-offset gradually increasing -
Of course, I would like for the y-offset not to appear, the top plot should be identical to the last 50 samples of the bottom plot
Both plots have identical data sets.
The code that I'm using to generate this is:
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
from time import sleep
win = pg.GraphicsWindow()
win.setWindowTitle('Sliding Window Test')
p1 = win.addPlot()
p1.setLabels(left='Large Range')
## create third ViewBox.
## this time we need to create a new axis as well.
p3 = pg.ViewBox()
ax3 = pg.AxisItem('right')
p1.layout.addItem(ax3, 2, 3)
p1.scene().addItem(p3)
ax3.linkToView(p3)
p3.setXLink(p1)
ax3.setZValue(-10000)
ax3.setLabel('Small Range', color='#ff0000')
win.nextRow()
p5 = win.addPlot()
p5.setLabels(left='Large Range')
## create third ViewBox.
## this time we need to create a new axis as well.
p7 = pg.ViewBox()
ax7 = pg.AxisItem('right')
p5.layout.addItem(ax7, 2, 3)
p5.scene().addItem(p7)
ax7.linkToView(p7)
p7.setXLink(p5)
ax7.setZValue(-10000)
ax7.setLabel('Small Range', color='#ff0000')
## Handle view resizing
def updateViews():
## view has resized; update auxiliary views to match
global p1, p3, p5, p7
p3.setGeometry(p1.vb.sceneBoundingRect())
p7.setGeometry(p5.vb.sceneBoundingRect())
## need to re-update linked axes since this was called
## incorrectly while views had different shapes.
## (probably this should be handled in ViewBox.resizeEvent)
p3.linkedViewChanged(p1.vb, p3.XAxis)
p7.linkedViewChanged(p5.vb, p7.XAxis)
updateViews()
p1.vb.sigResized.connect(updateViews)
p5.vb.sigResized.connect(updateViews)
data1 = []
data3 = []
curve1 = p1.plot()
curve3 = pg.PlotCurveItem(pen='r')
p3.addItem(curve3)
curve5 = p5.plot()
curve7 = pg.PlotCurveItem(pen='r')
p7.addItem(curve7)
data1 = [1000.0*r - 400 for r in np.random.random(size=600)]
data3 = [1.5*r for r in np.random.random(size=600)]
p1.setRange(yRange=(-400, 600))
p3.setRange(yRange=(0, 1.5))
p5.setRange(yRange=(-400, 600))
p7.setRange(yRange=(0, 1.5))
timer = pg.QtCore.QTimer()
r = 0
def update():
global timer
global r
if r > 50:
curve1.setData(data1[r-50:r])
curve3.setData(data3[r-50:r])
curve1.setPos(r - 50, r)
curve3.setPos(r - 50, r)
else:
curve1.setData(data1[:r])
curve3.setData(data3[:r])
curve5.setData(data1[:r])
curve7.setData(data3[:r])
r +=1
if r >= 600:
timer.stop()
timer.timeout.connect(update)
timer.start(100)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
Simple error: both curves in the top plot are shifted in the y-direction because of these lines:
curve1.setPos(r - 50, r)
curve3.setPos(r - 50, r)
They should instead look like:
curve1.setPos(r - 50, 0)
curve3.setPos(r - 50, 0)

Splitting a bezier curve

I'm working on a game for iPhone which creates a path after your character as you move (movement is similar to snake but curvy in terms of steering). The way im doing it now is by just keeping all the vertices the player has been on in an array and then just draw a circle on every one of them each and every frame.
I wanna move on to using bezier curves instead. I've done a lot of reading about them and I understand them quite well, but im not really good with math. I've came to an understanding that i should use DeCasteljau's algorithm to split the curve at a specific t but i haven't found out just which formula to use and how to implement this in code.
So what I currently have is all the controlpoints for a curve at t=1. Now i just want to get all the controlpoints for t<1. Can somebody give me an easy to understand mathematical formula for this or an implementation (preferably in python or objective-c). Maybe there's even a object that you can use in iphone sdk to split curves already?
I managed to get it working, actually really simple math. Just calculate all the tangents for the bezier and you get the points.
Here's some python:
def sliceBezier(points, t):
x1, y1 = points[0]
x2, y2 = points[1]
x3, y3 = points[2]
x4, y4 = points[3]
x12 = (x2-x1)*t+x1
y12 = (y2-y1)*t+y1
x23 = (x3-x2)*t+x2
y23 = (y3-y2)*t+y2
x34 = (x4-x3)*t+x3
y34 = (y4-y3)*t+y3
x123 = (x23-x12)*t+x12
y123 = (y23-y12)*t+y12
x234 = (x34-x23)*t+x23
y234 = (y34-y23)*t+y23
x1234 = (x234-x123)*t+x123
y1234 = (y234-y123)*t+y123
return [(x1, y1), (x12, y12), (x123, y123), (x1234, y1234)]
To call it:
sliceBezier([(point1_x, point1_y),(controlpoint1_x, controlpoint1_y),(controlpoint2_x, controlpoint2_y),(point2_x, point2_y)], 0.23);
I implemented something like that, if you have a modern browser take a look here. It's implemented in javascript, and supports also higher order beziers.
Here is a solution using Apple's SIMD api. It is concise and returns both subdivided curves.
void SplitBezier(float t,
simd_float2 cv[4],
simd_float2 a[4],
simd_float2 b[4]) {
a[0] = cv[0];
b[3] = cv[3];
a[1] = simd_mix(cv[0], cv[1], t);
b[2] = simd_mix(cv[2], cv[3], t);
auto b12 = simd_mix(cv[1], cv[2], t);
a[2] = simd_mix(a[1], b12, t);
b[1] = simd_mix(b12, b[2], t);
a[3] = b[0] = simd_mix(a[2], b[1], t);
}

Resources