/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.nc2.ft.point;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import ucar.ma2.DataType;
import ucar.ma2.StructureData;
import ucar.ma2.StructureMembers;
import ucar.nc2.NCdumpW;
import ucar.nc2.VariableSimpleIF;
import ucar.nc2.constants.FeatureType;
import ucar.nc2.ft.*;
import ucar.nc2.time.CalendarDateRange;
import ucar.nc2.units.*;
import ucar.unidata.geoloc.EarthLocation;
import ucar.unidata.geoloc.LatLonRect;
import ucar.unidata.util.test.category.NeedsCdmUnitTest;
import ucar.unidata.util.test.TestDir;
import ucar.unidata.util.StringUtil2;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
/**
* Test PointFeatureTypes.
*
* @author caron
* @since Dec 16, 2008
*/
@RunWith(Parameterized.class)
@Category(NeedsCdmUnitTest.class)
public class TestPointDatasets {
public static List<Object[]> getAllFilesInDirectory(String topdir, FileFilter filter) {
List<FileSort> files = new ArrayList<>();
File topDir = new File(topdir);
for (File f : topDir.listFiles()) {
if (filter != null && !filter.accept(f)) continue;
files.add( new FileSort(f));
}
Collections.sort(files);
List<Object[]> result = new ArrayList<>();
for (FileSort f : files) {
result.add(new Object[] {f.path, FeatureType.ANY_POINT});
System.out.printf("%s%n", f.path);
}
return result;
}
private static class FileSort implements Comparable<FileSort> {
String path;
int order = 10;
FileSort(File f) {
this.path = f.getPath();
String name = f.getName().toLowerCase();
if (name.contains("point")) order = 1;
else if (name.contains("stationprofile")) order = 5;
else if (name.contains("station")) order = 2;
else if (name.contains("profile")) order = 3;
else if (name.contains("traj")) order = 4;
else if (name.contains("section")) order = 6;
}
@Override
public int compareTo(FileSort o) {
return order - o.order;
}
}
//////////////////////////////////////////////////////////////////////
public static String topdir = TestDir.cdmUnitTestDir;
private static final boolean showStructureData = false;
public static List<Object[]> getCFDatasets() {
List<Object[]> result = new ArrayList<>();
result.add(new Object[]{topdir + "cfPoint/point/filtered_apriori_super_calibrated_binned1.nc", FeatureType.POINT, 1001});
result.add(new Object[]{topdir + "cfPoint/point/nmcbob.shp.nc", FeatureType.POINT, 1196});
result.add(new Object[]{topdir + "cfPoint/station/rig_tower.2009-02-01.ncml", FeatureType.STATION, 17280});
result.add(new Object[]{topdir + "cfPoint/station/billNewDicast.nc", FeatureType.STATION, 78912});
result.add(new Object[]{topdir + "cfPoint/station/billOldDicast.nc", FeatureType.STATION, 19728});
result.add(new Object[]{topdir + "cfPoint/station/sampleDataset.nc", FeatureType.STATION, 1728});
result.add(new Object[]{topdir + "cfPoint/trajectory/rt_20090512_willy2.ncml", FeatureType.TRAJECTORY, 53176});
result.add(new Object[]{topdir + "cfPoint/trajectory/p1140004.ncml", FeatureType.TRAJECTORY, 245});
result.add(new Object[]{topdir + "cfPoint/stationProfile/timeSeriesProfile-Ragged-SingleStation-H.5.3.nc", FeatureType.STATION_PROFILE, 40});
// CF 1.0 multidim with dimensions reversed
//testPointDataset(topdir+"cfPoint/station/solrad_point_pearson.ncml", FeatureType.STATION, true);
return result;
}
public static List<Object[]> getPlugDatasets() {
List<Object[]> result = new ArrayList<>();
// cosmic
result.add(new Object[]{topdir + "ft/trajectory/cosmic/wetPrf_C005.2007.294.16.22.G17_0001.0002_nc", FeatureType.TRAJECTORY, 383});
// ndbc
result.add(new Object[]{topdir + "ft/station/ndbc/41001h1976.nc", FeatureType.STATION, 1405});
result.add(new Object[]{topdir + "ft/station/suomi/suoHWV_2006.105.00.00.0060_nc", FeatureType.STATION, 124});
result.add(new Object[]{topdir + "ft/station/suomi/gsuPWV_2006.105.00.00.1440_nc", FeatureType.STATION, 4848});
// fsl wind profilers
result.add(new Object[]{topdir + "ft/stationProfile/PROFILER_RASS_01hr_20091027_1500.nc", FeatureType.STATION_PROFILE, 198});
result.add(new Object[]{topdir + "ft/stationProfile/PROFILER_RASS_06min_20091028_2318.nc", FeatureType.STATION_PROFILE, 198});
result.add(new Object[]{topdir + "ft/stationProfile/PROFILER_wind_01hr_20091024_1200.nc", FeatureType.STATION_PROFILE, 1728});
result.add(new Object[]{topdir + "ft/stationProfile/PROFILER_wind_06min_20091030_2330.nc", FeatureType.STATION_PROFILE, 2088});
//gempack sounding
result.add(new Object[]{topdir + "ft/sounding/gempak/19580807_upa.ncml", FeatureType.STATION_PROFILE, 8769});
// gempak surface
result.add(new Object[]{topdir + "ft/point/gempak/2009103008_sb.gem", FeatureType.POINT, 3337});
result.add(new Object[]{topdir + "ft/point/gempak/2009110100_ship.gem", FeatureType.POINT, 938});
result.add(new Object[]{topdir + "ft/station/gempak/20091030_syn.gem", FeatureType.POINT, 55856});
result.add(new Object[]{topdir + "ft/station/gempak/20091030_syn.gem", FeatureType.STATION, 28328});
// netcdf buoy / synoptic / metars ( robb's perl decoder output)
result.add(new Object[]{topdir + "ft/point/netcdf/Surface_METAR_latest.nc", FeatureType.POINT, 7});
result.add(new Object[]{topdir + "ft/point/netcdf/Surface_Buoy_20090921_0000.nc", FeatureType.POINT, 32452});
result.add(new Object[]{topdir + "ft/point/netcdf/Surface_Synoptic_20090921_0000.nc", FeatureType.POINT, 1516});
//RAF-Nimbus
result.add(new Object[]{topdir + "ft/trajectory/aircraft/135_ordrd.nc", FeatureType.TRAJECTORY, 7741});
result.add(new Object[]{topdir + "ft/trajectory/aircraft/raftrack.nc", FeatureType.TRAJECTORY, 8157});
// Madis
result.add(new Object[]{topdir + "ft/trajectory/acars/acars_20091109_0800.nc", FeatureType.TRAJECTORY, 5063});
result.add(new Object[]{topdir + "ft/point/netcdf/19981110_1200", FeatureType.POINT, 2499});
result.add(new Object[]{topdir + "ft/station/madis2/hydro/20050729_1200", FeatureType.STATION, 1374});
result.add(new Object[]{topdir + "ft/sounding/netcdf/20070612_1200", FeatureType.STATION_PROFILE, 1788});
// unidata point obs
result.add(new Object[]{topdir + "ft/station/200501q3h-gr.nc", FeatureType.STATION, 5023});
result.add(new Object[]{topdir + "ft/point/netcdf/20080814_LMA.ncml", FeatureType.POINT, 277477});
// nldn
result.add(new Object[]{topdir + "ft/point/200929100.ingest", FeatureType.POINT, 1165});
// uspln
result.add(new Object[]{topdir + "ft/point/uspln_20061023.18", FeatureType.POINT, 3483});
// FslRaob
// assert 63 == checkPointDataset(TestDir.testdataDir + "sounding/netcdf/raob_soundings20216.cdf", FeatureType.STATION_PROFILE, false);
//assert 4638 == checkPointDataset(TestDir.testdataDir + "sounding/netcdf/Upperair_20060621_0000.nc", FeatureType.STATION_PROFILE, false);
return result;
}
public static List<Object[]> getGempakDatasets() {
List<Object[]> result = new ArrayList<>();
result.add(new Object[]{topdir + "ft/sounding/gempak/19580807_upa.ncml", FeatureType.STATION_PROFILE, 8769});
// (GEMPAK IOSP) stn = psuedoStruct, obs = multidim Structure, time(time) as extraJoin
//checkPointDataset(TestDir.cdmUnitTestDir + "formats/gempak/surface/19580807_sao.gem", FeatureType.STATION, true);
// stationAsPoint (GEMPAK IOSP) stn = psuedoStruct, obs = multidim Structure, time(time) as extraJoin
//testPointDataset(TestDir.cdmUnitTestDir + "formats/gempak/surface/20090521_sao.gem", FeatureType.POINT, true);
//testGempakAll(TestDir.cdmUnitTestDir + "formats/gempak/surface/20090524_sao.gem");
//testGempakAll(TestDir.cdmUnitTestDir+"C:/data/ft/station/09052812.sf");
//testPointDataset("collection:C:/data/formats/gempak/surface/#yyyyMMdd#_sao\\.gem", FeatureType.STATION, true);
//checkPointDataset("collection:D:/formats/gempak/surface/#yyyyMMdd#_sao\\.gem", FeatureType.STATION, true);
return result;
}
public static List<Object[]> getMiscDatasets() {
List<Object[]> result = new ArrayList<>();
result.add(new Object[]{TestDir.cdmUnitTestDir + "ft/point/ldm/04061912_buoy.nc", FeatureType.POINT, 218});
result.add(new Object[]{TestDir.cdmUnitTestDir + "ft/point/netcdf/Surface_Buoy_20090921_0000.nc", FeatureType.POINT, 32452});
result.add(new Object[]{TestDir.cdmUnitTestDir + "ft/station/multiStationMultiVar.ncml", FeatureType.STATION, 15});
result.add(new Object[]{TestDir.cdmUnitTestDir + "cfPoint/station/sampleDataset.nc", FeatureType.STATION, 1728});
result.add(new Object[]{TestDir.cdmUnitTestDir + "ft/station/200501q3h-gr.nc", FeatureType.STATION, 5023}); // */
return result;
}
@Parameterized.Parameters(name="{0}")
public static List<Object[]> getTestParameters() {
List<Object[]> result = new ArrayList<>();
result.addAll(getCFDatasets());
result.addAll(getPlugDatasets());
result.addAll(getGempakDatasets());
result.addAll(getMiscDatasets());
return result;
}
String location;
FeatureType ftype;
int countExpected;
boolean show = false;
public TestPointDatasets(String location, FeatureType ftype, int countExpected) {
this.location = location;
this.ftype = ftype;
this.countExpected = countExpected;
}
@Test
public void checkPointDataset() throws IOException {
assert countExpected == checkPointDataset(location, ftype, show);
}
public static int checkPointDataset(String location, FeatureType type, boolean show) throws IOException {
File fileIn = new File(location);
String absIn = fileIn.getCanonicalPath();
absIn = StringUtil2.replace(absIn, "\\", "/");
System.out.printf("================ TestPointFeatureCollection read %s %n", absIn);
Formatter out = new Formatter();
try (FeatureDataset fdataset = FeatureDatasetFactoryManager.open(type, location, null, out)) {
if (fdataset == null) {
System.out.printf("**failed on %s %n --> %s %n", location, out);
assert false;
}
// FeatureDataset
if (show) {
System.out.printf("----------- testPointDataset getDetailInfo -----------------%n");
fdataset.getDetailInfo(out);
System.out.printf("%s %n", out);
} else {
System.out.printf(" Feature Type %s %n", fdataset.getFeatureType());
}
return checkPointDataset(fdataset, show);
}
}
public static int checkPointDataset(FeatureDataset fdataset, boolean show) throws IOException {
long start = System.currentTimeMillis();
int count = 0;
Date d1 = fdataset.getStartDate();
Date d2 = fdataset.getEndDate();
if ((d1 != null) && (d2 != null))
assert d1.before(d2) || d1.equals(d2);
List<VariableSimpleIF> dataVars = fdataset.getDataVariables();
assert dataVars != null;
for (VariableSimpleIF v : dataVars) {
assert null != fdataset.getDataVariable(v.getShortName());
}
// FeatureDatasetPoint
assert fdataset instanceof FeatureDatasetPoint;
FeatureDatasetPoint fdpoint = (FeatureDatasetPoint) fdataset;
for (FeatureCollection fc : fdpoint.getPointFeatureCollectionList()) {
assert (fc instanceof PointFeatureCollection) || (fc instanceof NestedPointFeatureCollection) : fc.getClass().getName();
if (fc instanceof PointFeatureCollection) {
PointFeatureCollection pfc = (PointFeatureCollection) fc;
count = checkPointFeatureCollection(pfc, show);
System.out.println("PointFeatureCollection getData count= " + count + " size= " + pfc.size());
assert count == pfc.size();
} else if (fc instanceof StationTimeSeriesFeatureCollection) {
count = checkStationFeatureCollection((StationTimeSeriesFeatureCollection) fc);
//testNestedPointFeatureCollection((StationTimeSeriesFeatureCollection) fc, show);
} else if (fc instanceof StationProfileFeatureCollection) {
count = checkStationProfileFeatureCollection((StationProfileFeatureCollection) fc, show);
if (showStructureData) showStructureData((StationProfileFeatureCollection) fc);
} else if (fc instanceof SectionFeatureCollection) {
count = checkSectionFeatureCollection((SectionFeatureCollection) fc, show);
} else if (fc instanceof ProfileFeatureCollection) {
count = checkProfileFeatureCollection((ProfileFeatureCollection) fc, show);
} else {
count = checkNestedPointFeatureCollection((NestedPointFeatureCollection) fc, show);
}
}
long took = System.currentTimeMillis() - start;
System.out.printf(" nobs=%d took= %d msec%n", count, took);
return count;
}
static int checkNestedPointFeatureCollection(NestedPointFeatureCollection npfc, boolean show) throws IOException {
long start = System.currentTimeMillis();
int count = 0;
PointFeatureCollectionIterator iter = npfc.getPointFeatureCollectionIterator(-1);
while (iter.hasNext()) {
PointFeatureCollection pfc = iter.next();
if (show)
System.out.printf(" PointFeatureCollection=%s %n", pfc);
count += checkPointFeatureCollection(pfc, show);
}
long took = System.currentTimeMillis() - start;
if (show)
System.out.println(" testNestedPointFeatureCollection complete count= " + count + " full iter took= " + took + " msec");
return count;
}
static int checkStationProfileFeatureCollection(StationProfileFeatureCollection stationProfileFeatureCollection, boolean show) throws IOException {
long start = System.currentTimeMillis();
int count = 0;
stationProfileFeatureCollection.resetIteration();
while (stationProfileFeatureCollection.hasNext()) {
ucar.nc2.ft.StationProfileFeature spf = stationProfileFeatureCollection.next();
List<Date> times = spf.getTimes();
if (show) {
System.out.printf("times= ");
for (Date t : times) System.out.printf("%s, ", t);
System.out.printf("%n");
}
spf.resetIteration();
while (spf.hasNext()) {
ucar.nc2.ft.ProfileFeature pf = spf.next();
assert pf.getName() != null;
//assert pf.getTime() != null;
if (show)
System.out.printf(" ProfileFeature=%s %n", pf);
count += checkPointFeatureCollection(pf, show);
}
}
long took = System.currentTimeMillis() - start;
if (show)
System.out.println(" testStationProfileFeatureCollection complete count= " + count + " full iter took= " + took + " msec");
return count;
}
static int checkSectionFeatureCollection(SectionFeatureCollection sectionFeatureCollection, boolean show) throws IOException {
long start = System.currentTimeMillis();
int count = 0;
sectionFeatureCollection.resetIteration();
while (sectionFeatureCollection.hasNext()) {
ucar.nc2.ft.SectionFeature spf = sectionFeatureCollection.next();
spf.resetIteration();
while (spf.hasNext()) {
ucar.nc2.ft.ProfileFeature pf = spf.next();
assert pf.getName() != null;
// assert pf.getTime() != null;
if (show)
System.out.printf(" ProfileFeature=%s %n", pf);
count += checkPointFeatureCollection(pf, show);
}
}
long took = System.currentTimeMillis() - start;
if (show)
System.out.println(" testStationProfileFeatureCollection complete count= " + count + " full iter took= " + took + " msec");
return count;
}
static int checkProfileFeatureCollection(ProfileFeatureCollection profileFeatureCollection, boolean show) throws IOException {
long start = System.currentTimeMillis();
int count = 0;
profileFeatureCollection.resetIteration();
while (profileFeatureCollection.hasNext()) {
ucar.nc2.ft.ProfileFeature pf = profileFeatureCollection.next();
assert pf.getName() != null;
// assert pf.getTime() != null;
count += checkPointFeatureCollection(pf, show);
}
long took = System.currentTimeMillis() - start;
if (show)
System.out.println(" testStationProfileFeatureCollection complete count= " + count + " full iter took= " + took + " msec");
return count;
}
static void showStructureData(StationProfileFeatureCollection stationProfileFeatureCollection) throws IOException {
PrintWriter pw = new PrintWriter(System.out);
stationProfileFeatureCollection.resetIteration();
while (stationProfileFeatureCollection.hasNext()) {
ucar.nc2.ft.StationProfileFeature stationProfile = stationProfileFeatureCollection.next();
System.out.printf("stationProfile=%d %n", stationProfile.hashCode());
stationProfile.resetIteration();
while (stationProfile.hasNext()) {
ucar.nc2.ft.ProfileFeature profile = stationProfile.next();
System.out.printf("-profile=%d %n", profile.hashCode());
profile.resetIteration();
while (profile.hasNext()) {
ucar.nc2.ft.PointFeature pointFeature = profile.next();
System.out.printf("--pointFeature=%d %n", pointFeature.hashCode());
StructureData sdata = pointFeature.getDataAll();
NCdumpW.printStructureData(pw, sdata);
}
}
}
}
static int checkPointFeatureCollection(PointFeatureCollection pfc, boolean show) throws IOException {
if (show) {
System.out.printf("----------- testPointFeatureCollection -----------------%n");
System.out.println(" test PointFeatureCollection " + pfc.getName());
System.out.println(" calcBounds");
}
pfc.calcBounds();
if (show) {
System.out.println(" bb= " + pfc.getBoundingBox());
System.out.println(" dateRange= " + pfc.getDateRange());
System.out.println(" npts= " + pfc.size());
}
int n = pfc.size();
if (n <= 0) {
System.out.println(" empty " + pfc.getName());
//pfc.calcBounds();
return 0; // empty
}
LatLonRect bb = pfc.getBoundingBox();
assert bb != null;
DateRange dr = pfc.getDateRange();
assert dr != null;
// read all the data - check that it is contained in the bbox, dateRange
if (show) System.out.println(" complete iteration");
long start = System.currentTimeMillis();
int count = 0;
pfc.resetIteration();
while (pfc.hasNext()) {
PointFeature pf = pfc.next();
checkPointFeature(pf, pfc.getTimeUnit());
assert bb.contains(pf.getLocation().getLatLon()) : pf.getLocation().getLatLon();
if (!dr.contains(pf.getObservationTimeAsDate()))
System.out.printf(" date out of Range= %s on %s %n", pf.getObservationTimeAsDate(), pfc.getName());
count++;
}
long took = System.currentTimeMillis() - start;
if (show)
System.out.println(" testPointFeatureCollection complete count= " + count + " full iter took= " + took + " msec");
// subset with a bounding box, test result is in the bounding box
LatLonRect bb2 = new LatLonRect(bb.getLowerLeftPoint(), bb.getHeight() / 2, bb.getWidth() / 2);
PointFeatureCollection subset = pfc.subset(bb2, (CalendarDateRange) null);
if (show) System.out.println(" subset bb= " + bb2.toString2());
start = System.currentTimeMillis();
int counts = 0;
PointFeatureIterator iters = subset.getPointFeatureIterator(-1);
while (iters.hasNext()) {
PointFeature pf = iters.next();
assert pf != null;
assert pf.getLocation() != null;
assert bb2.contains(pf.getLocation().getLatLon()) : bb2.toString2() + " does not contains point " + pf.getLocation().getLatLon();
//System.out.printf(" contains point %s%n",pf.getLocation().getLatLon());
checkPointFeature(pf, pfc.getTimeUnit());
counts++;
}
took = System.currentTimeMillis() - start;
if (show)
System.out.println(" testPointFeatureCollection subset count= " + counts + " full iter took= " + took + " msec");
return count;
}
// check that the location and times are filled out
// read and test the data
static private void checkPointFeature(PointFeature pobs, DateUnit timeUnit) throws java.io.IOException {
EarthLocation loc = pobs.getLocation();
assert loc != null;
assert null != pobs.getNominalTimeAsDate();
assert null != pobs.getObservationTimeAsDate();
assert timeUnit.makeDate(pobs.getNominalTime()).equals(pobs.getNominalTimeAsDate());
assert timeUnit.makeDate(pobs.getObservationTime()).equals(pobs.getObservationTimeAsDate());
StructureData sdata = pobs.getDataAll();
assert null != sdata;
checkData(sdata);
}
// read each field, check datatype
static private void checkData(StructureData sdata) {
for (StructureMembers.Member member : sdata.getMembers()) {
DataType dt = member.getDataType();
if (dt == DataType.FLOAT) {
sdata.getScalarFloat(member);
sdata.getJavaArrayFloat(member);
} else if (dt == DataType.DOUBLE) {
sdata.getScalarDouble(member);
sdata.getJavaArrayDouble(member);
} else if (dt == DataType.BYTE) {
sdata.getScalarByte(member);
sdata.getJavaArrayByte(member);
} else if (dt == DataType.SHORT) {
sdata.getScalarShort(member);
sdata.getJavaArrayShort(member);
} else if (dt == DataType.INT) {
sdata.getScalarInt(member);
sdata.getJavaArrayInt(member);
} else if (dt == DataType.LONG) {
sdata.getScalarLong(member);
sdata.getJavaArrayLong(member);
} else if (dt == DataType.CHAR) {
sdata.getScalarChar(member);
sdata.getJavaArrayChar(member);
sdata.getScalarString(member);
} else if (dt == DataType.STRING) {
sdata.getScalarString(member);
}
if ((dt != DataType.STRING) && (dt != DataType.CHAR) && (dt != DataType.STRUCTURE) && (dt != DataType.SEQUENCE)) {
sdata.convertScalarFloat(member.getName());
}
}
}
////////////////////////////////////////////////////////////
static int checkStationFeatureCollection(StationTimeSeriesFeatureCollection sfc) throws IOException {
System.out.printf("--------------------------\nComplete Iteration for %s %n", sfc.getName());
int countStns = countLocations(sfc);
// try a subset
LatLonRect bb = sfc.getBoundingBox();
assert bb != null;
LatLonRect bb2 = new LatLonRect(bb.getLowerLeftPoint(), bb.getHeight() / 2, bb.getWidth() / 2);
System.out.println("Subset= " + bb2.toString2());
StationTimeSeriesFeatureCollection sfcSub = sfc.subset(bb2);
int countSub = countLocations(sfcSub);
assert countSub <= countStns;
System.out.println("Flatten= " + bb2.toString2());
PointFeatureCollection flatten = sfc.flatten(bb2, (CalendarDateRange) null);
int countFlat = countLocations(flatten);
assert countFlat <= countStns;
flatten = sfc.flatten(null, (CalendarDateRange) null);
return countObs(flatten);
}
static int countLocations(StationTimeSeriesFeatureCollection sfc) throws IOException {
System.out.printf(" Station List Size = %d %n", sfc.getStations().size());
// check uniqueness
Map<String, StationTimeSeriesFeature> stns = new HashMap<>(5000);
Map<MyLocation, StationTimeSeriesFeature> locs = new HashMap<>(5000);
sfc.resetIteration();
while (sfc.hasNext()) {
StationTimeSeriesFeature sf = sfc.next();
StationTimeSeriesFeature other = stns.get(sf.getName());
if (other != null) {
System.out.printf(" duplicate name = %s %n", sf);
System.out.printf(" of = %s %n", other);
} else
stns.put(sf.getName(), sf);
MyLocation loc = new MyLocation(sf);
StationTimeSeriesFeature already = locs.get(loc);
if (already != null) {
System.out.printf(" duplicate location %s(%s) of %s(%s) %n", sf.getName(), sf.getDescription(),
already.getName(), already.getDescription());
} else
locs.put(loc, sf);
}
System.out.printf(" unique locs = %d %n", locs.size());
System.out.printf(" unique stns = %d %n", stns.size());
return stns.size();
}
/////////////////////////////////////////////////////////
public static void checkLocation(String location, FeatureType type, boolean show) throws IOException {
Formatter out = new Formatter();
FeatureDataset fdataset = FeatureDatasetFactoryManager.open(type, location, null, out);
if (fdataset == null) {
System.out.printf("**failed on %s %n --> %s %n", location, out);
assert false;
}
assert fdataset instanceof FeatureDatasetPoint;
FeatureDatasetPoint fdpoint = (FeatureDatasetPoint) fdataset;
List<FeatureCollection> collectionList = fdpoint.getPointFeatureCollectionList();
FeatureCollection fc = collectionList.get(0);
if (fc instanceof PointFeatureCollection) {
PointFeatureCollection pfc = (PointFeatureCollection) fc;
countLocations(pfc);
LatLonRect bb = pfc.getBoundingBox();
LatLonRect bb2 = new LatLonRect(bb.getLowerLeftPoint(), bb.getHeight() / 2, bb.getWidth() / 2);
PointFeatureCollection subset = pfc.subset(bb2, (CalendarDateRange) null);
countLocations(subset);
} else if (fc instanceof StationTimeSeriesFeatureCollection) {
StationTimeSeriesFeatureCollection sfc = (StationTimeSeriesFeatureCollection) fc;
PointFeatureCollection pfcAll = sfc.flatten(null, (CalendarDateRange) null);
System.out.printf("Unique Locations all = %d %n", countLocations(pfcAll));
LatLonRect bb = sfc.getBoundingBox();
assert bb != null;
LatLonRect bb2 = new LatLonRect(bb.getLowerLeftPoint(), bb.getHeight() / 2, bb.getWidth() / 2);
PointFeatureCollection pfcSub = sfc.flatten(bb2, (CalendarDateRange) null);
System.out.printf("Unique Locations sub1 = %d %n", countLocations(pfcSub));
StationTimeSeriesFeatureCollection sfcSub = sfc.subset(bb2);
PointFeatureCollection pfcSub2 = sfcSub.flatten(null, (CalendarDateRange) null);
System.out.printf("Unique Locations sub2 = %d %n", countLocations(pfcSub2));
// Dons
sfc = sfc.subset(bb2);
PointFeatureCollection subDon = sfc.flatten(bb2, (CalendarDateRange) null);
System.out.printf("Unique Locations subDon = %d %n", countLocations(subDon));
}
}
static int countLocations(PointFeatureCollection pfc) throws IOException {
int count = 0;
Set<MyLocation> locs = new HashSet<>(80000);
pfc.resetIteration();
while (pfc.hasNext()) {
PointFeature pf = pfc.next();
MyLocation loc = new MyLocation(pf.getLocation());
if (!locs.contains(loc)) locs.add(loc);
count++;
//if (count % 1000 == 0) System.out.printf("Count %d%n", count);
}
System.out.printf("Count Points = %d Unique points = %d %n", count, locs.size());
return locs.size();
//The problem is that all the locations are coming up with the same value. This:
//always returns the same lat/lon/alt (of the first observation).
//(pos was populated going through the PointFeatureIterator).
}
static int countObs(PointFeatureCollection pfc) throws IOException {
int count = 0;
pfc.resetIteration();
while (pfc.hasNext()) {
PointFeature pf = pfc.next();
StructureData sd = pf.getDataAll();
count++;
}
return count;
}
private static class MyLocation {
double lat, lon, alt;
public MyLocation(EarthLocation from) {
this.lat = from.getLatitude();
this.lon = from.getLongitude();
this.alt = Double.isNaN(from.getAltitude()) ? 0.0 : from.getAltitude();
}
@Override
public boolean equals(Object oo) {
if (this == oo) return true;
if (!(oo instanceof MyLocation)) return false;
MyLocation other = (MyLocation) oo;
return (lat == other.lat) && (lon == other.lon) && (alt == other.alt);
}
@Override
public int hashCode() {
if (hashCode == 0) {
int result = 17;
result += 37 * result + lat * 10000;
result += 37 * result + lon * 10000;
result += 37 * result + alt * 10000;
hashCode = result;
}
return hashCode;
}
private int hashCode = 0;
}
}