AscDataReader extends DataReader { @Override public List<VortexData> getDtos() { String fileName = new File(path).getName().toLowerCase(); String shortName; String fullName; String description; AtomicBoolean isPrismTemporalDaily = new AtomicBoolean(); AtomicBoolean isPrismTemporalMonthly = new AtomicBoolean(); AtomicBoolean isPrismNormal = new AtomicBoolean(); AtomicBoolean isQpfHourly = new AtomicBoolean(); if (fileName.matches("prism.*ppt.*stable.*")) { shortName = "precipitation"; fullName = "precipitation"; description = "precipitation"; if (fileName.matches("prism.*ppt.*stable.*(d1|d2).*")) isPrismTemporalDaily.set(true); if (fileName.matches("prism.*ppt.*stable.*m3.*")) isPrismTemporalMonthly.set(true); } else if (fileName.matches("prism.*ppt.*normal.*")) { shortName = "precipitation"; fullName = "precipitation"; description = "precipitation"; isPrismNormal.set(true); } else if (fileName.matches("prism.*tmean.*stable.*")){ shortName = "mean temperature"; fullName = "mean temperature"; description = "mean temperature"; if (fileName.matches("prism.*tmean.*stable.*(d1|d2).*")) isPrismTemporalDaily.set(true); if (fileName.matches("prism.*tmean.*stable.*m3.*")) isPrismTemporalMonthly.set(true); } else if (fileName.matches("prism.*tmin.*stable.*")){ shortName = "minimum temperature"; fullName = "minimum temperature"; description = "minimum temperature"; if (fileName.matches("prism.*tmin.*stable.*d2.*(d1|d2).*")) isPrismTemporalDaily.set(true); if (fileName.matches("prism.*tmin.*stable.*m3.*")) isPrismTemporalMonthly.set(true); } else if (fileName.matches("prism.*tmax.*stable.*")){ shortName = "maximum temperature"; fullName = "maximum temperature"; description = "maximum temperature"; if (fileName.matches("prism.*tmax.*stable.*(d1|d2).*")) isPrismTemporalDaily.set(true); if (fileName.matches("prism.*tmax.*stable.*m3.*")) isPrismTemporalMonthly.set(true); } else if (fileName.matches("prism.*tdmean.*stable.*")){ shortName = "mean dewpoint temperature"; fullName = "mean dewpoint temperature"; description = "mean dewpoint temperature"; if (fileName.matches("prism.*tdmean.*stable.*(d1|d2).*")) isPrismTemporalDaily.set(true); if (fileName.matches("prism.*tdmean.*stable.*m3.*")) isPrismTemporalMonthly.set(true); } else if (fileName.matches("prism.*vpdmin.*stable.*")){ shortName = "minimum vapor pressure deficit"; fullName = "minimum vapor pressure deficit"; description = "minimum vapor pressure deficit"; if (fileName.matches("prism.*vpdmin.*stable.*(d1|d2).*")) isPrismTemporalDaily.set(true); if (fileName.matches("prism.*vpdmin.*stable.*m3.*")) isPrismTemporalMonthly.set(true); } else if (fileName.matches("prism.*vpdmax.*stable.*")){ shortName = "maximum vapor pressure deficit"; fullName = "maximum vapor pressure deficit"; description = "maximum vapor pressure deficit"; if (fileName.matches("prism.*vpdmax.*stable.*(d1|d2).*")) isPrismTemporalDaily.set(true); if (fileName.matches("prism.*vpdmax.*stable.*m3.*")) isPrismTemporalMonthly.set(true); } else if (fileName.matches("qpf.*1hr.*")) { shortName = "precipitation"; fullName = "precipitation"; description = "precipitation"; isQpfHourly.set(true); } else if (fileName.matches(".*yr.*ha.*")) { shortName = "precipitation-frequency"; fullName = "precipitation-frequency"; description = "precipitation-frequency"; } else if (fileName.toLowerCase().matches("windspeed.*")) { shortName = "windspeed"; fullName = "windspeed"; description = "windspeed"; } else { shortName = ""; fullName = ""; description = ""; } ZonedDateTime startTime; ZonedDateTime endTime; Duration interval; if (isPrismTemporalDaily.get()) { String string1 = path; String string2 = string1.substring(0, string1.lastIndexOf('_')); String string3 = string2.substring(string2.length() - 8); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); LocalDate date = LocalDate.parse(string3, formatter); startTime = ZonedDateTime.of(LocalDateTime.of(date, LocalTime.of(0, 0)), ZoneId.of("UTC")).minusHours(12); endTime = ZonedDateTime.of(LocalDateTime.of(date.plusDays(1), LocalTime.of(0, 0)), ZoneId.of("UTC")).minusHours(12); interval = Duration.between(startTime, endTime); } else if (isPrismNormal.get()){ startTime = ZonedDateTime.of(1981, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")); endTime = ZonedDateTime.of(2010, 12, 31, 0, 0, 0, 0, ZoneId.of("UTC")); interval = Duration.between(startTime, endTime); } else if (isPrismTemporalMonthly.get()) { Pattern pattern = Pattern.compile("\\d{6}"); Matcher matcher = pattern.matcher(path); String dateString = ""; while (matcher.find()) { dateString = matcher.group(0); } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM"); YearMonth yearMonth; try { yearMonth = YearMonth.parse(dateString, formatter); } catch (DateTimeParseException e) { logger.log(Level.WARNING, e, e::getMessage); return Collections.emptyList(); } LocalDateTime startDay = LocalDateTime.of(yearMonth.getYear(), yearMonth.getMonth(), 1, 0, 0); startTime = ZonedDateTime.of(startDay, ZoneId.of("UTC")); endTime = startTime.plusMonths(1); interval = Duration.between(startTime, endTime); } else if (isQpfHourly.get()) { String filenameSansExt = fileName.replaceFirst("[.][^.]+$", ""); String dateString = filenameSansExt.substring(filenameSansExt.length() - 8); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHH"); LocalDateTime localDateTime = LocalDateTime.parse(dateString, formatter); endTime = ZonedDateTime.of(localDateTime, ZoneId.of("UTC")); startTime = endTime.minusHours(1); interval = Duration.ofHours(1); } else { Pattern pattern = Pattern.compile("\\d{4}_\\d{2}_\\d{2}t\\d{4}"); Matcher matcher = pattern.matcher(fileName); List<String> dateStrings = new ArrayList<>(); while (matcher.find()){ dateStrings.add(matcher.group(0)); } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd't'Hmm"); if (dateStrings.size() == 2) { startTime = ZonedDateTime.of(LocalDateTime.parse(dateStrings.get(0), formatter), ZoneId.of("Z")); endTime = ZonedDateTime.of(LocalDateTime.parse(dateStrings.get(1), formatter), ZoneId.of("Z")); interval = Duration.between(startTime, endTime); } else if(dateStrings.size() == 1 ) { startTime = ZonedDateTime.of(LocalDateTime.parse(dateStrings.get(0), formatter), ZoneId.of("Z")); endTime = ZonedDateTime.from(startTime); interval = Duration.ZERO; } else { startTime = null; endTime = null; interval = null; } } String units; if (fileName.contains("ppt") || fileName.contains("qpf")){ units = "mm"; } else if (fileName.contains("tmean")){ units = "Degrees C"; } else if (fileName.contains("tmin")){ units = "Degrees C"; } else if (fileName.contains("tmax")){ units = "Degrees C"; } else if (fileName.contains("tdmean")){ units = "Degrees C"; } else if (fileName.contains("vpdmin")){ units = "hPa"; } else if (fileName.contains("vpdmax")) { units = "hPa"; } else if (fileName.matches(".*yr.*ha.*")) { units = "1/1000 in"; } else { units = ""; } Dataset dataset = gdal.Open(path); double[] geoTransform = dataset.GetGeoTransform(); double dx = geoTransform[1]; double dy = geoTransform[5]; double ulx = geoTransform[0]; double uly = geoTransform[3]; int nx = dataset.GetRasterXSize(); int ny = dataset.GetRasterYSize(); String wkt = dataset.GetProjection(); Band band = dataset.GetRasterBand(1); float[] data = new float[nx * ny]; band.ReadRaster(0, 0, nx, ny, gdalconst.GDT_Float32, data); dataset.delete(); band.delete(); VortexGrid dto = VortexGrid.builder() .dx(dx).dy(dy).nx(nx).ny(ny) .originX(ulx).originY(uly) .wkt(wkt).data(data).units(units) .fileName(path).shortName(shortName) .fullName(fullName).description(description) .startTime(startTime).endTime(endTime) .interval(interval) .build(); List<VortexData> list = new ArrayList<>(); list.add(dto); return list; } AscDataReader(DataReaderBuilder builder); @Override List<VortexData> getDtos(); static Set<String> getVariables(String pathToAsc); @Override int getDtoCount(); @Override VortexData getDto(int idx);  }
@Test void PrismImportPassesRegression() { String path = new File(getClass().getResource( "/regression/io/asc_reader/PRISM_ppt_stable_4kmD2_20170101_asc.asc").getFile()).toString(); DataReader reader = DataReader.builder() .path(path) .variable("ppt") .build(); VortexGrid grid = (VortexGrid) reader.getDtos().get(0); float[] data = grid.data(); float max = Float.MIN_VALUE; for (float datum : data) { max = Math.max(max, datum); } assertEquals(208.298, max, 1E-3); assertEquals(.04167, grid.dx(), 1E-3); assertEquals(621, grid.ny()); assertEquals(1405, grid.nx()); }
@Test void QpfHourlyImport(){ String path = new File(getClass().getResource("/QPF_1HR_AZ_19121900.asc").getFile()).toString(); DataReader reader = DataReader.builder() .path(path) .variable("precipitation") .build(); VortexGrid grid = (VortexGrid) reader.getDtos().get(0); assertEquals(grid.endTime(), ZonedDateTime.of(2019, 12,19, 0, 0, 0, 0, ZoneId.of("UTC"))); }
@Test void Atlas14Import(){ String path = new File(getClass().getResource("/orb100yr24ha/orb100yr24ha.asc").getFile()).toString(); DataReader reader = DataReader.builder() .path(path) .variable("orb100yr24ha") .build(); VortexGrid grid = (VortexGrid) reader.getDtos().get(0); assertNotNull(grid); }