
uk.ac.leeds.ccg.grids.d2.grid.Grids_Grid Maven / Gradle / Ivy
/*
* Copyright 2019 Andy Turner, University of Leeds.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.ac.leeds.ccg.grids.d2.grid;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import uk.ac.leeds.ccg.generic.io.Generic_FileStore;
import uk.ac.leeds.ccg.generic.io.Generic_Path;
import uk.ac.leeds.ccg.generic.io.Generic_IO;
import uk.ac.leeds.ccg.grids.d2.Grids_2D_ID_int;
import uk.ac.leeds.ccg.grids.d2.Grids_2D_ID_long;
import uk.ac.leeds.ccg.grids.memory.Grids_Account;
import uk.ac.leeds.ccg.grids.memory.Grids_AccountDetail;
import uk.ac.leeds.ccg.grids.core.Grids_Environment;
import uk.ac.leeds.ccg.grids.core.Grids_Object;
import uk.ac.leeds.ccg.grids.d2.chunk.Grids_Chunk;
import uk.ac.leeds.ccg.grids.d2.chunk.d.Grids_ChunkDoubleSinglet;
import uk.ac.leeds.ccg.grids.d2.chunk.i.Grids_ChunkIntSinglet;
import uk.ac.leeds.ccg.grids.d2.stats.Grids_Stats;
import uk.ac.leeds.ccg.grids.io.Grids_ESRIAsciiGridImporter.Header;
import uk.ac.leeds.ccg.grids.d2.util.Grids_Utilities;
import java.util.HashSet;
import java.util.stream.Collectors;
/**
* For two dimensional (d2) grid instances - grids representing a regular
* lattice like square celled raster arrangement of values in a plane aligned in
* rows and columns matching up with orthogonal axes X and Y. All values in a
* grid are of the same type and all "cells" are effectively the same size. The
* cellsize along with the bounding box dimensions of the grid are stored as
* {@link java.math.BigDecimal} values. The supported types of values are:
* {@code boolean}, {@link Boolean}; or a specific type of
* {@link java.lang.Number}. With the exception of the {@code boolean} type each
* type has a specific no data value (noDataValue). The rows and columns of
* cells in a grid are indexed by positive {@code long} values and these can
* provide a unique {@link Grids_2D_ID_long} identifier for each cell - though
* typically these are not used as grids are subdivided into chunks and it is
* the rows and columns of cells in these rows and columns of chunks that are
* primarily used.
*
* Chunks are organised into a map with each chunk indexed by a unique
* {@link Grids_2D_ID_int} identifier which gives the chunk row and chunk
* column. Each grid has a minimum of one chunk and a maximum of
* {@link Integer#MAX_VALUE}.
*
* The first row of chunks and first column of chunks start in row 0, column 0.
* Cells in row 0 have the smallest X axis bounds. Cells in column 0 have the
* smallest Y axis bounds of all cells in the grid. The number of chunk rows
* (nChunkRows) and the number of chunk columns (nChunkCols) is determined by
* the overall number of rows and columns in the grid and some parameters which
* set the typical number of rows (chunkNRows) and number of columns
* (chunkNCols) for the chunks in the grid.
*
* In the general case (where there are more than two rows and columns of
* chunks) - most chunks have the same number of rows and columns of cells. The
* number of rows (chunkNRows) multiplied by the number of columns (chunkNCols)
* in these chunks cannot exceed {@link Integer#MAX_VALUE}. But chunkNRows and
* chunkNCols can be different and so chunks represent rectangular sections of
* the grid.
*
* The number of rows in the final row of chunks and the number of columns in
* the final column of chunks may have a smaller chunkNRows and chunkNCols than
* chunks in the rest of the grid.
*
* The are a few different types of chunk distinguished by how they store and
* provide access to the cell values. Singlet chunks are those chunks for which
* all cell values in the chunk are the same. Singlet chunks data is represented
* with a single value. As soon as there are more than two values in the cells
* of a chunk, then an alternative storage is needed. Chunks may also store the
* values in a map or in an array.
*
* The grid and the chunks individually can be cached to a file store for
* persistence and to make available fast access memory for other processing.
* Caching a chunk and then setting it to null in the map of chunks allows for
* the memory that chunk was using to be garbage collected and made available
* for other purposes. When required chunks that are not currently loaded can be
* reloaded from the cache. Whether a cache effectively represents the same set
* of values as a chunk in memory will all depend on whether and how the values
* of the chunk have changed.
*
* What the most appropriate type of chunk is for storing values will depend on
* whether the data are changing, what the variety and distribution of values
* is, and which values are going to be retrieved and stored and in what order.
* Some types of chunk perform better than others depending on the density and
* variety of values in the chunk.
*
* It requires effort to change the in memory chunk from one type to another, so
* whether this is worth it all depends on: the memory demands and available
* memory; how much the data are changing; and the relative importance of the
* speed of computation over the memory footprint.
*
* Each grid has a statistics instance associated with it which provides access
* to summary statistics about the grid. The statistics are broadly of two
* types: those which are more or less updated as the underlying data are
* changed; and, those where no effort is made to keep them up-to-date as the
* underlying data changes. Having ready access to summary statistics about the
* values in a grid can be very useful, but there are costs associated with
* keeping them more up to date if they are not going to be used.
*
* It may require experiments and some understanding of the data and the
* processing that will be done in order to make a good decision about what
* types of statistic and chunks to use. In general, as the variety and density
* of data values increases the more likely it becomes that an array of values
* will be best. For sparse data where the majority of a chunk is noDataValues
* or is of the same value, then the better the map type storage is.
*
* There is a trade off between efficient storage, speed and flexibility. This
* may further vary depending on the architecture and capabilities of the
* machines being used.
*
* @author Andy Turner
* @version 1.0.0
*/
public abstract class Grids_Grid extends Grids_Object {
private static final long serialVersionUID = 1L;
/**
* The file store in which this is stored.
*/
protected final Generic_FileStore fs;
/**
* The file store ID for this grid.
*/
protected final long fsID;
/**
* The data are stored in a map with chunk ID keys and values that are
* either chunks, or {@code null} - if the chunk is not stored in the fast
* access memory, but in the file store {@link #fs}.
*/
protected TreeMap data;
/**
* A set of chunks worth swapping. These do not include singlet type chunks.
*/
protected HashSet worthSwapping;
/**
* For storing the number of chunk rows.
*/
protected int nChunkRows;
/**
* For storing the number of chunk columns.
*/
protected int nChunkCols;
/**
* For storing the (usual) number of rows of cells in a chunk. The number of
* rows in the final chunk row may be less.
*/
protected int chunkNRows;
/**
* For storing the (usual) number of columns of cells in a chunk. The number
* of columns in the final chunk column may be less.
*/
protected int chunkNCols;
/**
* For storing the number of rows in the grid.
*/
protected long nRows;
/**
* For storing the number of columns in the grid.
*/
protected long nCols;
/**
* For storing the Name of the grid.
*/
protected String name;
/**
* The dimensions of the grid.
*/
protected Grids_Dimensions dim;
/**
* A reference to the grid stats.
*/
protected Grids_Stats stats;
/**
* @param e The grids environment.
* @param fs The file store in which this grid is stored.
* @param id The id of the directory for this grid in the file store.
* @throws java.lang.Exception If encountered.
*/
protected Grids_Grid(Grids_Environment e, Generic_FileStore fs, long id)
throws Exception {
super(e);
this.fs = fs;
this.fsID = id;
}
protected void init() throws IOException {
env.setDataToClear(true);
env.addGrid(this);
}
/**
* Initialises non transient Grids_Grid fields from g.
*
* @param g The Grids_Grid from which the non transient Grids_Grid fields of
* this are set.
* @throws java.io.IOException If encountered.
*/
protected void init(Grids_Grid g) throws IOException {
chunkNCols = g.chunkNCols;
chunkNRows = g.chunkNRows;
dim = g.dim;
name = g.name;
nChunkCols = g.nChunkCols;
nChunkRows = g.nChunkRows;
nCols = g.nCols;
nRows = g.nRows;
init();
}
protected void init(Grids_Stats stats, int chunkNRows, int chunkNCols) {
this.stats = stats;
this.stats.setGrid(this);
this.chunkNRows = chunkNRows;
this.chunkNCols = chunkNCols;
name = fs.getBaseDir().getFileName().toString() + fsID;
initNChunkRows();
initNChunkCols();
data = new TreeMap<>();
worthSwapping = new HashSet<>();
}
protected void init(Grids_Stats stats, int chunkNRows, int chunkNCols,
long nRows, long nCols, Grids_Dimensions dimensions) {
this.nRows = nRows;
this.nCols = nCols;
dim = dimensions;
init(stats, chunkNRows, chunkNCols);
}
protected void init(Grids_Grid g, Grids_Stats stats, int chunkNRows,
int chunkNCols, long startRow, long startCol, long endRow,
long endCol) {
nRows = endRow - startRow + 1;
nCols = endCol - startCol + 1;
initDimensions(g, startRow, startCol);
init(stats, chunkNRows, chunkNCols);
}
/**
* Sets the references to this in the chunks.
*/
protected void setReferenceInChunks() {
Iterator ite = data.keySet().iterator();
while (ite.hasNext()) {
data.get(ite.next()).initGrid(this);
}
}
/**
* @return A set of all chunk IDs.
*/
public Set getChunkIDs() {
return data.keySet();
}
/**
* Override to provide a more detailed fields description.
*
* @return A text description of the fields of this.
*/
public String getFieldsDescription() {
String r = "chunkNcols=" + chunkNCols + ", ";
r += "chunkNrows=" + chunkNRows + ", ";
r += "nChunkCols=" + nChunkCols + ", ";
r += "nChunkRows=" + nChunkRows + ", ";
r += "nCols=" + nCols + ", ";
r += "nRows=" + nRows + ", ";
r += "fs=" + fs.toString() + ", ";
r += "id=" + fsID + ", ";
r += "name=" + name + ", ";
r += "dimensions=" + getDimensions().toString() + ", ";
if (data == null) {
r += "data=null, ";
} else {
r += "data.size()=" + data.size() + ", ";
}
Set grids = env.getGrids();
if (grids == null) {
r += "grids=null, ";
} else {
r += "grids.size()=" + grids.size() + ", ";
}
r += getStats().toString();
return r;
}
/**
* @return A text description of this.
*/
@Override
public String toString() {
return getClass().getSimpleName() + "[" + getFieldsDescription() + "]";
}
/**
* @return The path to the directory in {@link #fs} where this is currently
* stored.
*/
public Generic_Path getDirectory() {
return new Generic_Path(fs.getPath(fsID));
}
/**
* @return {@link #name}
*/
public String getName() {
return name;
}
/**
* Sets {@link #name} to {@code name}.
*
* @param name What {@link #name} is set to.
*/
public void setName(String name) {
this.name = name;
}
/**
* @return {@link #nCols}
*/
public final long getNCols() {
return nCols;
}
/**
* @return {@link #nRows}.
*/
public final long getNRows() {
return nRows;
}
/**
* @return {@link #nChunkRows}
*/
public final int getNChunkRows() {
return nChunkRows;
}
/**
* Initialises NChunkRows.
*/
protected final void initNChunkRows() {
long cnr = (long) chunkNRows;
if ((nRows % cnr) != 0) {
nChunkRows = (int) (nRows / cnr) + 1;
} else {
nChunkRows = (int) (nRows / cnr);
}
}
/**
* @return {@link #nChunkCols}.
*/
public final int getNChunkCols() {
return nChunkCols;
}
/**
* @return the number of chunks in this as a long.
* @throws java.lang.Exception If the number of chunks is greater than
* {@link Integer#MAX_VALUE}.
*/
public final long getNChunks() throws Exception {
long nChunks = (long) nChunkRows * (long) nChunkCols;
if (nChunks > Integer.MAX_VALUE) {
throw new Exception("Error nChunks > Integer.MAX_VALUE");
}
return nChunks;
}
/**
* Initialises NChunkCols.
*/
protected final void initNChunkCols() {
long cnc = (long) this.chunkNCols;
if ((nCols % cnc) != 0) {
nChunkCols = (int) (nCols / cnc) + 1;
} else {
nChunkCols = (int) (nCols / cnc);
}
}
/**
* @return {@link #chunkNRows}
*/
public final int getChunkNRows() {
return chunkNRows;
}
/**
* @param cr The chunk row for which the number of rows of cells in the
* chunk is returned.
* @return The number of rows of cells in the chunks in the chunk row
* indexed by {@code cr}.
*/
public final int getChunkNRows(int cr) {
if (cr > -1 && cr < nChunkRows) {
if (cr == (nChunkRows - 1)) {
return getChunkNRowsFinalRowChunk();
} else {
return chunkNRows;
}
} else {
return 0;
}
}
/**
* @return {@link #chunkNCols}
*/
public final int getChunkNCols() {
return chunkNCols;
}
/**
* @param cc The chunk column for which the number of columns of cells in
* the chunks is returned.
* @return The number of columns of cells in the chunks in the chunk column
* indexed by {@code cc}.
*/
public final int getChunkNCols(int cc) {
if (cc > -1 && cc < nChunkCols) {
if (cc == (nChunkCols - 1)) {
return getChunkNColsFinalColChunk();
} else {
return chunkNCols;
}
} else {
return 0;
}
}
/**
* @return The number of rows of cells in the chunks in the final row of
* chunks.
*/
public final int getChunkNRowsFinalRowChunk() {
return (int) (nRows - ((long) (nChunkRows - 1) * (long) chunkNRows));
}
/**
* @return The number of columns of cells in the chunks in the final column
* of chunks.
*/
public final int getChunkNColsFinalColChunk() {
return (int) (nCols - ((long) (nChunkCols - 1) * (long) chunkNCols));
}
/**
* @return The number of rows in chunk with ID {@code i}.
* @param i The ID of the chunk for which the number of rows in that chunk
* is returned.
*/
public final int getChunkNRows(Grids_2D_ID_int i) {
if (i.getRow() < (nChunkRows - 1)) {
return chunkNRows;
} else {
return getChunkNRowsFinalRowChunk();
}
}
/**
* @return The number of columns in chunk with ID {@code i}.
* @param i The ID of the chunk for which the number of columns in that
* chunk is returned.
*/
public final int getChunkNCols(Grids_2D_ID_int i) {
if (i.getCol() < (nChunkCols - 1)) {
return chunkNCols;
} else {
return getChunkNColsFinalColChunk();
}
}
/**
* @return the Dimensions
*/
public Grids_Dimensions getDimensions() {
return dim;
}
/**
* This method is for convenience.
*
* @return {@code dim.getCellsize()}.
*/
public final BigDecimal getCellsize() {
return dim.getCellsize();
}
/**
* @param distance The length of a straight line for which the cell distance
* is returned.
* @return An integer value equal to the number of cells in a vertical or
* horizontal direction that a line of distance would intersect. On the
* boundary is in.
*/
public final BigDecimal getCellDistance(BigDecimal distance) {
BigDecimal[] dar = distance.divideAndRemainder(getCellsize());
BigDecimal r = dar[0];
if (dar[1].compareTo(BigDecimal.ZERO) == 1) {
r = r.add(BigDecimal.ONE);
}
return r;
}
/**
* @return Set of chunk IDs for cells that's centroids are intersected by
* circle with centre at x-coordinate x, y-coordinate y, and radius
* distance.
* @param distance The radius of the circle for which intersecting chunk IDs
* are returned.
* @param x The x-coordinate of the circle centre from which cell values are
* returned.
* @param y The y-coordinate of the circle centre from which cell values are
* returned.
* @param row The row index at y.
* @param col The col index at x.
* @param dp The decimal places for the distance calculations.
* @param rm The RoundingMode for the distance calculations.
*/
public Set getChunkIDs(BigDecimal distance,
BigDecimal x, BigDecimal y, long row, long col, int dp,
RoundingMode rm) {
Set r = new HashSet<>();
long delta = distance.divideToIntegralValue(getCellsize())
.longValueExact();
for (long p = -delta; p <= delta; p++) {
BigDecimal cellY = getCellY(row + p);
for (long q = -delta; q <= delta; q++) {
BigDecimal cellX = getCellX(col + q);
BigDecimal d2 = Grids_Utilities.distance(cellX, cellY, x, y,
dp, rm);
if (d2.compareTo(distance) == -1) {
r.add(new Grids_2D_ID_int(getChunkRow(row + p),
getChunkCol(col + q)));
}
}
}
return r;
}
/**
* This is for getting all the chunk IDs between (rowMin, colMin) and
* (rowMax, colMax). This way returns a subset of keys from {@link #data}.
*
* @return A set of chunk identifiers for all chunks in the range given by
* rowMin, rowMax, colMin, colMax.
*
* @param rowMin The minimum end of the row range.
* @param rowMax The maximum end of the row range.
* @param colMin The minimum end of the column range.
* @param colMax The maximum end of the column range.
*/
public Set getChunkIDs(long rowMin, long rowMax,
long colMin, long colMax) {
return getChunkIDs(getChunkRow(rowMin), getChunkRow(rowMax),
getChunkCol(colMin), getChunkCol(colMax));
// This implementation creates new Grids_2D_ID_int instances.
// Set r = new HashSet<>();
// int cnr = getChunkNRows();
// int cnc = getChunkNCols();
// for (long row = rowMin; row <= rowMax; row += cnr) {
// int cr = getChunkRow(row);
// for (long col = colMin; col <= colMax; col += cnc) {
// int cc = getChunkCol(col);
// r.add(new Grids_2D_ID_int(cr, cc));
// }
// }
// return r;
}
/**
* This is for getting all the chunk IDs between (crMin, ccMin) and (crMax,
* ccMax). This way returns a subset of keys from {@link #data}.
*
* @return A set of chunk identifiers for all chunks in the range given by
* crMin, crMax, ccMin, ccMax.
*
* @param crMin The minimum chunk row.
* @param crMax The maximum chunk row.
* @param ccMin The minimum chunk column.
* @param ccMax The maximum chunk column.
*/
public Set getChunkIDs(int crMin, int crMax, int ccMin,
int ccMax) {
return data.keySet().parallelStream()
.filter(i -> i.getRow() >= crMin)
.filter(i -> i.getRow() <= crMax)
.filter(i -> i.getCol() >= ccMin)
.filter(i -> i.getCol() <= ccMax).collect(Collectors.toSet());
// // This implementation creates new Grids_2D_ID_int instances.
// Set r = new HashSet<>();
// for (int cr = crMin; cr <= crMax; cr++) {
// for (int cc = ccMin; cc <= ccMax; cc++) {
// r.add(new Grids_2D_ID_int(cr, cc));
// }
// }
// return r;
}
/**
* @return Chunk column index for the chunks intersecting the line
* x-coordinate x.
* @param x The x-coordinate of the line intersecting the chunk column index
* returned.
*/
public final int getChunkCol(BigDecimal x) {
return getChunkCol(getCol(x));
}
/**
* @return Chunk column index for the Grids_Chunk intersecting the cell
* column index {@code col}.
*
* @param col The cell column index.
*/
public final int getChunkCol(long col) {
return (int) (col / (long) chunkNCols);
}
/**
* @return Chunk cell column index of the cells that intersect the line
* {@code x}.
* @param x The x-coordinate of the line intersecting the chunk cell column
* index returned.
*/
public final int getChunkCellCol(BigDecimal x) {
return getChunkCellCol(getCol(x));
}
/**
* @return Chunk cell column index of the cells in the grid column
* {@code col}.
* @param col The column in the grid for which the chunk cell row index is
* returned.
*/
public final int getChunkCellCol(long col) {
return (int) (col - (getChunkCol(col) * chunkNCols));
}
/**
* @return Chunk cell row index of the cells that intersect the line y.
* @param y The y-coordinate of the line for which the chunk cell row index
* is returned.
*/
public final int getChunkCellRow(BigDecimal y) {
return getChunkCellRow(getRow(y));
}
/**
* @return Chunk cell row index of the cells in the grid row {@code row}.
* @param row The row in the grid for which the chunk cell row index is
* returned.
*/
public final int getChunkCellRow(long row) {
return (int) (row - (getChunkRow(row) * chunkNRows));
}
/**
* @param x The x-coordinate.
* @return Cell column of the cells that intersect line {@code x}.
*/
public final long getCol(BigDecimal x) {
Grids_Dimensions d = getDimensions();
BigDecimal dx = x.subtract(d.getXMin());
long r = dx.divideToIntegralValue(d.getCellsize()).longValueExact();
if (dx.compareTo(BigDecimal.ZERO) == -1) {
return r - 1L;
} else {
return r;
}
}
/**
* Get the cell column.
*
* @param cc The chunk column.
* @param ccc The chunk cell column.
* @return {@code ((long) cc * (long) chunkNCols) + (long) ccc}
*/
public final long getCol(int cc, int ccc) {
return ((long) cc * (long) chunkNCols) + (long) ccc;
}
/**
* @return Chunk row index for the chunks intersecting the line given by
* y-coordinate y.
* @param y The y-coordinate of the line for which the chunk row index is
* returned.
*/
public final int getChunkRow(BigDecimal y) {
return getChunkRow(getRow(y));
}
/**
* @return Chunk row index for the chunk intersecting the cells with cell
* row index {@code row}.
* @param row The cell row of the cells that's chunk row index is returned.
*/
public final int getChunkRow(long row) {
return (int) (row / (long) chunkNRows);
}
/**
* @param y The y axis coordinate.
* @return Cell row of the cells that intersect the y axis coordinate y.
*/
public final long getRow(BigDecimal y) {
Grids_Dimensions d = getDimensions();
BigDecimal dy = y.subtract(d.getYMin());
long r = dy.divideToIntegralValue(d.getCellsize()).longValueExact();
if (dy.compareTo(BigDecimal.ZERO) == -1) {
return r - 1L;
} else {
return r;
}
}
/**
* Get the cell row.
*
* @param cr The chunk row.
* @param ccr The cell row in the chunk.
* @return {@code ((long) cr * (long) chunkNRows) + (long) ccr}
*/
public final long getRow(int cr, int ccr) {
return ((long) cr * (long) chunkNRows) + (long) ccr;
}
/**
* A new cell ID for the cell given by cell row index {@code row}, cell
* column index {@code col}. An ID is returned even if that cell would not
* be in the grid.
*
* @param row The cell row index.
* @param col The cell column index.
* @return A new cell ID for the cell given by cell row index {@code row}.
*/
public final Grids_2D_ID_long getCellID(long row, long col) {
return new Grids_2D_ID_long(row, col);
}
/**
* A new cell ID for the x-coordinate {@code x}, y-coordinate {@code y}. An
* ID is returned even if that cell would not be in the grid.
*
* @return A new cell ID for the x-coordinate {@code x}, y-coordinate
* {@code y}.
* @param x The x-coordinate.
* @param y The y-coordinate.
*/
public final Grids_2D_ID_long getCellID(BigDecimal x, BigDecimal y) {
return new Grids_2D_ID_long(getRow(y), getCol(x));
}
/**
* Attempts to write this instance to a file.
*
* @throws java.io.IOException If encountered.
*/
public void cache() throws IOException, Exception {
swapChunks();
Generic_IO.writeObject(this, getPathThisFile(getDirectory()));
}
/**
* Attempts to swap a chunk in {@link #data} from {@link #worthSwapping}.
* This method does not consider those chunks in {@link #env}.notToClear.
*
* @return The chunk ID of the chunk that was cleared or {@code null} if no
* chunk was cleared.
* @throws java.io.IOException If encountered.
*/
public final Grids_2D_ID_int swapChunk() throws IOException, Exception {
if (worthSwapping.isEmpty()) {
return null;
}
Grids_2D_ID_int i = worthSwapping.stream().findAny().get();
swapChunk(i); // This removes i from worthSwapping.
return i;
}
/**
* Attempts to swap a chunk in {@link #data} that is in
* {@link #worthSwapping} and {@code s}.This method does not consider those
* chunks in {@link #env}.notToClear.
*
* @param s The set of chunk IDs for which one chunk may be cleared.
* @return The chunk ID of the chunk that was cleared or {@code null} if no
* chunk was cleared.
* @throws java.io.IOException If encountered.
*/
public final Grids_2D_ID_int swapChunk(Set s)
throws IOException, Exception {
if (worthSwapping.isEmpty()) {
return null;
}
Set s2 = worthSwapping.stream().filter(i
-> s.contains(i)).collect(Collectors.toSet());
Iterator ite = s2.iterator();
while (ite.hasNext()) {
Grids_2D_ID_int i = ite.next();
if (swapChunk(i)) {
return i;
}
}
return null;
}
/**
* Attempts to cache the chunk with chunk ID {@code i} if there is not
* already an up-to-date cache.
*
* @param i The chunk ID of the chunk to be cached.
* @return True if Grids_Chunk on file is up to date.
* @throws java.io.IOException If encountered.
*/
public final boolean cache(Grids_2D_ID_int i) throws IOException,
Exception {
boolean r = true;
Grids_Chunk c = data.get(i);
if (c != null) {
if (!c.isCacheUpToDate()) {
Path file = Paths.get(getDirectory().toString(),
i.getRow() + "_" + i.getCol());
//Files.createDirectory(file.getParent());
Generic_IO.writeObject(c, file);
//System.gc();
c.setCacheUpToDate(true);
}
} else {
r = false;
}
return r;
}
/**
* Attempts to swap chunks that have a chunk ID in {@code s}.
*
* @param s A Set containing the chunk IDs of the chunks to swap.
* @return The number of chunks swapped.
*/
public final int swapChunks(Set s) {
return worthSwapping.parallelStream().filter(i -> s.contains(i))
.collect(Collectors.summingInt((Grids_2D_ID_int i) -> {
try {
if (swapChunk(i)) {
return 1;
}
} catch (Exception ex) {
ex.printStackTrace(System.err);
env.env.log(ex.getMessage());
}
return 0;
}));
// int r = 0;
// Iterator ite = s.iterator();
// while (ite.hasNext()) {
// Grids_2D_ID_int cid = ite.next();
// if (isWorthCaching(cid)) {
// if (cache(cid)) {
// r ++;
// }
// }
// }
// return r;
}
/**
* Attempts to swap a chunk and return the details of any swapping done.
*
* @param hoome If {@code true} then if in the initial attempt to swap a
* chunk an OutOfMemoryError is thrown, then an attempt to handle this is
* made by: clearing the memory reserve, caching a chunk from this grid, and
* re-initialising the memory reserve (which may involve swapping out chunks
* from other grids and perhaps also swapping out other data). If false then
* OutOfMemoryErrors are caught and thrown.
* @return A detailed account of what was swapped.
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public Grids_AccountDetail swapChunk_AccountDetail(boolean hoome)
throws IOException, Exception {
try {
Grids_AccountDetail r = swapChunk_AccountDetail();
r.add(env.checkAndMaybeFreeMemory_AccountDetail(hoome));
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_AccountDetail r = swapChunk_AccountDetail();
if (r.detail.isEmpty()) {
throw e;
}
r.add(env.initMemoryReserve_AccountDetail(hoome));
r.add(swapChunk_AccountDetail(hoome));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap a chunk and return the details of any swapping done.
*
* @return A detailed account of what was swapped.
* @throws java.io.IOException If encountered.
*/
public Grids_AccountDetail swapChunk_AccountDetail() throws IOException,
Exception {
Grids_AccountDetail r = new Grids_AccountDetail();
Grids_2D_ID_int i = swapChunk();
if (i != null) {
Set s = new HashSet<>(1);
clearChunk(i);
s.add(i);
r.detail.put(this, s);
}
return r;
}
/**
* Attempts to cache a chunk and return the id of the chunk cached. This is
* one of the lowest level memory handling operation of this class.
*
* @param camfm If {@code true} check and maybe free memory.
* @param hoome If {@code true} then an attempt is made to handle an
* OutOfMemoryErrors encountered by swapping data.
* @return An account of what was cached.
* @throws java.io.IOException If encountered.
*/
public Grids_2D_ID_int swapChunk_AccountChunk(boolean camfm, boolean hoome)
throws IOException, Exception {
try {
Grids_2D_ID_int r = swapChunk_AccountChunk();
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_2D_ID_int r = swapChunk_AccountChunk();
if (r == null) {
if (!env.swapChunk(env.HOOMEF)) {
throw e;
}
}
env.initMemoryReserve(env.env);
return swapChunk_AccountChunk(camfm, hoome);
} else {
throw e;
}
}
}
/**
* Attempt to swap a chunk and return it's ID.
*
* @return An account of what was swapped.
* @throws java.io.IOException If encountered.
*/
public Grids_2D_ID_int swapChunk_AccountChunk() throws IOException, Exception {
Grids_2D_ID_int i = swapChunk();
if (i != null) {
clearChunk(i);
}
return i;
}
/**
* Swap all chunks.
*
* @return An account of what was cached.
* @throws Exception If encountered.
* @throws IOException If encountered.
*/
public Grids_Account swapChunks_Account() throws IOException, Exception {
Grids_Account r = new Grids_Account();
for (int cri = 0; cri < nChunkRows; cri++) {
for (int cci = 0; cci < nChunkCols; cci++) {
if (swapChunk(new Grids_2D_ID_int(cri, cci))) {
r.add();
}
}
}
return r;
}
/**
* Swap chunks in {@code s}.
*
* @param s A set of chunk IDs of chunks to swap.
* @return An account of any swapping
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public Grids_Account swapChunks_Account(Set s)
throws IOException, Exception {
Grids_Account r = new Grids_Account();
Iterator ite = s.iterator();
while (ite.hasNext()) {
if (swapChunk(ite.next())) {
r.add();
}
}
return r;
}
/**
* @param s A set of chunk IDs of chunks no to swap.
* @param camfm If {@code true} check and maybe free memory.
* @param hoome If {@code true} then an attempt is made to handle an
* OutOfMemoryErrors encountered by swapping data.
* @return Chunk ID of any swapped chunk or {@code null}.
* @throws IOException If encountered.
*/
public Grids_2D_ID_int swapChunkExcept_AccountChunk(
Set s, boolean camfm,
boolean hoome) throws IOException, Exception {
try {
Grids_2D_ID_int r = swapChunkExcept_AccountChunk(s);
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_2D_ID_int r = swapChunkExcept_AccountChunk(s);
if (r == null) {
if (!env.swapChunk(env.HOOMEF)) {
throw e;
}
}
env.initMemoryReserve(env.env);
return r;
} else {
throw e;
}
}
}
/**
* Swap a chunk except a chunk with chunk ID in {@code s}.
*
* @param s The set with chunk IDs not to swap.
* @return The chunk ID of any chunk swapped.
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public Grids_2D_ID_int swapChunkExcept_AccountChunk(
Set s) throws IOException, Exception {
Iterator ite = worthSwapping.iterator();
while (ite.hasNext()) {
Grids_2D_ID_int i = ite.next();
if (!s.contains(i)) {
cache(i);
clearChunk(i);
return i;
}
}
// for (chunkRow = 0; chunkRow < NChunkRows; chunkRow++) {
// for (chunkCol = 0; chunkCol < NChunkCols; chunkCol++) {
// chunkID = new Grids_2D_ID_int(chunkRow, chunkCol);
// if (!chunkIDs.contains(chunkID)) {
// if (isWorthCaching(chunkID)) {
// swapChunk(chunkID);
// clearChunk(chunkID);
// return chunkID;
// }
// }
// }
// }
return null;
}
/**
* @param i The chunk ID of the chunk to test if it is of a singlet type.
* @return {@code true} if chunk is of a singlet type.
*/
public boolean isChunkSingleValueChunk(Grids_2D_ID_int i) {
return data.get(i) instanceof Grids_ChunkDoubleSinglet
|| data.get(i) instanceof Grids_ChunkIntSinglet;
}
/**
* Caches the chunk with chunk ID {@code i} to file.
*
* @param i The chunk ID.
* @param camfm If {@code true} check and maybe free memory.
* @param hoome If {@code true} then an attempt is made to handle an
* OutOfMemoryErrors encountered by swapping data.
* @throws java.io.IOException If encountered.
*/
public void swap(Grids_2D_ID_int i, boolean camfm, boolean hoome)
throws IOException, Exception {
try {
swapChunk(i);
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
freeSomeMemoryAndResetReserve(i, e);
swap(i, camfm, hoome);
} else {
throw e;
}
}
}
/**
* Checks the chunk with chunk ID {@code i}. If there is not already an up
* to date cache then it is cached. If the chunk is cached, then it is
* cleared from memory.
*
* @param i The chunk ID of the chunk to cache (if the cache is not already
* up to date) and anyway clear.
* @return {@code 1} if a chunk is cleared and {@code 0} otherwise.
* @throws java.io.IOException If encountered.
*/
public boolean swapChunk(Grids_2D_ID_int i) throws IOException,
Exception {
if (cache(i)) {
clearChunk(i);
return true;
}
return false;
}
/**
* Attempts to write to file and clear from the cache any chunk in this.This
* is one of the lowest level memory handling operation of this class.
*
* @param camfm If {@code true} check and maybe free memory.
* @param hoome If {@code true} then an attempt is made to handle an
* OutOfMemoryErrors encountered by swapping data.
* @return Chunk ID of a swapped chunk.
* @throws java.io.IOException If encountered.
*/
public Grids_2D_ID_int swapChunk(boolean camfm, boolean hoome) throws IOException,
Exception {
try {
Grids_2D_ID_int r = swapChunk();
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
freeSomeMemoryAndResetReserve(e);
return swapChunk(camfm, hoome);
} else {
throw e;
}
}
}
/**
* Attempts to write to file and clear from the cache a Grids_Chunk in
* this._AbstractGrid2DSquareCell_Set.
*
* @param cid A chunk id of a chunk not to be cached
* @param camfm checkAndMaybeFreeMemory
* @param hoome If true then OutOfMemoryErrors are caught, cache operations
* are initiated, then the method is re-called. If false then
* OutOfMemoryErrors are caught and thrown.
* @return The Grids_2D_ID_int of Grids_Chunk cached or null.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
*/
public Grids_AccountDetail swapChunkExcept_AccountDetail(Grids_2D_ID_int cid, boolean camfm,
boolean hoome) throws IOException, Exception {
try {
Grids_AccountDetail r = swapChunkExcept_AccountDetail(cid);
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_AccountDetail r = swapChunkExcept_AccountDetail(cid);
if (r.detail.isEmpty()) {
r.add(env.swapChunkExcept_AccountDetail(this, cid, false));
}
r.add(env.initMemoryReserve_AccountDetail(this, cid, hoome));
r.add(swapChunkExcept_AccountDetail(cid));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to cache a chunk and make it available for garbage collection.
*
* @param chunkID The id of a chunk not to swap out.
* @return The chunk ids of chunks swapped out or {@code null} if no chunks
* were made available for garbage collection.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
*/
public Grids_AccountDetail swapChunkExcept_AccountDetail(Grids_2D_ID_int chunkID)
throws IOException, Exception {
Grids_AccountDetail r = new Grids_AccountDetail();
for (int cri = 0; cri < nChunkRows; cri++) {
for (int cci = 0; cci < nChunkCols; cci++) {
Grids_2D_ID_int bid = new Grids_2D_ID_int(cri, cci);
if (!bid.equals(chunkID)) {
if (isWorthCaching(bid)) {
cache(bid);
clearChunk(bid);
Set chunks;
chunks = new HashSet<>(1);
chunks.add(bid);
r.detail.put(this, chunks);
return r;
}
}
}
}
return r;
}
/**
* @param cid The id of the chunk not to swap out.
* @param camfm If true then there is a further attempt to check and maybe
* free memory once a chunk is swapped out or otherwise cleared from memory.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return The chunk id of the chunk swapped out.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public Grids_2D_ID_int swapChunkExcept_AccountChunk(
Grids_2D_ID_int cid, boolean camfm, boolean hoome)
throws IOException, Exception {
try {
Grids_2D_ID_int r = swapChunkExcept_AccountChunk(cid);
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_2D_ID_int r = swapChunkExcept_AccountChunk(cid);
if (r == null) {
if (env.swapChunkExcept_Account(this, cid, false, false).detail < 1L) {
throw e;
}
}
env.initMemoryReserve(this, cid, hoome);
return r;
} else {
throw e;
}
}
}
/**
* @param cid The id of the chunk not to swap out.
* @return The chunk id of the chunk swapped out.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public Grids_2D_ID_int swapChunkExcept_AccountChunk(
Grids_2D_ID_int cid) throws IOException, Exception {
for (int cri = 0; cri < nChunkRows; cri++) {
for (int cci = 0; cci < nChunkCols; cci++) {
Grids_2D_ID_int r = new Grids_2D_ID_int(cri, cci);
if (!r.equals(cid)) {
if (isWorthCaching(r)) {
cache(r);
clearChunk(r);
return r;
}
}
}
}
return null;
}
/**
* Attempts to swap out or clear from memory all chunks in this except that
* with ID {@code i}.
*
* @param i The ID of a chunk not to clear from memory.
* @param camfm If true then there is a further attempt to check and maybe
* free memory once a chunk is swapped out or otherwise cleared from memory.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return The number of chunks cached.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final Grids_AccountDetail swapChunksExcept_AccountDetail(Grids_2D_ID_int i, boolean camfm,
boolean hoome) throws IOException, Exception {
try {
Grids_AccountDetail r = swapChunksExcept_AccountDetail(i);
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_AccountDetail r = swapChunkExcept_AccountDetail(i);
if (r.detail.isEmpty()) {
r = env.swapChunkExcept_AccountDetail(this, i, false);
if (r.detail.isEmpty()) {
throw e;
}
}
r.add(env.initMemoryReserve_AccountDetail(this, i, hoome));
r.add(swapChunksExcept_AccountDetail(i, camfm, hoome));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap out or clear from memory all chunks in this except that
* with ID {@code i}.
*
* @param i The id of a chunk not to clear from memory.
* @return Details of which chunks have been cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
*/
public final Grids_AccountDetail swapChunksExcept_AccountDetail(
Grids_2D_ID_int i) throws IOException, Exception {
Grids_AccountDetail r = new Grids_AccountDetail();
Set s = new HashSet<>();
for (int chunkRow = 0; chunkRow < nChunkRows; chunkRow++) {
for (int chunkCol = 0; chunkCol < nChunkCols; chunkCol++) {
Grids_2D_ID_int i2 = new Grids_2D_ID_int(chunkRow, chunkCol);
if (!i.equals(i2)) {
if (isWorthCaching(i2)) {
cache(i2);
clearChunk(i2);
s.add(i2);
}
}
}
}
r.detail.put(this, s);
return r;
}
/**
* Swap out or clear from memory all chunks in this that are in
* {@link #worthSwapping}.
*/
public void swapChunks() {
worthSwapping.parallelStream().forEach(i -> {
try {
swapChunk(i);
} catch (Exception ex) {
ex.printStackTrace(System.err);
env.env.log(ex.getMessage());
}
});
}
/**
* Attempts to swap out or clear from memory all chunks in this except those
* with IDs in {@code s}.
*
* @param s The set of IDs of chunks not to clear from memory.
* @param camfm If true then there is a further attempt to check and maybe
* free memory once a chunk is swapped out or otherwise cleared from memory.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return The number of chunks cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public Grids_Account swapChunksExcept_Account(Set s,
boolean camfm, boolean hoome) throws IOException, Exception {
try {
Grids_Account r = new Grids_Account();
r.add(swapChunksExcept(s));
if (camfm) {
r.add(env.checkAndMaybeFreeMemory_Account(hoome));
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_Account r = env.swapChunkExcept_Account(this, s, false);
if (r.detail == 0) {
throw e;
}
r.add(env.initMemoryReserve_Account(this, s, hoome));
r.add(swapChunksExcept_Account(s, camfm, hoome));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap out or clear from memory all chunks in this except those
* with IDs in {@code s}.
*
* @param s The set of IDs of chunks not to clear from memory.
* @param camfm If true then there is a further attempt to check and maybe
* free memory once a chunk is swapped out or otherwise cleared from memory.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return Details of which chunks have been cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final Grids_AccountDetail swapChunksExcept_AccountDetail(
Set s,
boolean camfm, boolean hoome) throws IOException,
Exception {
try {
Grids_AccountDetail r = new Grids_AccountDetail();
swapChunksExcept(s, r);
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_AccountDetail r = swapChunkExcept_AccountDetail(s);
if (r.detail.isEmpty()) {
env.addToNotToClear(this, s);
r = env.swapChunk_AccountDetail(env.HOOMEF);
if (r.detail.isEmpty()) {
throw e;
}
}
r.add(env.initMemoryReserve_AccountDetail(this, s, hoome));
r.add(swapChunksExcept_AccountDetail(s, camfm, hoome));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap out or clear from memory all chunks in this except those
* with IDs in {@code s}.
*
* @param s The set of IDs of chunks not to clear from memory.
* @param a An account for adding details of which chunks have been cleared.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
*/
public final void swapChunksExcept(Set s, Grids_AccountDetail a)
throws IOException, Exception {
Set s2 = new HashSet<>();
for (int cri = 0; cri < nChunkRows; cri++) {
for (int cci = 0; cci < nChunkCols; cci++) {
Grids_2D_ID_int i = new Grids_2D_ID_int(cri, cci);
if (!s.contains(i)) {
if (isWorthCaching(i)) {
cache(i);
clearChunk(i);
s2.add(i);
}
}
}
}
a.detail.put(this, s2);
}
/**
* Attempts to swap out or clear from memory a chunk in this except that
* with ID {@code i}.
*
* @param i The ID of the chunk not to clear from memory.
* @param camfm If true then there is a further attempt to check and maybe
* free memory once a chunk is swapped out or otherwise cleared from memory.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return The number of chunks cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final Grids_Account swapChunkExcept_Account(Grids_2D_ID_int i,
boolean camfm, boolean hoome) throws IOException, Exception {
try {
Grids_Account r = new Grids_Account();
if (swapChunkExcept(i)) {
r.add();
}
if (camfm) {
r.add(env.checkAndMaybeFreeMemory_Account(hoome));
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_Account r = env.swapChunkExcept_Account(this, i, false, false);
if (r.detail < 1) {
r = env.swapChunkExcept_Account(this, i, false, false);
if (r.detail < 1) {
throw e;
}
}
r.add(env.initMemoryReserve_Account(this, i, hoome));
r.add(swapChunksExcept_Account(i, camfm, hoome));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap out or clear from memory a chunk in this except that
* with ID {@code i}.
*
* @param i The ID of the chunk not to clear from memory.
* @return 1L if a chunk was cleared from memory and 0L otherwise.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
*/
public final boolean swapChunkExcept(Grids_2D_ID_int i)
throws IOException, Exception {
return swapChunk(worthSwapping.stream().filter(i2 -> i2 != i).findAny()
.get());
// for (int cri = 0; cri < nChunkRows; cri++) {
// for (int cci = 0; cci < nChunkCols; cci++) {
// Grids_2D_ID_int i2 = new Grids_2D_ID_int(cri, cci);
// if (!i.equals(i2)) {
// if (isWorthCaching(i2)) {
// cache(i2);
// clearChunk(i2);
// return 1;
// }
// }
// }
// }
// return 0;
}
/**
* Attempts to swap out or clear from memory all chunks in this except that
* with ID {@code i}.
*
* @param i The ID of the chunk not to clear from memory.
* @param camfm If {@code true} check and maybe free memory.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return The number of chunks cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final Grids_Account swapChunksExcept_Account(Grids_2D_ID_int i,
boolean camfm, boolean hoome)
throws IOException, Exception {
try {
Grids_Account r = new Grids_Account();
r.add(Grids_Grid.this.swapChunksExcept(i));
if (camfm) {
r.add(env.checkAndMaybeFreeMemory_Account(i, hoome));
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_Account r = env.swapChunkExcept_Account(this, i, false, false);
if (r.detail < 1) {
r = env.swapChunkExcept_Account(this, i, false, false);
if (r.detail < 1) {
throw e;
}
}
r.add(env.initMemoryReserve_Account(this, i, hoome));
r.add(swapChunksExcept_Account(i, camfm, hoome));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap out or clear from memory all chunks in this except that
* with ID {@code i}.
*
* @param i The ID of the chunk not to clear from memory.
* @return The number of chunks cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final int swapChunksExcept(Grids_2D_ID_int i)
throws IOException, Exception {
return worthSwapping.parallelStream().filter(i2 -> i2 != i)
.collect(Collectors.summingInt((Grids_2D_ID_int i2) -> {
try {
if (swapChunk(i2)) {
return 1;
}
} catch (Exception ex) {
ex.printStackTrace(System.err);
env.env.log(ex.getMessage());
}
return 0;
}));
// int r = 0;
// for (int cri = 0; cri < nChunkRows; cri++) {
// for (int cci = 0; cci < nChunkCols; cci++) {
// Grids_2D_ID_int id2 = new Grids_2D_ID_int(cri, cci);
// r += swapChunkExcept(i);
// if (i != id2) {
// if (isWorthCaching(i)) {
// cache(i);
// clearChunk(i);
// r++;
// }
// }
// }
// }
// return r;
}
/**
* Attempts to swap out or clear from memory all chunks in this except those
* with IDs in {@code s}.
*
* @param s The set of chunk IDs not to clear from memory.
* @return The number of chunks cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final int swapChunksExcept(Set s)
throws IOException, Exception {
return worthSwapping.parallelStream().filter(i2 -> !s.contains(i2))
.collect(Collectors.summingInt((Grids_2D_ID_int i2) -> {
try {
if (swapChunk(i2)) {
return 1;
}
} catch (Exception ex) {
ex.printStackTrace(System.err);
env.env.log(ex.getMessage());
}
return 0;
}));
// long r = 0L;
// for (int cri = 0; cri < nChunkRows; cri++) {
// for (int cci = 0; cci < nChunkCols; cci++) {
// Grids_2D_ID_int chunkID = new Grids_2D_ID_int(cri, cci);
// if (!s.contains(chunkID)) {
// if (isWorthCaching(chunkID)) {
// cache(chunkID);
// clearChunk(chunkID);
// r++;
// }
// }
// }
// }
// return r;
}
/**
* Attempts to swap out or clear from memory all chunks in this except those
* with IDs in {@code s}.
*
* @param s The set of chunk IDs not to clear from memory.
* @param camfm If true then there is a further attempt to check and maybe
* free memory once a chunk is swapped out or otherwise cleared from memory.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return Details of which chunks have been cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final Grids_AccountDetail swapChunkExcept_AccountDetail(Set s, boolean camfm,
boolean hoome) throws IOException, Exception {
try {
Grids_AccountDetail r = swapChunkExcept_AccountDetail(s);
if (camfm) {
env.checkAndMaybeFreeMemory(hoome);
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_AccountDetail r = swapChunkExcept_AccountDetail(s);
if (r == null) {
if (!env.swapChunk(env.HOOMEF)) {
throw e;
}
}
env.initMemoryReserve(env.env);
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap out or clear from memory all chunks in this except those
* with IDs in {@code s}.
*
* @param s The set of chunk IDs not to clear from memory.
* @return Details of which chunks have been cleared from memory.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final Grids_AccountDetail swapChunkExcept_AccountDetail(
Set s) throws IOException, Exception {
Grids_AccountDetail r = new Grids_AccountDetail();
for (int cri = 0; cri < nChunkRows; cri++) {
for (int cci = 0; cci < nChunkCols; cci++) {
Grids_2D_ID_int i = new Grids_2D_ID_int(cri, cci);
if (!s.contains(i)) {
if (isWorthCaching(i)) {
cache(i);
clearChunk(i);
r.detail.put(this, s);
return r;
}
}
}
}
return r;
}
/**
* Attempts to swap out or clear from memory all chunks in this.
*
* @param camfm If true then there is a further attempt to check and maybe
* free memory once a chunk is swapped out or otherwise cleared from memory.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return The number of chunks cleared.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
*/
public final Grids_AccountDetail swapChunks_AccountDetail(boolean camfm, boolean hoome)
throws IOException, Exception {
try {
Grids_AccountDetail r = swapChunks_AccountDetail();
if (camfm) {
r.add(env.checkAndMaybeFreeMemory_AccountDetail(hoome));
}
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
Grids_AccountDetail r = swapChunks_AccountDetail();
if (r.detail.isEmpty()) {
r = env.swapChunk_AccountDetail(false);
if (r.detail.isEmpty()) {
throw e;
}
}
r.add(env.initMemoryReserve_AccountDetail(hoome));
r.add(swapChunks_AccountDetail(camfm, hoome));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap out or clear from memory all chunks in this.
*
* @return Details of the chunks cleared.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
*/
public final Grids_AccountDetail swapChunks_AccountDetail()
throws IOException, Exception {
Grids_AccountDetail r = new Grids_AccountDetail();
Set s = new HashSet<>();
for (int cri = 0; cri < nChunkRows; cri++) {
for (int cci = 0; cci < nChunkCols; cci++) {
Grids_2D_ID_int i = new Grids_2D_ID_int(cri, cci);
if (isWorthCaching(i)) {
cache(i);
clearChunk(i);
s.add(i);
}
}
}
if (s.isEmpty()) {
return r;
}
r.detail.put(this, s);
return r;
}
/**
* Attempts to swap out or clear from memory all chunks in this from (cri0,
* cci0) to (cri1, cci1) in row major order.
*
* @param cri0 The chunk row index of the first chunk to be cleared.
* @param cci0 The chunk column index of the first chunk to be cleared.
* @param cri1 The chunk row index of the last chunk to be cleared.
* @param cci1 The chunk column index of the last chunk to be cleared.
* @param hoome If true then an attempt is made to handle any encountered
* {@link OutOfMemoryError}.
* @return The number of chunks cleared.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final Grids_Account swapChunks_Account(int cri0, int cci0, int cri1,
int cci1, boolean hoome) throws IOException, Exception {
try {
Grids_Account r = swapChunks_Account(cri0, cci0, cri1, cci1);
r.add(env.checkAndMaybeFreeMemory_Account(hoome));
return r;
} catch (OutOfMemoryError e) {
if (hoome) {
env.clearMemoryReserve(env.env);
if (swapChunk() == null) {
throw e;
}
Grids_Account r = new Grids_Account();
r.detail = 1L;
r.add(env.initMemoryReserve_Account(env.HOOMEF));
r.add(swapChunks_Account(cri0, cci0, cri1, cci1, hoome));
return r;
} else {
throw e;
}
}
}
/**
* Attempts to swap out or clear from memory all chunks in this from (cri0,
* cci0) to (cri1, cci1) in row major order.
*
* @param cri0 The chunk row index of the first chunk to be cleared.
* @param cci0 The chunk column index of the first chunk to be cleared.
* @param cri1 The chunk row index of the last chunk to be cleared.
* @param cci1 The chunk column index of the last chunk to be cleared.
* @return The number of chunks cached.
* @throws java.io.IOException If encountered.
* @throws java.lang.Exception If encountered.
* @throws OutOfMemoryError If this cannot be handled.
*/
public final Grids_Account swapChunks_Account(int cri0, int cci0, int cri1,
int cci1) throws IOException, Exception {
Grids_Account r = new Grids_Account();
if (cri0 != cri1) {
for (int cci = cci0; cci < nChunkCols; cci++) {
if (swapChunk(new Grids_2D_ID_int(cri0, cci))) {
r.add();
}
}
for (int cri = cri0 + 1; cri < cri1; cri++) {
for (int cci = 0; cci < nChunkCols; cci++) {
if (swapChunk(new Grids_2D_ID_int(cri0, cci))) {
r.add();
}
}
}
for (int cci = 0; cci < cci1; cci++) {
if (swapChunk(new Grids_2D_ID_int(cri0, cci))) {
r.add();
}
}
} else {
for (int cci = cci0; cci < cci1 + 1; cci++) {
if (swapChunk(new Grids_2D_ID_int(cri0, cci))) {
r.add();
}
}
}
return r;
}
/**
* @return {@code true} if the chunk with the chunk ID {@code i} is in the
* fast access memory.
* @param i The ID of the chunk tested as to whether it is in the fast
* access memory.
*/
public final boolean isLoaded(Grids_2D_ID_int i) {
return data.get(i) != null;
// return data.containsKey(chunkID);
}
/**
* @return {@code true} if the chunk given by chunk ID {@code i} is worth
* caching - as determined by whether it is a single .
* @param i The ID of the chunk tested as to whether it is worth caching.
*/
public final boolean isWorthCaching(Grids_2D_ID_int i) {
if (isLoaded(i)) {
return !isChunkSingleValueChunk(i);
}
return false;
}
/**
* For releasing a grid2DSquareCellChunk stored in memory. This is usually
* only done after the equivalent of cacheToFileChunk(ID) has been called.
*
* @param chunkID The Grids_2D_ID_int of the grid2DSquareCellChunk to be
* cleared.
*/
public final void clearChunk(Grids_2D_ID_int chunkID) {
data.replace(chunkID, null);
worthSwapping.remove(chunkID);
//System.gc();
}
/**
* Clear all chunks by setting them to null in {@link #data}.
*/
public final void clearChunks() {
data.keySet().parallelStream().forEach(i -> data.replace(i, null));
worthSwapping = new HashSet<>();
//System.gc();
}
/**
* @return a Grids_2D_ID_long[] - the cell IDs for cells thats centroids are
* intersected by circle with centre at x-coordinate x, y-coordinate y, and
* radius distance.
* @param x the x-coordinate of the circle centre from which cell values are
* returned.
* @param y the y-coordinate of the circle centre from which cell values are
* returned.
* @param distance the radius of the circle for which intersected cell
* values are returned.
* @param dp The decimal places for the distance calculations.
* @param rm The RoundingMode for the distance calculations.
*/
public final Grids_2D_ID_long[] getCellIDs(BigDecimal x, BigDecimal y,
BigDecimal distance, int dp, RoundingMode rm) {
return getCellIDs(x, y, getRow(y), getCol(x), distance, dp, rm);
}
/**
* @return The cell IDs that's centroids would be within a circle with
* radius distance centred at the centroid of the cell at row, col.
* @param row the row index for the cell that's centroid is the circle
* centre from which cell values are returned.
* @param col the column index for the cell that's centroid is the circle
* centre from which cell values are returned.
* @param distance the radius of the circle for which intersected cell
* values are returned.
* @param dp The decimal places for the distance calculations.
* @param rm The RoundingMode for the distance calculations.
*/
public final Grids_2D_ID_long[] getCellIDs(long row, long col,
BigDecimal distance, int dp, RoundingMode rm) {
return getCellIDs(getCellX(col), getCellY(row), row, col, distance, dp,
rm);
}
/**
* @return The cell IDs that's centroids would be within a circle with
* radius distance centred at x-coordinate x, y-coordinate y.
* @param x the x-coordinate of the circle centre from which cell values are
* returned.
* @param y the y-coordinate of the circle centre from which cell values are
* returned.
* @param row the row index at y.
* @param col the col index at x.
* @param distance the radius of the circle for which intersected cell
* values are returned.
* @param dp The decimal places for the distance calculations.
* @param rm The RoundingMode for the distance calculations.
*/
public Grids_2D_ID_long[] getCellIDs(BigDecimal x, BigDecimal y, long row,
long col, BigDecimal distance, int dp, RoundingMode rm) {
Grids_2D_ID_long[] r;
Set r2 = new HashSet<>();
long delta = distance.divideToIntegralValue(getCellsize()).longValueExact();
for (long p = -delta; p <= delta; p++) {
BigDecimal cellY = getCellY(row + p);
for (long q = -delta; q <= delta; q++) {
BigDecimal cellX = getCellX(col + q);
BigDecimal d2 = Grids_Utilities.distance(cellX, cellY, x, y,
dp, rm);
if (d2.compareTo(distance) == -1) {
r2.add(new Grids_2D_ID_long(row + p, col + q));
}
}
}
r = new Grids_2D_ID_long[r2.size()];
return r2.toArray(r);
}
/**
* @return Nearest cell ID to point at x-coordinate {@code x}, y-coordinate
* {@code y}.
* @param x The x-coordinate.
* @param y The y-coordinate.
*/
public Grids_2D_ID_long getNearestCellID(BigDecimal x, BigDecimal y) {
return getNearestCellID(x, y, getRow(y), getCol(x));
}
/**
* @return Nearest cell ID to cell row {@code r}, cell column {@code c}.
* @param r The cell row.
* @param c The cell column.
*/
public Grids_2D_ID_long getNearestCellID(long r, long c) {
return getNearestCellID(getCellX(c), getCellY(r), r, c);
}
/**
* @return Nearest cell ID to point given by x-coordinate x, y-coordinate y
* in cell row {@code r}, cell column {@code c}.
* @param x The x-coordinate.
* @param y The y-coordinate.
* @param row The cell row.
* @param col The cell column.
*/
public Grids_2D_ID_long getNearestCellID(BigDecimal x, BigDecimal y,
long row, long col) {
Grids_2D_ID_long cellID;
boolean isInGrid = isInGrid(x, y);
if (!isInGrid) {
long p;
long q;
if (x.compareTo(dim.getXMax()) >= 0) {
q = nCols - 1;
if (y.compareTo(dim.getYMax()) == 1) {
p = 0;
} else {
if (y.compareTo(dim.getYMin()) == -1) {
p = nRows - 1;
} else {
p = getRow(y);
}
}
} else {
if (x.compareTo(dim.getXMin()) == -1) {
q = 0;
if (y.compareTo(dim.getYMax()) >= 0) {
p = 0;
} else {
if (y.compareTo(dim.getYMin()) == -1) {
p = nRows - 1;
} else {
p = getRow(y);
}
}
} else {
q = getCol(x);
if (y.compareTo(dim.getYMax()) >= 0) {
p = 0;
} else {
p = nRows - 1;
}
}
}
cellID = new Grids_2D_ID_long(p, q);
} else {
cellID = new Grids_2D_ID_long(row, col);
}
return cellID;
}
/**
* @return Height of the grid.
*/
public final BigDecimal getHeight() {
return dim.getYMax().subtract(dim.getYMin());
}
/**
* @return Width of the grid.
*/
public final BigDecimal getWidth() {
return dim.getXMax().subtract(dim.getXMin());
}
/**
* For testing if two grids have the same dimensions and values.
*
* @param g The grid to test against.
* @return {@code true} if this is the same as {@code g} and false
* otherwise.
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public abstract boolean isSameDimensionsAndValues(Grids_Grid g) throws
IOException, Exception;
/**
* If the dimensions are the same, then so are the numbers of rows and
* columns.
*
* @param g The grid to compare with.
* @return {@code true} if this has the same dimensions as g.
*/
public boolean isSameDimensions(Grids_Grid g) {
return dim.equals(g.dim);
}
/**
* For finding out if grid {@code g} and this have the same dimensions and
* alignment of chunks.
*
* @param g A grid to compare.
* @return {@code true} if grid {@code g} and this have the same dimensions
* and alignment of chunks.
*/
public boolean isSameDimensionsAndChunks(Grids_Grid g) {
Grids_Dimensions gDim = g.getDimensions();
if (dim.equals(gDim)) {
if (chunkNRows == g.getChunkNRows()) {
if (chunkNCols == g.getChunkNCols()) {
if (nChunkRows == g.getNChunkRows()) {
if (nChunkCols == g.getNChunkCols()) {
return true;
}
}
}
}
}
return false;
}
/**
* Two grids are coincident if they overlap and have cells that are the same
* size and for those that overlap they have the same centroids.
*
* @param g The grid to test for coincidence.
* @return {@code true} if the two grids are coincident.
*/
public boolean isCoincident(Grids_Grid g) {
if (dim.getCellsize().compareTo(g.dim.getCellsize()) != 0) {
return false;
}
if (dim.equals(g.dim)) {
return true;
}
if (!dim.intersects(g.dim)) {
return false;
}
BigDecimal gXMin = g.dim.getXMin();
BigDecimal xMin = dim.getXMin();
if (xMin.compareTo(gXMin) == -1) {
BigDecimal x = xMin;
BigDecimal cs = dim.getCellsize();
do {
x = x.add(cs);
} while (x.compareTo(gXMin) == -1);
if (x.compareTo(gXMin) != 0) {
return false;
}
} else if (xMin.compareTo(gXMin) == 1) {
BigDecimal x = gXMin;
BigDecimal cs = dim.getCellsize();
do {
x = x.add(cs);
} while (x.compareTo(xMin) == -1);
if (x.compareTo(xMin) != 0) {
return false;
}
}
BigDecimal gYMin = g.dim.getYMin();
BigDecimal yMin = dim.getYMin();
if (yMin.compareTo(gYMin) == -1) {
BigDecimal y = yMin;
BigDecimal cs = dim.getCellsize();
do {
y = y.add(cs);
} while (y.compareTo(gYMin) == -1);
if (y.compareTo(gYMin) != 0) {
return false;
}
} else if (yMin.compareTo(gYMin) == 1) {
BigDecimal y = gYMin;
BigDecimal cs = dim.getCellsize();
do {
y = y.add(cs);
} while (y.compareTo(yMin) == -1);
if (y.compareTo(yMin) != 0) {
return false;
}
}
return true;
}
/**
* For finding out if point given by x-coordinate {@code x}, y-coordinate
* {@code y} is in this grid.
*
* @return {@code true} if point given by x-coordinate {@code x},
* y-coordinate {@code y} is in this grid. Anything on the boundary is
* considered to be in.
* @param x The x-coordinate of the point to test.
* @param y The y-coordinate of the point to test.
*/
public final boolean isInGrid(BigDecimal x, BigDecimal y) {
return x.compareTo(dim.getXMin()) != -1
&& y.compareTo(dim.getYMin()) != -1
&& x.compareTo(dim.getXMax()) != 1
&& y.compareTo(dim.getYMax()) != 1;
}
/**
* For finding out if the cell in row {@code r} and column {@code c} is in
* this grid.
*
* @param r The cell row to test.
* @param c The cell column to test.
* @return True if (row, col) in the Grid.
*/
public final boolean isInGrid(long r, long c) {
return r >= 0 && r < nRows && c >= 0 && c < nCols;
}
/**
* For finding out if the cell with cell ID {@code i} is in this grid.
*
* @param i The cell ID to test.
* @return {@code true} if cell with cell ID {@code i} is in the Grid.
*/
public final boolean isInGrid(Grids_2D_ID_long i) {
return isInGrid(i.getRow(), i.getCol());
}
/**
* For finding out if the chunk with chunk ID {@code i} is in this grid.
*
* @param i The chunk ID to test.
* @return True if chunk with ID {@code i} is in the Grid.
*/
public final boolean isInGrid(Grids_2D_ID_int i) {
return isInGrid(i.getRow(), i.getCol());
}
/**
* For finding out if the cell with chunk cell row {@code ccr} and chunk
* cell column {@code ccc} in chunk in chunk row {@code chunkRow} and chunk
* column {@code cc} is in the dimensions of this grid. This does not
* necessitate loading the chunk.
*
* @param cr The chunk row index to test.
* @param cc The chunk column index to test.
* @param ccr The row index in the chunk to test.
* @param ccc The column index in the chunk to test.
* @return {@code true} if cell with chunk cell row {@code ccr} and chunk
* cell column {@code ccc} in chunk in chunk row {@code chunkRow} and chunk
* column {@code cc} is in the dimensions of this grid.
*/
public final boolean isInGrid(int cr, int cc, int ccr, int ccc) {
return isInGrid(getRow(cr, ccr), getCol(cc, ccc));
}
/**
* @param col The cell col index for which the centroid x-coordinate is
* returned.
* @return The x-coordinate of the centroid of col as a BigDecimal.
*/
public final BigDecimal getCellX(long col) {
return dim.getXMin().add(dim.getCellsize().multiply(
BigDecimal.valueOf(col))).add(dim.getHalfCellsize());
}
/**
* @return The x-coordinate of the centroid for cell with cell with ID
* {@code i}.
* @param i The chunk ID.
*/
public final BigDecimal getCellX(Grids_2D_ID_long i) {
return getCellX(i.getCol());
}
/**
* @param row The cell row index for which the centroid y-coordinate is
* returned.
* @return The y-coordinate of the centroid for row as a BigDecimal.
*/
public final BigDecimal getCellY(long row) {
return dim.getYMin().add(dim.getCellsize().multiply(
BigDecimal.valueOf(row))).add(dim.getHalfCellsize());
}
/**
* @param i The cell ID for which the centroid x-coordinate is returned.
* @return The y-coordinate of the centroid of cell with cell ID {@code i}.
*/
public final BigDecimal getCellY(Grids_2D_ID_long i) {
return getCellY(i.getRow());
}
/**
* @param halfCellsize Half the grid cellsize.
* @return BigDecimal[] r where;
*
* - r[0] xmin, left most x-coordinate of cell that intersects point at
* (x,y)
* - r[1] ymin, lowest y-coordinate of cell that intersects point at
* (x,y)
* - r[2] xmax, right most x-coordinate of cell that intersects point at
* (x,y)
* - r[3] ymax, highest y-coordinate of cell that intersects point at
* (x,y).
*
* @param row The row index of the cell for which the bounds are returned.
* @param col The column index of the cell for which the bounds are
* returned.
*/
public final BigDecimal[] getCellBounds(BigDecimal halfCellsize,
long row, long col) {
BigDecimal[] r = new BigDecimal[4];
BigDecimal x = getCellX(col);
BigDecimal y = getCellY(row);
r[0] = x.subtract(halfCellsize);
r[1] = y.subtract(halfCellsize);
r[2] = x.add(halfCellsize);
r[3] = y.add(halfCellsize);
return r;
}
/**
* @return The next chunk ID to {@code i} in a row major order of chunk IDs,
* or {@code null}.
* @param i The chunkID of the current chunk in a row major order of chunks.
* @param ncr The number of chunk rows.
* @param ncc The number of chunk columns.
*/
public Grids_2D_ID_int getNextChunkID(Grids_2D_ID_int i, int ncr, int ncc) {
int r = i.getRow();
int c = i.getCol();
if (c < ncc - 1) {
return new Grids_2D_ID_int(r, c + 1);
} else {
if (r < ncr - 1) {
return new Grids_2D_ID_int(r + 1, 0);
}
}
return null;
}
/**
* @return The previous chunk ID to {@code i} in a row major order of chunk
* IDs, or {@code null}.
* @param i The chunkID of the current chunk in a row major order of chunks.
* @param ncr The number of chunk rows.
* @param ncc The number of chunk columns.
*/
public Grids_2D_ID_int getPreviousChunkID(Grids_2D_ID_int i, int ncr,
int ncc) {
int r = i.getRow();
int c = i.getCol();
if (c > 0) {
return new Grids_2D_ID_int(r, c - 1);
} else {
if (r > 0) {
return new Grids_2D_ID_int(r - 1, 0);
}
}
return null;
}
/**
* For freeing memory and resetting the memory reserve.
*
* @param notToClear Chunks not to clear in memory management.
* @param e An OutOfMemoryError that may get thrown.
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public void freeSomeMemoryAndResetReserve(
HashMap> notToClear,
OutOfMemoryError e) throws IOException, Exception {
Iterator ite = notToClear.keySet().iterator();
while (ite.hasNext()) {
Grids_Grid g = ite.next();
if (env.swapChunkExcept_Account(g, notToClear.get(g), false).detail > 0) {
env.initMemoryReserve(notToClear, env.HOOMET);
return;
}
}
throw e;
}
/**
* For freeing memory and resetting the memory reserve.
*
* @param cr Chunk row index of a chunk not to swap.
* @param cc Chunk column index of a chunk not to swap.
* @param e An OutOfMemoryError that may get thrown.
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public void freeSomeMemoryAndResetReserve(int cr, int cc,
OutOfMemoryError e) throws IOException, Exception {
//env.clearMemoryReserve(env.env);
freeSomeMemoryAndResetReserve(new Grids_2D_ID_int(cr, cc), e);
}
/**
* For freeing memory and resetting the memory reserve.
*
* @param s A set containing chunk IDs not to swap.
* @param e An OutOfMemoryError that may get thrown.
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public void freeSomeMemoryAndResetReserve(Set s,
OutOfMemoryError e) throws IOException, Exception {
if (env.swapChunkExcept_Account(this, s, false).detail < 1L) {
throw e;
}
env.initMemoryReserve(this, s, env.HOOMET);
}
/**
* For freeing memory and resetting the memory reserve.
*
* @param i Chunk ID of a chunk not to clear.
* @param e An OutOfMemoryError that may get thrown.
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public void freeSomeMemoryAndResetReserve(Grids_2D_ID_int i,
OutOfMemoryError e) throws IOException, Exception {
if (env.swapChunkExcept_Account(this, i, false, false).detail == 0) {
throw e;
}
env.initMemoryReserve(this, i, env.HOOMET);
}
/**
* For freeing memory and resetting the memory reserve.
*
* @param e An OutOfMemoryError that may get thrown.
* @throws IOException If encountered.
* @throws Exception If encountered.
*/
public void freeSomeMemoryAndResetReserve(OutOfMemoryError e)
throws IOException, Exception {
if (!env.swapChunk(env.HOOMEF)) {
throw e;
}
env.initMemoryReserve(env.env);
}
/**
* @return {@link #data}
*/
public TreeMap getData() {
return data;
}
/**
* Initialises {@link #dim} from {@code header}. This assumes that
* {@link #nRows} and {@link #nCols} are already initialised.
*
* @param header The header.
* @param r The start row index.
* @param c The start column index.
*/
public void initDimensions(Header header, long r, long c) {
BigDecimal cellsize = header.cellsize;
BigDecimal xMin = header.xll.add(cellsize.multiply(new BigDecimal(c)));
BigDecimal yMin = header.yll.add(cellsize.multiply(new BigDecimal(r)));
BigDecimal xMax = xMin.add(new BigDecimal(Long.toString(nCols))
.multiply(cellsize));
BigDecimal yMax = yMin.add(new BigDecimal(Long.toString(nRows))
.multiply(cellsize));
dim = new Grids_Dimensions(xMin, xMax, yMin, yMax, cellsize);
}
/**
* For initialising {@link #dim}. This assumes that {@link #nRows} and
* {@link #nCols} are already initialised.
*
* @param g The grid.
* @param r The start row index in {@code g}.
* @param c The start column index in {@code g}.
*/
public void initDimensions(Grids_Grid g, long r, long c) {
dim = g.getDimensions(); // temporary assignment
BigDecimal startColIndexBigDecimal = new BigDecimal(c);
BigDecimal startRowIndexBigDecimal = new BigDecimal(r);
BigDecimal nRowsBigDecimal = new BigDecimal(nRows);
BigDecimal nColsBigDecimal = new BigDecimal(nCols);
BigDecimal xMin;
BigDecimal yMin;
BigDecimal xMax;
BigDecimal yMax;
BigDecimal cellsize;
if (dim == null) {
cellsize = BigDecimal.ONE;
xMin = startColIndexBigDecimal;
yMin = startRowIndexBigDecimal;
xMax = xMin.add(nColsBigDecimal);
yMax = yMin.add(nRowsBigDecimal);
} else {
cellsize = dim.getCellsize();
xMin = dim.getXMin().add(startColIndexBigDecimal.multiply(cellsize));
yMin = dim.getYMin().add(startRowIndexBigDecimal.multiply(cellsize));
xMax = dim.getXMin().add(nColsBigDecimal.multiply(cellsize));
yMax = dim.getYMin().add(nRowsBigDecimal.multiply(cellsize));
}
dim = new Grids_Dimensions(xMin, xMax, yMin, yMax, cellsize);
}
/**
* For getting the chunk with chunk ID {@code i}.
*
* @return The chunk with chunk ID {@code i}.
* @param i The chunk ID.
* @throws IOException If encountered.
* @throws ClassNotFoundException If encountered.
* @throws Exception If encountered.
*/
public abstract Grids_Chunk getChunk(Grids_2D_ID_int i)
throws IOException, ClassNotFoundException, Exception;
/**
* If not loaded, this attempts to load into memory the chunk with chunk ID
* {@code i}. If it was not loaded then this means that the chunk perhaps
* contained only no data values.
*
* @param i The chunk ID of the chunk to be loaded.
* @return {@code true} if the chunk was loaded and {@code false} otherwise.
* @throws IOException If encountered.
* @throws ClassNotFoundException If encountered.
* @throws Exception If encountered.
*/
public boolean loadChunk(Grids_2D_ID_int i) throws IOException,
ClassNotFoundException, Exception {
if (!isLoaded(i)) {
Path f = Paths.get(getDirectory().toString(),
"" + i.getRow() + "_" + i.getCol());
if (Files.exists(f)) {
//env.env.log("Loading chunk from file" + f);
Object o = Generic_IO.readObject(f);
Grids_Chunk chunk = (Grids_Chunk) o;
chunk.env = env;
chunk.initGrid(this);
chunk.initChunkID(i);
data.put(i, chunk);
return true;
} else {
/**
* It is assumed that the chunk is all noDataValues so if this
* is called in a process which is attempting to set a value,
* then the chunk and value should be created without trying to
* load from the file.
*/
return false;
}
}
return false;
}
/**
* For getting the chunk at chunk row index {@code r}, chunk col index
* {@code c}.
*
* @param cr The chunk row index.
* @param cc The chunk column index.
* @return Grids_AbstractGridChunkDouble.
* @throws IOException If encountered.
* @throws ClassNotFoundException If encountered.
* @throws Exception If encountered.
*/
public final Grids_Chunk getChunk(int cr, int cc)
throws IOException, ClassNotFoundException, Exception {
return getChunk(new Grids_2D_ID_int(cr, cc));
}
/**
* For getting the chunk with chunk ID {@code i} at chunk row index
* {@code r}, chunk col index {@code c}.
*
* @param i The chunk ID.
* @param cr The chunk row index.
* @param cc The chunk column index.
* @return The specific chunk
* @throws IOException If encountered.
* @throws ClassNotFoundException If encountered.
* @throws Exception If encountered.
*/
public abstract Grids_Chunk getChunk(Grids_2D_ID_int i, int cr, int cc)
throws IOException, ClassNotFoundException, Exception;
/**
* For getting the grid statistics.
*
* @return The {@link #stats} cast appropriately.
*/
public abstract Grids_Stats getStats();
/**
* For getting the path for the serialization of this.
*
* @param p The directory path that is to contain the file.
* @return The path for the serialization of this.
*/
public Path getPathThisFile(Generic_Path p) {
return Paths.get(p.toString(), "grid.dat");
}
/**
* For printing out some or all of the values in row major order. There is
* no good memory handling for this yet. It is best if r and c are small. It
* might be good to develop a new version that allows for a set of
* rows/columns to include in the print out.
*
* @param r The number of rows to print.
* @param c The number of columns to print.
* @throws Exception If encountered.
*/
public void log(long r, long c) throws Exception {
env.env.log("name=" + getName());
env.env.log(toString());
env.env.log("dimensions=" + dim.toString());
long nrows = getNRows();
long ncols = getNCols();
int cols = (int) Math.min(ncols, c);
//int rows = (int) Math.min(nrows, r);
//String dashes = getDashes((cols * 13) + 1);
String dashes = getDashes(ncols, cols);
env.env.log(" yMax " + getColMarkers(ncols, cols));
env.env.log(getStringValue(dim.getYMax()) + " " + dashes);
String bars = getBars(ncols, cols);
String barsAndDashes = getBarsAndDashes(ncols, cols);
env.env.log(bars);
if (nrows < r) {
// Print out the top rows
long row;
for (row = nrows - 1; row > 0; row--) {
logRow(ncols, c, row);
logBars(bars, barsAndDashes);
}
// Print out the bottom row.
row = 0;
logRow(ncols, c, row);
env.env.log(bars);
} else {
// Print out the top row
long row = nrows - 1;
logRow(ncols, c, row);
env.env.log(bars);
// Print a break
env.env.log(barsAndDashes);
env.env.log("");
env.env.log(bars);
env.env.log("");
env.env.log(barsAndDashes);
env.env.log(bars);
// Print out the bottom
for (row = r - 2; row > 0; row--) {
logRow(ncols, c, row);
logBars(bars, barsAndDashes);
}
logRow(ncols, c, row);
env.env.log(bars);
}
env.env.log(getStringValue(dim.getYMin()) + " " + dashes);
env.env.log(" Ymin " + getStringValue(dim.getXMin()) + getSpaces((cols * 13) - 5) + getStringValue(dim.getXMax()));
env.env.log(" Xmin" + getSpaces(cols * 13) + "Xmax");
}
/**
* Used to help log a view of the grid.
*
* @param bars Spacers to make a cell appear more cell like.
* @param barsAndDashes Dividers that divide between rows of the grid.
*/
protected void logBars(String bars, String barsAndDashes) {
env.env.log(bars);
env.env.log(barsAndDashes);
env.env.log(bars);
}
/**
* @param ncols The number of columns in the grid.
* @param cols The number of columns that to be printed out.
* @return A String for a gap to make the cells in the grid printed out to
* appear more cell like.
*/
public String getBars(long ncols, int cols) {
String s = getSpaces(12);
String r = s + "|";
if (ncols < cols) {
for (int i = 0; i < cols; i++) {
r += s + "|";
}
} else {
for (int i = 0; i < cols - 1; i++) {
r += s + "|";
}
r += " |" + s + "|";
}
return r;
}
/**
* @param ncols The number of columns in the grid.
* @param cols The number of columns that to be printed out.
* @return A String to represent a break between two rows of the grid.
*/
public String getBarsAndDashes(long ncols, int cols) {
String s = getSpaces(12);
String d = getDashes2(12);
String r = s + "|";
if (ncols < cols) {
for (int i = 0; i < cols; i++) {
r += d + "|";
}
} else {
for (int i = 0; i < cols - 1; i++) {
r += d + "|";
}
r += " - |" + d + "|";
}
return r;
}
/**
* @param ncols The number of columns in the grid.
* @param cols The number of columns that to be printed out.
* @return A string for indicating the columns of the grid.
*/
protected String getColMarkers(long ncols, int cols) {
String s = "";
if (ncols < cols) {
for (int i = 0; i < cols; i++) {
s += " " + getStringValue(BigDecimal.valueOf(i)) + " ";
}
} else {
for (int i = 0; i < cols - 1; i++) {
s += " " + getStringValue(BigDecimal.valueOf(i)) + " ";
}
s += " " + getStringValue(BigDecimal.valueOf(ncols - 1L)) + " ";
}
return s;
}
/**
* @param ncols The number of columns in the grid.
* @param cols The number of columns to be printed out.
* @return A string for representing the top and bottom edge of the grid.
*/
public String getDashes(long ncols, int cols) {
String r = "";
if (ncols < cols) {
int n = (cols * 13) + 1;
return getDashes2(n);
} else {
int n = ((cols - 1) * 13) + 1;
r += getDashes2(n);
r += " - ";
r += getDashes2(14);
}
return r;
}
/**
* @param n The number of dashes in the result.
* @return A String with {@code n} dashes "-"
*/
public String getDashes2(int n) {
String r = "";
for (int i = 0; i < n; i++) {
r += "-";
}
return r;
}
/**
* Used to help log a view of the grid.
*
* @param ncols The number of columns in the grid.
* @param c The number of columns to be printed out.
* @param row The row of the grid to be logged.
* @throws java.lang.Exception If encountered.
*/
protected abstract void logRow(long ncols, long c, long row) throws Exception;
/**
* Used to help log a view of the grid. This aims to present numerical
* values in 10 characters which may involve rounding. If the number has
* fewer than 10 characters it is padded with spaces. The returned String is
* always of length 10.
*
* @param v The value to return as a String.
* @return {@code v} as a string rounded if necessary using
* {@code RoundingMode.HALF_UP}.
*/
public String getStringValue(BigDecimal v) {
String r = v.toEngineeringString();
if (r.length() > 10) {
BigDecimal v2 = v.setScale(v.scale() - (v.precision() - 3),
RoundingMode.HALF_UP);
r = v2.toEngineeringString();
}
while (r.length() < 9) {
r = " " + r + " ";
}
if (r.length() < 10) {
r = " " + r;
}
//System.out.println(r.length());
return r;
}
/**
* @param n The length of the String returned.
* @return A String comprising of {@code n} spaces " ".
*/
public String getSpaces(int n) {
String r = "";
for (int i = 0; i < n; i++) {
r += " ";
}
return r;
}
/**
* POJO for nearest values cell IDs and distance.
*/
public class NearestValuesCellIDsAndDistance {
public Grids_2D_ID_long[] cellIDs;
public BigDecimal distance;
public NearestValuesCellIDsAndDistance() {
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy