class Chem::Spatial::Grid
- Chem::Spatial::Grid
- Reference
- Object
Overview
TODO add support for non-cubic grids (use lattice instead of bounds?) - i to coords: origin.x + (i / nx) * lattice.a - coords to i: ?
TODO implement functionality from vmd's volmap
Included Modules
Defined in:
chem/io/reader.crchem/io/writer.cr
chem/spatial/grid.cr
Constructors
- .[](ni : Int, nj : Int, nk : Int) : self
- .atom_distance(structure : Structure, dim : Dimensions, bounds : Bounds | Nil = nil) : self
-
.atom_distance_like(other : self | Info, structure : Structure) : self
Returns a grid filled with the distances to the nearest atom.
- .build(dim : Dimensions, bounds : Bounds, &block : Pointer(Float64), Int32 -> ) : self
-
.build(info : Info, & : Pointer(Float64), Int32 -> ) : self
Creates a new
Grid
with info and yields a buffer to be filled. -
.empty_like(other : self | Info) : self
Returns a zero-filled grid with the same bounds and points as other.
-
.fill_like(other : self | Info, value : Number) : self
Returns a grid with the same bounds and points as other filled with value.
- .from_chgcar(input : ::IO | Path | String, *args, **options) : self
- .from_cube(input : ::IO | Path | String, *args, **options) : self
- .from_dx(input : ::IO | Path | String, *args, **options) : self
- .from_locpot(input : ::IO | Path | String, *args, **options) : self
- .new(dim : Dimensions, bounds : Bounds, initial_value : Float64)
- .new(dim : Dimensions, bounds : Bounds)
- .new(dim : Dimensions, bounds : Bounds, &block : Location -> Number)
-
.vdw_mask(structure : Structure, dim : Dimensions, bounds : Bounds | Nil = nil, delta : Float64 = 0.02) : self
TODO add more tests FIXME: check delta calculation (grid.resolution.min / 2 shouldn't be enough?)
-
.vdw_mask_like(other : self | Info, structure : Structure, delta : Float64 = 0.02) : self
Returns a grid mask with the points at the vdW spheres set to 1.
Class Method Summary
- .info(input : ::IO | Path | String, format : IO::FileFormat) : Info
- .info(path : Path | String) : Info
Instance Method Summary
- #*(rhs : Number) : self
- #*(rhs : self) : self
- #+(rhs : Number) : self
- #+(rhs : self) : self
- #-(rhs : Number) : self
- #-(rhs : self) : self
- #/(rhs : Number) : self
- #/(rhs : self) : self
-
#==(rhs : self) : Bool
Returns
true
if this reference is the same as other. - #[](*args, **options) : Float64
- #[]=(i : Int, j : Int, k : Int, value : Float64) : Float64
- #[]=(i : Int, value : Float64) : Float64
- #[]=(loc : Location, value : Float64) : Float64
- #[]?(i : Int, j : Int, k : Int) : Float64 | Nil
- #[]?(loc : Location) : Float64 | Nil
-
#[]?(vec : Vector) : Float64 | Nil
TODO add interpolation (check ARBInterp)
- #bounds : Bounds
- #coords_at(*args, **options) : Vector
- #coords_at?(i : Int, j : Int, k : Int) : Vector | Nil
- #coords_at?(i : Int) : Vector | Nil
- #coords_at?(loc : Location) : Vector | Nil
- #dim : Dimensions
-
#dup : self
Returns a shallow copy of this object.
-
#each_axial_slice(axis : Int, reuse : Bool | Array(Float64) = false, & : Array(Float64) -> ) : Nil
Iterates over slices along axis.
- #each_coords(& : Vector -> ) : Nil
- #each_loc(vec : Vector, cutoff : Number, & : Location, Float64 -> ) : Nil
- #each_loc(& : Location -> ) : Nil
- #each_with_coords(& : Float64, Vector -> ) : Nil
- #each_with_loc(& : Float64, Location -> ) : Nil
- #includes?(*args, **options)
- #includes?(*args, **options, &)
- #index(loc : Location) : Int32 | Nil
- #index(vec : Vector) : Int32 | Nil
- #index!(*args, **options) : Int32
- #loc_at(*args, **options) : Location
- #loc_at?(i : Int) : Location | Nil
- #loc_at?(vec : Vector) : Location | Nil
-
#map(& : Float64 -> Float64) : self
Returns an
Array
with the results of running the block against each element of the collection. - #map!(& : Float64 -> Float64) : self
- #map_with_coords(& : Float64, Vector -> Number) : self
- #map_with_coords!(& : Float64, Vector -> Number) : self
-
#map_with_index(& : Float64, Int32 -> Number) : self
Like
#map
, but the block gets passed both the element and its index. - #map_with_index!(& : Float64, Int32 -> Number) : self
- #map_with_loc(& : Float64, Location -> Number) : self
- #map_with_loc!(& : Float64, Location -> Number) : self
-
#mask(& : Float64 -> Bool) : self
Returns a grid mask.
-
#mask(value : Number, delta : Number) : self
Returns a grid mask.
-
#mask(pattern) : self
Returns a grid mask.
-
#mask!(& : Float64 -> Bool) : self
Masks a grid by the passed block.
-
#mask!(value : Number, delta : Number) : self
Masks a grid by value+/-delta.
-
#mask!(pattern) : self
Masks a grid by pattern.
-
#mask_by_coords(& : Vector -> Bool) : self
Returns a grid mask.
-
#mask_by_coords!(& : Vector -> Bool) : self
Masks a grid by coordinates.
-
#mask_by_index(& : Int32 -> Bool) : self
Returns a grid mask.
-
#mask_by_index!(& : Int32 -> Bool) : self
Masks a grid by index.
-
#mask_by_loc(& : Location -> Bool) : self
Returns a grid mask.
-
#mask_by_loc!(& : Location -> Bool) : self
Masks a grid by location.
-
#mean(axis : Int) : Array(Float64)
Returns the arithmetic mean along axis.
-
#mean : Float64
Returns the arithmetic mean of the grid elements.
-
#mean_with_coords(axis : Int) : Array(Tuple(Float64, Float64))
Returns the arithmetic mean along axis with its coordinates.
- #ni : Int32
- #nj : Int32
- #nk : Int32
- #origin(*args, **options)
- #origin(*args, **options, &)
- #resolution : Tuple(Float64, Float64, Float64)
-
#size : Int32
Returns the number of elements in this container.
- #step(di : Int, dj : Int, dk : Int) : self
- #step(n : Int) : self
-
#to_a : Array(Float64)
Returns an
Array
with all the elements in the collection. - #to_chgcar(output : ::IO | Path | String, *args, **options) : Nil
- #to_chgcar(*args, **options) : String
- #to_cube(output : ::IO | Path | String, *args, **options) : Nil
- #to_cube(*args, **options) : String
- #to_dx(output : ::IO | Path | String, *args, **options) : Nil
- #to_dx(*args, **options) : String
- #to_locpot(output : ::IO | Path | String, *args, **options) : Nil
- #to_locpot(*args, **options) : String
- #to_unsafe : Pointer(Float64)
-
#unsafe_fetch(i : Int) : Float64
Returns the element at the given index, without doing any bounds check.
- #unsafe_fetch(loc : Location) : Float64
- #volume(*args, **options)
- #volume(*args, **options, &)
Instance methods inherited from module Indexable(Float64)
index!(of object, offset : Int = 0) : Intindex!(offset : Int = 0, &block : T -> Bool) : Int index!
Constructor Detail
Returns a grid filled with the distances to the nearest atom. It will have the same bounds and points as other.
structure = Structure.read "path/to/file"
info = Grid::Info.new Bounds[1.5, 2.135, 6.12], {10, 10, 10}
grid = Grid.atom_distance structure, info.dim, info.bounds
Grid.atom_distance_like(info, structure) == grid # => true
Creates a new Grid
with info and yields a buffer to be filled.
This method is unsafe, but it is usually used to initialize the buffer in a linear fashion, e.g., reading values from a file.
Grid.build(Grid.info("/path/to/file")) do |buffer, size|
size.times do |i|
buffer[i] = read_value
end
end
Returns a zero-filled grid with the same bounds and points as other.
grid = Grid.from_dx "/path/to/grid"
other = Grid.empty_like grid
other.bounds == grid.bounds # => true
other.dim == grid.dim # => true
other.to_a.minmax # => {0.0, 0.0}
Returns a grid with the same bounds and points as other filled with value.
grid = Grid.from_dx "/path/to/grid"
other = Grid.fill_like grid, 2345.123
other.bounds == grid.bounds # => true
other.dim == grid.dim # => true
other.to_a.minmax # => {2345.123, 2345.123}
TODO add more tests
FIXME check delta calculation (grid.resolution.min / 2 shouldn't be enough?)
Returns a grid mask with the points at the vdW spheres set to 1. It will have the same bounds and points as other.
structure = Structure.read "path/to/file"
info = Grid::Info.new Bounds[5.213, 6.823, 10.352], {20, 25, 40}
grid = Grid.vdw_mask structure, info.dim, info.bounds
Grid.vdw_mask_like(info, structure) == grid # => true
Class Method Detail
Instance Method Detail
Returns true
if this reference is the same as other. Invokes same?
.
Returns a shallow copy of this object.
This allocates a new object and copies the contents of
self
into it.
Iterates over slices along axis. Axis is specified as an integer: 0-2 refer to the direction of the first, second or third basis vector, respectively.
grid = Grid.new({2, 3, 2}, Bounds[1, 1, 1]) { |i, j, k| i * 6 + j * 2 + k }
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
slices = [] of Array(Float64)
grid.each_axial_slice(axis: 1) { |slice| slices << slice }
slices # => [[0, 1, 6, 7], [2, 3, 8, 9], [4, 5, 10, 11]]
When using read-only slices, one can specify the reuse option to prevent many memory allocations:
- If reuse is an
Array
, this array will be reused. - If reuse is true, the method will create a new array and reuse it.
- If reuse is false (default), a new array is created and yielded on each iteration.
Returns an Array
with the results of running the block against each element of the collection.
[1, 2, 3].map { |i| i * 10 } # => [10, 20, 30]
Like #map
, but the block gets passed both the element and its index.
["Alice", "Bob"].map_with_index { |name, i| "User ##{i}: #{name}" }
# => ["User #0: Alice", "User #1: Bob"]
Accepts an optional offset parameter, which tells it to start counting from there.
Returns a grid mask. Elements for which the passed block returns true
are set to
1, otherwise 0.
Grid masks are very useful to deal with multiple grids, and when points are to be selected based on one grid only.
grid = Grid.new({2, 2, 2}, Bounds[10, 10, 10]) { |i, j, k| i + j + k }
grid.to_a # => [0, 1, 1, 2, 1, 2, 2, 3]
grid.mask(&.>(1)).to_a # => [0, 0, 0, 1, 0, 1, 1, 1]
grid.to_a # => [0, 1, 1, 2, 1, 2, 2, 3]
Returns a grid mask. Elements for which (value - ele).abs <= delta
returns
true
are set to 1, otherwise 0.
Grid masks are very useful to deal with multiple grids, and when points are to be selected based on one grid only.
grid = Grid.new({2, 2, 3}, Bounds[1, 1, 1]) { |i, j, k| (i + 1) * (j + 1) * (k + 1) / 5 }
grid.to_a # => [0.2, 0.4, 0.6, 0.4, 0.8, 1.2, 0.4, 0.8, 1.2, 0.8, 1.6, 2.4]
grid.mask(1, 0.5).to_a # => [0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0]
grid.to_a # => [0.2, 0.4, 0.6, 0.4, 0.8, 1.2, 0.4, 0.8, 1.2, 0.8, 1.6, 2.4]
Returns a grid mask. Elements for which pattern === element
returns true
are
set to 1, otherwise 0.
Grid masks are very useful to deal with multiple grids, and when points are to be selected based on one grid only.
grid = Grid.new({2, 2, 3}, Bounds[1, 1, 1]) { |i, j, k| (i + 1) * (j + 1) * (k + 1) }
grid.to_a # => [1, 2, 3, 2, 4, 6, 2, 4, 6, 4, 8, 12]
grid.mask(2..4.5).to_a # => [0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0]
grid.to_a # => [1, 2, 3, 2, 4, 6, 2, 4, 6, 4, 8, 12]
Masks a grid by the passed block. Elements for which the passed block returns
false
are set to 0.
Optimized version of creating a mask and applying it to the same grid, but avoids
creating intermediate grids. This is equivalent to grid = grid * grid.mask { ... }
.
grid = Grid.new({2, 2, 2}, Bounds[10, 10, 10]) { |i, j, k| i + j + k }
grid.to_a # => [0, 1, 1, 2, 1, 2, 2, 3]
grid.mask! &.>(1)
grid.to_a # => [0, 0, 0, 2, 0, 2, 2, 3]
Masks a grid by value+/-delta. Elements for which (value - ele).abs > delta
returns true
are set to 0.
Optimized version of creating a mask and applying it to the same grid, but avoids
creating intermediate grids. This is equivalent to grid = grid * grid.mask(value, delta)
grid = Grid.new({2, 2, 3}, Bounds[1, 1, 1]) { |i, j, k| (i + j + k) / 5 }
grid.to_a # => [0.0, 0.2, 0.4, 0.2, 0.4, 0.6, 0.2, 0.4, 0.6, 0.4, 0.6, 0.8]
grid.mask! 0.5, 0.1
grid.to_a # => [0.0, 0.0, 0.4, 0.0, 0.4, 0.6, 0.0, 0.4, 0.6, 0.4, 0.6, 0.0]
Masks a grid by pattern. Elements for which pattern === element
returns
false
are set to 0.
Optimized version of creating a mask and applying it to the same grid, but avoids
creating intermediate grids. This is equivalent to grid = grid * grid.mask(pattern)
grid = Grid.new({2, 2, 3}, Bounds[1, 1, 1]) { |i, j, k| (i + 1) * (j + 1) * (k + 1) }
grid.to_a # => [1, 2, 3, 2, 4, 6, 2, 4, 6, 4, 8, 12]
grid.mask! 2..4.5
grid.to_a # => [0, 2, 3, 2, 4, 0, 2, 4, 0, 4, 0, 0]
Returns a grid mask. Coordinates for which the passed block returns true
are set
to 1, otherwise 0.
Grid masks are very useful to deal with multiple grids, and when points are to be selected based on one grid only.
grid = Grid.new({2, 2, 2}, Bounds[10, 10, 10]) { |i, j, k| i * 4 + j * 2 + k }
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
grid.mask_by_coords(&.x.==(0)).to_a # => [1, 1, 1, 1, 0, 0, 0, 0]
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
Masks a grid by coordinates. Coordinates for which the passed block returns
false
are set to 0.
Optimized version of creating a mask and applying it to the same grid, but avoids
creating intermediate grids. This is equivalent to grid = grid * grid.mask_by_coords { ... }
grid = Grid.new({2, 2, 2}, Bounds[5, 5, 5]) { |i, j, k| i * 4 + j * 2 + k }
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
grid.mask_by_coords! { |vec| vec.y == 5 }
grid.to_a # => [0, 0, 2, 3, 0, 0, 6, 7]
Returns a grid mask. Indexes for which the passed block returns true
are set to
1, otherwise 0.
Grid masks are very useful to deal with multiple grids, and when points are to be selected based on one grid only.
grid = Grid.new({2, 2, 2}, Bounds[10, 10, 10]) { |i, j, k| i * 4 + j * 2 + k }
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
grid.mask_by_index(&.>(4)).to_a # => [0, 0, 0, 0, 0, 1, 1, 1]
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
Masks a grid by index. Indexes for which the passed block returns false
are set
to 0.
Optimized version of creating a mask and applying it to the same grid, but avoids
creating intermediate grids. This is equivalent to grid = grid * grid.mask_by_index { ... }
grid = Grid.new({2, 2, 2}, Bounds[1, 1, 1]) { |i, j, k| i * 4 + j * 2 + k }
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
grid.mask_by_index! &.<(3)
grid.to_a # => [0, 1, 2, 0, 0, 0, 0, 0]
Returns a grid mask. Locations for which the passed block returns true
are set
to 1, otherwise 0.
Grid masks are very useful to deal with multiple grids, and when points are to be selected based on one grid only.
grid = Grid.new({2, 2, 2}, Bounds[10, 10, 10]) { |i, j, k| i * 4 + j * 2 + k }
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
grid.mask_by_loc { |i, j, k| k == 1 }.to_a # => [0, 1, 0, 1, 0, 1, 0, 1]
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
Masks a grid by location. Locations for which the passed block returns false
are
set to 0.
Optimized version of creating a mask and applying it to the same grid, but avoids
creating intermediate grids. This is equivalent to grid = grid * grid.mask_by_loc { ... }
grid = Grid.new({2, 2, 2}, Bounds[1, 1, 1]) { |i, j, k| i * 4 + j * 2 + k }
grid.to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
grid.mask_by_loc! { |(i, j, k)| i == 1 }
grid.to_a # => [0, 0, 0, 0, 4, 5, 6, 7]
Returns the arithmetic mean along axis. Axis is specified as an integer: 0-2 refer to the direction of the first, second or third basis vector, respectively.
Raises IndexError is axis is out of bounds.
grid = Grid.new({2, 3, 4}, Bounds[1, 1, 1]) { |i, j, k| i * 12 + j * 4 + k }
grid.mean(axis: 0) # => [5.5, 17.5]
grid.mean(axis: 1) # => [7.5, 11.5, 15.5]
grid.mean(axis: 2) # => [10, 11, 12, 13]
grid.mean(axis: 3) # raises IndexError
Returns the arithmetic mean of the grid elements.
grid = Grid.new({2, 3, 4}, Bounds[1, 1, 1]) { |i, j, k| i * 12 + j * 4 + k }
grid.mean # => 11.5
Returns the arithmetic mean along axis with its coordinates. Axis is specified as an integer: 0-2 refer to the direction of the first, second or third basis vector, respectively.
Raises IndexError is axis is out of bounds.
grid = Grid.new({2, 3, 5}, Bounds[1, 1, 1]) { |i, j, k| i * 12 + j * 4 + k }
grid.mean(axis: 1) # => [{9.5, 0.0}, {14.5, 0.5}, {19.5, 1.0}]
Returns the number of elements in this container.
Returns an Array
with all the elements in the collection.
{1, 2, 3}.to_a # => [1, 2, 3]
Returns the element at the given index, without doing any bounds check.
Indexable
makes sure to invoke this method with index in 0...size
,
so converting negative indices to positive ones is not needed here.
Clients never invoke this method directly. Instead, they access
elements with #[](index)
and #[]?(index)
.
This method should only be directly invoked if you are absolutely sure the index is in bounds, to avoid a bounds check for a small boost of performance.