package ucar.coord; import net.jcip.annotations.Immutable; import ucar.nc2.grib.GribNumbers; import ucar.nc2.grib.VertCoord; import ucar.nc2.grib.grib1.Grib1ParamLevel; import ucar.nc2.grib.grib1.Grib1Record; import ucar.nc2.grib.grib1.Grib1SectionProductDefinition; import ucar.nc2.grib.grib1.tables.Grib1Customizer; import ucar.nc2.grib.grib2.Grib2Pds; import ucar.nc2.grib.grib2.Grib2Record; import ucar.nc2.grib.grib2.Grib2Utils; import ucar.nc2.grib.grib2.table.Grib2Customizer; import ucar.nc2.util.Indent; import ucar.nc2.util.Misc; import java.util.*; /** * Vertical GRIB coordinates * Effectively immutable; setName() can only be called once. * * @author caron * @since 11/27/13 */ @Immutable public class CoordinateVert implements Coordinate { private final List<VertCoord.Level> levelSorted; private final int code; // Grib1 - code table 3; Grib2 - Code table 4.5 private String name; private final VertCoord.VertUnit vunit; private final boolean isLayer; public CoordinateVert(int code, VertCoord.VertUnit vunit, List<VertCoord.Level> levelSorted) { this.levelSorted = Collections.unmodifiableList(levelSorted); this.code = code; this.vunit = vunit; this.isLayer = levelSorted.get(0).isLayer(); } public List<VertCoord.Level> getLevelSorted() { return levelSorted; } @Override public List<? extends Object> getValues() { return levelSorted; } @Override public int getIndex(Object val) { return levelSorted.indexOf(val); } @Override public Object getValue(int idx) { if (idx >= levelSorted.size()) return null; return levelSorted.get(idx); } @Override public int getSize() { return levelSorted.size(); } @Override public Type getType() { return Type.vert; } @Override public int estMemorySize() { return 160 + getSize() * ( 40 + Misc.referenceSize); } @Override public String getUnit() { return vunit == null ? null : vunit.getUnits(); } public VertCoord.VertUnit getVertUnit() { return vunit; } public boolean isLayer() { return isLayer; } public boolean isPositiveUp() { return vunit.isPositiveUp(); } public int getCode() { return code; } @Override public String getName() { return name; } public void setName(String name) { if (this.name != null) throw new IllegalStateException("Cant modify"); this.name = name; } @Override public void showInfo(Formatter info, Indent indent) { info.format("%s%s: ", indent, getType()); for (VertCoord.Level level : levelSorted) info.format(" %s", level); info.format(" (%d)%n", levelSorted.size()); } @Override public void showCoords(Formatter info) { info.format("Levels: (%s)%n", getUnit()); for (VertCoord.Level level : levelSorted) info.format(" %s%n", level); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CoordinateVert that = (CoordinateVert) o; if (code != that.code) return false; if (!levelSorted.equals(that.levelSorted)) return false; return true; } @Override public int hashCode() { int result = levelSorted.hashCode(); result = 31 * result + code; return result; } ////////////////////////////////////////////////////////////// /* public CoordinateBuilder makeBuilder() { return new Builder(code); } */ static public class Builder2 extends CoordinateBuilderImpl<Grib2Record> { int code; VertCoord.VertUnit vunit; public Builder2(int code, VertCoord.VertUnit vunit) { this.code = code; this.vunit = vunit; } @Override public Object extract(Grib2Record gr) { Grib2Pds pds = gr.getPDS(); boolean hasLevel2 = pds.getLevelType2() != GribNumbers.MISSING; double level2val = hasLevel2 ? pds.getLevelValue2() : GribNumbers.UNDEFINEDD; boolean isLayer = Grib2Utils.isLayer(pds); return new VertCoord.Level(pds.getLevelValue1(), level2val, isLayer); } @Override public Coordinate makeCoordinate(List<Object> values) { List<VertCoord.Level> levelSorted = new ArrayList<>(values.size()); for (Object val : values) levelSorted.add( (VertCoord.Level) val); Collections.sort(levelSorted); return new CoordinateVert(code, vunit, levelSorted); } } static public class Builder1 extends CoordinateBuilderImpl<Grib1Record> { int code; Grib1Customizer cust; public Builder1(Grib1Customizer cust, int code) { this.cust = cust; this.code = code; } @Override public Object extract(Grib1Record gr) { Grib1SectionProductDefinition pds = gr.getPDSsection(); boolean isLayer = cust.isLayer(pds.getLevelType()); Grib1ParamLevel plevel = cust.getParamLevel(pds); double level2val = isLayer ? plevel.getValue2() : GribNumbers.UNDEFINEDD; return new VertCoord.Level(plevel.getValue1(), level2val, isLayer); } @Override public Coordinate makeCoordinate(List<Object> values) { List<VertCoord.Level> levelSorted = new ArrayList<>(values.size()); for (Object val : values) levelSorted.add( (VertCoord.Level) val); Collections.sort(levelSorted); return new CoordinateVert(code, cust.getVertUnit(code), levelSorted); } } }