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

ucar.nc2.dataset.CoordinateAxis1DTime Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */

package ucar.nc2.dataset;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ucar.nc2.time.*;
import ucar.nc2.units.TimeUnit;
import ucar.nc2.Variable;
import ucar.nc2.Dimension;
import ucar.nc2.Attribute;
import ucar.nc2.util.NamedAnything;
import ucar.nc2.util.NamedObject;
import ucar.ma2.*;

import java.util.*;
import java.io.IOException;

import ucar.nc2.units.DateRange;

/**
 * A 1-dimensional Coordinate Axis representing Calendar time.
 * Its coordinate values can be represented as Dates.
 * 

* May use udunit dates, or ISO Strings. * * @author caron */ public class CoordinateAxis1DTime extends CoordinateAxis1D { static private final Logger logger = LoggerFactory.getLogger(CoordinateAxis1DTime.class); static public CoordinateAxis1DTime factory(NetcdfDataset ncd, VariableDS org, Formatter errMessages) throws IOException { if (org instanceof CoordinateAxis1DTime) return (CoordinateAxis1DTime) org; if (org.getDataType() == DataType.CHAR) return new CoordinateAxis1DTime(ncd, org, errMessages, org.getDimension(0).getShortName()); else if (org.getDataType() == DataType.STRING) return new CoordinateAxis1DTime(ncd, org, errMessages, org.getDimensionsString()); else return new CoordinateAxis1DTime(ncd, org, errMessages); } //////////////////////////////////////////////////////////////// private final CoordinateAxisTimeHelper helper; private List cdates = null; // for section and slice @Override protected Variable copy() { return new CoordinateAxis1DTime(this.ncd, this); } // copy constructor private CoordinateAxis1DTime(NetcdfDataset ncd, CoordinateAxis1DTime org) { super(ncd, org); helper = org.helper; this.cdates = org.cdates; } @Override public CoordinateAxis1DTime section(Range r) throws InvalidRangeException { CoordinateAxis1DTime s = (CoordinateAxis1DTime) super.section(r); List cdates = getCalendarDates(); List cdateSection = new ArrayList<>(cdates.size()); for (int idx : r) cdateSection.add(cdates.get( idx)); s.cdates = cdateSection; return s; } /** * Get the the ith CalendarDate. * @param idx index * @return the ith CalendarDate */ public CalendarDate getCalendarDate (int idx) { List cdates = getCalendarDates(); // in case we want to lazily evaluate return cdates.get(idx); } /** * Get calendar date range * @return calendar date range */ public CalendarDateRange getCalendarDateRange() { List cd = getCalendarDates(); int last = cd.size(); return (last > 0) ? CalendarDateRange.of(cd.get(0), cd.get(last-1)) : null; } @Override public List getNames() { List cdates = getCalendarDates(); List names = new ArrayList<>(cdates.size()); for (CalendarDate cd : cdates) names.add(new NamedAnything(CalendarDateFormatter.toDateTimeStringISO(cd), getShortName())); // "calendar date")); return names; } /** * only if isRegular() LOOK REDO * * @return time unit * @throws Exception on bad unit string */ public TimeUnit getTimeResolution() throws Exception { String tUnits = getUnitsString(); StringTokenizer stoker = new StringTokenizer(tUnits); double tResolution = getIncrement(); return new TimeUnit(tResolution, stoker.nextToken()); } /** * Given a Date, find the corresponding time index on the time coordinate axis. * Can only call this is hasDate() is true. * This will return *

    *
  • i, if time(i) <= d < time(i+1). *
  • 0, if d < time(0) *
  • n-1, if d > time(n-1), where n is length of time coordinates *
* * @param d date to look for * @return corresponding time index on the time coordinate axis * @throws UnsupportedOperationException is no time axis or isDate() false */ public int findTimeIndexFromCalendarDate(CalendarDate d) { List cdates = getCalendarDates(); // LOOK linear search, switch to binary int index = 0; while (index < cdates.size()) { if (d.compareTo(cdates.get(index)) < 0) break; index++; } return Math.max(0, index - 1); } /** * See if the given CalendarDate appears as a coordinate * * @param date test this * @return true if equals a coordinate */ public boolean hasCalendarDate(CalendarDate date) { List cdates = getCalendarDates(); for (CalendarDate cd : cdates) { // LOOK linear search, switch to binary if (date.equals(cd)) return true; } return false; } /** * Get the list of datetimes in this coordinate as CalendarDate objects. * @return list of CalendarDates. */ public List getCalendarDates() { return cdates; } public CalendarDate[] getCoordBoundsDate( int i) { double[] intv = getCoordBounds(i); CalendarDate[] e = new CalendarDate[2]; e[0] = helper.makeCalendarDateFromOffset(intv[0]); e[1] = helper.makeCalendarDateFromOffset(intv[1]); return e; } public CalendarDate getCoordBoundsMidpointDate( int i) { double[] intv = getCoordBounds(i); double midpoint = (intv[0]+intv[1])/2; return helper.makeCalendarDateFromOffset(midpoint); } //////////////////////////////////////////////////////////////////////// /** * Constructor for CHAR or STRING variables. * Must be ISO dates. * * @param ncd the containing dataset * @param org the underlying Variable * @param errMessages put error messages here; may be null * @param dims list of dimensions * @throws IOException on read error * @throws IllegalArgumentException if cant convert coordinate values to a Date */ private CoordinateAxis1DTime(NetcdfDataset ncd, VariableDS org, Formatter errMessages, String dims) throws IOException { super(ncd, org.getParentGroup(), org.getShortName(), DataType.STRING, dims, org.getUnitsString(), org.getDescription()); //Gotta set the original var. Otherwise it would be unable to read the values this.orgVar = org; this.orgName = org.orgName; this.helper = new CoordinateAxisTimeHelper(getCalendarFromAttribute(), null); if (org.getDataType() == DataType.CHAR) cdates = makeTimesFromChar(org, errMessages); else cdates = makeTimesFromStrings(org, errMessages); List atts = org.getAttributes(); for (Attribute att : atts) { addAttribute(att); } } private List makeTimesFromChar(VariableDS org, Formatter errMessages) throws IOException { int ncoords = (int) org.getSize(); int rank = org.getRank(); int strlen = org.getShape(rank - 1); ncoords /= strlen; List result = new ArrayList<>(ncoords); ArrayChar data = (ArrayChar) org.read(); ArrayChar.StringIterator ii = data.getStringIterator(); ArrayObject.D1 sdata = (ArrayObject.D1) Array.factory(DataType.STRING, new int[] {ncoords}); for (int i = 0; i < ncoords; i++) { String coordValue = ii.next(); CalendarDate cd = makeCalendarDateFromStringCoord(coordValue, org, errMessages); sdata.set(i, coordValue); result.add( cd); } setCachedData(sdata, true); return result; } private List makeTimesFromStrings( VariableDS org, Formatter errMessages) throws IOException { int ncoords = (int) org.getSize(); List result = new ArrayList<>(ncoords); ArrayObject data = (ArrayObject) org.read(); IndexIterator ii = data.getIndexIterator(); for (int i = 0; i < ncoords; i++) { String coordValue = (String) ii.getObjectNext(); CalendarDate cd = makeCalendarDateFromStringCoord( coordValue, org, errMessages); result.add(cd); } return result; } private CalendarDate makeCalendarDateFromStringCoord(String coordValue, VariableDS org, Formatter errMessages) throws IOException { CalendarDate cd = helper.makeCalendarDateFromOffset(coordValue); if (cd == null) { if (errMessages != null) { errMessages.format("String time coordinate must be ISO formatted= %s%n", coordValue); logger.info("Char time coordinate must be ISO formatted= {} file = {}", coordValue, org.getDatasetLocation()); } throw new IllegalArgumentException(); } return cd; } /** * Constructor for numeric values - must have units * @param ncd the containing dataset * @param org the underlying Variable * @throws IOException on read error */ private CoordinateAxis1DTime(NetcdfDataset ncd, VariableDS org, Formatter errMessages) throws IOException { super(ncd, org); this.helper= new CoordinateAxisTimeHelper(getCalendarFromAttribute(), getUnitsString()); // make the coordinates int ncoords = (int) org.getSize(); List result = new ArrayList<>(ncoords); Array data = org.read(); int count = 0; IndexIterator ii = data.getIndexIterator(); for (int i = 0; i < ncoords; i++) { double val = ii.getDoubleNext(); if (Double.isNaN(val)) continue; // WTF ?? result.add( helper.makeCalendarDateFromOffset(val)); count++; } // if we encountered NaNs, shorten it up if (count != ncoords) { Dimension localDim = new Dimension(getShortName(), count, false); setDimension(0, localDim); // set the shortened values Array shortData = Array.factory(data.getDataType(), new int[]{count}); Index ima = shortData.getIndex(); int count2 = 0; ii = data.getIndexIterator(); for (int i = 0; i < ncoords; i++) { double val = ii.getDoubleNext(); if (Double.isNaN(val)) continue; shortData.setDouble(ima.set0(count2), val); count2++; } // here we have to decouple from the original variable cache = new Cache(); setCachedData(shortData, true); } cdates = result; } /////////////////////////////////////////////////////// /** * Does not handle non-standard Calendars * @deprecated use getCalendarDates() to correctly interpret calendars */ public java.util.Date[] getTimeDates() { List cdates = getCalendarDates(); Date[] timeDates = new Date[cdates.size()]; int index = 0; for (CalendarDate cd : cdates) timeDates[index++] = cd.toDate(); return timeDates; } /** * Does not handle non-standard Calendars * @deprecated use getCalendarDate() */ public java.util.Date getTimeDate (int idx) { return getCalendarDate(idx).toDate(); } /** * Does not handle non-standard Calendars * @deprecated use getCalendarDateRange() */ public DateRange getDateRange() { CalendarDateRange cdr = getCalendarDateRange(); return cdr.toDateRange(); } /** * Does not handle non-standard Calendars * @deprecated use findTimeIndexFromCalendarDate */ public int findTimeIndexFromDate(java.util.Date d) { return findTimeIndexFromCalendarDate( CalendarDate.of(d)); } /** * Does not handle non-standard Calendars * @deprecated use hasCalendarDate */ public boolean hasTime(Date date) { List cdates = getCalendarDates(); for (CalendarDate cd : cdates) { if (date.equals(cd.toDate())) return true; } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy