bugfix for saving shape dbf file

This commit is contained in:
wyq 2024-01-07 21:22:02 +08:00
parent 854e480362
commit 46c5fc079c
27 changed files with 142 additions and 2771 deletions

View File

@ -10,7 +10,6 @@ import org.meteoinfo.data.meteodata.Variable;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.InvalidRangeException;
import org.meteoinfo.ndarray.io.npy.Npy;
import org.meteoinfo.ndarray.io.npy.NpyArray;
import org.meteoinfo.ndarray.io.npy.NpyUtil;
import java.io.*;
@ -25,15 +24,14 @@ public class NumpyDataInfo extends DataInfo implements IGridDataInfo {
public void readDataInfo(String fileName) {
this.setFileName(fileName);
File file = new File(fileName);
NpyArray npyArray = Npy.read(file);
Array array = NpyUtil.toMIArray(npyArray);
Array array = Npy.load(file);
this.addAttribute(new Attribute("File type", "Numpy"));
int[] shape = npyArray.shape();
int[] shape = array.getShape();
String name = "a";
Variable variable = new Variable();
variable.setName(name);
variable.setDataType(NpyUtil.toMIDataType(npyArray.dataType()));
variable.setDataType(array.getDataType());
variable.setCachedData(array);
for (int i = 0; i < shape.length; i++) {
Dimension dim = new Dimension();

View File

@ -1175,15 +1175,15 @@ public class VectorLayer extends MapLayer {
/**
* Edit: Add a field
*
* @param aField The field
* @param field The field
*/
public void editAddField(Field aField) {
public void editAddField(Field field) {
for (int i = 0; i < this.getFieldNumber(); i++) {
if (aField.getColumnName().equals(_attributeTable.getTable().getColumns().get(i).getColumnName())) {
aField.setColumnName(aField.getColumnName() + "_1");
if (field.getColumnName().equals(_attributeTable.getTable().getColumns().get(i).getColumnName())) {
field.setColumnName(field.getColumnName() + "_1");
}
}
_attributeTable.getTable().addColumn(aField);
_attributeTable.addField(field);
}
/**

View File

@ -1,32 +1,30 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\io\matlab">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\test">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\city"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\burf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj\calculate"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\LaSW"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\LaSW\airship"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\text"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\array"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\numpy"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\numpy"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\isosurface"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\matlab"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\array"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\test"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\numpy\load_npz_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\numpy\load_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\matlab\loadmat_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\test\test_class_inherit.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\numpy\load_npz_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\numpy\load_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\matlab\loadmat_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\test\test_class_inherit.py"/>
</RecentFiles>
</File>
<Font>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="config.xml" Type="configurefile">
<Path OpenPath="D:\Temp\test"/>
<Path OpenPath="D:\Temp\traj\Sample"/>
<Font>
<TextFont FontName="YaHei Consolas Hybrid" FontSize="14"/>
<LegendFont FontName="宋体" FontSize="12"/>
@ -8,5 +8,5 @@
<ScriptLanguage Language="Jython"/>
<LookFeel LafDecorated="true" Name="FlatLightLaf"/>
<Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-5,1" MainFormSize="1293,685" ShowMeteoDataDlg="true"/>
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685" ShowMeteoDataDlg="true"/>
</MeteoInfo>

View File

@ -40,9 +40,9 @@ import org.meteoinfo.geometry.shape.Shape;
*/
public class FrmOutputMapData extends javax.swing.JDialog {
private List<VectorLayer> _mapLayers = new ArrayList<>();
private VectorLayer _currentLayer;
private FrmMain _parent;
private List<VectorLayer> mapLayers = new ArrayList<>();
private VectorLayer currentLayer;
private FrmMain parent;
/**
* Creates new form FrmOutputMapData
@ -53,7 +53,7 @@ public class FrmOutputMapData extends javax.swing.JDialog {
super(parent, modal);
initComponents();
_parent = (FrmMain) parent;
this.parent = (FrmMain) parent;
initialize();
}
@ -62,17 +62,17 @@ public class FrmOutputMapData extends javax.swing.JDialog {
//Get map layer list
int i;
for (i = 0; i < _parent.getMapDocument().getActiveMapFrame().getMapView().getLayerNum(); i++) {
if (_parent.getMapDocument().getActiveMapFrame().getMapView().getLayers().get(i).getLayerType() == LayerTypes.VECTOR_LAYER) {
VectorLayer aLayer = (VectorLayer) _parent.getMapDocument().getActiveMapFrame().getMapView().getLayers().get(i);
_mapLayers.add(aLayer);
for (i = 0; i < parent.getMapDocument().getActiveMapFrame().getMapView().getLayerNum(); i++) {
if (parent.getMapDocument().getActiveMapFrame().getMapView().getLayers().get(i).getLayerType() == LayerTypes.VECTOR_LAYER) {
VectorLayer aLayer = (VectorLayer) parent.getMapDocument().getActiveMapFrame().getMapView().getLayers().get(i);
mapLayers.add(aLayer);
}
}
this.jComboBox_MapLayer.removeAllItems();
if (_mapLayers.size() > 0) {
for (i = 0; i < _mapLayers.size(); i++) {
this.jComboBox_MapLayer.addItem(_mapLayers.get(i).getLayerName());
if (mapLayers.size() > 0) {
for (i = 0; i < mapLayers.size(); i++) {
this.jComboBox_MapLayer.addItem(mapLayers.get(i).getLayerName());
}
this.jComboBox_MapLayer.setSelectedIndex(0);
}
@ -175,7 +175,7 @@ public class FrmOutputMapData extends javax.swing.JDialog {
private void jComboBox_MapLayerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox_MapLayerActionPerformed
// TODO add your handling code here:
if (this.jComboBox_MapLayer.getItemCount() > 0) {
_currentLayer = _mapLayers.get(this.jComboBox_MapLayer.getSelectedIndex());
currentLayer = mapLayers.get(this.jComboBox_MapLayer.getSelectedIndex());
int i;
String str = this.jComboBox_OutputFormat.getSelectedItem().toString();
@ -183,7 +183,7 @@ public class FrmOutputMapData extends javax.swing.JDialog {
this.jComboBox_OutputFormat.addItem("ASCII wmp File");
this.jComboBox_OutputFormat.addItem("Shape File");
this.jComboBox_OutputFormat.addItem("KML File");
switch (_currentLayer.getShapeType()) {
switch (currentLayer.getShapeType()) {
case POLYGON:
case POLYGON_M:
case POLYGON_Z:
@ -268,14 +268,14 @@ public class FrmOutputMapData extends javax.swing.JDialog {
}
BufferedWriter sw = new BufferedWriter(new FileWriter(file));
List<Integer> selIndexes = _currentLayer.getSelectedShapeIndexes();
boolean hasSelShape = _currentLayer.hasSelectedShapes();
int shpNum = _currentLayer.getShapeNum();
List<Integer> selIndexes = currentLayer.getSelectedShapeIndexes();
boolean hasSelShape = currentLayer.hasSelectedShapes();
int shpNum = currentLayer.getShapeNum();
if (hasSelShape) {
shpNum = selIndexes.size();
}
int i;
switch (_currentLayer.getShapeType()) {
switch (currentLayer.getShapeType()) {
case POINT:
sw.write("Point");
sw.newLine();
@ -283,20 +283,20 @@ public class FrmOutputMapData extends javax.swing.JDialog {
sw.newLine();
PointShape aPS;
if (hasSelShape) {
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
aPS = (PointShape) _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
aPS = (PointShape) currentLayer.getShapes().get(i);
if (aPS.isSelected()) {
sw.write(String.valueOf(aPS.getPoint().X) + "," + String.valueOf(aPS.getPoint().Y));
sw.newLine();
}
this.jProgressBar1.setValue((i + 1) * 100 / _currentLayer.getShapeNum());
this.jProgressBar1.setValue((i + 1) * 100 / currentLayer.getShapeNum());
}
} else {
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
aPS = (PointShape) _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
aPS = (PointShape) currentLayer.getShapes().get(i);
sw.write(String.valueOf(aPS.getPoint().X) + "," + String.valueOf(aPS.getPoint().Y));
sw.newLine();
this.jProgressBar1.setValue((i + 1) * 100 / _currentLayer.getShapeNum());
this.jProgressBar1.setValue((i + 1) * 100 / currentLayer.getShapeNum());
}
}
break;
@ -306,8 +306,8 @@ public class FrmOutputMapData extends javax.swing.JDialog {
sw.newLine();
int shapeNum = 0;
PolylineShape aPLS;
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
aPLS = (PolylineShape) _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
aPLS = (PolylineShape) currentLayer.getShapes().get(i);
if (hasSelShape) {
if (!aPLS.isSelected()) {
continue;
@ -318,8 +318,8 @@ public class FrmOutputMapData extends javax.swing.JDialog {
sw.write(String.valueOf(shpNum));
sw.newLine();
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
aPLS = (PolylineShape) _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
aPLS = (PolylineShape) currentLayer.getShapes().get(i);
if (hasSelShape) {
if (!aPLS.isSelected()) {
continue;
@ -347,7 +347,7 @@ public class FrmOutputMapData extends javax.swing.JDialog {
shapeNum += 1;
}
this.jProgressBar1.setValue((i + 1) * 100 / _currentLayer.getShapeNum());
this.jProgressBar1.setValue((i + 1) * 100 / currentLayer.getShapeNum());
}
break;
case POLYGON:
@ -355,8 +355,8 @@ public class FrmOutputMapData extends javax.swing.JDialog {
sw.newLine();
shapeNum = 0;
PolygonShape aPGS;
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
aPGS = (PolygonShape) _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
aPGS = (PolygonShape) currentLayer.getShapes().get(i);
if (hasSelShape) {
if (!aPGS.isSelected()) {
continue;
@ -367,8 +367,8 @@ public class FrmOutputMapData extends javax.swing.JDialog {
sw.write(String.valueOf(shapeNum));
sw.newLine();
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
aPGS = (PolygonShape) _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
aPGS = (PolygonShape) currentLayer.getShapes().get(i);
if (hasSelShape) {
if (!aPGS.isSelected()) {
continue;
@ -397,7 +397,7 @@ public class FrmOutputMapData extends javax.swing.JDialog {
shapeNum += 1;
}
this.jProgressBar1.setValue((i + 1) * 100 / _currentLayer.getShapeNum());
this.jProgressBar1.setValue((i + 1) * 100 / currentLayer.getShapeNum());
}
break;
}
@ -436,14 +436,14 @@ public class FrmOutputMapData extends javax.swing.JDialog {
}
int i;
boolean hasSelShape = _currentLayer.hasSelectedShapes();
boolean hasSelShape = currentLayer.hasSelectedShapes();
//Get grid set
PolygonShape aPGS;
Extent aExtent = new Extent();
int n = 0;
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
aPGS = (PolygonShape) _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
aPGS = (PolygonShape) currentLayer.getShapes().get(i);
if (hasSelShape) {
if (!aPGS.isSelected()) {
continue;
@ -490,8 +490,8 @@ public class FrmOutputMapData extends javax.swing.JDialog {
for (j = 0; j < aGDP.xNum; j++) {
aPoint.X = aGDP.dataExtent.minX + j * xSize;
isIn = false;
for (p = 0; p < _currentLayer.getShapeNum(); p++) {
aPGS = (PolygonShape) _currentLayer.getShapes().get(p);
for (p = 0; p < currentLayer.getShapeNum(); p++) {
aPGS = (PolygonShape) currentLayer.getShapes().get(p);
if (hasSelShape) {
if (!aPGS.isSelected()) {
continue;
@ -586,14 +586,14 @@ public class FrmOutputMapData extends javax.swing.JDialog {
//Create a VectorLayer with selected shapes
int i, j;
VectorLayer aLayer = new VectorLayer(_currentLayer.getShapeType());
for (i = 0; i < _currentLayer.getFieldNumber(); i++) {
aLayer.editAddField(_currentLayer.getField(i).getColumnName(), _currentLayer.getField(i).getDataType());
VectorLayer aLayer = new VectorLayer(currentLayer.getShapeType());
for (i = 0; i < currentLayer.getFieldNumber(); i++) {
aLayer.editAddField(currentLayer.getField(i).getColumnName(), currentLayer.getField(i).getDataType());
}
boolean hasSelShape = _currentLayer.hasSelectedShapes();
boolean hasSelShape = currentLayer.hasSelectedShapes();
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
Shape aPS = _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
Shape aPS = currentLayer.getShapes().get(i);
if (hasSelShape) {
if (!aPS.isSelected()) {
continue;
@ -603,15 +603,15 @@ public class FrmOutputMapData extends javax.swing.JDialog {
try {
if (aLayer.editInsertShape(aPS, sNum)) {
for (j = 0; j < aLayer.getFieldNumber(); j++) {
aLayer.editCellValue(j, sNum, _currentLayer.getCellValue(j, i));
aLayer.editCellValue(j, sNum, currentLayer.getCellValue(j, i));
}
}
} catch (Exception ex) {
Logger.getLogger(FrmOutputMapData.class.getName()).log(Level.SEVERE, null, ex);
}
FrmOutputMapData.this.jProgressBar1.setValue((int) ((double) i / _currentLayer.getShapeNum() * 100));
FrmOutputMapData.this.jProgressBar1.setValue((int) ((double) i / currentLayer.getShapeNum() * 100));
}
aLayer.setProjInfo(_currentLayer.getProjInfo());
aLayer.setProjInfo(currentLayer.getProjInfo());
aLayer.saveFile(fileName);
return "";
@ -634,14 +634,14 @@ public class FrmOutputMapData extends javax.swing.JDialog {
//Create a VectorLayer with selected shapes
int i, j;
VectorLayer aLayer = new VectorLayer(_currentLayer.getShapeType());
for (i = 0; i < _currentLayer.getFieldNumber(); i++) {
aLayer.editAddField(_currentLayer.getField(i).getColumnName(), _currentLayer.getField(i).getDataType());
VectorLayer aLayer = new VectorLayer(currentLayer.getShapeType());
for (i = 0; i < currentLayer.getFieldNumber(); i++) {
aLayer.editAddField(currentLayer.getField(i));
}
boolean hasSelShape = _currentLayer.hasSelectedShapes();
boolean hasSelShape = currentLayer.hasSelectedShapes();
for (i = 0; i < _currentLayer.getShapeNum(); i++) {
Shape aPS = _currentLayer.getShapes().get(i);
for (i = 0; i < currentLayer.getShapeNum(); i++) {
Shape aPS = currentLayer.getShapes().get(i);
if (hasSelShape) {
if (!aPS.isSelected()) {
continue;
@ -651,15 +651,15 @@ public class FrmOutputMapData extends javax.swing.JDialog {
try {
if (aLayer.editInsertShape(aPS, sNum)) {
for (j = 0; j < aLayer.getFieldNumber(); j++) {
aLayer.editCellValue(j, sNum, _currentLayer.getCellValue(j, i));
aLayer.editCellValue(j, sNum, currentLayer.getCellValue(j, i));
}
}
} catch (Exception ex) {
Logger.getLogger(FrmOutputMapData.class.getName()).log(Level.SEVERE, null, ex);
}
FrmOutputMapData.this.jProgressBar1.setValue((int) ((double) i / _currentLayer.getShapeNum() * 100));
FrmOutputMapData.this.jProgressBar1.setValue((int) ((double) i / currentLayer.getShapeNum() * 100));
}
aLayer.setProjInfo(_currentLayer.getProjInfo());
aLayer.setProjInfo(currentLayer.getProjInfo());
aLayer.saveFile(fileName);
FrmOutputMapData.this.setCursor(Cursor.getDefaultCursor());
@ -689,7 +689,7 @@ public class FrmOutputMapData extends javax.swing.JDialog {
if (!fileName.substring(fileName.length() - extent.length()).equals(extent)) {
fileName = fileName + "." + extent;
}
_currentLayer.saveAsKMLFile(fileName);
currentLayer.saveAsKMLFile(fileName);
this.setCursor(Cursor.getDefaultCursor());
}

View File

@ -54,6 +54,7 @@ public class MatLabUtil {
case INT:
case UINT:
for (int i = 0; i < array.getSize(); i++) {
array.setInt(index, matArray.getInt(i));
current = index.getCurrentCounter();
for (int j = 0; j < ndim; j++) {
if (current[j] < shape[j] - 1) {
@ -64,12 +65,12 @@ public class MatLabUtil {
}
}
index.set(current);
array.setInt(index, matArray.getInt(i));
}
break;
case LONG:
case ULONG:
for (int i = 0; i < array.getSize(); i++) {
array.setLong(index, matArray.getLong(i));
current = index.getCurrentCounter();
for (int j = 0; j < ndim; j++) {
if (current[j] < shape[j] - 1) {
@ -80,11 +81,11 @@ public class MatLabUtil {
}
}
index.set(current);
array.setLong(index, matArray.getLong(i));
}
break;
case FLOAT:
for (int i = 0; i < array.getSize(); i++) {
array.setFloat(index, matArray.getFloat(i));
current = index.getCurrentCounter();
for (int j = 0; j < ndim; j++) {
if (current[j] < shape[j] - 1) {
@ -95,11 +96,11 @@ public class MatLabUtil {
}
}
index.set(current);
array.setFloat(index, matArray.getFloat(i));
}
break;
case DOUBLE:
for (int i = 0; i < array.getSize(); i++) {
array.setDouble(index, matArray.getDouble(i));
current = index.getCurrentCounter();
for (int j = 0; j < ndim; j++) {
if (current[j] < shape[j] - 1) {
@ -110,11 +111,22 @@ public class MatLabUtil {
}
}
index.set(current);
array.setDouble(index, matArray.getDouble(i));
}
break;
}
if (ndim >= 3) {
int[] shapeIdx = new int[ndim];
int idx = 0;
for (int i = ndim - 1; i > 1; i--) {
shapeIdx[idx] = i;
idx += 1;
}
shapeIdx[idx] = 0;
shapeIdx[idx + 1] = 1;
array = array.permute(shapeIdx);
}
return array;
}

View File

@ -1,36 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.util.Arrays;
import java.util.Objects;
abstract class AbstractNpyArray<T> implements NpyArray<T> {
protected final int[] shape;
protected final T data;
protected final boolean fortranOrder;
protected AbstractNpyArray(int[] shape, T data, boolean fortranOrder) {
this.shape = Objects.requireNonNull(shape);
this.data = Objects.requireNonNull(data);
this.fortranOrder = fortranOrder;
}
@Override
public final int[] shape() {
return shape;
}
@Override
public final boolean hasColumnOrder() {
return fortranOrder;
}
@Override
public T data() {
return data;
}
protected final int[] copyShape() {
return Arrays.copyOf(shape, shape.length);
}
}

View File

@ -1,416 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import org.meteoinfo.ndarray.io.npy.dict.NpyHeaderDict;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.util.Arrays;
public final class Array2d {
private Array2d() {
}
/**
* Checks if the given array is a valid 2-dimensional array. We do not check
* this in the other utility methods of this class. So if you are not sure
* if an array is a 2D array you should call this method to check this before
* calling the other methods of this class.
*
* @param array the NPY array to check
* @return {@code true} if the array has 2 dimensions and each dimensions is
* {@code > 1}.
*/
public static boolean isValid(NpyArray<?> array) {
if (array == null || array.shape() == null)
return false;
int[] shape = array.shape();
int rowCount = shape[0];
int colCount = shape[1];
return rowCount > 0
&& colCount > 0
&& rowCount * colCount == array.size();
}
public static int rowCountOf(NpyArray<?> array) {
return array.shape()[0];
}
public static int columnCountOf(NpyArray<?> array) {
return array.shape()[1];
}
public static int indexOf(NpyArray<?> array, int row, int col) {
if (array.hasColumnOrder()) {
int rows = array.shape()[0];
return col * rows + row;
} else {
int cols = array.shape()[1];
return row * cols + col;
}
}
public static boolean get(NpyBooleanArray array, int row, int col) {
int i = indexOf(array, row, col);
return array.data[i];
}
public static boolean[] getRow(NpyBooleanArray array, int row) {
int cols = array.shape[1];
if (!array.hasColumnOrder()) {
int offset = row * cols;
return Arrays.copyOfRange(array.data, offset, offset + cols);
}
int rows = array.shape[0];
boolean[] values = new boolean[cols];
int offset = 0;
for (int col = 0; col < cols; col++) {
values[col] = array.data[offset + row];
offset += rows;
}
return values;
}
public static boolean[] getColumn(NpyBooleanArray array, int col) {
int rows = array.shape[0];
if (array.hasColumnOrder()) {
int offset = col * rows;
return Arrays.copyOfRange(array.data, offset, offset + rows);
}
int cols = array.shape[1];
boolean[] values = new boolean[rows];
int offset = 0;
for (int row = 0; row < rows; row++) {
values[row] = array.data[offset + col];
offset += cols;
}
return values;
}
public static byte get(NpyByteArray array, int row, int col) {
int i = indexOf(array, row, col);
return array.data[i];
}
public static byte[] getRow(NpyByteArray array, int row) {
int cols = array.shape[1];
if (!array.hasColumnOrder()) {
int offset = row * cols;
return Arrays.copyOfRange(array.data, offset, offset + cols);
}
int rows = array.shape[0];
byte[] values = new byte[cols];
int offset = 0;
for (int col = 0; col < cols; col++) {
values[col] = array.data[offset + row];
offset += rows;
}
return values;
}
public static byte[] getColumn(NpyByteArray array, int col) {
int rows = array.shape[0];
if (array.hasColumnOrder()) {
int offset = col * rows;
return Arrays.copyOfRange(array.data, offset, offset + rows);
}
int cols = array.shape[1];
byte[] values = new byte[rows];
int offset = 0;
for (int row = 0; row < rows; row++) {
values[row] = array.data[offset + col];
offset += cols;
}
return values;
}
public static double get(NpyDoubleArray array, int row, int col) {
int i = indexOf(array, row, col);
return array.data[i];
}
public static double[] getRow(NpyDoubleArray array, int row) {
int cols = array.shape[1];
if (!array.hasColumnOrder()) {
int offset = row * cols;
return Arrays.copyOfRange(array.data, offset, offset + cols);
}
int rows = array.shape[0];
double[] values = new double[cols];
int offset = 0;
for (int col = 0; col < cols; col++) {
values[col] = array.data[offset + row];
offset += rows;
}
return values;
}
public static double[] getColumn(NpyDoubleArray array, int col) {
int rows = array.shape[0];
if (array.hasColumnOrder()) {
int offset = col * rows;
return Arrays.copyOfRange(array.data, offset, offset + rows);
}
int cols = array.shape[1];
double[] values = new double[rows];
int offset = 0;
for (int row = 0; row < rows; row++) {
values[row] = array.data[offset + col];
offset += cols;
}
return values;
}
public static float get(NpyFloatArray array, int row, int col) {
int i = indexOf(array, row, col);
return array.data[i];
}
public static float[] getRow(NpyFloatArray array, int row) {
int cols = array.shape[1];
if (!array.hasColumnOrder()) {
int offset = row * cols;
return Arrays.copyOfRange(array.data, offset, offset + cols);
}
int rows = array.shape[0];
float[] values = new float[cols];
int offset = 0;
for (int col = 0; col < cols; col++) {
values[col] = array.data[offset + row];
offset += rows;
}
return values;
}
public static float[] getColumn(NpyFloatArray array, int col) {
int rows = array.shape[0];
if (array.hasColumnOrder()) {
int offset = col * rows;
return Arrays.copyOfRange(array.data, offset, offset + rows);
}
int cols = array.shape[1];
float[] values = new float[rows];
int offset = 0;
for (int row = 0; row < rows; row++) {
values[row] = array.data[offset + col];
offset += cols;
}
return values;
}
public static int get(NpyIntArray array, int row, int col) {
int i = indexOf(array, row, col);
return array.data[i];
}
public static int[] getRow(NpyIntArray array, int row) {
int cols = array.shape[1];
if (!array.hasColumnOrder()) {
int offset = row * cols;
return Arrays.copyOfRange(array.data, offset, offset + cols);
}
int rows = array.shape[0];
int[] values = new int[cols];
int offset = 0;
for (int col = 0; col < cols; col++) {
values[col] = array.data[offset + row];
offset += rows;
}
return values;
}
public static int[] getColumn(NpyIntArray array, int col) {
int rows = array.shape[0];
if (array.hasColumnOrder()) {
int offset = col * rows;
return Arrays.copyOfRange(array.data, offset, offset + rows);
}
int cols = array.shape[1];
int[] values = new int[rows];
int offset = 0;
for (int row = 0; row < rows; row++) {
values[row] = array.data[offset + col];
offset += cols;
}
return values;
}
public static long get(NpyLongArray array, int row, int col) {
int i = indexOf(array, row, col);
return array.data[i];
}
public static long[] getRow(NpyLongArray array, int row) {
int cols = array.shape[1];
if (!array.hasColumnOrder()) {
int offset = row * cols;
return Arrays.copyOfRange(array.data, offset, offset + cols);
}
int rows = array.shape[0];
long[] values = new long[cols];
int offset = 0;
for (int col = 0; col < cols; col++) {
values[col] = array.data[offset + row];
offset += rows;
}
return values;
}
public static long[] getColumn(NpyLongArray array, int col) {
int rows = array.shape[0];
if (array.hasColumnOrder()) {
int offset = col * rows;
return Arrays.copyOfRange(array.data, offset, offset + rows);
}
int cols = array.shape[1];
long[] values = new long[rows];
int offset = 0;
for (int row = 0; row < rows; row++) {
values[row] = array.data[offset + col];
offset += cols;
}
return values;
}
public static short get(NpyShortArray array, int row, int col) {
int i = indexOf(array, row, col);
return array.data[i];
}
public static short[] getRow(NpyShortArray array, int row) {
int cols = array.shape[1];
if (!array.hasColumnOrder()) {
int offset = row * cols;
return Arrays.copyOfRange(array.data, offset, offset + cols);
}
int rows = array.shape[0];
short[] values = new short[cols];
int offset = 0;
for (int col = 0; col < cols; col++) {
values[col] = array.data[offset + row];
offset += rows;
}
return values;
}
public static short[] getColumn(NpyShortArray array, int col) {
int rows = array.shape[0];
if (array.hasColumnOrder()) {
int offset = col * rows;
return Arrays.copyOfRange(array.data, offset, offset + rows);
}
int cols = array.shape[1];
short[] values = new short[rows];
int offset = 0;
for (int row = 0; row < rows; row++) {
values[row] = array.data[offset + col];
offset += cols;
}
return values;
}
public static NpyArray<?> readRow(File file, int row) {
try (RandomAccessFile raf = new RandomAccessFile(file, "r");
java.nio.channels.FileChannel channel = raf.getChannel()) {
NpyHeader header = NpyHeader.read(channel);
return readRow(raf, header, row);
} catch (IOException e) {
throw new RuntimeException(
"failed to read a row " + row + " from NPY file " + file, e);
}
}
public static NpyArray<?> readRow(
RandomAccessFile file, NpyHeader header, int row) {
NpyHeaderDict dict = header.dict();
int rows = dict.sizeOfDimension(0);
int columns = dict.sizeOfDimension(1);
return dict.hasFortranOrder()
? Npy.readElements(file, header, columns, row, rows)
: Npy.readRange(file, header, columns, row * columns);
}
public static NpyArray<?> readColumn(File file, int column) {
try (RandomAccessFile raf = new RandomAccessFile(file, "r");
java.nio.channels.FileChannel channel = raf.getChannel()) {
NpyHeader header = NpyHeader.read(channel);
return readColumn(raf, header, column);
} catch (IOException e) {
throw new RuntimeException(
"failed to read a column " + column + " from NPY file " + file, e);
}
}
public static NpyArray<?> readColumn(
RandomAccessFile file, NpyHeader header, int column) {
NpyHeaderDict dict = header.dict();
int rows = dict.sizeOfDimension(0);
int columns = dict.sizeOfDimension(1);
return dict.hasFortranOrder()
? Npy.readRange(file, header, rows, column * rows)
: Npy.readElements(file, header, rows, column, columns);
}
public static <T extends NpyArray<?>> T switchOrder(T array) {
return OrderSwitch2d.of(array);
}
/**
* Read the diagonal of the 2d-array (matrix) stored in the given NPY file.
*
* @param file the NPY file
* @return the diagonal of the matrix
*/
public static NpyArray<?> readDiag(File file) {
try (RandomAccessFile raf = new RandomAccessFile(file, "r");
java.nio.channels.FileChannel channel = raf.getChannel()) {
NpyHeader header = NpyHeader.read(channel);
return readDiag(raf, header);
} catch (IOException e) {
throw new RuntimeException(
"failed to read diagonal from NPY file " + file, e);
}
}
public static NpyArray<?> readDiag(RandomAccessFile file, NpyHeader header) {
NpyHeaderDict dict = header.dict();
int elemSize = dict.dataType() == NpyDataType.U
? 4
: Math.max(dict.dataType().size(), 1);
int rows = dict.sizeOfDimension(0);
int cols = dict.sizeOfDimension(1);
int n = Math.min(rows, cols);
if (n < 1)
throw new IndexOutOfBoundsException(String.valueOf(n));
try {
NpyArrayReader reader = NpyArrayReader.of(Npy.shape1d(dict, n));
ByteBuffer buffer = ByteBuffer.allocate(elemSize);
buffer.order(header.byteOrder());
java.nio.channels.FileChannel channel = file.getChannel();
long pos = header.dataOffset();
long seekDist = dict.hasFortranOrder()
? (long) (rows + 1) * elemSize
: (long) (cols + 1) * elemSize;
for (int i = 0; i < n; i++) {
file.seek(pos);
channel.read(buffer);
buffer.flip();
reader.readNextFrom(buffer);
pos += seekDist;
buffer.clear();
}
return reader.finish();
} catch (IOException e) {
throw new RuntimeException(
"failed to read diagonal from NPY file: " + file, e);
}
}
}

View File

@ -1,47 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
class ChannelReader {
private static final int MAX_BUFFER_SIZE = 8 * 1024;
private final ReadableByteChannel channel;
private final NpyHeader header;
private ChannelReader(ReadableByteChannel channel, NpyHeader header) {
this.channel = channel;
this.header = header;
}
static NpyArray<?> read(ReadableByteChannel channel, NpyHeader header)
throws IOException, NpyFormatException {
return new ChannelReader(channel, header).read();
}
private NpyArray<?> read() throws IOException, NpyFormatException {
long totalBytes = header.dict().dataSize();
int bufferSize = totalBytes > 0 && totalBytes < ((long) MAX_BUFFER_SIZE)
? (int) totalBytes
: MAX_BUFFER_SIZE;
NpyArrayReader builder = NpyArrayReader.of(header.dict());
ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
buffer.order(header.byteOrder());
long readBytes = 0;
while (readBytes < totalBytes) {
int n = channel.read(buffer);
if (n <= 0)
break;
buffer.flip();
builder.readAllFrom(buffer);
buffer.clear();
readBytes += n;
}
return builder.finish();
}
}

View File

@ -30,24 +30,6 @@ public class Npy {
return load(file);
}
/**
* Load the content of the given file into NPY array instance.
*
* @param file the NPY file to read
* @return the mapped NPY array
* @throws NpyFormatException if the NPY format is invalid or unsupported
* @throws RuntimeException IO exceptions are wrapped in runtime exceptions
*/
public static NpyArray<?> read(File file) {
try (RandomAccessFile f = new RandomAccessFile(file, "r");
FileChannel channel = f.getChannel()) {
NpyHeader header = NpyHeader.read(channel);
return ChannelReader.read(channel, header);
} catch (IOException e) {
throw new RuntimeException("failed to read file: " + file, e);
}
}
/**
* Load the content of the given file into NPY array instance.
*
@ -83,15 +65,6 @@ public class Npy {
}
}
public static NpyArray<?> read(ReadableByteChannel channel) {
try {
NpyHeader header = NpyHeader.read(channel);
return ChannelReader.read(channel, header);
} catch (IOException e) {
throw new RuntimeException("failed to read NPY array from channel", e);
}
}
/**
* Opens the given file as a random access file and reads the NPY header. It
* calls the given consumer with the opened file and header and closes the
@ -111,128 +84,6 @@ public class Npy {
}
}
/**
* Reads a range of {@code n} elements from an array in an NPY file. Say you
* have an NPY file with an array {@code [1, 2, 3, 4]}, then
* {@code readRange(file, 2, 1)} would read {@code 2} elements starting from
* an offset of {@code 1} and thus would return {@code [2, 3]}.
*
* @param file a NPY file
* @param n the number of elements that should be read from the file
* @param offset the 0-based position of the first element of the range
* @return a one-dimensional array with {@code n} elements
*/
public static NpyArray<?> readRange(File file, int n, int offset) {
try (RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel()) {
NpyHeader header = NpyHeader.read(channel);
return readRange(raf, header, n, offset);
} catch (IOException e) {
throw new RuntimeException(
"failed to read a range of " +
n + " elements from NPY file " + file, e);
}
}
/**
* Same as {@link #readRange(File, int, int)} but with an opened NPY file.
*
* @param file the opened NPY file
* @param header the NPY header of the file
* @param n the number of elements that should be read from the file
* @param offset the 0-based position of the first element of the range
* @return a one-dimensional array with {@code n} elements
*/
public static NpyArray<?> readRange(
RandomAccessFile file, NpyHeader header, int n, int offset) {
NpyHeaderDict dict = header.dict();
int elemSize = dict.dataType() == NpyDataType.U
? 4
: Math.max(dict.dataType().size(), 1);
try {
// seek to the reading position and read the data
long start = header.dataOffset();
if (offset > 0) {
start += (long) elemSize * (long) offset;
}
file.seek(start);
int byteCount = n * elemSize;
ByteBuffer buffer = ByteBuffer.allocate(byteCount)
.order(dict.byteOrder().toJava());
if (file.getChannel().read(buffer) < byteCount) {
throw new IndexOutOfBoundsException(
"failed to read " + n + " elements from file");
}
buffer.flip();
// read the range into an array
NpyHeaderDict rangeDict = shape1d(dict, n);
NpyArrayReader reader = NpyArrayReader.of(rangeDict);
reader.readAllFrom(buffer);
return reader.finish();
} catch (IOException e) {
throw new RuntimeException(
"failed to read range from NPY file: " + file, e);
}
}
public static NpyArray<?> readElements(File file, int n, int offset, int inc) {
try (RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel()) {
NpyHeader header = NpyHeader.read(channel);
return readElements(raf, header, n, offset, inc);
} catch (IOException e) {
throw new RuntimeException(
"failed to read " + n + " elements from NPY file " + file, e);
}
}
public static NpyArray<?> readElements(
RandomAccessFile file, NpyHeader header, int n, int offset, int inc) {
if (inc == 1)
return readRange(file, header, n, offset);
NpyHeaderDict dict = header.dict();
int elemSize = dict.dataType() == NpyDataType.U
? 4
: Math.max(dict.dataType().size(), 1);
try {
// read the data
ByteBuffer buffer = ByteBuffer.allocate(n * elemSize)
.order(dict.byteOrder().toJava());
long fileOffset = header.dataOffset();
if (offset > 0) {
fileOffset += (long) elemSize * (long) offset;
}
FileChannel channel = file.getChannel();
for (int i = 0; i < n; i++) {
file.seek(fileOffset + (long) i * inc * elemSize);
buffer.limit(buffer.position() + elemSize);
if (channel.read(buffer) < elemSize) {
throw new IndexOutOfBoundsException(
"failed to read " + n + " elements from file");
}
}
buffer.flip();
// read the range into an array
NpyHeaderDict rangeDict = shape1d(dict, n);
NpyArrayReader reader = NpyArrayReader.of(rangeDict);
reader.readAllFrom(buffer);
return reader.finish();
} catch (IOException e) {
throw new RuntimeException(
"failed to read elements from NPY file: " + file, e);
}
}
static NpyHeaderDict shape1d(NpyHeaderDict dict, int n) {
return NpyHeaderDict.of(dict.dataType())
.withTypeSize(dict.typeSize())
@ -319,101 +170,4 @@ public class Npy {
throw new RuntimeException("failed to write npy data", e);
}
}
public static void write(File file, NpyArray<?> array) {
try (RandomAccessFile f = new RandomAccessFile(file, "rw");
FileChannel channel = f.getChannel()) {
write(channel, array);
} catch (IOException e) {
throw new RuntimeException("failed to write array to file " + file, e);
}
}
public static void write(WritableByteChannel channel, NpyArray<?> array) {
try {
NpyDataType dataType = array.dataType();
// handle strings
if (array.isCharArray()) {
NpyCharArray charArray = array.asCharArray();
NpyHeaderDict dict = NpyHeaderDict.of(dataType)
.withByteOrder(dataType == NpyDataType.S
? NpyByteOrder.NOT_APPLICABLE
: NpyByteOrder.LITTLE_ENDIAN)
.withTypeSize(charArray.size())
.create();
byte[] bytes = charArray.asByteArray().data();
Npy.write(channel, dict, bytes);
return;
}
// write the header
NpyHeaderDict dict = NpyHeaderDict.of(dataType)
.withShape(array.shape())
.withFortranOrder(array.hasColumnOrder())
.withByteOrder(NpyByteOrder.LITTLE_ENDIAN)
.create();
channel.write(ByteBuffer.wrap(dict.toNpyHeader()));
// allocate a buffer
long totalBytes = dict.dataSize();
int maxBufferSize = 8 * 1024;
int bufferSize = totalBytes < maxBufferSize
? (int) totalBytes
: maxBufferSize;
ByteBuffer buffer = ByteBuffer.allocate(bufferSize)
.order(ByteOrder.LITTLE_ENDIAN);
// write data to the channel
for (int i = 0; i < array.size(); i++) {
array.writeElementTo(i, buffer);
if (!buffer.hasRemaining()) {
buffer.flip();
channel.write(buffer);
buffer.clear();
}
}
if (buffer.position() > 0) {
buffer.flip();
channel.write(buffer);
}
} catch (IOException e) {
throw new RuntimeException("failed to write NPY array to channel", e);
}
}
public static void write(OutputStream stream, NpyArray<?> array) {
// do not close the channel here because it would
// close the underlying output stream which is
// not the idea of this function.
WritableByteChannel channel = Channels.newChannel(stream);
write(channel, array);
}
public static NpyArray<?> memmap(File file) {
try (RandomAccessFile f = new RandomAccessFile(file, "r");
FileChannel channel = f.getChannel()) {
NpyHeader header = NpyHeader.read(channel);
long dataSize = header.dict().dataSize();
// only a buffer of size < Integer.MAX_VALUE can be mapped
// into memory. if the size of the stored array is larger
// we take the normal reader currently
long max = Integer.MAX_VALUE;
if (dataSize >= max)
return ChannelReader.read(channel, header);
java.nio.MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_ONLY, header.dataOffset(), dataSize);
buffer.order(header.byteOrder());
NpyArrayReader builder = NpyArrayReader.of(header.dict());
builder.readAllFrom(buffer);
return builder.finish();
} catch (IOException e) {
throw new RuntimeException("failed to memmap NPY file: " + file, e);
}
}
}

View File

@ -1,124 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
public interface NpyArray<T> {
T data();
int[] shape();
/**
* Returns {@code true} when this array is stored in column-major order
* (Fortran order).
*/
boolean hasColumnOrder();
/**
* Returns {@code true} when this array is stored in row-major order (C order).
*/
default boolean hasRowOrder() {
return !hasColumnOrder();
}
NpyDataType dataType();
/**
* Get the element by index.
*
* @param i Index
*
* @return The element
*/
Object getElement(int i);
/**
* Writes the element {@code i} of this array to the given buffer.
*
* @param i the 0-based position of the element in this array that should
* be written to the buffer; must have a value between {@code 0}
* inclusively and {@link #size()} exclusively.
* @param buffer the byte buffer to which the element should be written
*/
void writeElementTo(int i, ByteBuffer buffer);
/**
* Returns the size of this array. That is the number of elements of this
* array.
*
* @return the number of elements of this array
*/
int size();
default boolean isBigIntegerArray() {
return false;
}
default boolean isBooleanArray() {
return false;
}
NpyBooleanArray asBooleanArray();
/**
* Returns true if this array is an instance of {@link NpyByteArray}.
*/
default boolean isByteArray() {
return false;
}
/**
* Converts this array into an instance of {@link NpyByteArray}. If this
* array is already such an instance it is directly returned without copying.
* Otherwise the values of this array are casted into a new
* {@link NpyByteArray}. Note that such casting can result in data loss.
*
* @return this array as an instance of {@link NpyByteArray}
*/
NpyByteArray asByteArray();
default boolean isDoubleArray() {
return false;
}
/**
* Convert this array into a double array. If this array is already a double
* array it is directly returned without making a copy of it.
*
* @return this array if it is a double array, otherwise a converted array
*/
NpyDoubleArray asDoubleArray();
default boolean isFloatArray() {
return false;
}
NpyFloatArray asFloatArray();
default boolean isIntArray() {
return false;
}
NpyIntArray asIntArray();
default boolean isLongArray() {
return false;
}
NpyLongArray asLongArray();
default boolean isShortArray() {
return false;
}
NpyShortArray asShortArray();
default boolean isCharArray() {
return false;
}
default NpyCharArray asCharArray() {
return asIntArray().asCharArray();
}
}

View File

@ -1,306 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import org.meteoinfo.ndarray.io.npy.dict.NpyHeaderDict;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
abstract class NpyArrayReader {
protected final NpyHeaderDict dict;
protected final int elementCount;
private final int elementSize;
private int pos;
private NpyArrayReader(NpyHeaderDict dict) {
this.dict = dict;
NpyDataType type = dict.dataType();
this.elementCount = type == NpyDataType.S || type == NpyDataType.U
? dict.typeSize()
: dict.numberOfElements();
this.elementSize = type == NpyDataType.S ? 1
: type == NpyDataType.U ? 4 : type.size();
this.pos = 0;
}
static NpyArrayReader of(NpyHeaderDict dict) throws NpyFormatException {
switch (dict.dataType()) {
case bool:
return new BooleanBuilder(dict);
case f2:
return new FloatBuilder(dict, NpyUtil::f2ToFloat);
case f4:
return new FloatBuilder(dict, ByteBuffer::getFloat);
case f8:
return new DoubleBuilder(dict);
case i1:
return new ByteBuilder(dict);
case i2:
return new ShortBuilder(dict, ByteBuffer::getShort);
case i4:
return new IntBuilder(dict, ByteBuffer::getInt);
case i8:
return new LongBuilder(dict, ByteBuffer::getLong);
case u1:
return new ShortBuilder(dict, NpyUtil::u1ToShort);
case u2:
return new IntBuilder(dict, NpyUtil::u2ToInt);
case u4:
return new LongBuilder(dict, NpyUtil::u4ToLong);
case u8:
return new BigIntBuilder(dict);
case S:
return new AsciiBuilder(dict);
case U:
return new UnicodeBuilder(dict);
default:
throw new NpyFormatException(
"unsupported data type: " + dict.dataType());
}
}
final void readAllFrom(ByteBuffer buffer) {
while (pos != elementCount && buffer.remaining() >= elementSize) {
nextInto(buffer, pos);
pos++;
}
}
final void readNextFrom(ByteBuffer buffer) {
nextInto(buffer, pos);
pos++;
}
abstract void nextInto(ByteBuffer buffer, int pos);
abstract NpyArray<?> finish();
private static final class BooleanBuilder extends NpyArrayReader {
private final boolean[] data;
private BooleanBuilder(NpyHeaderDict dict) {
super(dict);
this.data = new boolean[elementCount];
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = buffer.get() != 0;
}
@Override
NpyBooleanArray finish() {
return new NpyBooleanArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class ByteBuilder extends NpyArrayReader {
private final byte[] data;
private ByteBuilder(NpyHeaderDict dict) {
super(dict);
this.data = new byte[elementCount];
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = buffer.get();
}
@Override
NpyByteArray finish() {
return new NpyByteArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class DoubleBuilder extends NpyArrayReader {
private final double[] data;
private DoubleBuilder(NpyHeaderDict dict) {
super(dict);
this.data = new double[elementCount];
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = buffer.getDouble();
}
@Override
NpyDoubleArray finish() {
return new NpyDoubleArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class FloatBuilder extends NpyArrayReader {
private final float[] data;
private final ToFloatFunction<ByteBuffer> fn;
private FloatBuilder(NpyHeaderDict dict, ToFloatFunction<ByteBuffer> fn) {
super(dict);
this.data = new float[elementCount];
this.fn = fn;
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = fn.applyAsFloat(buffer);
}
@Override
NpyFloatArray finish() {
return new NpyFloatArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class IntBuilder extends NpyArrayReader {
private final int[] data;
private final ToIntFunction<ByteBuffer> fn;
private IntBuilder(NpyHeaderDict dict, ToIntFunction<ByteBuffer> fn) {
super(dict);
this.data = new int[elementCount];
this.fn = fn;
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = fn.applyAsInt(buffer);
}
@Override
NpyIntArray finish() {
return new NpyIntArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class ShortBuilder extends NpyArrayReader {
private final short[] data;
private final ToShortFunction<ByteBuffer> fn;
private ShortBuilder(NpyHeaderDict dict, ToShortFunction<ByteBuffer> fn) {
super(dict);
this.data = new short[elementCount];
this.fn = fn;
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = fn.applyAsShort(buffer);
}
@Override
NpyShortArray finish() {
return new NpyShortArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class LongBuilder extends NpyArrayReader {
private final long[] data;
private final ToLongFunction<ByteBuffer> fn;
private LongBuilder(NpyHeaderDict dict, ToLongFunction<ByteBuffer> fn) {
super(dict);
this.data = new long[elementCount];
this.fn = fn;
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = fn.applyAsLong(buffer);
}
@Override
NpyLongArray finish() {
return new NpyLongArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class BigIntBuilder extends NpyArrayReader {
private final BigInteger[] data;
private BigIntBuilder(NpyHeaderDict dict) {
super(dict);
this.data = new BigInteger[elementCount];
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = NpyUtil.u8ToBigInteger(buffer);
}
@Override
NpyBigIntArray finish() {
return new NpyBigIntArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class AsciiBuilder extends NpyArrayReader {
private final CharBuffer chars;
private boolean terminated = false;
private AsciiBuilder(NpyHeaderDict dict) {
super(dict);
this.chars = CharBuffer.allocate(elementCount);
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
if (terminated)
return;
char next = (char)buffer.get();
if (next == 0) {
terminated = true;
return;
}
chars.put(next);
}
@Override
NpyCharArray finish() {
char[] data;
if (chars.remaining() == 0) {
data = chars.array();
} else {
chars.flip();
data = new char[chars.limit()];
chars.get(data, 0, chars.limit());
}
return new NpyCharArray(dict.shape(), data, dict.hasFortranOrder());
}
}
private static final class UnicodeBuilder extends NpyArrayReader {
private final int[] data;
private UnicodeBuilder(NpyHeaderDict dict) {
super(dict);
this.data = new int[elementCount];
}
@Override
void nextInto(ByteBuffer buffer, int pos) {
data[pos] = buffer.getInt();
}
@Override
NpyCharArray finish() {
NpyIntArray ints = new NpyIntArray(dict.shape(), data, dict.hasFortranOrder());
return ints.asCharArray();
}
}
}

View File

@ -1,154 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.math.BigInteger;
import java.nio.ByteBuffer;
public final class NpyBigIntArray extends AbstractNpyArray<BigInteger[]> {
public NpyBigIntArray(int[] shape, BigInteger[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyBigIntArray vectorOf(BigInteger[] data) {
return new NpyBigIntArray(new int[] {data.length}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in row-major order (C order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyBigIntArray rowOrderOf(BigInteger[] data, int rows, int cols) {
return new NpyBigIntArray(new int[]{rows, cols}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in column-major order (
* Fortran order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyBigIntArray columnOrderOf(BigInteger[] data, int rows, int cols) {
return new NpyBigIntArray(new int[]{rows, cols}, data, true);
}
@Override
public NpyDataType dataType() {
return NpyDataType.u8;
}
@Override
public int size() {
return data.length;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
BigInteger value = data[i];
if (value == null) {
buffer.putLong(0);
} else {
buffer.putLong(value.longValueExact());
}
}
@Override
public boolean isBigIntegerArray() {
return true;
}
@Override
public NpyBooleanArray asBooleanArray() {
boolean[] booleans = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
BigInteger val = data[i];
if (val != null) {
booleans[i] = val.longValueExact() != 0;
}
}
return new NpyBooleanArray(copyShape(), booleans, fortranOrder);
}
@Override
public NpyByteArray asByteArray() {
byte[] bytes = new byte[data.length];
for (int i = 0; i < data.length; i++) {
BigInteger val = data[i];
if (val != null) {
bytes[i] = (byte) val.intValueExact();
}
}
return new NpyByteArray(copyShape(), bytes, fortranOrder);
}
@Override
public NpyDoubleArray asDoubleArray() {
double[] doubles = new double[data.length];
for (int i = 0; i < data.length; i++) {
BigInteger val = data[i];
if (val != null) {
doubles[i] = val.doubleValue();
}
}
return new NpyDoubleArray(copyShape(), doubles, fortranOrder);
}
@Override
public NpyFloatArray asFloatArray() {
float[] floats = new float[data.length];
for (int i = 0; i < data.length; i++) {
BigInteger val = data[i];
if (val != null) {
floats[i] = (float) val.doubleValue();
}
}
return new NpyFloatArray(copyShape(), floats, fortranOrder);
}
@Override
public NpyIntArray asIntArray() {
int[] ints = new int[data.length];
for (int i = 0; i < data.length; i++) {
BigInteger val = data[i];
if (val != null) {
ints[i] = val.intValueExact();
}
}
return new NpyIntArray(copyShape(), ints, fortranOrder);
}
@Override
public NpyLongArray asLongArray() {
long[] longs = new long[data.length];
for (int i = 0; i < data.length; i++) {
BigInteger val = data[i];
if (val != null) {
longs[i] = val.longValueExact();
}
}
return new NpyLongArray(copyShape(), longs, fortranOrder);
}
@Override
public NpyShortArray asShortArray() {
short[] shorts = new short[data.length];
for (int i = 0; i < data.length; i++) {
BigInteger val = data[i];
if (val != null) {
shorts[i] = (short) val.intValueExact();
}
}
return new NpyShortArray(copyShape(), shorts, fortranOrder);
}
}

View File

@ -1,138 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
public final class NpyBooleanArray extends AbstractNpyArray<boolean[]> {
public NpyBooleanArray(int[] shape, boolean[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyBooleanArray vectorOf(boolean[] data) {
return new NpyBooleanArray(new int[] {data.length}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in row-major order (C order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyBooleanArray rowOrderOf(boolean[] data, int rows, int cols) {
return new NpyBooleanArray(new int[]{rows, cols}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in column-major order (
* Fortran order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyBooleanArray columnOrderOf(boolean[] data, int rows, int cols) {
return new NpyBooleanArray(new int[]{rows, cols}, data, true);
}
@Override
public NpyDataType dataType() {
return NpyDataType.bool;
}
@Override
public int size() {
return data.length;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
byte b = data[i] ? (byte) 1 : (byte) 0;
buffer.put(b);
}
@Override
public boolean isBooleanArray() {
return true;
}
@Override
public NpyBooleanArray asBooleanArray() {
return this;
}
@Override
public NpyByteArray asByteArray() {
byte[] bytes = new byte[data.length];
for (int i = 0; i < data.length; i++) {
if (data[i]) {
bytes[i] = 1;
}
}
return new NpyByteArray(copyShape(), bytes, fortranOrder);
}
@Override
public NpyDoubleArray asDoubleArray() {
double[] doubles = new double[data.length];
for (int i = 0; i < data.length; i++) {
if (data[i]) {
doubles[i] = 1d;
}
}
return new NpyDoubleArray(copyShape(), doubles, fortranOrder);
}
@Override
public NpyFloatArray asFloatArray() {
float[] floats = new float[data.length];
for (int i = 0; i < data.length; i++) {
if (data[i]) {
floats[i] = 1f;
}
}
return new NpyFloatArray(copyShape(), floats, fortranOrder);
}
@Override
public NpyIntArray asIntArray() {
int[] ints = new int[data.length];
for (int i = 0; i < data.length; i++) {
if (data[i]) {
ints[i] = 1;
}
}
return new NpyIntArray(copyShape(), ints, fortranOrder);
}
@Override
public NpyLongArray asLongArray() {
long[] longs = new long[data.length];
for (int i = 0; i < data.length; i++) {
if (data[i]) {
longs[i] = 1L;
}
}
return new NpyLongArray(copyShape(), longs, fortranOrder);
}
@Override
public NpyShortArray asShortArray() {
short[] shorts = new short[data.length];
for (int i = 0; i < data.length; i++) {
if (data[i]) {
shorts[i] = 1;
}
}
return new NpyShortArray(copyShape(), shorts, fortranOrder);
}
}

View File

@ -1,124 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
public final class NpyByteArray extends AbstractNpyArray<byte[]> {
public NpyByteArray(int[] shape, byte[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyByteArray vectorOf(byte[] data) {
return new NpyByteArray(new int[] {data.length}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in row-major order (C order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyByteArray rowOrderOf(byte[] data, int rows, int cols) {
return new NpyByteArray(new int[]{rows, cols}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in column-major order (
* Fortran order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyByteArray columnOrderOf(byte[] data, int rows, int cols) {
return new NpyByteArray(new int[]{rows, cols}, data, true);
}
@Override
public NpyDataType dataType() {
return NpyDataType.i1;
}
@Override
public int size() {
return data.length;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
buffer.put(data[i]);
}
@Override
public boolean isByteArray() {
return true;
}
@Override
public NpyByteArray asByteArray() {
return this;
}
@Override
public NpyBooleanArray asBooleanArray() {
boolean[] booleans = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
booleans[i] = i != 0;
}
return new NpyBooleanArray(copyShape(), booleans, fortranOrder);
}
@Override
public NpyDoubleArray asDoubleArray() {
double[] doubles = new double[data.length];
for (int i = 0; i < data.length; i++) {
doubles[i] = data[i];
}
return new NpyDoubleArray(copyShape(), doubles, fortranOrder);
}
@Override
public NpyFloatArray asFloatArray() {
float[] floats = new float[data.length];
for (int i = 0; i < data.length; i++) {
floats[i] = data[i];
}
return new NpyFloatArray(copyShape(), floats, fortranOrder);
}
@Override
public NpyIntArray asIntArray() {
int[] ints = new int[data.length];
for (int i = 0; i < data.length; i++) {
ints[i] = data[i];
}
return new NpyIntArray(copyShape(), ints, fortranOrder);
}
@Override
public NpyLongArray asLongArray() {
long[] longs = new long[data.length];
for (int i = 0; i < data.length; i++) {
longs[i] = data[i];
}
return new NpyLongArray(copyShape(), longs, fortranOrder);
}
@Override
public NpyShortArray asShortArray() {
short[] shorts = new short[data.length];
for (int i = 0; i < data.length; i++) {
shorts[i] = data[i];
}
return new NpyShortArray(copyShape(), shorts, fortranOrder);
}
}

View File

@ -1,152 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.charset.StandardCharsets;
public class NpyCharArray extends AbstractNpyArray<char[]> {
private NpyDataType type;
public NpyCharArray(int[] shape, char[] data) {
super(shape, data, false);
}
public NpyCharArray(int[] shape, char[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyCharArray of(String s) {
char[] chars = s.toCharArray();
return new NpyCharArray(new int[0], chars);
}
@Override
public NpyDataType dataType() {
if (type != null)
return type;
boolean isAscii = StandardCharsets.US_ASCII
.newEncoder()
.canEncode(CharBuffer.wrap(data));
type = isAscii
? NpyDataType.S
: NpyDataType.U;
return type;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
if (dataType() == NpyDataType.S) {
buffer.put((byte) data[i]);
} else {
buffer.putInt(data[i]);
}
}
@Override
public int size() {
return data.length;
}
@Override
public boolean isCharArray() {
return true;
}
@Override
public NpyBooleanArray asBooleanArray() {
boolean[] booleans = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
booleans[i] = data[i] != 0;
}
return new NpyBooleanArray(copyShape(), booleans, fortranOrder);
}
/**
* Converts this character array into a byte array. If the characters in this
* array can be encoded in ASCII, a NULL-terminated byte array will be
* returned. Otherwise, an array with the 4-byte unicode code-points encoded
* in little-endian order will be returned.
*
* @return the NPY byte-array representation of this character array
*/
@Override
public NpyByteArray asByteArray() {
NpyDataType type = dataType();
if (type == NpyDataType.S) {
// write as NULL terminated string
byte[] bytes = new byte[data.length + 1];
for (int i = 0; i < data.length; i++) {
bytes[i] = (byte) data[i];
}
return NpyByteArray.vectorOf(bytes);
}
// write unicode code points
byte[] bytes = new byte[data.length * 4];
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.order(ByteOrder.LITTLE_ENDIAN);
for (char datum : data) {
buffer.putInt(datum);
}
return NpyByteArray.vectorOf(bytes);
}
@Override
public NpyCharArray asCharArray() {
return this;
}
@Override
public NpyDoubleArray asDoubleArray() {
return asIntArray().asDoubleArray();
}
@Override
public NpyFloatArray asFloatArray() {
return asIntArray().asFloatArray();
}
@Override
public NpyIntArray asIntArray() {
IntBuffer buffer = IntBuffer.allocate(data.length);
int pos = 0;
while (pos < data.length) {
int codePoint = Character.codePointAt(data, pos);
buffer.put(codePoint);
pos += Character.charCount(codePoint);
}
int[] ints;
if (buffer.remaining() == 0) {
ints = buffer.array();
} else {
buffer.flip();
ints = new int[buffer.limit()];
buffer.get(ints, 0, buffer.limit());
}
return new NpyIntArray(copyShape(), ints, fortranOrder);
}
@Override
public NpyLongArray asLongArray() {
return asIntArray().asLongArray();
}
@Override
public NpyShortArray asShortArray() {
return asIntArray().asShortArray();
}
@Override
public String toString() {
return String.valueOf(data);
}
}

View File

@ -1,123 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
public final class NpyDoubleArray extends AbstractNpyArray<double[]> {
public NpyDoubleArray(int[] shape, double[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyDoubleArray vectorOf(double[] data) {
return new NpyDoubleArray(new int[]{data.length}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in row-major order (C order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyDoubleArray rowOrderOf(double[] data, int rows, int cols) {
return new NpyDoubleArray(new int[]{rows, cols}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in column-major order (
* Fortran order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyDoubleArray columnOrderOf(double[] data, int rows, int cols) {
return new NpyDoubleArray(new int[]{rows, cols}, data, true);
}
@Override
public NpyDataType dataType() {
return NpyDataType.f8;
}
@Override
public int size() {
return data.length;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
buffer.putDouble(data[i]);
}
@Override
public boolean isDoubleArray() {
return true;
}
@Override
public NpyDoubleArray asDoubleArray() {
return this;
}
@Override
public NpyBooleanArray asBooleanArray() {
boolean[] booleans = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
booleans[i] = data[i] != 0;
}
return new NpyBooleanArray(copyShape(), booleans, fortranOrder);
}
@Override
public NpyByteArray asByteArray() {
byte[] bytes = new byte[data.length];
for (int i = 0; i < data.length; i++) {
bytes[i] = (byte) data[i];
}
return new NpyByteArray(copyShape(), bytes, fortranOrder);
}
@Override
public NpyFloatArray asFloatArray() {
float[] floats = new float[data.length];
for (int i = 0; i < data.length; i++) {
floats[i] = (float) data[i];
}
return new NpyFloatArray(copyShape(), floats, fortranOrder);
}
@Override
public NpyIntArray asIntArray() {
int[] ints = new int[data.length];
for (int i = 0; i < data.length; i++) {
ints[i] = (int) data[i];
}
return new NpyIntArray(copyShape(), ints, fortranOrder);
}
@Override
public NpyLongArray asLongArray() {
long[] longs = new long[data.length];
for (int i = 0; i < data.length; i++) {
longs[i] = (long) data[i];
}
return new NpyLongArray(copyShape(), longs, fortranOrder);
}
@Override
public NpyShortArray asShortArray() {
short[] shorts = new short[data.length];
for (int i = 0; i < data.length; i++) {
shorts[i] = (short) data[i];
}
return new NpyShortArray(copyShape(), shorts, fortranOrder);
}
}

View File

@ -1,123 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
public final class NpyFloatArray extends AbstractNpyArray<float[]> {
public NpyFloatArray(int[] shape, float[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyFloatArray vectorOf(float[] data) {
return new NpyFloatArray(new int[]{data.length}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in row-major order (C order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyFloatArray rowOrderOf(float[] data, int rows, int cols) {
return new NpyFloatArray(new int[]{rows, cols}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in column-major order (
* Fortran order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyFloatArray columnOrderOf(float[] data, int rows, int cols) {
return new NpyFloatArray(new int[]{rows, cols}, data, true);
}
@Override
public NpyDataType dataType() {
return NpyDataType.f4;
}
@Override
public int size() {
return data.length;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
buffer.putFloat(data[i]);
}
@Override
public boolean isFloatArray() {
return true;
}
@Override
public NpyBooleanArray asBooleanArray() {
boolean[] booleans = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
booleans[i] = i != 0;
}
return new NpyBooleanArray(copyShape(), booleans, fortranOrder);
}
@Override
public NpyByteArray asByteArray() {
byte[] bytes = new byte[data.length];
for (int i = 0; i < data.length; i++) {
bytes[i] = (byte) data[i];
}
return new NpyByteArray(copyShape(), bytes, fortranOrder);
}
@Override
public NpyDoubleArray asDoubleArray() {
double[] doubles = new double[data.length];
for (int i = 0; i < data.length; i++) {
doubles[i] = data[i];
}
return new NpyDoubleArray(copyShape(), doubles, fortranOrder);
}
@Override
public NpyFloatArray asFloatArray() {
return this;
}
@Override
public NpyIntArray asIntArray() {
int[] ints = new int[data.length];
for (int i = 0; i < data.length; i++) {
ints[i] = (int) data[i];
}
return new NpyIntArray(copyShape(), ints, fortranOrder);
}
@Override
public NpyLongArray asLongArray() {
long[] longs = new long[data.length];
for (int i = 0; i < data.length; i++) {
longs[i] = (long) data[i];
}
return new NpyLongArray(copyShape(), longs, fortranOrder);
}
@Override
public NpyShortArray asShortArray() {
short[] shorts = new short[data.length];
for (int i = 0; i < data.length; i++) {
shorts[i] = (short) data[i];
}
return new NpyShortArray(copyShape(), shorts, fortranOrder);
}
}

View File

@ -1,167 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
public final class NpyIntArray extends AbstractNpyArray<int[]> {
public NpyIntArray(int[] shape, int[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyIntArray vectorOf(int[] data) {
return new NpyIntArray(new int[] {data.length}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in row-major order (C order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyIntArray rowOrderOf(int[] data, int rows, int cols) {
return new NpyIntArray(new int[]{rows, cols}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in column-major order (
* Fortran order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyIntArray columnOrderOf(int[] data, int rows, int cols) {
return new NpyIntArray(new int[]{rows, cols}, data, true);
}
@Override
public NpyDataType dataType() {
return NpyDataType.i4;
}
@Override
public int size() {
return data.length;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
buffer.putInt(data[i]);
}
@Override
public boolean isIntArray() {
return true;
}
@Override
public NpyIntArray asIntArray() {
return this;
}
@Override
public NpyBooleanArray asBooleanArray() {
boolean[] booleans = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
booleans[i] = data[i] != 0;
}
return new NpyBooleanArray(copyShape(), booleans, fortranOrder);
}
@Override
public NpyByteArray asByteArray() {
byte[] bytes = new byte[data.length];
for (int i = 0; i < data.length; i++) {
bytes[i] = (byte) data[i];
}
return new NpyByteArray(copyShape(), bytes, fortranOrder);
}
@Override
public NpyCharArray asCharArray() {
int bufferSize = Math.max(data.length, 10);
CharBuffer buffer = CharBuffer.allocate(bufferSize);
for (int i : data) {
char[] next = Character.toChars(i);
// because a code point can result in multiple
// characters, we may need to allocate a larger
// buffer here
if (buffer.remaining() < next.length) {
bufferSize = Math.max(
bufferSize + next.length,
bufferSize + (bufferSize >> 1));
if (bufferSize < 0)
throw new OutOfMemoryError();
char[] chars = new char[bufferSize];
buffer.flip();
int nextPos = buffer.limit();
buffer.get(chars, 0, nextPos);
buffer = CharBuffer.wrap(chars);
buffer.position(nextPos);
}
for (char c : next) {
buffer.put(c);
}
}
char[] chars;
if (buffer.remaining() == 0) {
chars = buffer.array();
} else {
buffer.flip();
chars = new char[buffer.limit()];
buffer.get(chars, 0, buffer.limit());
}
return new NpyCharArray(copyShape(), chars, fortranOrder);
}
@Override
public NpyDoubleArray asDoubleArray() {
double[] doubles = new double[data.length];
for (int i = 0; i < data.length; i++) {
doubles[i] = data[i];
}
return new NpyDoubleArray(copyShape(), doubles, fortranOrder);
}
@Override
public NpyFloatArray asFloatArray() {
float[] floats = new float[data.length];
for (int i = 0; i < data.length; i++) {
floats[i] = (float) data[i];
}
return new NpyFloatArray(copyShape(), floats, fortranOrder);
}
@Override
public NpyLongArray asLongArray() {
long[] longs = new long[data.length];
for (int i = 0; i < data.length; i++) {
longs[i] = data[i];
}
return new NpyLongArray(copyShape(), longs, fortranOrder);
}
@Override
public NpyShortArray asShortArray() {
short[] shorts = new short[data.length];
for (int i = 0; i < data.length; i++) {
shorts[i] = (short) data[i];
}
return new NpyShortArray(copyShape(), shorts, fortranOrder);
}
}

View File

@ -1,124 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
public final class NpyLongArray extends AbstractNpyArray<long[]> {
public NpyLongArray(int[] shape, long[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyLongArray vectorOf(long[] data) {
return new NpyLongArray(new int[] {data.length}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in row-major order (C order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyLongArray rowOrderOf(long[] data, int rows, int cols) {
return new NpyLongArray(new int[]{rows, cols}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in column-major order (
* Fortran order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyLongArray columnOrderOf(long[] data, int rows, int cols) {
return new NpyLongArray(new int[]{rows, cols}, data, true);
}
@Override
public NpyDataType dataType() {
return NpyDataType.i8;
}
@Override
public int size() {
return data.length;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
buffer.putLong(data[i]);
}
@Override
public boolean isLongArray() {
return true;
}
@Override
public NpyLongArray asLongArray() {
return this;
}
@Override
public NpyBooleanArray asBooleanArray() {
boolean[] booleans = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
booleans[i] = i != 0;
}
return new NpyBooleanArray(copyShape(), booleans, fortranOrder);
}
@Override
public NpyByteArray asByteArray() {
byte[] bytes = new byte[data.length];
for (int i = 0; i < data.length; i++) {
bytes[i] = (byte) data[i];
}
return new NpyByteArray(copyShape(), bytes, fortranOrder);
}
@Override
public NpyDoubleArray asDoubleArray() {
double[] doubles = new double[data.length];
for (int i = 0; i < data.length; i++) {
doubles[i] = data[i];
}
return new NpyDoubleArray(copyShape(), doubles, fortranOrder);
}
@Override
public NpyFloatArray asFloatArray() {
float[] floats = new float[data.length];
for (int i = 0; i < data.length; i++) {
floats[i] = (float) data[i];
}
return new NpyFloatArray(copyShape(), floats, fortranOrder);
}
@Override
public NpyIntArray asIntArray() {
int[] ints = new int[data.length];
for (int i = 0; i < data.length; i++) {
ints[i] = (int) data[i];
}
return new NpyIntArray(copyShape(), ints, fortranOrder);
}
@Override
public NpyShortArray asShortArray() {
short[] shorts = new short[data.length];
for (int i = 0; i < data.length; i++) {
shorts[i] = (short) data[i];
}
return new NpyShortArray(copyShape(), shorts, fortranOrder);
}
}

View File

@ -1,124 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.nio.ByteBuffer;
public final class NpyShortArray extends AbstractNpyArray<short[]> {
public NpyShortArray(int[] shape, short[] data, boolean fortranOrder) {
super(shape, data, fortranOrder);
}
public static NpyShortArray vectorOf(short[] data) {
return new NpyShortArray(new int[] {data.length}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in row-major order (C order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyShortArray rowOrderOf(short[] data, int rows, int cols) {
return new NpyShortArray(new int[]{rows, cols}, data, false);
}
/**
* Wraps the given data in a 2-dimensional array in column-major order (
* Fortran order).
*
* @param data the data of the array
* @param rows the number of rows of the array
* @param cols the number of columns of the array
* @return a 2d array of the given shape
*/
public static NpyShortArray columnOrderOf(short[] data, int rows, int cols) {
return new NpyShortArray(new int[]{rows, cols}, data, true);
}
@Override
public NpyDataType dataType() {
return NpyDataType.i2;
}
@Override
public int size() {
return data.length;
}
@Override
public Object getElement(int i) {
return data[i];
}
@Override
public void writeElementTo(int i, ByteBuffer buffer) {
buffer.putShort(data[i]);
}
@Override
public boolean isShortArray() {
return true;
}
@Override
public NpyShortArray asShortArray() {
return this;
}
@Override
public NpyBooleanArray asBooleanArray() {
boolean[] booleans = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
booleans[i] = i != 0;
}
return new NpyBooleanArray(copyShape(), booleans, fortranOrder);
}
@Override
public NpyByteArray asByteArray() {
byte[] bytes = new byte[data.length];
for (int i = 0; i < data.length; i++) {
bytes[i] = (byte) data[i];
}
return new NpyByteArray(copyShape(), bytes, fortranOrder);
}
@Override
public NpyDoubleArray asDoubleArray() {
double[] doubles = new double[data.length];
for (int i = 0; i < data.length; i++) {
doubles[i] = data[i];
}
return new NpyDoubleArray(copyShape(), doubles, fortranOrder);
}
@Override
public NpyFloatArray asFloatArray() {
float[] floats = new float[data.length];
for (int i = 0; i < data.length; i++) {
floats[i] = data[i];
}
return new NpyFloatArray(copyShape(), floats, fortranOrder);
}
@Override
public NpyIntArray asIntArray() {
int[] ints = new int[data.length];
for (int i = 0; i < data.length; i++) {
ints[i] = data[i];
}
return new NpyIntArray(copyShape(), ints, fortranOrder);
}
@Override
public NpyLongArray asLongArray() {
long[] longs = new long[data.length];
for (int i = 0; i < data.length; i++) {
longs[i] = data[i];
}
return new NpyLongArray(copyShape(), longs, fortranOrder);
}
}

View File

@ -161,21 +161,4 @@ public class NpyUtil {
throw new NpyFormatException("Unsupported data type: " + dataType);
}
}
/**
* Convert Npy array to MeteoInfo array
*
* @param npyArray Npy array
* @return MeteoInfo array
*/
public static Array toMIArray(NpyArray npyArray) {
DataType dataType = toMIDataType(npyArray.dataType());
int[] shape = npyArray.shape();
Array array = Array.factory(dataType, shape);
for (int i = 0; i < array.getSize(); i++) {
array.setObject(i, npyArray.getElement(i));
}
return array;
}
}

View File

@ -91,38 +91,6 @@ public class Npz {
}
}
/**
* Read an array from an entry of a NPZ file.
*
* @param npz the NPZ file
* @param entry the name of the entry in which the array is stored
* @return the NPY array of the entry
*/
public static NpyArray<?> read(File npz, String entry) {
try (ZipFile zip = new ZipFile(npz)) {
return read(zip, entry);
} catch (IOException e) {
throw new RuntimeException("failed to read zip file: " + npz, e);
}
}
/**
* Read an array from an entry of a NPZ file.
*
* @param npz the NPZ file
* @param entry the name of the entry in which the array is stored
* @return the NPY array of the entry
*/
public static NpyArray<?> read(ZipFile npz, String entry) {
ZipEntry e = npz.getEntry(entry);
try (java.io.InputStream stream = npz.getInputStream(e);
java.nio.channels.ReadableByteChannel channel = Channels.newChannel(stream)) {
return Npy.read(channel);
} catch (IOException ex) {
throw new RuntimeException("failed to read entry " + entry, ex);
}
}
/**
* Open the given file as an NPZ file. This function is useful when you want
* to do multiple things with a NPZ file, e.g.
@ -183,15 +151,4 @@ public class Npz {
}
}
public static void write(ZipOutputStream npz, String entry, NpyArray<?> array) {
ZipEntry e = new ZipEntry(entry);
try {
npz.putNextEntry(e);
Npy.write(npz, array);
npz.closeEntry();
} catch (IOException ex) {
throw new RuntimeException("failed to write NPZ entry: " + entry, ex);
}
}
}

View File

@ -1,197 +0,0 @@
package org.meteoinfo.ndarray.io.npy;
import java.math.BigInteger;
class OrderSwitch2d<T extends NpyArray<?>> {
private final T array;
private final int rows;
private final int cols;
private OrderSwitch2d(T array) {
this.array = array;
this.rows = Array2d.rowCountOf(array);
this.cols = Array2d.columnCountOf(array);
}
static <T extends NpyArray<?>> T of(T array) {
return new OrderSwitch2d<T>(array).apply();
}
@SuppressWarnings("unchecked")
private T apply() {
if (array.isBigIntegerArray())
return (T) switchBigInts((NpyBigIntArray) array);
if (array.isBooleanArray())
return (T) switchBooleans(array.asBooleanArray());
if (array.isByteArray())
return (T) switchBytes(array.asByteArray());
if (array.isCharArray())
return (T) switchChars(array.asCharArray());
if (array.isDoubleArray())
return (T) switchDoubles(array.asDoubleArray());
if (array.isFloatArray())
return (T) switchFloats(array.asFloatArray());
if (array.isIntArray())
return (T) switchInts(array.asIntArray());
if (array.isLongArray())
return (T) switchLongs(array.asLongArray());
if (array.isShortArray())
return (T) switchShorts(array.asShortArray());
throw new IllegalArgumentException("unsupported array type: " + array);
}
private NpyBigIntArray switchBigInts(NpyBigIntArray a) {
BigInteger[] data = a.data;
BigInteger[] newData = new BigInteger[data.length];
iter((pos, newPos) -> {
BigInteger value = data[pos];
if (value == null)
return;
newData[newPos] = value; // BigInts are immutable; so this is fine
});
return a.hasColumnOrder()
? NpyBigIntArray.rowOrderOf(newData, rows, cols)
: NpyBigIntArray.columnOrderOf(newData, rows, cols);
}
private NpyBooleanArray switchBooleans(NpyBooleanArray a) {
boolean[] data = a.data;
boolean[] newData = new boolean[data.length];
iter((pos, newPos) -> {
boolean value = data[pos];
if (!value)
return;
newData[newPos] = true;
});
return a.hasColumnOrder()
? NpyBooleanArray.rowOrderOf(newData, rows, cols)
: NpyBooleanArray.columnOrderOf(newData, rows, cols);
}
private NpyByteArray switchBytes(NpyByteArray a) {
byte[] data = a.data;
byte[] newData = new byte[data.length];
iter((pos, newPos) -> {
byte value = data[pos];
if (value == 0)
return;
newData[newPos] = value;
});
return a.hasColumnOrder()
? NpyByteArray.rowOrderOf(newData, rows, cols)
: NpyByteArray.columnOrderOf(newData, rows, cols);
}
private NpyCharArray switchChars(NpyCharArray a) {
char[] data = a.data;
char[] newData = new char[data.length];
iter((pos, newPos) -> {
char value = data[pos];
if (value == 0)
return;
newData[newPos] = value;
});
return a.hasColumnOrder()
? new NpyCharArray(new int[]{rows, cols}, newData, false)
: new NpyCharArray(new int[]{rows, cols}, newData, true);
}
private NpyDoubleArray switchDoubles(NpyDoubleArray a) {
double[] data = a.data;
double[] newData = new double[data.length];
iter((pos, newPos) -> {
double value = data[pos];
if (value == 0)
return;
newData[newPos] = value;
});
return a.hasColumnOrder()
? NpyDoubleArray.rowOrderOf(newData, rows, cols)
: NpyDoubleArray.columnOrderOf(newData, rows, cols);
}
private NpyFloatArray switchFloats(NpyFloatArray a) {
float[] data = a.data;
float[] newData = new float[data.length];
iter((pos, newPos) -> {
float value = data[pos];
if (value == 0)
return;
newData[newPos] = value;
});
return a.hasColumnOrder()
? NpyFloatArray.rowOrderOf(newData, rows, cols)
: NpyFloatArray.columnOrderOf(newData, rows, cols);
}
private NpyIntArray switchInts(NpyIntArray a) {
int[] data = a.data;
int[] newData = new int[data.length];
iter((pos, newPos) -> {
int value = data[pos];
if (value == 0)
return;
newData[newPos] = value;
});
return a.hasColumnOrder()
? NpyIntArray.rowOrderOf(newData, rows, cols)
: NpyIntArray.columnOrderOf(newData, rows, cols);
}
private NpyLongArray switchLongs(NpyLongArray a) {
long[] data = a.data;
long[] newData = new long[data.length];
iter((pos, newPos) -> {
long value = data[pos];
if (value == 0)
return;
newData[newPos] = value;
});
return a.hasColumnOrder()
? NpyLongArray.rowOrderOf(newData, rows, cols)
: NpyLongArray.columnOrderOf(newData, rows, cols);
}
private NpyShortArray switchShorts(NpyShortArray a) {
short[] data = a.data;
short[] newData = new short[data.length];
iter((pos, newPos) -> {
short value = data[pos];
if (value == 0)
return;
newData[newPos] = value;
});
return a.hasColumnOrder()
? NpyShortArray.rowOrderOf(newData, rows, cols)
: NpyShortArray.columnOrderOf(newData, rows, cols);
}
private void iter(IndexFn fn) {
int pos = 0;
if (array.hasColumnOrder()) {
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
int newPos = row * cols + col;
fn.accept(pos, newPos);
pos++;
}
}
} else {
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
int newPos = col * rows + row;
fn.accept(pos, newPos);
pos++;
}
}
}
}
@FunctionalInterface
interface IndexFn {
void accept(int pos, int newPos);
}
}

View File

@ -41,7 +41,7 @@ public final class AttributeTable implements Cloneable {
private int _headerLength;
private int _recordLength;
private int _numFields;
private List<Field> _columns;
private List<Field> fields;
private byte _fileType;
private EndianDataOutputStream _writer;
private File _file;
@ -87,7 +87,7 @@ public final class AttributeTable implements Cloneable {
private void configure() {
_fileType = 0x03;
_dataTable = new DataTable();
_columns = new ArrayList<>();
fields = new ArrayList<>();
_attributesPopulated = true; // only turn this false during an "open" method
_deletedRows = new ArrayList<>();
_characterContent = new char[1];
@ -263,7 +263,7 @@ public final class AttributeTable implements Cloneable {
_numFields = (_headerLength - FileDescriptorSize - 1) / FileDescriptorSize;
// _numFields = (_headerLength - FileDescriptorSize) / FileDescriptorSize;
_columns = new ArrayList<>();
fields = new ArrayList<>();
for (int i = 0; i < _numFields; i++) {
arr = new byte[18];
@ -304,7 +304,7 @@ public final class AttributeTable implements Cloneable {
Field myField = new Field(name, Code, tempLength, decimalcount);
//myField.DataAddress = dataAddress; // not sure what this does yet
_columns.add(myField); // Store fields accessible by an index
fields.add(myField); // Store fields accessible by an index
_dataTable.getColumns().add(myField);
}
@ -416,7 +416,7 @@ public final class AttributeTable implements Cloneable {
for (int col = 0; col < _dataTable.getColumns().size(); col++) {
// find the length of the field.
Field CurrentField = _columns.get(col);
Field CurrentField = fields.get(col);
// find the field type
char tempFieldType = CurrentField.getTypeCharacter();
@ -494,6 +494,19 @@ public final class AttributeTable implements Cloneable {
return result;
}
/**
* Add a field
*
* @param field The field to be added
*/
public void addField(Field field) {
if (fields == null) {
fields = new ArrayList<>();
}
fields.add(field);
this._dataTable.addColumn(field);
}
/**
* Save the file
*/
@ -565,13 +578,13 @@ public final class AttributeTable implements Cloneable {
_numRecords = this._dataTable.getRows().size();
_updateDate = LocalDateTime.now();
_headerLength = FileDescriptorSize + FileDescriptorSize * _dataTable.getColumns().size() + 1;
if (_columns == null) {
_columns = new ArrayList<>();
if (fields == null) {
fields = new ArrayList<>();
}
// Delete any fields from the columns list that are no
// longer in the data Table.
List<Field> removeFields = new ArrayList<>();
for (Field fld : _columns) {
for (Field fld : fields) {
if (!_dataTable.getColumnNames().contains(fld.getColumnName())) {
removeFields.add(fld);
} else {
@ -579,7 +592,7 @@ public final class AttributeTable implements Cloneable {
}
}
for (Field field : removeFields) {
_columns.remove(field);
fields.remove(field);
}
// Add new columns that exist in the data Table, but don't have a matching field yet.
@ -588,28 +601,23 @@ public final class AttributeTable implements Cloneable {
if (columnNameExists(dc.getColumnName())) {
continue;
}
// Field fld = (Field) dc;
// if (fld == null) {
// fld = new Field(dc);
// }
Field fld = new Field(dc);
tempColumns.add(fld);
}
}
_columns = tempColumns;
fields = tempColumns;
// Recalculate the recordlength
for (Field fld : _columns) {
for (Field fld : fields) {
//_recordLength = _recordLength + fld.Length + 1;
_recordLength = _recordLength + fld.getLength();
}
}
private boolean columnNameExists(String name) {
for (Field fld : _columns) {
for (Field fld : fields) {
if (fld.getColumnName().equals(name)) {
return true;
}
@ -647,8 +655,8 @@ public final class AttributeTable implements Cloneable {
// write all of the header records
Field currentField;
for (int i = 0; i < _columns.size(); i++) {
currentField = _columns.get(i);
for (int i = 0; i < fields.size(); i++) {
currentField = fields.get(i);
// write the field name
byte[] bytes = currentField.getColumnName().getBytes(this.encoding);
for (int j = 0; j < 11; j++) {
@ -695,8 +703,8 @@ public final class AttributeTable implements Cloneable {
//int len = _recordLength - 1;
StringBuffer tmps;
//String s;
for (int fld = 0; fld < _columns.size(); fld++) {
Field currentField = _columns.get(fld);
for (int fld = 0; fld < fields.size(); fld++) {
Field currentField = fields.get(fld);
String name = currentField.getColumnName();
Object columnValue = _dataTable.getRows().get(row).getValue(name);
@ -727,11 +735,15 @@ public final class AttributeTable implements Cloneable {
case 'n':
// int?
String fs;
if (currentField.getDataType() == DataType.INT) {
fs = String.format("%1$" + String.valueOf(currentField.getLength()) + "d", columnValue);
} else {
fs = String.format("%1$" + String.valueOf(currentField.getLength()) + "."
+ String.valueOf(currentField.getDecimalCount()) + "f", columnValue);
switch (currentField.getDataType()) {
case INT:
case LONG:
fs = String.format("%1$" + String.valueOf(currentField.getLength()) + "d", columnValue);
break;
default:
fs = String.format("%1$" + String.valueOf(currentField.getLength()) + "."
+ String.valueOf(currentField.getDecimalCount()) + "f", columnValue);
break;
}
if (fs.length() > currentField.getLength()) {
fs = fs.substring(0, currentField.getLength());

View File

@ -254,6 +254,8 @@ public class DataColumn {
switch (this.dataType) {
case INT:
return Integer.MIN_VALUE;
case LONG:
return Long.MIN_VALUE;
case FLOAT:
return Float.NaN;
case DOUBLE:
@ -275,6 +277,14 @@ public class DataColumn {
return Integer.valueOf(vStr);
}
break;
case LONG:
if (!(value instanceof Long)) {
String vStr = value.toString();
if (vStr.isEmpty())
return Long.MIN_VALUE;
return Long.valueOf(vStr);
}
break;
case DOUBLE:
if (!(value instanceof Double)) {
String vStr = value.toString();

View File

@ -68,6 +68,7 @@ import org.meteoinfo.ndarray.DataType;
fieldNumDec = 9;
break;
case INT:
case LONG:
fieldLen = 11;
break;
case BOOLEAN:
@ -183,6 +184,7 @@ import org.meteoinfo.ndarray.DataType;
return 'F';
case DOUBLE:
case INT:
case LONG:
return 'N';
default:
return 'C';