All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bc.zarr.ZarrHeader Maven / Gradle / Ivy

Go to download

JZarr is a Java library providing an implementation of chunked, compressed, N-dimensional arrays close to the zarr-python package.

The newest version!
/*
 *
 * MIT License
 *
 * Copyright (c) 2020. Brockmann Consult GmbH ([email protected])
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
package com.bc.zarr;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.StreamSupport;

public class ZarrHeader {

    private final int[] chunks;
    private final Compressor compressor;
    private final String dimension_separator;
    private final String dtype;
    private final Number fill_value;
    private final String filters = null;
    private final String order = "C";
    private final int[] shape;
    private final int zarr_format = 2;

    public ZarrHeader(int[] shape, int[] chunks, String dtype, ByteOrder byteOrder, Number fill_value, Compressor compressor, String dimension_separator) {
        this.chunks = chunks;
        if (compressor == null || CompressorFactory.nullCompressor.equals(compressor)) {
            this.compressor = null;
        } else {
            this.compressor = compressor;
        }

        final int numBytes = Integer.parseInt(dtype.replaceAll("\\D", ""));

        if (numBytes > 1) {
            this.dtype = translateByteOrder(byteOrder) + dtype;
        } else {
            this.dtype = "|" + dtype;
        }
        this.fill_value = fill_value;
        this.shape = shape;

        if (dimension_separator != null) {
            this.dimension_separator = dimension_separator;
        }
        else {
            // consistent with ArrayParams' handling of null separators
            this.dimension_separator = ".";
        }
    }

    public int[] getChunks() {
        return chunks;
    }

    public Compressor getCompressor() {
        return compressor;
    }

    public String getDtype() {
        return dtype;
    }

    public DataType getRawDataType() {
        return getRawDataType(dtype);
    }

    private static DataType getRawDataType(String dtype) {
        dtype = dtype.replace(">", "");
        dtype = dtype.replace("<", "");
        dtype = dtype.replace("|", "");
        return DataType.valueOf(dtype);
    }

    public ByteOrder getByteOrder() {
        return getByteOrder(this.dtype);
    }

    private static ByteOrder getByteOrder(String dtype) {
        if (dtype.startsWith(">")) {
            return ByteOrder.BIG_ENDIAN;
        } else if (dtype.startsWith("<")) {
            return ByteOrder.LITTLE_ENDIAN;
        } else if (dtype.startsWith("|")) {
            return ByteOrder.nativeOrder();
        }
        return ByteOrder.BIG_ENDIAN;
    }

    private String translateByteOrder(ByteOrder order) {
        if (order == null) {
            order = ByteOrder.nativeOrder();
        }
        if (ByteOrder.BIG_ENDIAN.equals(order)) {
            return ">";
        }
        return "<";
    }

    public Number getFill_value() {
        return fill_value;
    }

    public int[] getShape() {
        return shape;
    }

    public String getDimension_separator() {
        return dimension_separator;
    }

    public DimensionSeparator getDimensionSeparator() {
        String separator = this.dimension_separator;
        for (DimensionSeparator sep : DimensionSeparator.values()) {
            if (sep.getSeparatorChar().equals(separator)) {
                return sep;
            }
        }
        return null;
    }

    static class ZarrHeaderSerializer extends StdSerializer {

        protected ZarrHeaderSerializer() {
            super(ZarrHeader.class);
        }

        @Override
        public void serialize(ZarrHeader value, JsonGenerator gen, SerializerProvider provider) throws IOException {
            gen.writeStartObject();
            gen.writeObjectField("chunks", value.getChunks());
            gen.writeFieldName("compressor");
            gen.writeObject(value.getCompressor());
            gen.writeStringField("dtype", value.getDtype());
            gen.writeObjectField("fill_value", value.getFill_value());
            gen.writeObjectField("filters", value.filters);
            gen.writeObjectField("order", value.order);
            gen.writeObjectField("shape", value.getShape());
            gen.writeStringField("dimension_separator", value.getDimension_separator());
            gen.writeNumberField("zarr_format", value.zarr_format);
            gen.writeEndObject();
        }
    }

    static class ZarrHeaderDeSerializer extends StdDeserializer {

        protected ZarrHeaderDeSerializer() {
            super(ZarrHeader.class);
        }

        @Override
        public ZarrHeader deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            ObjectCodec codec = p.getCodec();
            TreeNode root = codec.readTree(p);
            int[] shape = StreamSupport.stream(((ArrayNode) root.path("shape")).spliterator(), false).mapToInt(JsonNode::asInt).toArray();
            int[] chunks = StreamSupport.stream(((ArrayNode) root.path("chunks")).spliterator(), false).mapToInt(JsonNode::asInt).toArray();
            String dtype = ((JsonNode) root.path("dtype")).asText();
            JsonNode fillValueNode = (JsonNode) root.path("fill_value");
            final Number fill;
            if (fillValueNode.isLong()) {
                fill = fillValueNode.longValue();
            } else if (fillValueNode.isFloat()) {
                fill = fillValueNode.floatValue();
            } else {
                fill = fillValueNode.asDouble();
            }

            Map compBean = codec.readValue(root.path("compressor").traverse(codec), HashMap.class);
            Compressor compressor;
            if (compBean == null) {
                compressor = CompressorFactory.nullCompressor;
            } else {
                compressor = CompressorFactory.create(compBean);
            }
            final JsonNode separatorNode = (JsonNode) root.path("dimension_separator");
            String dimension_separator = null;
            if (separatorNode != null) {
                dimension_separator = separatorNode.asText();
            }
            return new ZarrHeader(shape, chunks, getRawDataType(dtype).toString(), getByteOrder(dtype), fill, compressor, dimension_separator);
        }

    }

    static void register(ObjectMapper objectMapper) {
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(ZarrHeader.class, new ZarrHeaderSerializer());
        simpleModule.addDeserializer(ZarrHeader.class, new ZarrHeaderDeSerializer());

        objectMapper.registerModules(simpleModule);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy