I have a matrix defined mxn 128x128. And I have translated my 2d x,y positions onto this 1D matrix grid. My 2d coordinates accept positions using numbers 0->127 i.e. any combo in ranges {x=0,y=0}-->{x=127,y=127}. I'm implementing algorithms that take the neighboring positions of these nodes. Specifically the 8 surrounding positions of distance i (lets say i=1). So considering node={0,0}, my neighbours are generated by adding these vectors to said node:
two_d_nodes={
{0,i*1},{0,-i*1},{-i*1,0},{i*1,0},
{i*1,i*1},{i*1,-i*1},{-i*1,-i*1},{-i*1,i*1}
}
In terms of 2d though I am excluding neighbours outside the boundary. So in the above for node={0,0}, only neighours {0,1},{1,1}{1,0} are generated. Setting the boundary is basically just implementing some form of:
if x>=0 and y>=0 and x<=127 and y<=127 then...
The 1d translation of node={0,0} is node={0} and my vector additions translated to 1d are:
one_d_nodes={{128},{-128},{-1},{1},{129},{-127},{-129},{127}}
However the relationship with the 2d boundary expressions doesn't hold true here. Or at least I don't know how to translate it. In response I tried generating all the loose cases of the grid:
{0,127,16256,16383} --the 4 corner positions
node%128==0 --right-side boundary
node%128==1 --left-side boundary
node>1 and node<128 --top-side boundary
node>127*128 and node<128*128 --bottom-side boundary
Then tried implementing special cases....where I just ignored generating the specific out of bounds neighbours. That was messy, and didn't even work for some reason. Regardless I feel I am missing a much cleaner method.
So my question is: How do I translate my 2d boundaries onto my 1d grid for the purposes of only generating neighbours within the boundary?
The following is in regards to the answer below:
function newmatrix(node) --node={x=0,y=0}
local matrix={}
add(matrix,{(node.y<<8)+node.x}) --matrix= {{0},...}
--lets say [1 2 3] is a width=3; height=1 matrix,
--then the above line maps my 2d coord to a matrix of width=256, height=128
matrix.height, matrix.width = #node,#node[1] --1,1
return matrix
end
function indexmatrix(matrix, r,c)
if r > 1 and r <= matrix.height and c > 1 and c <= matrix.width then
return matrix[matrix.width * r + c]
else
return false
end
end
function getneighbors(matrix, r, c)
local two_d_nodes={
{0,1},{0,-1},{-1,0},{1,0},
{1,1},{1,-1},{-1,-1},{-1,1}
}
local neighbors = {}
for index, node in ipairs(two_d_nodes) do
table.insert(neighbors, indexmatrix(matrix, r + node[1], c + node[2]))
end
return neighbors
end
--Usage:
m={x=0,y=0}
matrix=newmatrix(m) --{{0}}
--here's where I'm stuck, cause idk what r and c are
--normally I'd grab my neighbors next....
neighbors=getneighbors(matrix)
--then I have indexmatrix for...?
--my understanding is that I am using indexmatrix to
--check if the nieghbors are within the bounds or not, is that right?
--can you illustrate how it would work for my code here, it should
--toss out anything with x less then 0 and y less than 0. Same as in OP's ex
indexmatrix(matrix) ---not sure what to do here
Attempt 2 in regards to the comment sections below:
function indexmatrix(matrix, x ,y)
if x > 1 and x <= matrix['height'] and y > 1 and y <= matrix['width'] then
return matrix[matrix['width'] * x + y]
else
return false
end
end
function getneighbors(matrix, pos_x, pos_y)
local two_d_nodes={
{0,1},{0,-1},{-1,0},{1,0},
{1,1},{1,-1},{-1,-1},{-1,1}
}
local neighbors = {}
for _, node in ipairs(two_d_nodes) do
add(neighbors, indexmatrix(matrix, pos_x + node[1], pos_y + node[2]))
end
return neighbors
end
matrix={} --128 columns/width, 128 rows/height
for k=1,128 do
add(matrix,{}) ----add() is same as table.insert()
for i=1,128 do
matrix[k][i]=i
end
end
id_matrix={{}} --{ {1...16k}}
for j=1,128*128 do
id_matrix[1][j]=j
end
id_matrix.height, id_matrix.width = 128,128
position={x=0,y=0}
neighbors = getNeighbors(matrix, position.x, position.y)
Attempt 3: A working dumbed down version of the code given. Not what I wanted at all.
function indexmatrix(x,y)
if x>=0 and y>=0 and x<127 and y<127 then
return 128 * x + y
else
return false
end
end
function getneighbors(posx,posy)
local two_d_nodes={
{0,1},{0,-1},{-1,0},{1,0},
{1,1},{1,-1},{-1,-1},{-1,1}
}
local neighbors = {}
for _, node in pairs(two_d_nodes) do
add(neighbors, indexmatrix(posx+node[1], posy + node[2]))
end
return neighbors
end
pos={x=0,y=10}
neighbors = getneighbors(pos.x,pos.y)
Edit: The equation to map 2D coordinates to 1D, y = mx + z, is a function of two variables. It is not possible for a multivariable equation to have a single solution unless a system of equations is given that gets x or z in terms of the other variable. Because x and z are independent of one another, the short answer to the question is: no
Instead, the constraints on x and z must be used to ensure integrity of the 1D coordinates.
What follows is an example of how to work with a 1D array as if it were a 2D matrix.
Let's say we have a constructor that maps a 2D table to a 1D matrix
local function newMatrix(m) -- m is 128x128 Matrix
local Matrix = {}
--logic to map m to 1D array
-- ...
return Matrix -- Matrix is m 1x16384 Array
end
The numeric indices are reserved, but we can add non-numeric keys to store information about the matrix. Let's store the number of rows and columns as height and width. We can do this in the constructor
local function newMatrix(m)
local Matrix = {}
--logic to map to 1D array
-- ...
-- Store row and column info in the matrix
Matrix.height, Matrix.width = #m, #m[1] -- Not the best way
return Matrix
end
Although the matrix is now a 1x16384 array, we can create a function that allows us to interact with the 1D array like it's still a 2D matrix. This function will get the value of a position in the matrix, but we return false/nil if the indices are out of bounds.
To be clear, the formula to map 2D coordinates to a 1D coordinate for a matrix, and can be found here:
1D position = 2D.x * Matrix-Width + 2D.y
And here's what that function could look like:
local function indexMatrix(Matrix, r,c)
if r >= 1 and r <= Matrix.height and c >= 1 and c <= Matrix.width then
return Matrix[Matrix.width * r + c] -- the above formula
else
return false -- out of bounds
end
end
We can now index our Matrix with any bounds without fear of returning an incorrect element.
Finally, we can make a function to grab the neighbors given a 2D position. In this function, we add vectors to the given 2D position to get surrounding positions, and then index the matrix using the indexMatrix function. Because indexMatrix checks if a 2D position is within the bounds of the original Matrix (before it was converted), we only get neighbors that exist.
local function getNeighbors(Matrix, r, c) -- r,c = row, column (2D position)
local two_d_nodes={
{0,1},{0,-1},{-1,0},{1,0},
{1,1},{1,-1},{-1,-1},{-1,1}
}
local neighbors = {}
for index, node in ipairs(two_d_nodes) do
-- Add each vector to the given position and get the node from the Matrix
table.insert(neighbors, indexMatrix(Matrix, r + node[1], c + node[2]))
end
return neighbors
end
You can either skip elements that return false from indexMatrix or remove them after the fact. Or anything else that sounds better to you (this code is not great, it's just meant to be an example). Wrap it in a for i ... do loop and you can go out an arbitrary distance.
I hope I haven't assumed too much and that this is helpful. Just know it's not foolproof (the # operator stops counting at the first nil, for instance)
Edit: Usage
Matrix = {
{1,2,3...128}, -- row 1
{1,2,3...128},
...
{1,2,3...128}, -- row 128
}
Array = newMatrix(Matrix) -- Convert to 1D Array ({1,2,3,...,16384})
--Array.width = 128, Array.height = 128
position = {x=0, y=0}
neighbors = getNeighbors(Array, position.x, position.y)
-- neighbors is: {{0,1}, false, false, {1,0}, {1,1}, false, false, false}
library(highcharter)
highchart() %>%
hc_add_series(name='Polygon',type='polygon',data=list(c(1,4),c(2,4), c(3,3), c(2,3)),
borderRadius = 10, lineColor = "red", lineWidth = 3)][1]][1]
Hello everybody. I use a polygon to display some data. I would prefer to have the borders to be round, but the borderRadius attribute does not work for the polygon.
Does anyone have an idea how to archieve a rounded look of my polygon? Documentation did not help in this case :-(. This is made the the R Highcharter package, but I would also be totally fine with an example in die native JS Library.
Thank you!
This works somewhat:
spline.poly <- function(xy, vertices, k=3, ...) {
# Assert: xy is an n by 2 matrix with n >= k.
# Wrap k vertices around each end.
n <- dim(xy)[1]
if (k >= 1) {
data <- rbind(xy[(n-k+1):n,], xy, xy[1:k, ])
} else {
data <- xy
}
# Spline the x and y coordinates.
data.spline <- spline(1:(n+2*k), data[,1], n=vertices, ...)
x <- data.spline$x
x1 <- data.spline$y
x2 <- spline(1:(n+2*k), data[,2], n=vertices, ...)$y
# Retain only the middle part.
cbind(x1, x2)[k < x & x <= n+k, ]
}
X <- matrix(c(resultdf$yAxis, resultdf$xAxis), ncol=2)
hpts <- chull(X) # Creates indices of a convex hull from a matrix
hpts <- c(hpts, hpts[1]) # connect last and first dot
hpts <- data.frame(X[hpts, ])
hpts <- data.frame(spline.poly(as.matrix(data.frame(hpts$X1, hpts$X2)), 500)) %>%
setNames(c("yAxis", "xAxis"))
the spline.poly function creates a lot of new points which connect to a more rounded shape :-)
I'm working on a problem where I have all the variables as categorical variables and applied MCA. When I visualize MCA results combined with clusters obtained through K-modes (applied independently of MCA), the clusters overlap with each other. I was wondering instead of applying k-modes, I should simply get MCA components and apply K-means or other clustering algorithm on those components. Does that make sense?
I don't think K-Means allows overlapping. The sample result is assigned to closest cluster, but not to all, so there is no overlapping. Check out the code sample below.
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi
def voronoi_finite_polygons_2d(vor, radius=None):
"""
Reconstruct infinite voronoi regions in a 2D diagram to finite
regions.
Parameters
----------
vor : Voronoi
Input diagram
radius : float, optional
Distance to 'points at infinity'.
Returns
-------
regions : list of tuples
Indices of vertices in each revised Voronoi regions.
vertices : list of tuples
Coordinates for revised Voronoi vertices. Same as coordinates
of input vertices, with 'points at infinity' appended to the
end.
"""
if vor.points.shape[1] != 2:
raise ValueError("Requires 2D input")
new_regions = []
new_vertices = vor.vertices.tolist()
center = vor.points.mean(axis=0)
if radius is None:
radius = vor.points.ptp().max()*2
# Construct a map containing all ridges for a given point
all_ridges = {}
for (p1, p2), (v1, v2) in zip(vor.ridge_points, vor.ridge_vertices):
all_ridges.setdefault(p1, []).append((p2, v1, v2))
all_ridges.setdefault(p2, []).append((p1, v1, v2))
# Reconstruct infinite regions
for p1, region in enumerate(vor.point_region):
vertices = vor.regions[region]
if all([v >= 0 for v in vertices]):
# finite region
new_regions.append(vertices)
continue
# reconstruct a non-finite region
ridges = all_ridges[p1]
new_region = [v for v in vertices if v >= 0]
for p2, v1, v2 in ridges:
if v2 < 0:
v1, v2 = v2, v1
if v1 >= 0:
# finite ridge: already in the region
continue
# Compute the missing endpoint of an infinite ridge
t = vor.points[p2] - vor.points[p1] # tangent
t /= np.linalg.norm(t)
n = np.array([-t[1], t[0]]) # normal
midpoint = vor.points[[p1, p2]].mean(axis=0)
direction = np.sign(np.dot(midpoint - center, n)) * n
far_point = vor.vertices[v2] + direction * radius
new_region.append(len(new_vertices))
new_vertices.append(far_point.tolist())
# sort region counterclockwise
vs = np.asarray([new_vertices[v] for v in new_region])
c = vs.mean(axis=0)
angles = np.arctan2(vs[:,1] - c[1], vs[:,0] - c[0])
new_region = np.array(new_region)[np.argsort(angles)]
# finish
new_regions.append(new_region.tolist())
return new_regions, np.asarray(new_vertices)
# make up data points
np.random.seed(1234)
points = np.random.rand(15, 2)
# compute Voronoi tesselation
vor = Voronoi(points)
# plot
regions, vertices = voronoi_finite_polygons_2d(vor)
print("--")
print(regions)
print("--")
print(vertices)
# colorize
for region in regions:
polygon = vertices[region]
plt.fill(*zip(*polygon), alpha=0.4)
plt.plot(points[:,0], points[:,1], 'ko')
plt.axis('equal')
plt.xlim(vor.min_bound[0] - 0.1, vor.max_bound[0] + 0.1)
plt.ylim(vor.min_bound[1] - 0.1, vor.max_bound[1] + 0.1)
I think some clustering algos actually do allow overlapping. Do a Google search and you will find what you are looking for.
Hope that helps.
I have a sfc_multipoint object and want to use st_buffer but with different distances for every single point in the multipoint object.
Is that possible?
The multipoint object are coordinates.
table = data
Every coordinate point (in the table in "lon" and "lat") should have a buffer with a different size. This buffer size is containt in the table in row "dist".
The table is called data.
This is my code:
library(sf)
coords <- matrix(c(data$lon,data$lat), ncol = 2)
tt <- st_multipoint(coords)
sfc <- st_sfc(tt, crs = 4326)
dt <- st_sf(data.frame(geom = sfc))
web <- st_transform(dt, crs = 3857)
geom <- st_geometry(web)
buf <- st_buffer(geom, dist = data$dist)
But it uses just the first dist of (0.100).
This is the result. Just really small buffers.
small buffer
For visualization see this picture. It´s just an example to show that the buffer should get bigger. example result
I think that he problem here is in how you are "creating" the points dataset.
Replicating your code with dummy data, doing this:
library(sf)
data <- data.frame(lat = c(0,1,2,3), lon = c(0,1,2,3), dist = c(0.1,0.2,0.3, 0.4))
coords <- matrix(c(data$lon,data$lat), ncol = 2)
tt <- st_multipoint(coords)
does not give you multiple points, but a single MULTIPOINT feature:
tt
#> MULTIPOINT (0 0, 1 1, 2 2, 3 3)
Therefore, only a single buffer distance can be "passed" to it and you get:
plot(sf::st_buffer(tt, data$dist))
To solve the problem, you need probably to build the point dataset differently. For example, using:
tt <- st_as_sf(data, coords = c("lon", "lat"))
gives you:
tt
#> Simple feature collection with 4 features and 1 field
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 0 ymin: 0 xmax: 3 ymax: 3
#> epsg (SRID): NA
#> proj4string: NA
#> dist geometry
#> 1 0.1 POINT (0 0)
#> 2 0.2 POINT (1 1)
#> 3 0.3 POINT (2 2)
#> 4 0.4 POINT (3 3)
You see that tt is now a simple feature collection made of 4 points, on which buffering with multiple distances will indeed work:
plot(sf::st_buffer(tt, data$dist))
HTH!
I am training 1000 images of 28x28 size. But before training, I am performing ZCA whitening on my data by taking the reference from How to implement ZCA Whitening? Python.
Since I have 1000 data images of size 28x28, after flattening, it becomes 1000x784.
But as given in the code below, whether X is my image dataset of 1000x784?
If it is so, then it means the ZCAMatrix size is 1000x1000.
In this case, for prediction I have a image of size 28x28, or we can say, size of 1x784.So it doesn't make sense to multiply ZCAMatrix to the image.
So I think, X is the transpose of image data set. Am I right?
If I am right, then the size of ZCAMatrix is 784x784.
Now how should I calculate the ZCA whitened image, whether I should use np.dot(ZCAMatrix, transpose_of_image_to_be_predict) or np.dot(image_to_be_predict, ZCAMatrix)?
Suggestion would be greatly appreciate.
def zca_whitening_matrix(X):
"""
Function to compute ZCA whitening matrix (aka Mahalanobis whitening).
INPUT: X: [M x N] matrix.
Rows: Variables
Columns: Observations
OUTPUT: ZCAMatrix: [M x M] matrix
"""
# Covariance matrix [column-wise variables]: Sigma = (X-mu)' * (X-mu) / N
sigma = np.cov(X, rowvar=True) # [M x M]
# Singular Value Decomposition. X = U * np.diag(S) * V
U,S,V = np.linalg.svd(sigma)
# U: [M x M] eigenvectors of sigma.
# S: [M x 1] eigenvalues of sigma.
# V: [M x M] transpose of U
# Whitening constant: prevents division by zero
epsilon = 1e-5
# ZCA Whitening matrix: U * Lambda * U'
ZCAMatrix = np.dot(U, np.dot(np.diag(1.0/np.sqrt(S + epsilon)), U.T)) # [M x M]
return ZCAMatrix
And an example of the usage:
X = np.array([[0, 2, 2], [1, 1, 0], [2, 0, 1], [1, 3, 5], [10, 10, 10] ]) # Input: X [5 x 3] matrix
ZCAMatrix = zca_whitening_matrix(X) # get ZCAMatrix
ZCAMatrix # [5 x 5] matrix
xZCAMatrix = np.dot(ZCAMatrix, X) # project X onto the ZCAMatrix
xZCAMatrix # [5 x 3] matrix
I got the reference from the Keras code available here.
It is very clear that in my case the co-variance matrix will give 784x784 matrix, on which Singular Value Decomposition is performed. It gives 3 matrix that is used to calculate the principal_components, and that principal_components is used to find the ZCA whitened data.
Now my question was
how should I calculate the ZCA whitened image, whether I should use
np.dot(ZCAMatrix, transpose_of_image_to_be_predict) or
np.dot(image_to_be_predict, ZCAMatrix)? Suggestion would be greatly
appreciate.
For this I got the reference from here.
Here I need to use np.dot(image_to_be_predict, ZCAMatrix) to calculate the ZCA whitened image.