use of org.n52.sos.netcdf.data.subsensor.SubSensor in project SOS by 52North.
the class AbstractNetcdfEncoder method populateHeightDepthArray.
private Double populateHeightDepthArray(AbstractSensorDataset sensorDataset, Array heightDephtArray, Variable v) throws EncodingException {
Index index = heightDephtArray.getIndex();
int indexCounter = 0;
Double consistentBinHeight = null;
for (SubSensor subSensor : sensorDataset.getSubSensors()) {
if (subSensor instanceof ProfileSubSensor) {
index.setDim(0, indexCounter++);
heightDephtArray.setDouble(index, checkValue(v, ((ProfileSubSensor) subSensor).getHeight()));
// check for consistent bin size
if (subSensor instanceof BinProfileSubSensor) {
double binHeight = checkValue(v, ((BinProfileSubSensor) subSensor).getBinHeight());
if (consistentBinHeight == null) {
consistentBinHeight = binHeight;
} else if (consistentBinHeight != getNetcdfHelper().getFillValue() && consistentBinHeight != binHeight) {
// mark bin height as inconsistent
consistentBinHeight = getNetcdfHelper().getFillValue();
}
}
} else {
throw new EncodingException("Non-profile subsensors not supported.");
}
}
return consistentBinHeight;
}
use of org.n52.sos.netcdf.data.subsensor.SubSensor in project SOS by 52North.
the class AbstractNetcdfEncoder method encodeSensorDataToNetcdf.
protected void encodeSensorDataToNetcdf(File netcdfFile, AbstractSensorDataset sensorDataset, Version version) throws EncodingException, IOException {
String sensor = sensorDataset.getSensorIdentifier();
sensorDataset.getSensor().setSensorDescription(getProcedureDescription(sensor, sensorDataset.getProcedureDescription()));
NetcdfFileWriter writer = getNetcdfFileWriter(netcdfFile, version);
// set fill on, doesn't seem to have any effect though
writer.setFill(true);
Map<Variable, Array> variableArrayMap = Maps.newHashMap();
int numTimes = sensorDataset.getTimes().size();
// FIXME shouldn't assume that all subsensors are heights (or rename
// subsensors if they are)
int numHeightDepth = sensorDataset.getSubSensors().size() > 0 ? sensorDataset.getSubSensors().size() : 1;
// global attributes
addGlobaleAttributes(writer, sensorDataset);
// add appropriate dims for feature type
List<Dimension> timeDims = Lists.newArrayList();
List<Dimension> latLngDims = Lists.newArrayList();
List<Dimension> latDims = Lists.newArrayList();
List<Dimension> lngDims = Lists.newArrayList();
List<Dimension> zDims = Lists.newArrayList();
List<Dimension> obsPropDims = Lists.newArrayList();
// REQUIRED for NetCDF-3
// add Dimensions
// dTime = writer.addDimension(null, CFStandardNames.TIME.getName(),
// numTimes);
Dimension dTime = writer.addUnlimitedDimension(getVariableDimensionCaseName(CFStandardNames.TIME.getName()));
dTime.setLength(numTimes);
timeDims.add(dTime);
if (!(sensorDataset instanceof StaticLocationDataset)) {
zDims.add(dTime);
}
obsPropDims.add(dTime);
// set up lat/lng dimensions
// FIXME do not set time dimension for static location dataset
// if ((sensorDataset instanceof StaticLocationDataset)) {
// latLngDims.add(dTime);
// }
// set up z dimensions
String dimensionName;
if (useHeight()) {
dimensionName = getVariableDimensionCaseName(CFStandardNames.HEIGHT.getName());
} else {
dimensionName = getVariableDimensionCaseName(CFStandardNames.DEPTH.getName());
}
// profile/timeSeriesProfile
Dimension dZ = writer.addDimension(null, dimensionName, numHeightDepth);
if (!(sensorDataset instanceof StaticLocationDataset)) {
// trajectory
zDims.add(dTime);
}
zDims.add(dZ);
obsPropDims.add(dZ);
variableArrayMap.putAll(getNetcdfProfileSpecificVariablesArrays(writer, sensorDataset));
// time var
Variable vTime = addVariableTime(writer, timeDims);
if (numTimes > 1 && writer.getVersion().isNetdf4format()) {
vTime.addAttribute(new Attribute(CDM.CHUNK_SIZES, getNetcdfHelper().getChunkSizeTime()));
}
ArrayDouble timeArray = new ArrayDouble(getDimShapes(timeDims));
initArrayWithFillValue(timeArray, getNetcdfHelper().getFillValue());
Array latArray = getLatitudeArray(sensorDataset);
Array lonArray = getLongitudeArray(sensorDataset);
// add lat/long dimensions
long latSize = 1;
if (latArray != null) {
latSize = latArray.getSize();
}
Dimension dLat = writer.addDimension(null, getVariableDimensionCaseName(CFStandardNames.LATITUDE.getName()), (int) latSize);
latDims.add(dLat);
long lonSize = 1;
if (lonArray != null) {
lonSize = lonArray.getSize();
}
Dimension dLon = writer.addDimension(null, getVariableDimensionCaseName(CFStandardNames.LONGITUDE.getName()), (int) lonSize);
lngDims.add(dLon);
// lat/lon var
Variable vLat;
Variable vLon;
if (latLngDims.size() > 0) {
vLat = addVariableLatitude(writer, latLngDims);
vLon = addVariableLongitude(writer, latLngDims);
} else {
vLat = addVariableLatitude(writer, latDims);
vLon = addVariableLongitude(writer, lngDims);
}
// height/depth var
Variable vHeightDepth;
if (useHeight()) {
vHeightDepth = addVariableHeight(writer, zDims);
} else {
vHeightDepth = addVariableDepth(writer, zDims);
}
String coordinateString = Joiner.on(' ').join(Lists.newArrayList(vTime.getFullName(), vLat.getFullName(), vLon.getFullName(), vHeightDepth.getFullName()));
Map<OmObservableProperty, Variable> obsPropVarMap = Maps.newHashMap();
Map<Variable, Array> varDataArrayMap = Maps.newHashMap();
for (OmObservableProperty obsProp : sensorDataset.getPhenomena()) {
// obs prop var
Variable vObsProp = addVariableForObservedProperty(writer, obsProp, obsPropDims, coordinateString);
obsPropVarMap.put(obsProp, vObsProp);
// init obs prop data array
Array obsPropArray = getArray(obsPropDims);
initArrayWithFillValue(obsPropArray, getNetcdfHelper().getFillValue());
varDataArrayMap.put(vObsProp, obsPropArray);
}
// populate heights array for profile
Array heightDephtArray = null;
if (zDims.size() == 1 && hasDimension(zDims, dZ) && !sensorDataset.getSubSensors().isEmpty()) {
heightDephtArray = initHeightDephtArray(zDims);
Double consistentBinHeight = populateHeightDepthArray(sensorDataset, heightDephtArray, vHeightDepth);
String verticalResolution = null;
if (consistentBinHeight == null) {
verticalResolution = ACDDConstants.POINT;
} else if (consistentBinHeight != getNetcdfHelper().getFillValue()) {
verticalResolution = consistentBinHeight + " " + CFConstants.UNITS_METERS + " " + ACDDConstants.BINNED;
}
if (verticalResolution != null) {
writer.addGroupAttribute(null, new Attribute(ACDDConstants.GEOSPATIAL_VERTICAL_RESOLUTION, verticalResolution));
}
}
// iterate through sensorDataset, set values
int timeCounter = 0;
for (Time time : sensorDataset.getTimes()) {
// set time value
Index timeIndex = timeArray.getIndex();
int timeIndexCounter = 0;
// }
if (hasDimension(timeDims, dTime)) {
timeIndex.setDim(timeIndexCounter++, timeCounter++);
}
timeArray.set(timeIndex, getTimeValue(time));
// data values
Map<OmObservableProperty, Map<SubSensor, Value<?>>> obsPropMap = sensorDataset.getDataValues().get(time);
for (Entry<OmObservableProperty, Map<SubSensor, Value<?>>> entry : obsPropMap.entrySet()) {
OmObservableProperty obsProp = entry.getKey();
Variable variable = obsPropVarMap.get(obsProp);
Array array = varDataArrayMap.get(variable);
for (Entry<SubSensor, Value<?>> subSensorEntry : obsPropMap.get(obsProp).entrySet()) {
SubSensor subSensor = subSensorEntry.getKey();
Value<?> value = subSensorEntry.getValue();
Object valObj = value.getValue();
if (!(valObj instanceof Number)) {
throw new EncodingException("Value class %s not supported", valObj.getClass().getCanonicalName());
}
Index index = array.getIndex();
int obsPropDimCounter = 0;
for (Dimension dim : obsPropDims) {
// } else if (dim.equals(dTime)){
if (dim.equals(dTime)) {
// time index dim
index.setDim(obsPropDimCounter++, timeCounter - 1);
} else if (dim.equals(dZ) && dim.getLength() > 1) {
// height/depth index dim
index.setDim(obsPropDimCounter++, sensorDataset.getSubSensors().indexOf(subSensor));
}
}
if (array instanceof ArrayFloat) {
((ArrayFloat) array).set(index, ((Number) valObj).floatValue());
} else {
((ArrayDouble) array).set(index, ((Number) valObj).doubleValue());
}
}
}
}
// create the empty netCDF with dims/vars/attributes defined
variableArrayMap.put(vTime, timeArray);
if (latArray != null) {
variableArrayMap.put(vLat, latArray);
}
if (lonArray != null) {
variableArrayMap.put(vLon, lonArray);
}
if (heightDephtArray != null) {
variableArrayMap.put(vHeightDepth, heightDephtArray);
}
variableArrayMap.putAll(varDataArrayMap);
// create the empty netCDF with dims/vars/attributes defined
writeToFile(writer, variableArrayMap);
writer.close();
}
use of org.n52.sos.netcdf.data.subsensor.SubSensor in project SOS by 52North.
the class NetCDFUtil method processObservation.
default void processObservation(OmObservation sosObs, SetMultimap<String, OmObservableProperty> sensorPhens, Map<String, AbstractFeature> sensorProcedure, SetMultimap<String, Double> sensorLngs, SetMultimap<String, Double> sensorLats, SetMultimap<String, Double> sensorHeights, Map<String, Map<Time, Map<OmObservableProperty, Map<SubSensor, Value<?>>>>> obsValuesMap) throws EncodingException {
OmObservationConstellation obsConst = sosObs.getObservationConstellation();
// first, resolve the procId to an asset type
String sensor = obsConst.getProcedure().getIdentifier();
if (!sensorProcedure.containsKey(sensor)) {
sensorProcedure.put(sensor, obsConst.getProcedure());
}
AbstractPhenomenon absPhen = obsConst.getObservableProperty();
Map<String, OmObservableProperty> phenomenaMap = new HashMap<>();
if (absPhen instanceof OmCompositePhenomenon) {
for (OmObservableProperty phen : ((OmCompositePhenomenon) absPhen).getPhenomenonComponents()) {
// TODO should the unit be set like this? seems sketchy
if (phen.getUnit() == null && sosObs.getValue() != null && sosObs.getValue().getValue() != null && sosObs.getValue().getValue().getUnit() != null) {
phen.setUnit(sosObs.getValue().getValue().getUnit());
}
phenomenaMap.put(phen.getIdentifier(), phen);
}
} else {
OmObservableProperty phen = (OmObservableProperty) absPhen;
// TODO should the unit be set like this? seems sketchy
if (phen.getUnit() == null && sosObs.getValue() != null && sosObs.getValue().getValue() != null && sosObs.getValue().getValue().getUnit() != null) {
phen.setUnit(sosObs.getValue().getValue().getUnit());
}
phenomenaMap.put(phen.getIdentifier(), phen);
}
List<OmObservableProperty> phenomena = new ArrayList<>(phenomenaMap.values());
sensorPhens.putAll(sensor, phenomena);
// get foi
AbstractFeature aFoi = obsConst.getFeatureOfInterest();
if (!(aFoi instanceof AbstractSamplingFeature)) {
throw new EncodingException("Encountered a feature which isn't a SamplingFeature");
}
AbstractSamplingFeature foi = (AbstractSamplingFeature) aFoi;
for (Point point : FeatureUtil.getFeaturePoints(foi)) {
try {
// TODO is this correct?
Point p = (Point) getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(point);
sensorLngs.put(sensor, p.getX());
sensorLats.put(sensor, p.getY());
} catch (OwsExceptionReport e) {
throw new EncodingException("Exception while normalizing feature coordinate axis order.", e);
}
}
Set<Double> featureHeights = FeatureUtil.getFeatureHeights(foi);
sensorHeights.putAll(sensor, featureHeights);
String phenId = obsConst.getObservableProperty().getIdentifier();
ObservationValue<?> iObsValue = sosObs.getValue();
if (!(iObsValue instanceof SingleObservationValue)) {
throw new EncodingException("Only SingleObservationValues are supported.");
}
SingleObservationValue<?> singleObsValue = (SingleObservationValue<?>) iObsValue;
Time obsTime = singleObsValue.getPhenomenonTime();
// TODO Quality
Value<?> obsValue = singleObsValue.getValue();
if (!(obsValue instanceof QuantityValue)) {
throw new EncodingException("Only QuantityValues are supported.");
}
QuantityValue quantityValue = (QuantityValue) obsValue;
// axes shouldn't be composite phenomena
if (phenomena.size() == 1) {
OmObservableProperty phenomenon = phenomena.get(0);
// add dimensional values to procedure dimension tracking maps
if (isLng(phenomenon.getIdentifier())) {
sensorLngs.get(sensor).add(quantityValue.getValue().doubleValue());
}
if (isLat(phenomenon.getIdentifier())) {
sensorLats.get(sensor).add(quantityValue.getValue().doubleValue());
}
if (isZ(phenomenon.getIdentifier())) {
Double zValue = quantityValue.getValue().doubleValue();
sensorHeights.get(sensor).add(zValue);
}
}
// check for samplingGeometry in observation
if (sosObs.isSetParameter()) {
if (sosObs.isSetHeightDepthParameter()) {
if (sosObs.isSetHeightParameter()) {
sensorHeights.get(sensor).add(sosObs.getHeightParameter().getValue().getValue().doubleValue());
} else if (sosObs.isSetDepthParameter()) {
sensorHeights.get(sensor).add(sosObs.getDepthParameter().getValue().getValue().doubleValue());
}
}
if (hasSamplingGeometry(sosObs)) {
Geometry geometry = getSamplingGeometryGeometry(sosObs);
Set<Point> points = FeatureUtil.getPoints(geometry);
for (Point point : points) {
try {
Point p = (Point) getGeometryHandler().switchCoordinateAxisFromToDatasourceIfNeeded(point);
sensorLngs.put(sensor, p.getX());
sensorLats.put(sensor, p.getY());
} catch (OwsExceptionReport e) {
throw new EncodingException("Exception while normalizing sampling geometry coordinate axis order.");
}
}
sensorHeights.putAll(sensor, FeatureUtil.getHeights(points));
}
}
// get the sensor's data map
Map<Time, Map<OmObservableProperty, Map<SubSensor, Value<?>>>> sensorObsMap = obsValuesMap.get(sensor);
if (sensorObsMap == null) {
sensorObsMap = new HashMap<>();
obsValuesMap.put(sensor, sensorObsMap);
}
// get the map of the asset's phenomena by time
Map<OmObservableProperty, Map<SubSensor, Value<?>>> obsPropMap = sensorObsMap.get(obsTime);
if (obsPropMap == null) {
obsPropMap = new HashMap<>();
sensorObsMap.put(obsTime, obsPropMap);
}
OmObservableProperty phen = phenomenaMap.get(phenId);
Map<SubSensor, Value<?>> subSensorMap = obsPropMap.get(phen);
if (subSensorMap == null) {
subSensorMap = new HashMap<>();
obsPropMap.put(phen, subSensorMap);
}
// add obs value to subsensor map (null subsensors are ok)
if (sosObs.isSetParameter() && hasSamplingGeometry(sosObs)) {
subSensorMap.put(createSubSensor(sensor, getSamplingGeometryGeometry(sosObs)), obsValue);
} else {
subSensorMap.put(createSubSensor(sensor, foi), obsValue);
}
}
use of org.n52.sos.netcdf.data.subsensor.SubSensor in project SOS by 52North.
the class NetCDFUtil method createNetCDFSosObservations.
/**
* Organizes OmObservation collection into a list of NetCDFObservation
* blocks, each of which contain a single feature type
*
* @param omObservations
* The collection of observations to transform
* @return List<NetCDFObservation> ready for encoding
* @throws EncodingException
* if an error occurs
*/
default List<NetCDFObservation> createNetCDFSosObservations(ObservationStream omObservations) throws EncodingException, OwsExceptionReport {
// the main map of observation value strings by asset, time, phenomenon,
// and subsensor (height, profile bin, etc)
Map<String, Map<Time, Map<OmObservableProperty, Map<SubSensor, Value<?>>>>> obsValuesMap = new HashMap<>();
SetMultimap<String, OmObservableProperty> sensorPhens = HashMultimap.create();
Map<String, AbstractFeature> sensorProcedure = Maps.newHashMap();
// Map<StationAsset,TimePeriod> stationPeriodMap = new
// HashMap<StationAsset,TimePeriod>();
// maps to keep track of unique dimension values by sensor (these may or
// may not vary, determining the feature type)
SetMultimap<String, Double> sensorLngs = HashMultimap.create();
SetMultimap<String, Double> sensorLats = HashMultimap.create();
SetMultimap<String, Double> sensorHeights = HashMultimap.create();
while (omObservations.hasNext()) {
OmObservation sosObs = omObservations.next();
if (sosObs.getValue() instanceof StreamingValue<?>) {
StreamingValue<?> streaming = (StreamingValue<?>) sosObs.getValue();
while (streaming.hasNext()) {
processObservation(streaming.next(), sensorPhens, sensorProcedure, sensorLngs, sensorLats, sensorHeights, obsValuesMap);
}
} else {
processObservation(sosObs, sensorPhens, sensorProcedure, sensorLngs, sensorLats, sensorHeights, obsValuesMap);
}
}
// now we know about each station's dimensions, sort into CF feature
// types
// sampling time periods
// TimePeriod pointSamplingTimePeriod = new TimePeriod();
TimePeriod timeSeriesSamplingTimePeriod = new TimePeriod();
// TimePeriod profileSamplingTimePeriod = new TimePeriod();
TimePeriod timeSeriesProfileSamplingTimePeriod = new TimePeriod();
TimePeriod trajectorySamplingTimePeriod = new TimePeriod();
TimePeriod trajectoryProfileSamplingTimePeriod = new TimePeriod();
// station datasets
// Map<SensorAsset,PointSensorDataset> pointSensorDatasets =
// new HashMap<SensorAsset,PointSensorDataset>();
Map<String, TimeSeriesSensorDataset> timeSeriesSensorDatasets = new HashMap<>();
// Map<SensorAsset,ProfileSensorDataset> profileSensorDatasets =
// new HashMap<SensorAsset,ProfileSensorDataset>();
Map<String, TimeSeriesProfileSensorDataset> timeSeriesProfileSensorDatasets = new HashMap<>();
Map<String, TrajectorySensorDataset> trajectorySensorDatasets = new HashMap<>();
Map<String, TrajectoryProfileSensorDataset> trajectoryProfileSensorDatasets = new HashMap<>();
// phenomena
// Set<OmObservableProperty> pointPhenomena = new
// HashSet<OmObservableProperty>();
Set<OmObservableProperty> timeSeriesPhenomena = new HashSet<>();
// Set<OmObservableProperty> profilePhenomena = new
// HashSet<OmObservableProperty>();
Set<OmObservableProperty> timeSeriesProfilePhenomena = new HashSet<>();
Set<OmObservableProperty> trajectoryPhenomena = new HashSet<>();
Set<OmObservableProperty> trajectoryProfilePhenomena = new HashSet<>();
// envelopes
// Envelope pointEnvelope = new Envelope();
Envelope timeSeriesEnvelope = new Envelope();
// Envelope profileEnvelope = new Envelope();
Envelope timeSeriesProfileEnvelope = new Envelope();
Envelope trajectoryEnvelope = new Envelope();
Envelope trajectoryProfileEnvelope = new Envelope();
for (Map.Entry<String, Map<Time, Map<OmObservableProperty, Map<SubSensor, Value<?>>>>> obsValuesEntry : obsValuesMap.entrySet()) {
IdentifierDatasetSensor datasetSensor = new IdentifierDatasetSensor(obsValuesEntry.getKey());
String sensor = datasetSensor.getSensorIdentifier();
Set<Time> sensorTimes = obsValuesEntry.getValue().keySet();
int lngCount = sensorLngs.get(sensor).size();
int latCount = sensorLats.get(sensor).size();
int heightCount = sensorHeights.get(sensor).size();
// int timeCount = sensorTimes.size();
boolean locationVaries = lngCount > 0 && latCount > 0 && (lngCount > 1 || latCount > 1);
boolean heightVaries = heightCount > 1;
// boolean timeVaries = timeCount > 1;
// set static dimension values where applicable
Double staticLng = null;
Double staticLat = null;
Double staticHeight = null;
// Time staticTime = null;
if (!locationVaries) {
if (!sensorLngs.get(sensor).isEmpty()) {
staticLng = sensorLngs.get(sensor).iterator().next();
}
if (!sensorLats.get(sensor).isEmpty()) {
staticLat = sensorLats.get(sensor).iterator().next();
}
}
if (!heightVaries) {
if (!sensorHeights.get(sensor).isEmpty()) {
staticHeight = sensorHeights.get(sensor).iterator().next();
}
}
// } else if( !locationVaries && !heightVaries && timeVaries){
if (!locationVaries && !heightVaries) {
// time series
timeSeriesSamplingTimePeriod.extendToContain(sensorTimes);
timeSeriesSensorDatasets.put(sensor, new TimeSeriesSensorDataset(datasetSensor, staticLng, staticLat, staticHeight, obsValuesEntry.getValue(), sensorProcedure.get(sensor)));
timeSeriesPhenomena.addAll(sensorPhens.get(sensor));
if (staticLng != null && staticLat != null) {
timeSeriesEnvelope.expandToInclude(staticLng, staticLat);
}
} else if (!locationVaries && heightVaries) {
// time series profile
timeSeriesProfileSamplingTimePeriod.extendToContain(sensorTimes);
timeSeriesProfileSensorDatasets.put(sensor, new TimeSeriesProfileSensorDataset(datasetSensor, staticLng, staticLat, obsValuesEntry.getValue(), sensorProcedure.get(sensor)));
timeSeriesProfilePhenomena.addAll(sensorPhens.get(sensor));
if (staticLng != null && staticLat != null) {
timeSeriesProfileEnvelope.expandToInclude(staticLng, staticLat);
}
} else if (locationVaries && !heightVaries) {
// trajectory
trajectorySamplingTimePeriod.extendToContain(sensorTimes);
trajectorySensorDatasets.put(sensor, new TrajectorySensorDataset(datasetSensor, staticHeight, obsValuesEntry.getValue(), sensorProcedure.get(sensor)));
trajectoryPhenomena.addAll(sensorPhens.get(sensor));
expandEnvelopeToInclude(trajectoryEnvelope, sensorLngs.get(sensor), sensorLats.get(sensor));
} else if (locationVaries && heightVaries) {
// trajectory profile
trajectoryProfileSamplingTimePeriod.extendToContain(sensorTimes);
trajectoryProfileSensorDatasets.put(sensor, new TrajectoryProfileSensorDataset(datasetSensor, obsValuesEntry.getValue(), sensorProcedure.get(sensor)));
trajectoryProfilePhenomena.addAll(sensorPhens.get(sensor));
expandEnvelopeToInclude(trajectoryProfileEnvelope, sensorLngs.get(sensor), sensorLats.get(sensor));
}
}
// build NetCDFObservations
List<NetCDFObservation> iSosObsList = new ArrayList<>(timeSeriesSensorDatasets.size() + timeSeriesProfileSensorDatasets.size() + trajectorySensorDatasets.size() + trajectoryProfileSensorDatasets.size());
// timeSeries
if (timeSeriesSensorDatasets.size() > 0) {
iSosObsList.add(new NetCDFObservation(CF.FeatureType.timeSeries, timeSeriesSamplingTimePeriod, timeSeriesSensorDatasets, timeSeriesPhenomena, timeSeriesEnvelope));
}
// time series profile
if (timeSeriesProfileSensorDatasets.size() > 0) {
iSosObsList.add(new NetCDFObservation(CF.FeatureType.timeSeriesProfile, timeSeriesProfileSamplingTimePeriod, timeSeriesProfileSensorDatasets, timeSeriesProfilePhenomena, timeSeriesProfileEnvelope));
}
// trajectory
if (trajectorySensorDatasets.size() > 0) {
iSosObsList.add(new NetCDFObservation(CF.FeatureType.trajectory, trajectorySamplingTimePeriod, trajectorySensorDatasets, trajectoryPhenomena, trajectoryEnvelope));
}
// trajectoryProfile
if (trajectoryProfileSensorDatasets.size() > 0) {
iSosObsList.add(new NetCDFObservation(CF.FeatureType.trajectoryProfile, trajectoryProfileSamplingTimePeriod, trajectoryProfileSensorDatasets, trajectoryProfilePhenomena, trajectoryProfileEnvelope));
}
return iSosObsList;
}
Aggregations