diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.classpath b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.classpath new file mode 100644 index 0000000000..ad32c83a78 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.project b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.project new file mode 100644 index 0000000000..aae180a2b7 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.project @@ -0,0 +1,28 @@ + + + com.raytheon.uf.common.dataplugin.grid + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.settings/org.eclipse.jdt.core.prefs b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..3f00c1463d --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Fri Feb 03 13:18:16 CST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..9f1e0aafde --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/META-INF/MANIFEST.MF @@ -0,0 +1,33 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Grid +Bundle-SymbolicName: com.raytheon.uf.common.dataplugin.grid +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: RAYTHEON +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization +Eclipse-BuddyPolicy: registered, ext, global +Import-Package: com.raytheon.uf.common.dataplugin, + com.raytheon.uf.common.dataplugin.annotations, + com.raytheon.uf.common.dataplugin.level, + com.raytheon.uf.common.dataplugin.persist, + com.raytheon.uf.common.datastorage.records, + com.raytheon.uf.common.geospatial, + com.raytheon.uf.common.gridcoverage, + com.raytheon.uf.common.localization, + com.raytheon.uf.common.parameter, + com.raytheon.uf.common.serialization, + com.raytheon.uf.common.serialization.annotations, + com.raytheon.uf.common.serialization.comm, + com.raytheon.uf.common.status, + com.raytheon.uf.common.time, + com.vividsolutions.jts.geom, + javax.measure.unit, + javax.persistence, + org.hibernate.annotations, + org.opengis.metadata.spatial +Export-Package: com.raytheon.uf.common.dataplugin.grid, + com.raytheon.uf.common.dataplugin.grid.dataset, + com.raytheon.uf.common.dataplugin.grid.request, + com.raytheon.uf.common.dataplugin.grid.units, + com.raytheon.uf.common.dataplugin.grid.util diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject new file mode 100644 index 0000000000..bdc0a8ab06 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject @@ -0,0 +1,4 @@ +com.raytheon.uf.common.dataplugin.grid.GridRecord +com.raytheon.uf.common.dataplugin.grid.GridInfoRecord +com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfo +com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfoSet \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/build.properties b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/build.properties new file mode 100644 index 0000000000..5791d48d5f --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + res/ diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/res/scripts/grid_indices.sql b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/res/scripts/grid_indices.sql new file mode 100644 index 0000000000..4c067488e1 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/res/scripts/grid_indices.sql @@ -0,0 +1,34 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +CREATE INDEX "gridDatasetReftime_idx" + ON grid + USING btree + (info_id, reftime, forecasttime); + +CREATE INDEX "gridinfoNameParamLevel_idx" + ON grid_info + USING btree + (datasetid, parameter_abbreviation, level_id); + +CREATE INDEX "gridinfoSecondryId_idx" + ON grid_info + USING btree + (secondaryid); diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridConstants.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridConstants.java new file mode 100644 index 0000000000..55ff4ae309 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridConstants.java @@ -0,0 +1,91 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid; + +/** + * + * Contains some useful constants for dealing with grid data, mostly just + * hibernate names of attributes. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 11, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class GridConstants { + + public static final String GRID = "grid"; + + public static final String PLUGIN_NAME = "pluginName"; + + public static final String INFO = "info"; + + public static final String INFO_ID = INFO + "." + GridInfoConstants.ID; + + public static final String DATASET_ID = INFO + "." + + GridInfoConstants.DATASET_ID; + + public static final String SECONDARY_ID = INFO + "." + + GridInfoConstants.SECONDARY_ID; + + public static final String ENSEMBLE_ID = INFO + "." + + GridInfoConstants.ENSEMBLE_ID; + + public static final String LOCATION = INFO + "." + + GridInfoConstants.LOCATION; + + public static final String LOCATION_ID = INFO + "." + + GridInfoConstants.LOCATION_ID; + + public static final String PARAMETER = INFO + "." + + GridInfoConstants.PARAMETER; + + public static final String PARAMETER_ABBREVIATION = INFO + "." + + GridInfoConstants.PARAMETER_ABBREVIATION; + + public static final String PARAMETER_NAME = INFO + "." + + GridInfoConstants.PARAMETER_NAME; + + public static final String PARAMETER_UNIT = INFO + "." + + GridInfoConstants.PARAMETER_UNIT; + + public static final String LEVEL = INFO + "." + GridInfoConstants.LEVEL; + + public static final String LEVEL_ID = INFO + "." + + GridInfoConstants.LEVEL_ID; + + public static final String MASTER_LEVEL_NAME = INFO + "." + + GridInfoConstants.MASTER_LEVEL_NAME; + + public static final String LEVEL_ONE = INFO + "." + + GridInfoConstants.LEVEL_ONE; + + public static final String LEVEL_TWO = INFO + "." + + GridInfoConstants.LEVEL_TWO; + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridInfoConstants.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridInfoConstants.java new file mode 100644 index 0000000000..8f0f9d6b2a --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridInfoConstants.java @@ -0,0 +1,73 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid; + +/** + * + * Contains some useful constants for dealing with grid info objects, mostly + * just hibernate names of attributes. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 11, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class GridInfoConstants { + + public static final String ID = "id"; + + public static final String DATASET_ID = "datasetId"; + + public static final String SECONDARY_ID = "secondaryId"; + + public static final String ENSEMBLE_ID = "ensembleId"; + + public static final String LOCATION = "location"; + + public static final String LOCATION_ID = LOCATION + ".id"; + + public static final String PARAMETER = "parameter"; + + public static final String PARAMETER_ABBREVIATION = PARAMETER + + ".abbreviation"; + + public static final String PARAMETER_NAME = PARAMETER + ".name"; + + public static final String PARAMETER_UNIT = PARAMETER + ".unitString"; + + public static final String LEVEL = "level"; + + public static final String LEVEL_ID = LEVEL + ".id"; + + public static final String MASTER_LEVEL_NAME = LEVEL + ".masterLevel.name"; + + public static final String LEVEL_ONE = LEVEL + ".levelonevalue"; + + public static final String LEVEL_TWO = LEVEL + ".leveltwovalue"; + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridInfoRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridInfoRecord.java new file mode 100644 index 0000000000..5b6f3c02b7 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridInfoRecord.java @@ -0,0 +1,248 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.PrimaryKeyJoinColumn; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +import com.raytheon.uf.common.dataplugin.annotations.DataURI; +import com.raytheon.uf.common.dataplugin.level.Level; +import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; +import com.raytheon.uf.common.gridcoverage.GridCoverage; +import com.raytheon.uf.common.parameter.Parameter; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Contains all attributes of a grid record except time. This is done to save + * space in the db since across time most grid data has the same + * level/parameter/etc so having all other information in a separate table saves + * space and improves theoretical performance. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * May 21, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +@Entity +@Table(name = "grid_info") +@SequenceGenerator(name = "GRIDINFO_GENERATOR", sequenceName = "gridinfo_seq", allocationSize = 1) +@DynamicSerialize +public class GridInfoRecord extends PersistableDataObject { + + private static final long serialVersionUID = 1L; + + /** The id */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "GRIDINFO_GENERATOR") + @DynamicSerializeElement + private Integer id; + + @Column + @DataURI(position = 0) + @DynamicSerializeElement + private String datasetId; + + /** + * Any string which can differentiate this record from other records with + * the same datasetId, examples of this would be for different versions of + * the same grid or for different events from the same model. + */ + @Column + @DataURI(position = 1) + @DynamicSerializeElement + private String secondaryId; + + @Column + @DynamicSerializeElement + @DataURI(position = 2) + private String ensembleId; + + /** The spatial information */ + @ManyToOne + @PrimaryKeyJoinColumn + @DataURI(position = 3) + @DynamicSerializeElement + private GridCoverage location; + + @ManyToOne + @PrimaryKeyJoinColumn + @DataURI(position = 4, embedded = true) + @DynamicSerializeElement + private Parameter parameter; + + @ManyToOne + @PrimaryKeyJoinColumn + @DynamicSerializeElement + @DataURI(position = 5, embedded = true) + private Level level; + + public GridInfoRecord() { + + } + + public GridInfoRecord(GridInfoRecord record) { + this.datasetId = record.getDatasetId(); + this.level = record.getLevel(); + this.location = record.getLocation(); + this.parameter = record.getParameter(); + this.ensembleId = record.getEnsembleId(); + this.secondaryId = record.getSecondaryId(); + this.id = record.getId(); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getDatasetId() { + return datasetId; + } + + public void setDatasetId(String datasetId) { + this.datasetId = datasetId; + } + + public String getSecondaryId() { + return secondaryId; + } + + public void setSecondaryId(String secondaryId) { + this.secondaryId = secondaryId; + } + + public String getEnsembleId() { + return ensembleId; + } + + public void setEnsembleId(String ensembleId) { + this.ensembleId = ensembleId; + } + + public GridCoverage getLocation() { + return location; + } + + public void setLocation(GridCoverage location) { + this.location = location; + } + + public Parameter getParameter() { + return parameter; + } + + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + public Level getLevel() { + return level; + } + + public void setLevel(Level level) { + this.level = level; + } + + @Override + public String toString() { + return "/" + datasetId + "/" + secondaryId + "/" + ensembleId + "/" + + location + "/" + parameter + "/" + level; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((datasetId == null) ? 0 : datasetId.hashCode()); + result = prime * result + + ((ensembleId == null) ? 0 : ensembleId.hashCode()); + result = prime * result + ((level == null) ? 0 : level.hashCode()); + result = prime * result + + ((location == null) ? 0 : location.hashCode()); + result = prime * result + + ((parameter == null) ? 0 : parameter.hashCode()); + result = prime * result + + ((secondaryId == null) ? 0 : secondaryId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + GridInfoRecord other = (GridInfoRecord) obj; + if (datasetId == null) { + if (other.datasetId != null) + return false; + } else if (!datasetId.equals(other.datasetId)) + return false; + if (ensembleId == null) { + if (other.ensembleId != null) + return false; + } else if (!ensembleId.equals(other.ensembleId)) + return false; + if (level == null) { + if (other.level != null) + return false; + } else if (!level.equals(other.level)) + return false; + if (location == null) { + if (other.location != null) + return false; + } else if (!location.equals(other.location)) + return false; + if (parameter == null) { + if (other.parameter != null) + return false; + } else if (!parameter.equals(other.parameter)) + return false; + if (secondaryId == null) { + if (other.secondaryId != null) + return false; + } else if (!secondaryId.equals(other.secondaryId)) + return false; + return true; + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridPathProvider.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridPathProvider.java new file mode 100644 index 0000000000..52ade9b034 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridPathProvider.java @@ -0,0 +1,128 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.uf.common.dataplugin.grid; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider; +import com.raytheon.uf.common.dataplugin.persist.IPersistable; + +/** + * Path provider for storing gridded data to HDF5 + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 4/24/09       1994        bphillip    Initial Creation
+ * 
+ * 
+ * + * @author bphillip + * @version 1 + */ +public class GridPathProvider extends DefaultPathProvider { + + private static final DecimalFormat forecastHourFormat = new DecimalFormat( + "000"); + + private static final int SECONDS_PER_HOUR = 3600; + + public static final String FORECAST_HR_TOKEN = "-FH-"; + + private static GridPathProvider instance = new GridPathProvider(); + + public static final List STATIC_PARAMETERS; + + static { + STATIC_PARAMETERS = new ArrayList(); + STATIC_PARAMETERS.add("staticTopo"); + STATIC_PARAMETERS.add("staticXspacing"); + STATIC_PARAMETERS.add("staticYspacing"); + STATIC_PARAMETERS.add("staticCoriolis"); + STATIC_PARAMETERS.add("staticSpacing"); + } + + public static GridPathProvider getInstance() { + return instance; + } + + protected GridPathProvider() { + + } + + @Override + public String getHDFFileName(String pluginName, IPersistable persistable) { + + if (persistable == null) { + throw new IllegalArgumentException( + "Expected argument persistable is null"); + } + + if (!(persistable instanceof GridRecord)) { + throw new IllegalArgumentException( + "Argument persistable is of wrong type. Expected " + + GridRecord.class + " but got " + + persistable.getClass()); + } else if (pluginName == null) { + throw new IllegalArgumentException( + "Expected argument pluginName not set on object " + + persistable.toString()); + } + + GridRecord pdo = (GridRecord) persistable; + StringBuffer sb = new StringBuffer(64); + sb.append(pdo.getDatasetId()); + Date refTime = pdo.getDataTime().getRefTime(); + String refTimeString = null; + synchronized (fileNameFormat) { + refTimeString = fileNameFormat.format(refTime); + } + sb.append(refTimeString); + sb.append(FORECAST_HR_TOKEN); + if (STATIC_PARAMETERS.contains(pdo.getParameter().getAbbreviation())) { + sb.append("000"); + } else { + long number = pdo.getDataTime().getFcstTime() / SECONDS_PER_HOUR; + String numberString = null; + synchronized (forecastHourFormat) { + numberString = forecastHourFormat.format(number); + } + sb.append(numberString); + } + sb.append(".h5"); + + return sb.toString(); + } + + public String formatTime(Date date) { + String retVal = null; + synchronized (fileNameFormat) { + retVal = fileNameFormat.format(date); + } + return retVal; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridRecord.java new file mode 100644 index 0000000000..a1db9909dc --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridRecord.java @@ -0,0 +1,239 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.PrimaryKeyJoinColumn; +import javax.persistence.Table; +import javax.persistence.Transient; +import javax.persistence.UniqueConstraint; + +import com.raytheon.uf.common.dataplugin.IDecoderGettable; +import com.raytheon.uf.common.dataplugin.annotations.DataURI; +import com.raytheon.uf.common.dataplugin.level.Level; +import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider; +import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject; +import com.raytheon.uf.common.geospatial.ISpatialEnabled; +import com.raytheon.uf.common.geospatial.ISpatialObject; +import com.raytheon.uf.common.gridcoverage.GridCoverage; +import com.raytheon.uf.common.parameter.Parameter; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * + * Record for storing generic gridded data. Everything interesting is stored in + * the info object since it allows us to reuse the info object for identical + * records at different times which saves db and improves theoretical + * performance. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * May 21, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +@Entity +@Table(name = "grid", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) +@DynamicSerialize +public class GridRecord extends PersistablePluginDataObject implements + ISpatialEnabled { + + private static final long serialVersionUID = 1L; + + @ManyToOne(cascade = { CascadeType.REFRESH }) + @PrimaryKeyJoinColumn + @DataURI(position = 1, embedded = true) + @DynamicSerializeElement + private GridInfoRecord info; + + /** + * Holds any extra attributes which may be specific to this data. These are + * not stored to the database or to hdf5 but they can be useful for passing + * additional parameters from a decoder to a post processor. + */ + @Transient + private Map extraAttributes; + + public GridRecord() { + super(); + } + + public GridRecord(GridRecord record) { + this.pluginName = record.getPluginName(); + this.dataTime = record.getDataTime(); + this.info = new GridInfoRecord(record.getInfoNotNull()); + if (record.getExtraAttributes() != null) { + this.extraAttributes = new HashMap( + record.getExtraAttributes()); + } + } + + public GridRecord(String uri) { + super(uri); + } + + public GridInfoRecord getInfo() { + + return info; + } + + public void setInfo(GridInfoRecord info) { + this.info = info; + } + + protected GridInfoRecord getInfoNotNull() { + if (info == null) { + info = new GridInfoRecord(); + } + return info; + } + + public String getDatasetId() { + return getInfoNotNull().getDatasetId(); + } + + public void setDatasetId(String datasetId) { + getInfoNotNull().setDatasetId(datasetId); + } + + public String getSecondaryId() { + return getInfoNotNull().getSecondaryId(); + } + + public void setSecondaryId(String secondaryId) { + getInfoNotNull().setSecondaryId(secondaryId); + } + + public GridCoverage getLocation() { + return getInfoNotNull().getLocation(); + } + + public void setLocation(GridCoverage location) { + getInfoNotNull().setLocation(location); + } + + public Parameter getParameter() { + return getInfoNotNull().getParameter(); + } + + public void setParameter(Parameter parameter) { + getInfoNotNull().setParameter(parameter); + } + + public Level getLevel() { + return getInfoNotNull().getLevel(); + } + + public void setLevel(Level level) { + getInfoNotNull().setLevel(level); + } + + public String getEnsembleId() { + return getInfoNotNull().getEnsembleId(); + } + + public void setEnsembleId(String ensembleId) { + getInfoNotNull().setEnsembleId(ensembleId); + } + + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } + + @Override + public ISpatialObject getSpatialObject() { + return getLocation(); + } + + @Override + public IHDFFilePathProvider getHDFPathProvider() { + return GridPathProvider.getInstance(); + } + + public Map getExtraAttributes() { + return extraAttributes; + } + + public void setExtraAttributes(Map extraAttributes) { + this.extraAttributes = extraAttributes; + } + + /** + * Add an attribute to the data, if there are no attributes then the + * attribute map is created. + * + * @param key + * @param value + * @return the previous value of the attribute or null if there was none. + */ + public Object addExtraAttribute(String key, Object value) { + if (extraAttributes == null) { + extraAttributes = new HashMap(); + } + return extraAttributes.put(key, value); + } + + public Object getExtraAttribute(String key) { + if (extraAttributes == null) { + return null; + } + return extraAttributes.get(key); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((info == null) ? 0 : info.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + GridRecord other = (GridRecord) obj; + if (info == null) { + if (other.info != null) + return false; + } else if (!info.equals(other.info)) + return false; + return true; + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfo.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfo.java new file mode 100644 index 0000000000..669c916f84 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfo.java @@ -0,0 +1,95 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid.dataset; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * + * Contains static information about a grid dataset. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 27, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +@XmlAccessorType(XmlAccessType.NONE) +public class DatasetInfo { + + /** The title of the model */ + @XmlElement + private String title; + + /** The model name */ + @XmlElement + private String datasetId; + + @XmlElement + private String alias; + + /** + * The intrinsic temporal resolution of the data. + */ + @XmlElement + private Integer dt; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDatasetId() { + return datasetId; + } + + public void setDatasetId(String datasetId) { + this.datasetId = datasetId; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public Integer getDt() { + return dt; + } + + public void setDt(Integer dt) { + this.dt = dt; + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfoLookup.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfoLookup.java new file mode 100644 index 0000000000..cb7721df58 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfoLookup.java @@ -0,0 +1,117 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid.dataset; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.bind.JAXBException; + +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationFile; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.serialization.JAXBManager; +import com.raytheon.uf.common.serialization.SerializationException; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; + +/** + * + * Provides logic to read datasetInfo files from localization and provide lookup + * by datasetId. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 27, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class DatasetInfoLookup { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(DatasetInfoLookup.class); + + private static DatasetInfoLookup instance; + + public static DatasetInfoLookup getInstance() { + if (instance == null) { + instance = new DatasetInfoLookup(); + } + return instance; + } + + private Map infoMap = new HashMap(); + + private DatasetInfoLookup() { + init(); + } + + private void init() { + JAXBManager manager = null; + try { + manager = new JAXBManager(DatasetInfoSet.class); + } catch (JAXBException e) { + statusHandler + .error("Error loading context for DatasetInfo, no datasetInfo will be loaded.", + e); + } + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext commonStaticBase = pathMgr.getContext( + LocalizationContext.LocalizationType.COMMON_STATIC, + LocalizationContext.LocalizationLevel.BASE); + + LocalizationContext commonStaticSite = pathMgr.getContext( + LocalizationContext.LocalizationType.COMMON_STATIC, + LocalizationContext.LocalizationLevel.SITE); + + LocalizationFile[] files = pathMgr.listFiles(new LocalizationContext[] { + commonStaticSite, commonStaticBase }, "grid" + + IPathManager.SEPARATOR + "datasetInfo", + new String[] { ".xml" }, true, true); + for (LocalizationFile file : files) { + if (file == null || !file.exists()) { + return; + } + try { + Object obj = manager.jaxbUnmarshalFromXmlFile(file.getFile()); + DatasetInfoSet set = (DatasetInfoSet) obj; + for (DatasetInfo info : set.getInfos()) { + infoMap.put(info.getDatasetId(), info); + } + } catch (SerializationException e) { + statusHandler.error( + "Error reading dataset info: " + file.getName() + + " has been ignored.", e); + } + } + + } + + public DatasetInfo getInfo(String datasetId) { + return infoMap.get(datasetId); + } +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfoSet.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfoSet.java new file mode 100644 index 0000000000..f7559b7bb3 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/dataset/DatasetInfoSet.java @@ -0,0 +1,62 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid.dataset; + +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * JAXB compatible root element for a list of datasetInfo objects + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 27, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class DatasetInfoSet { + + @XmlElements({ @XmlElement(name = "info", type = DatasetInfo.class) }) + private ArrayList infos; + + public ArrayList getInfos() { + return infos; + } + + public void setInfos(ArrayList infos) { + this.infos = infos; + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/request/GetGridTreeRequest.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/request/GetGridTreeRequest.java new file mode 100644 index 0000000000..235fb8504b --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/request/GetGridTreeRequest.java @@ -0,0 +1,45 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid.request; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.comm.IServerRequest; + +/** + * + * Request for the Grid DataTree. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 5, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +@DynamicSerialize +public class GetGridTreeRequest implements IServerRequest { + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/units/GridUnits.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/units/GridUnits.java new file mode 100644 index 0000000000..6b2e05e6fd --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/units/GridUnits.java @@ -0,0 +1,66 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid.units; + +import javax.measure.unit.NonSI; +import javax.measure.unit.SI; +import javax.measure.unit.UnitFormat; + +/** + * Provide alias for common units used in grid. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Oct 20, 2009            mschenke     Initial creation
+ * 
+ * 
+ * + * @author mschenke + * @version 1.0 + */ + +public class GridUnits { + + public static boolean register() { + UnitFormat.getInstance().alias(SI.METER, "gpm"); + UnitFormat.getUCUMInstance().alias(SI.METER, "gpm"); + UnitFormat.getInstance().alias(SI.MILLI(NonSI.BAR), "mb"); + UnitFormat.getUCUMInstance().alias(SI.MILLI(NonSI.BAR), "mb"); + UnitFormat.getInstance().alias(SI.CELSIUS, "C"); + UnitFormat.getUCUMInstance().alias(SI.CELSIUS, "C"); + UnitFormat.getInstance().alias(NonSI.FAHRENHEIT, "F"); + UnitFormat.getUCUMInstance().alias(NonSI.FAHRENHEIT, "F"); + UnitFormat.getInstance().alias(NonSI.DEGREE_ANGLE, "deg"); + UnitFormat.getUCUMInstance().alias(NonSI.DEGREE_ANGLE, "deg"); + UnitFormat.getInstance().alias(NonSI.DEGREE_ANGLE, "Degree"); + UnitFormat.getUCUMInstance().alias(NonSI.DEGREE_ANGLE, "Degree"); + UnitFormat.getInstance().alias(NonSI.KNOT, "kt"); + UnitFormat.getUCUMInstance().alias(NonSI.KNOT, "kt"); + UnitFormat.getInstance().alias(SI.SECOND, "sec"); + UnitFormat.getUCUMInstance().alias(SI.SECOND, "sec"); + UnitFormat.getInstance().alias(SI.METER, "meters"); + UnitFormat.getUCUMInstance().alias(SI.METER, "meters"); + return true; + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/util/StaticGridData.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/util/StaticGridData.java new file mode 100644 index 0000000000..fb4d813f72 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/util/StaticGridData.java @@ -0,0 +1,169 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid.util; + +import java.util.HashMap; +import java.util.Map; + +import org.opengis.metadata.spatial.PixelOrientation; + +import com.raytheon.uf.common.datastorage.records.FloatDataRecord; +import com.raytheon.uf.common.geospatial.MapUtil; +import com.raytheon.uf.common.gridcoverage.GridCoverage; +import com.vividsolutions.jts.geom.Coordinate; + +/** + * A class for calculating and caching static data for grids. + * + *
+ * SOFTWARE HISTORY
+ * Date			Ticket#		Engineer	Description
+ * ------------	----------	-----------	--------------------------
+ * Jul 24, 2008				brockwoo	Initial creation
+ * 
+ * 
+ * + * @author brockwoo + * @version 1.0 + */ + +public class StaticGridData { + private static Map instanceMap = new HashMap(); + + private static final double R_EARTH = 6370.0; + + private FloatDataRecord dx; + + private FloatDataRecord dy; + + private FloatDataRecord coriolis; + + private StaticGridData(GridCoverage gridCoverage) { + initStaticData(gridCoverage); + } + + public static synchronized StaticGridData getInstance( + GridCoverage gridCoverage) { + StaticGridData rval = instanceMap.get(gridCoverage); + + if (rval == null) { + rval = new StaticGridData(gridCoverage); + instanceMap.put(gridCoverage, rval); + } + + return rval; + } + + public FloatDataRecord getCoriolis() { + return this.coriolis; + } + + public FloatDataRecord getDx() { + return this.dx; + } + + public FloatDataRecord getDy() { + return this.dy; + } + + private void initStaticData(GridCoverage gridCoverage) { + int nx = gridCoverage.getNx(); + int ny = gridCoverage.getNy(); + int n = nx * ny; + float[] _coriolis = new float[n]; + float[] dxPtr = new float[n]; + float[] dyPtr = new float[n]; + float[] avgPtr = new float[n]; + double[] xx = new double[n]; + double[] yy = new double[n]; + double[] zz = new double[n]; + int i, j, k; + + for (j = k = 0; j < ny; j++) { + for (i = 0; i < nx; i++, k++) { + Coordinate location = new Coordinate(i, j); + Coordinate latLon = MapUtil.gridCoordinateToLatLon(location, + PixelOrientation.CENTER, gridCoverage); + latLon.x = Math.toRadians(latLon.x); + latLon.y = Math.toRadians(latLon.y); + xx[k] = Math.cos(latLon.y); + yy[k] = xx[k] * Math.sin(latLon.x); + xx[k] *= Math.cos(latLon.x); + zz[k] = Math.sin(latLon.y); + _coriolis[k] = (float) (zz[k] * 1.458e-4); + } + } + + this.coriolis = newRecord(_coriolis, nx, ny); + + int up, dn, lft, rgt; + long _nxm = nx - 1; + double d; + double icomp, jcomp, kcomp; + double dmax = 0.0; + dn = 0; + up = nx; + for (j = k = 0; j < ny; j++) { + if (up >= n) { + up -= nx; + } + lft = k; + for (i = 0; i < nx; i++, k++) { + rgt = (i < _nxm ? k + 1 : k); + icomp = yy[lft] * zz[rgt] - zz[lft] * yy[rgt]; + jcomp = zz[lft] * xx[rgt] - xx[lft] * zz[rgt]; + kcomp = xx[lft] * yy[rgt] - yy[lft] * xx[rgt]; + d = Math.sqrt(icomp * icomp + jcomp * jcomp + kcomp * kcomp); + dxPtr[k] = (float) (Math.asin(d) * 1000.0 * R_EARTH / (rgt - lft)); + icomp = yy[dn] * zz[up] - zz[dn] * yy[up]; + jcomp = zz[dn] * xx[up] - xx[dn] * zz[up]; + kcomp = xx[dn] * yy[up] - yy[dn] * xx[up]; + d = Math.sqrt(icomp * icomp + jcomp * jcomp + kcomp * kcomp); + dyPtr[k] = (float) (Math.asin(d) * 1000.0 * R_EARTH * nx / (up - dn)); + avgPtr[k] = (dxPtr[k] + dyPtr[k]) / 2.0f; + d = dxPtr[k] - dyPtr[k]; + if (d < 0) { + d = -d; + } + d /= avgPtr[k]; + if (d > dmax) { + dmax = d; + } + dn++; + up++; + lft = k; + } + if (j == 0) { + dn = 0; + } + } + if (dmax > 0.01) { + this.dx = newRecord(dxPtr, nx, ny); + this.dy = newRecord(dyPtr, nx, ny); + } else { + this.dx = this.dy = newRecord(avgPtr, nx, ny); + } + } + + private FloatDataRecord newRecord(float[] data, int nx, int ny) { + return new FloatDataRecord("DATA", "", data, 2, new long[] { nx, ny }); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/util/StaticGridDataType.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/util/StaticGridDataType.java new file mode 100644 index 0000000000..9259e3e57c --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/util/StaticGridDataType.java @@ -0,0 +1,56 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.grid.util; + +import java.util.ArrayList; +import java.util.List; + +/** + * The static grid data types are the same values for a coverage and can be + * calculated based off the coverage/model. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 17, 2010            rjpeter     Initial creation
+ * 
+ * 
+ * + * @author rjpeter + * @version 1.0 + */ + +public enum StaticGridDataType { + dx, dy, coriolis, _dt; + + private static List stringValues; + + public static List getStringValues() { + if (stringValues == null) { + stringValues = new ArrayList(values().length); + for (StaticGridDataType type : values()) { + stringValues.add(type.toString()); + } + } + return stringValues; + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/.classpath b/edexOsgi/com.raytheon.uf.edex.plugin.grid/.classpath new file mode 100644 index 0000000000..f77c5c56bb --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/.project b/edexOsgi/com.raytheon.uf.edex.plugin.grid/.project new file mode 100644 index 0000000000..8b4643dc92 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/.project @@ -0,0 +1,28 @@ + + + com.raytheon.uf.edex.plugin.grid + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/.settings/org.eclipse.jdt.core.prefs b/edexOsgi/com.raytheon.uf.edex.plugin.grid/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..5718e24147 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Fri Feb 03 13:25:55 CST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.plugin.grid/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..024752f577 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/META-INF/MANIFEST.MF @@ -0,0 +1,66 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Grid +Bundle-SymbolicName: com.raytheon.uf.edex.plugin.grid +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: RAYTHEON +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Import-Package: com.raytheon.edex.site, + com.raytheon.uf.common.dataplugin, + com.raytheon.uf.common.dataplugin.grid, + com.raytheon.uf.common.dataplugin.grid.dataset, + com.raytheon.uf.common.dataplugin.grid.request, + com.raytheon.uf.common.dataplugin.level, + com.raytheon.uf.common.dataplugin.persist, + com.raytheon.uf.common.dataquery.db, + com.raytheon.uf.common.datastorage, + com.raytheon.uf.common.datastorage.records, + com.raytheon.uf.common.derivparam.tree, + com.raytheon.uf.common.geospatial, + com.raytheon.uf.common.geospatial.interpolation, + com.raytheon.uf.common.gridcoverage, + com.raytheon.uf.common.gridcoverage.lookup, + com.raytheon.uf.common.parameter, + com.raytheon.uf.common.parameter.mapping, + com.raytheon.uf.common.serialization, + com.raytheon.uf.common.serialization.comm, + com.raytheon.uf.common.status, + com.raytheon.uf.common.util, + com.raytheon.uf.common.util.registry, + com.raytheon.uf.edex.core, + com.raytheon.uf.edex.core.dataplugin, + com.raytheon.uf.edex.core.props, + com.raytheon.uf.edex.database, + com.raytheon.uf.edex.database.cluster, + com.raytheon.uf.edex.database.dao, + com.raytheon.uf.edex.database.plugin, + com.raytheon.uf.edex.database.query, + com.raytheon.uf.edex.parameter, + com.vividsolutions.jts.geom, + javax.measure.converter, + javax.measure.unit, + org.apache.commons.logging, + org.geotools.coverage, + org.geotools.coverage.grid, + org.geotools.factory, + org.geotools.geometry, + org.geotools.geometry.jts, + org.geotools.referencing, + org.geotools.referencing.operation, + org.geotools.referencing.operation.builder, + org.geotools.referencing.operation.transform, + org.hibernate, + org.hibernate.criterion, + org.opengis.coverage.grid, + org.opengis.geometry, + org.opengis.metadata.spatial, + org.opengis.parameter, + org.opengis.referencing, + org.opengis.referencing.crs, + org.opengis.referencing.datum, + org.opengis.referencing.operation, + org.springframework.dao.support, + org.springframework.orm.hibernate3.support +Export-Package: com.raytheon.uf.edex.plugin.grid.dao, + com.raytheon.uf.edex.plugin.grid.handler, + com.raytheon.uf.edex.plugin.grid.topo diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/build.properties b/edexOsgi/com.raytheon.uf.edex.plugin.grid/build.properties new file mode 100644 index 0000000000..73974cda80 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + res/,\ + utility/ diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/res/spring/grid-common.xml b/edexOsgi/com.raytheon.uf.edex.plugin.grid/res/spring/grid-common.xml new file mode 100644 index 0000000000..2c946935c5 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/res/spring/grid-common.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + com.raytheon.uf.common.dataplugin.level + com.raytheon.uf.common.parameter + com.raytheon.uf.common.gridcoverage + + + + + + + + + + + + + + + + com.raytheon.uf.common.dataplugin.grid.units.GridUnits + + + register + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/res/spring/grid-request.xml b/edexOsgi/com.raytheon.uf.edex.plugin.grid/res/spring/grid-request.xml new file mode 100644 index 0000000000..73238581bf --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/res/spring/grid-request.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridDao.java b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridDao.java new file mode 100644 index 0000000000..c934b773d7 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridDao.java @@ -0,0 +1,406 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.uf.edex.plugin.grid.dao; + +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.measure.converter.UnitConverter; + +import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.dataplugin.grid.GridConstants; +import com.raytheon.uf.common.dataplugin.grid.GridPathProvider; +import com.raytheon.uf.common.dataplugin.grid.GridRecord; +import com.raytheon.uf.common.dataplugin.level.Level; +import com.raytheon.uf.common.dataplugin.level.LevelFactory; +import com.raytheon.uf.common.dataplugin.level.MasterLevel; +import com.raytheon.uf.common.dataplugin.persist.IPersistable; +import com.raytheon.uf.common.dataquery.db.QueryResult; +import com.raytheon.uf.common.datastorage.IDataStore; +import com.raytheon.uf.common.datastorage.Request; +import com.raytheon.uf.common.datastorage.StorageException; +import com.raytheon.uf.common.datastorage.StorageProperties; +import com.raytheon.uf.common.datastorage.StorageStatus; +import com.raytheon.uf.common.datastorage.records.AbstractStorageRecord; +import com.raytheon.uf.common.datastorage.records.FloatDataRecord; +import com.raytheon.uf.common.datastorage.records.IDataRecord; +import com.raytheon.uf.common.gridcoverage.GridCoverage; +import com.raytheon.uf.common.gridcoverage.lookup.GridCoverageLookup; +import com.raytheon.uf.common.parameter.Parameter; +import com.raytheon.uf.edex.core.EDEXUtil; +import com.raytheon.uf.edex.core.EdexException; +import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; +import com.raytheon.uf.edex.database.DataAccessLayerException; +import com.raytheon.uf.edex.database.plugin.PluginDao; +import com.raytheon.uf.edex.parameter.ParameterLookup; + +/** + * Data access object for accessing Grid records from the database + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 4/7/09       1994        bphillip    Initial Creation
+ * 
+ * 
+ * + * @author bphillip + * @version 1 + */ +public class GridDao extends PluginDao { + + private static String purgeModelCacheTopic = null; + + public static String setPurgeModelCacheTopic(String purgeModelCacheTopic) { + GridDao.purgeModelCacheTopic = purgeModelCacheTopic; + return purgeModelCacheTopic; + } + + public GridDao() throws PluginException { + super(GridConstants.GRID); + } + + public GridDao(String pluginName) throws PluginException { + super(pluginName); + } + + @Override + protected IDataStore populateDataStore(IDataStore dataStore, + IPersistable obj) throws Exception { + GridRecord gridRec = (GridRecord) obj; + Object messageData = gridRec.getMessageData(); + GridCoverage location = gridRec.getLocation(); + if (location != null && messageData instanceof float[]) { + long[] sizes = new long[] { location.getNx(), location.getNy() }; + String abbrev = gridRec.getParameter().getAbbreviation(); + String group = gridRec.getDataURI(); + if (GridPathProvider.STATIC_PARAMETERS.contains(abbrev)) { + group = "/" + location.getName(); + } + AbstractStorageRecord storageRecord = new FloatDataRecord("Data", + group, (float[]) messageData, 2, sizes); + + storageRecord.setCorrelationObject(gridRec); + StorageProperties sp = new StorageProperties(); + String compression = PluginRegistry.getInstance() + .getRegisteredObject(pluginName).getCompression(); + if (compression != null) { + sp.setCompression(StorageProperties.Compression + .valueOf(compression)); + } + sp.setChunked(true); + dataStore.addDataRecord(storageRecord, sp); + } else { + throw new Exception("Cannot create data record, spatialData = " + + location + " and messageData = " + messageData); + } + return dataStore; + } + + @Override + public void persistRecords(PluginDataObject... records) + throws PluginException { + List toPersist = new ArrayList( + records.length); + for (PluginDataObject record : records) { + GridRecord rec = (GridRecord) record; + if (rec.getParameter() == null + || rec.getParameter().getName() == null + || rec.getParameter().getName().equals("Missing")) { + logger.info("Discarding record due to missing or unknown parameter mapping: " + + record); + } else { + boolean validLevel = false; + Level level = rec.getLevel(); + + if (level != null) { + MasterLevel ml = level.getMasterLevel(); + + if (ml != null + && !LevelFactory.UNKNOWN_LEVEL.equals(ml.getName())) { + validLevel = true; + } + } + + if (validLevel) { + toPersist.add(rec); + } else { + logger.info("Discarding record due to missing or unknown level mapping: " + + record); + } + } + } + + super.persistRecords(toPersist.toArray(new PluginDataObject[toPersist + .size()])); + } + + @Override + public PluginDataObject[] persistToDatabase(PluginDataObject... records) { + return super.persistToDatabase(verifyRecords(records)); + } + + @Override + public StorageStatus persistToHDF5(PluginDataObject... records) + throws PluginException { + return super.persistToHDF5(verifyRecords(records)); + } + + @Override + public List getHDF5Data(List objects, + int tileSet) throws PluginException { + + List retVal = new ArrayList( + objects.size()); + + for (PluginDataObject rec : objects) { + if (rec instanceof GridRecord) { + try { + GridRecord obj = (GridRecord) rec; + IDataStore dataStore = getDataStore(obj); + String abbrev = obj.getParameter().getAbbreviation(); + if (GridPathProvider.STATIC_PARAMETERS.contains(abbrev)) { + IDataRecord[] record = new IDataRecord[4]; + record[0] = dataStore.retrieve("/" + + obj.getLocation().getName(), abbrev, + Request.ALL); + retVal.add(record); + } else { + /* connect to the data store and retrieve the data */ + IDataRecord[] record = new IDataRecord[4]; + record[0] = dataStore.retrieve(obj.getDataURI(), + "Data", Request.ALL); + + retVal.add(record); + } + } catch (StorageException e) { + throw new PluginException("Error getting HDF5 data", e); + } catch (FileNotFoundException e) { + throw new PluginException("Error getting HDF5 data", e); + } + } + } + + return retVal; + } + + private PluginDataObject[] verifyRecords(PluginDataObject... records) { + List toPersist = new ArrayList( + records.length); + for (PluginDataObject record : records) { + GridRecord rec = (GridRecord) record; + if (validateDataset(rec)) { + toPersist.add(rec); + } + } + return toPersist.toArray(new GridRecord[toPersist.size()]); + } + + private boolean validateDataset(GridRecord record) { + if (!validateParameter(record)) { + return false; + } + if (!validateLevel(record)) { + return false; + } + if (!validateCoverage(record)) { + return false; + } + record.setInfo(GridInfoCache.getInstance() + .getGridInfo(record.getInfo())); + return true; + + } + + private boolean validateParameter(GridRecord record) { + Parameter parameter = record.getParameter(); + boolean result = true; + if (parameter == null) { + result = false; + } else if (parameter.getName() == null) { + result = false; + } else if (parameter.getName().equals("Missing")) { + result = false; + } else { + Parameter dbParameter = ParameterLookup.getInstance() + .lookupParameter(parameter, true); + if (!parameter.equals(dbParameter)) { + // This check is for debugging purposes + // if (!parameter.getName().equals(dbParameter.getName())) { + // logger.info("Record parameter name(" + parameter.getName() + // + ") does not match database(" + // + dbParameter.getName() + ") " + // + record.getDataURI()); + // } + UnitConverter converter = Parameter.compareUnits(parameter, + dbParameter); + // if (converter == null) { + // logger.info("Record parameter unit(" + // + parameter.getUnitString() + // + ") does not match database(" + // + dbParameter.getUnitString() + ") " + // + record.getDataURI()); + // // For absolute accuracy we should abort if units don't + // // match, but currently we will persist it anyway. + // // result = false; + // } else + if (converter != null && converter != UnitConverter.IDENTITY) { + Object messageData = record.getMessageData(); + if (messageData instanceof float[]) { + float[] data = (float[]) messageData; + for (int i = 0; i < data.length; i++) { + data[i] = (float) converter.convert(data[i]); + } + } else { + logger.info("Unable to convert grid data to correct units: " + + record.getDataURI()); + } + } + } + record.setParameter(dbParameter); + } + if (!result) { + logger.info("Discarding record due to missing or unknown parameter mapping: " + + record); + } + return result; + } + + private boolean validateCoverage(GridRecord record) { + GridCoverage coverage = record.getLocation(); + if (coverage == null) { + logger.info("Discarding record due to missing location: " + record); + return false; + } + GridCoverage dbCoverage = GridCoverageLookup.getInstance().getCoverage( + coverage, false); + if (coverage == dbCoverage) { + return true; + } + if (dbCoverage == null) { + dbCoverage = GridCoverageLookup.getInstance().getCoverage(coverage, + true); + logger.error("Unable to persist " + record + + " because storing the location failed."); + if (dbCoverage == null) { + return false; + } + } + record.setLocation(dbCoverage); + if (!coverage.getId().equals(dbCoverage.getId())) { + record.setDataURI(null); + try { + record.constructDataURI(); + } catch (PluginException e) { + logger.info("Error constructing dataURI: " + record); + return false; + } + } + return true; + } + + private boolean validateLevel(GridRecord record) { + boolean result = false; + Level level = record.getLevel(); + + if (level != null) { + MasterLevel ml = level.getMasterLevel(); + + if (ml != null && !LevelFactory.UNKNOWN_LEVEL.equals(ml.getName())) { + result = true; + } + } + + if (!result) { + logger.info("Discarding record due to missing or unknown level mapping: " + + record); + } + return result; + } + + /** + * Overridden to clean up orphan GridInfoRecords. + */ + @Override + public void delete(List objs) { + super.delete(objs); + Set orphanedIds = new HashSet(objs.size()); + StringBuilder sqlString = new StringBuilder(objs.size() * 15 + 80); + sqlString + .append("select distinct info_id from awips.grid where info_id in ("); + for (PluginDataObject pdo : objs) { + if (pdo instanceof GridRecord) { + Integer id = ((GridRecord) pdo).getInfo().getId(); + if (orphanedIds.add(id)) { + if (orphanedIds.size() > 1) { + sqlString.append(", "); + } + sqlString.append(id); + } + } + } + sqlString.append(");"); + try { + QueryResult result = (QueryResult) this.executeNativeSql(sqlString + .toString()); + for (int i = 0; i < result.getResultCount(); i++) { + orphanedIds.remove((Integer) result.getRowColumnValue(i, 0)); + } + if (!orphanedIds.isEmpty()) { + sqlString = new StringBuilder(orphanedIds.size() * 15 + 60); + sqlString.append("delete from awips.grid_info where id in ("); + boolean first = true; + for (Integer id : orphanedIds) { + if (!first) { + sqlString.append(", "); + } else { + first = false; + } + sqlString.append(id); + } + sqlString.append(");"); + if (purgeModelCacheTopic != null) { + this.executeNativeSql(sqlString.toString()); + EDEXUtil.getMessageProducer().sendAsyncUri( + purgeModelCacheTopic, orphanedIds); + } else { + GridInfoCache.getInstance().purgeCache( + new ArrayList(orphanedIds)); + statusHandler + .warn("Unable to purge model cache of clustered edices"); + } + } + } catch (DataAccessLayerException e1) { + statusHandler.error("Error purging orphaned grid info entries", e1); + } catch (EdexException e) { + statusHandler.error( + "Error sending message to purge grid info topic", e); + } + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridInfoCache.java b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridInfoCache.java new file mode 100644 index 0000000000..ad4e8bab16 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridInfoCache.java @@ -0,0 +1,112 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.edex.plugin.grid.dao; + +import java.lang.ref.SoftReference; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +import com.raytheon.uf.common.dataplugin.grid.GridInfoRecord; +import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; +import com.raytheon.uf.edex.database.dao.CoreDao; +import com.raytheon.uf.edex.database.dao.DaoConfig; + +/** + * Cache the gridInfo objects from the database to avoid repeated lookups. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * May 21, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ + +public class GridInfoCache { + + private static GridInfoCache instance = new GridInfoCache(); + + public static GridInfoCache getInstance() { + return instance; + } + + private CoreDao dao; + + // A weak hashmap of soft references is used as a SoftSet. + private Map> cache = null; + + private GridInfoCache() { + cache = Collections + .synchronizedMap(new WeakHashMap>()); + dao = new CoreDao(DaoConfig.forClass(GridInfoRecord.class)); + } + + public GridInfoRecord getGridInfo(GridInfoRecord record) { + GridInfoRecord result = checkLocalCache(record); + if (result == null) { + synchronized (this) { + // It is possible that this query will return multiple results, + // for example if the record we are looking for has a null + // secondaryId but some db entries have a secondaryId set then + // this query will return all matching models ignoring + // secondaryId. In general these cases should be rare and small. + // So we handle it by caching everything returned and then + // double checking the cache. + List dbList = dao.queryByExample(record); + if (dbList != null && !dbList.isEmpty()) { + for (PersistableDataObject pdo : dbList) { + GridInfoRecord gir = (GridInfoRecord) pdo; + cache.put(gir, new SoftReference(gir)); + } + } + result = checkLocalCache(record); + if (result == null) { + dao.saveOrUpdate(record); + result = record; + } + } + } + return result; + } + + private GridInfoRecord checkLocalCache(GridInfoRecord record) { + GridInfoRecord result = null; + SoftReference ref = cache.get(record); + if (ref != null) { + result = ref.get(); + } + return result; + } + + public void purgeCache(List modelKeys) { + for (Integer key : modelKeys) { + cache.remove(key); + } + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/handler/GridTreeHandler.java b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/handler/GridTreeHandler.java new file mode 100644 index 0000000000..8ca65f1f5f --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/handler/GridTreeHandler.java @@ -0,0 +1,107 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.edex.plugin.grid.handler; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.raytheon.uf.common.dataplugin.grid.GridInfoConstants; +import com.raytheon.uf.common.dataplugin.grid.GridInfoRecord; +import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfo; +import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfoLookup; +import com.raytheon.uf.common.dataplugin.grid.request.GetGridTreeRequest; +import com.raytheon.uf.common.derivparam.tree.DataTree; +import com.raytheon.uf.common.serialization.comm.IRequestHandler; +import com.raytheon.uf.edex.database.dao.CoreDao; +import com.raytheon.uf.edex.database.dao.DaoConfig; +import com.raytheon.uf.edex.database.query.DatabaseQuery; + +/** + * Build a DataTree representing all the grid data in the db. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 5, 2012            bsteffen     Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ + +public class GridTreeHandler implements IRequestHandler { + + private static final String[] GRIDFIELDS = { GridInfoConstants.DATASET_ID, + GridInfoConstants.PARAMETER_ABBREVIATION, + GridInfoConstants.PARAMETER_NAME, GridInfoConstants.PARAMETER_UNIT, + GridInfoConstants.LEVEL_ID }; + + @Override + public DataTree handleRequest(GetGridTreeRequest request) throws Exception { + DataTree gridTree = null; + CoreDao gribDao = null; + List queryResults = null; + gribDao = new CoreDao(DaoConfig.forClass(GridInfoRecord.class)); + + // if we do not get a table back, just return an empty list + gridTree = new DataTree(); + DatabaseQuery query = new DatabaseQuery(GridInfoRecord.class.getName()); + + List distinctFields = Arrays.asList(GRIDFIELDS); + + query.addOrder(distinctFields.get(0), true); + query.addDistinctParameter(distinctFields); + queryResults = gribDao.queryByCriteria(query); + if (queryResults.size() > 0) { + for (Object gridField : queryResults) { + if (gridField.getClass().isArray()) { + ArrayList gridFields = new ArrayList( + Arrays.asList((Object[]) gridField)); + String model = gridFields.get(0).toString(); + gridTree.addBranch(model, getDt(model), gridFields.get(1) + .toString(), gridFields.get(2).toString(), + gridFields.get(3).toString(), gridFields.get(4) + .toString()); + } + } + } + return gridTree; + } + + private int getDt(String modelName) { + DatasetInfo info = DatasetInfoLookup.getInstance().getInfo(modelName); + if (info != null && info.getDt() != null) { + int dTinSeconds = info.getDt(); + + // dT <= 24 is in hours, need to convert to seconds + if (Math.abs(dTinSeconds) <= 24) { + dTinSeconds *= 3600; + } + return dTinSeconds; + } + return -1; + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/topo/StaticTopoData.java b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/topo/StaticTopoData.java new file mode 100644 index 0000000000..2753f73d24 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/topo/StaticTopoData.java @@ -0,0 +1,1117 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.uf.edex.plugin.grid.topo; + +import java.awt.Point; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.media.jai.JAI; + +import org.geotools.coverage.grid.GeneralGridEnvelope; +import org.geotools.coverage.grid.GridCoverage2D; +import org.geotools.coverage.grid.GridCoverageFactory; +import org.geotools.coverage.grid.GridGeometry2D; +import org.geotools.factory.Hints; +import org.geotools.geometry.DirectPosition2D; +import org.geotools.geometry.GeneralEnvelope; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.referencing.CRS; +import org.geotools.referencing.ReferencingFactoryFinder; +import org.geotools.referencing.operation.AbstractCoordinateOperationFactory; +import org.geotools.referencing.operation.builder.GridToEnvelopeMapper; +import org.geotools.referencing.operation.transform.IdentityTransform; +import org.opengis.geometry.DirectPosition; +import org.opengis.geometry.MismatchedDimensionException; +import org.opengis.metadata.spatial.PixelOrientation; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.crs.GeographicCRS; +import org.opengis.referencing.crs.ProjectedCRS; +import org.opengis.referencing.datum.PixelInCell; +import org.opengis.referencing.operation.CoordinateOperationFactory; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.MathTransformFactory; +import org.opengis.referencing.operation.TransformException; + +import com.raytheon.edex.site.SiteUtil; +import com.raytheon.uf.common.datastorage.DataStoreFactory; +import com.raytheon.uf.common.datastorage.IDataStore; +import com.raytheon.uf.common.datastorage.IDataStore.StoreOp; +import com.raytheon.uf.common.datastorage.Request; +import com.raytheon.uf.common.datastorage.StorageException; +import com.raytheon.uf.common.datastorage.StorageProperties; +import com.raytheon.uf.common.datastorage.StorageProperties.Compression; +import com.raytheon.uf.common.datastorage.records.FloatDataRecord; +import com.raytheon.uf.common.geospatial.CRSCache; +import com.raytheon.uf.common.geospatial.MapUtil; +import com.raytheon.uf.common.gridcoverage.GridCoverage; +import com.raytheon.uf.common.serialization.SerializationException; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.RunProcess; +import com.raytheon.uf.edex.core.props.PropertiesFactory; +import com.raytheon.uf.edex.database.cluster.ClusterLockUtils; +import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState; +import com.raytheon.uf.edex.database.cluster.ClusterTask; +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Envelope; + +/** + * Class used for accessing static topography information for GFE smart inits + * + *
+ * SOFTWARE HISTORY
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 09/27/2010   6394        bphillip    Initial creation
+ * 10/08/2010   6394        bphillip    Rewrote sections for optimal reading and writing performance
+ * 09/19/2011   10955       rferrel     Use RunProcess
+ * 04/18/2012   DR 14694    D. Friedman Fixes for static topography generation
+ * 05/09/2012   DR 14939    D. Friedman Fix errors in DR 14694
+ * 
+ * 
+ * + * @author bphillip + * @version 1.0 + */ +public class StaticTopoData { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(StaticTopoData.class); + + private static final float DATA_FILL = -9999; + + private static final float TOPO_FILL = -999999; + + /** The HDF5 data store used for accessing the topo data */ + private IDataStore sTopoDataStore; + + /** The HDF5 data store used for storing the site static topo data */ + private IDataStore siteDataStore; + + private static final String[] TOPO_FILES = new String[] { "us", "ak", + "carib", "pac", "world" }; + + private static final String TASK_NAME = "initStaticTopo"; + + /** The HDF dataset name for the static topo information for gfe */ + private static final String STOPO_DATASET = "Topo"; + + /** The .dat.gz suffix */ + private static final String DAT_GZ_SUFFIX = ".dat.gz"; + + /** + * Margin of extra data to retrieve when requesting the data slab from the + * data store + */ + private static final int DATA_MARGIN = 2; + + /** The base directory in which the topo files reside */ + private static final String FILE_PREFIX = PropertiesFactory.getInstance() + .getEnvProperties().getEnvValue("HDF5DIR") + + "/topo/"; + + /** The file containing the complete static topo data sets */ + private static final File topoFile = new File(FILE_PREFIX + "staticTopo.h5"); + + /** The file containing the site specific static topo data sets */ + private static final File siteTopoFile = new File(FILE_PREFIX + + "modelStaticTopo.h5"); + + /** A GridCoverageFactory instance for creating grid coverages */ + private GridCoverageFactory factory; + + /** HDF5 storage properties used for enabling compression */ + private static final StorageProperties sp; + + /** The singleton instance */ + private static StaticTopoData instance; + + // Initializes the storage properties + static { + sp = new StorageProperties(); + sp.setCompression(Compression.LZF); + sp.setChunked(true); + } + + /** + * Gets the singleton instance of StaticTopoData + * + * @return The singleton instance + */ + public static synchronized StaticTopoData getInstance() { + if (instance == null) { + instance = new StaticTopoData(); + } + return instance; + } + + /** + * Creates a new StaticTopoData instance + */ + private StaticTopoData() { + this.sTopoDataStore = DataStoreFactory.getDataStore(topoFile); + this.siteDataStore = DataStoreFactory.getDataStore(siteTopoFile); + + this.factory = new GridCoverageFactory(); + initStopoData(); + } + + /** + * Initializes the static topo data from the raw data + */ + private void initStopoData() { + statusHandler.handle(Priority.INFO, "Initializing static topo data"); + + try { + ClusterTask ct = null; + do { + ct = ClusterLockUtils.lock(TASK_NAME, "unpack", 300000, true); + } while (!LockState.SUCCESSFUL.equals(ct.getLockState())); + + try { + if (!topoFileExists()) { + // TODO: This will fail in a clustered server environment + // since + // static topo isn't installed to dx3/4 + statusHandler.handle(Priority.INFO, + "Static Topo file not found. Creating it..."); + + // Initializes the World topo data + statusHandler.handle(Priority.INFO, + "Initializing World Topo Data..."); + // DR#10955 + RunProcess + .getRunProcess() + .exec("gunzip " + FILE_PREFIX + "worldTopo" + + DAT_GZ_SUFFIX).waitFor(); + readTopoFile("world"); + statusHandler.handle(Priority.INFO, + "World Topo Data Initialized!"); + + // Initializes the US topo data + statusHandler.handle(Priority.INFO, + "Initializing US Topo Data..."); + // DR#10955 + RunProcess + .getRunProcess() + .exec("gunzip " + FILE_PREFIX + "usTopo" + + DAT_GZ_SUFFIX).waitFor(); + readTopoFile("us"); + statusHandler.handle(Priority.INFO, + "US Topo Data Initialized!"); + + // Initializes the Carribean topo data + statusHandler.handle(Priority.INFO, + "Initializing Carribean Topo Data..."); + // DR#10955 + RunProcess + .getRunProcess() + .exec("gunzip " + FILE_PREFIX + "caribTopo" + + DAT_GZ_SUFFIX).waitFor(); + readTopoFile("carib"); + statusHandler.handle(Priority.INFO, + "Carribean Topo Data Initialized!"); + + // Initializes the Alaska topo data + statusHandler.handle(Priority.INFO, + "Initializing Alaska Topo Data..."); + // DR#10955 + RunProcess + .getRunProcess() + .exec("gunzip " + FILE_PREFIX + "akTopo" + + DAT_GZ_SUFFIX).waitFor(); + readTopoFile("ak"); + statusHandler.handle(Priority.INFO, + "Alaska Topo Data Initialized!"); + + // Initializes the Pacific topo data + statusHandler.handle(Priority.INFO, + "Initializing Pacific Topo Data..."); + // DR#10955 + RunProcess + .getRunProcess() + .exec("gunzip " + FILE_PREFIX + "pacTopo" + + DAT_GZ_SUFFIX).waitFor(); + readTopoFile("pac"); + statusHandler.handle(Priority.INFO, + "Pacific Topo Data Initialized!"); + splitPacific(); + } + } finally { + if (ct != null) { + ClusterLockUtils.unlock(ct, false); + } + } + + initAttributes(); + } catch (Exception e) { + statusHandler.handle(Priority.CRITICAL, + "Error initializing static topo data!", e); + } + statusHandler.handle(Priority.INFO, "Static topo data initialized"); + } + + /** + * Splits the Pacific grid into east and west hemisphere chunks to reduce + * memory usage + * + * @throws Exception + */ + private void splitPacific() throws Exception { + Map pacAttributes = TopoAttributes.getAttributes("pac"); + int nx = (Integer) pacAttributes.get(TopoAttributes.NX); + int ny = (Integer) pacAttributes.get(TopoAttributes.NY); + + Map attributes = new HashMap(); + attributes.putAll(pacAttributes); + attributes.put(TopoAttributes.NX, nx / 2); + attributes.put(TopoAttributes.UR_LON, new Float(180.0f)); + float[] floatData = this.getSlab("pac", 0, 0, nx / 2, ny); + FloatDataRecord eastRecord = new FloatDataRecord("pac_east", "/", + floatData, 2, new long[] { nx / 2, ny }); + sTopoDataStore.addDataRecord(eastRecord, sp); + + FloatDataRecord attributeSet = new FloatDataRecord("attr" + "pac_east", + "/", new float[] { 0 }); + attributeSet.setDataAttributes(attributes); + sTopoDataStore.addDataRecord(attributeSet, sp); + sTopoDataStore.store(); + + attributes = new HashMap(); + attributes.putAll(pacAttributes); + attributes.put(TopoAttributes.NX, nx / 2); + attributes.put(TopoAttributes.LL_LON, new Float(-180.0f)); + floatData = this.getSlab("pac", nx / 2, 0, nx, ny); + FloatDataRecord westRecord = new FloatDataRecord("pac_west", "/", + floatData, 2, new long[] { nx / 2, ny }); + attributeSet = new FloatDataRecord("attr" + "pac_west", "/", + new float[] { 0 }); + attributeSet.setDataAttributes(attributes); + sTopoDataStore.addDataRecord(attributeSet, sp); + sTopoDataStore.addDataRecord(westRecord, sp); + sTopoDataStore.store(); + sTopoDataStore.delete("pac"); + sTopoDataStore.delete("attrpac"); + + } + + /** + * Checks to see if the topo file exists + * + * @return True if the file exists + */ + private boolean topoFileExists() { + try { + String[] modelArray = sTopoDataStore.getDatasets("/"); + if (modelArray.length == 0) { + return false; + } + } catch (Exception e) { + return false; + } + return true; + } + + /** + * Initializes the attributes so they can be easily retrieved + * + * @throws Exception + */ + private void initAttributes() throws Exception { + TopoAttributes.attributeMap.remove("world"); + TopoAttributes.attributeMap.remove("pac"); + String[] dataSets = sTopoDataStore.getDatasets("/"); + + for (String dataset : dataSets) { + if (dataset.startsWith("attr")) { + TopoAttributes.attributeMap.put( + dataset.replace("attr", ""), + sTopoDataStore.retrieve("/", dataset, + Request.buildPointRequest(new Point(0, 0))) + .getDataAttributes()); + } + } + } + + /** + * Initializes the topography data for the given site. The data is extracted + * from the static topo file and resampled according to the site location + * information + * + * @param modelName + * The site for which to initalize the topo data + * @param config + * The site's configuration information + * @throws StorageException + * @throws SerializationException + * If the topography data cannot be initialized for the given + * site + */ + public void initStopoData(GridCoverage coverage) throws StorageException, + SerializationException { + if (coverage.getNx() < 0 || coverage.getNy() < 0) { + statusHandler.handle(Priority.PROBLEM, coverage.getName() + + " is not applicable to " + SiteUtil.getSite() + + ". Skipping."); + return; + } + GridGeometry2D inGeom = MapUtil.getGridGeometry(coverage); + + // Gets the location data and extracts it from the static topo file + float[] finalData = null; + finalData = getTopoData(inGeom, coverage.getCrs(), coverage.getNx(), + coverage.getNy()); + + // Create an HDF5 data record and store it + FloatDataRecord outRecord = new FloatDataRecord(STOPO_DATASET, + coverage.spatialKey(), finalData, 2, new long[] { + inGeom.getGridRange().getHigh(0) + 1, + inGeom.getGridRange().getHigh(1) + 1 }); + siteDataStore.addDataRecord(outRecord, sp); + siteDataStore.store(StoreOp.REPLACE); + + statusHandler + .handle(Priority.INFO, + "Stopo data successfully initialized for " + + coverage.getName()); + } + + /** + * Private method used by the initialization code to see if the static topo + * data for a coverage has been initialized + */ + public boolean checkModelTopo(GridCoverage coverage) { + ClusterTask ct = ClusterLockUtils.lock(TASK_NAME, + coverage.spatialKey(), 120000, false); + + if (LockState.SUCCESSFUL.equals(ct.getLockState())) { + // set processed to true regardless of successfully + // update coverage so we don't infinite loop + try { + if (!topoExists(coverage)) { + statusHandler.handle( + Priority.INFO, + "Initializing static topo for grid " + + coverage.getName()); + initStopoData(coverage); + } + } catch (Exception e) { + statusHandler.handle( + Priority.INFO, + "Error storing static topo data for " + + coverage.getName(), e); + } finally { + ClusterLockUtils.unlock(ct, false); + } + return true; + } + return false; + } + + /** + * Chekcs if the static topo data for a model exists in the file + * + * @param modelName + * The model to check + * @return True if the data exists, else false + * @throws GribException + */ + private boolean topoExists(GridCoverage coverage) { + + List dataSets = null; + try { + String[] modelArray = siteDataStore.getDatasets(coverage + .spatialKey()); + dataSets = Arrays.asList(modelArray); + } catch (Exception e) { + return false; + } + + if (dataSets.contains(STOPO_DATASET)) { + return true; + } + + return false; + } + + /** + * Retrieves the static topo data for the given site + * + * @param modelName + * The site for which to get the static topo data + * @return The static topo data + * @throws GribException + * If an error occurs while retrieving the topo data + */ + public FloatDataRecord getStopoData(GridCoverage coverage) { + if (!topoExists(coverage)) { + while (!checkModelTopo(coverage)) { + } + } + FloatDataRecord record = null; + try { + record = (FloatDataRecord) siteDataStore.retrieve( + coverage.spatialKey(), STOPO_DATASET, Request.ALL); + + } catch (Exception e) { + statusHandler.handle( + Priority.INFO, + "Static topo data does not exist for grid " + + coverage.getName()); + return null; + } + return record; + } + + /** + * Extracts the the topo data from each of the topo data sets. + * + * @param inGeom + * The geometry of the data to be requested + * @param inCrs + * The coordinate reference system of the desired data + * @return A float array containing the extracted topo data + * @throws GribException + * If the data cannot be extracted + */ + private float[] getTopoData(GridGeometry2D inGeom, + CoordinateReferenceSystem inCrs, int coverageNx, int coverageNy) { + + /* + * Iterate through each of the data sets until the returned data set is + * fully populated + */ + float[] finalData = null; + + for (String topoData : TOPO_FILES) { + for (String dataSet : TopoAttributes.attributeMap.keySet()) { + if (dataSet.startsWith(topoData)) { + try { + finalData = extractTopoData(finalData, inCrs, inGeom, + coverageNx, coverageNy, dataSet); + } catch (Exception e) { + // Ignore + } + } + } + if (isPopulated(finalData)) { + break; + } + } + + for (int i = 0; i < finalData.length; i++) { + float v = finalData[i]; + if (Float.isNaN(v)) + finalData[i] = TOPO_FILL; + else if (v == DATA_FILL || (v > -0.5 && v < 0.5)) + finalData[i] = 0.0f; + else + finalData[i] = v; + } + return finalData; + + } + + /** + * Checks the provided array to see if it has been fully populated + * + * @param data + * The data to check + * @return True if the data is fully populated (i.e. There are not NaN + * values in the array) + */ + private boolean isPopulated(float[] data) { + if (data == null) { + return false; + } + for (int i = 0; i < data.length; i++) { + if (Float.isNaN(data[i])) { + return false; + } + } + return true; + } + + /** + * Extracts the topo data from the specified data set. The data is populated + * into the returned array + * + * @param finalData + * The topo data to be returned + * @param inCrs + * The CRS of the requested location + * @param inGeom + * The geometry of the requested location + * @param name + * The name of the data set from which to get the data + * @return The populated array of topo data + * @throws Exception + * If the data cannot be read + */ + private float[] extractTopoData(float[] finalData, + CoordinateReferenceSystem inCrs, GridGeometry2D inGeom, + int coverageNx, int coverageNy, String name) throws Exception { + String suffix = ""; + String[] tokens = name.split("-"); + if (tokens.length == 2) { + name = tokens[0]; + suffix = tokens[1]; + } + statusHandler.handle(Priority.INFO, "Extracting topo data from " + name + + suffix); + + // Gets the attributes for the data set + Map attributes = TopoAttributes.getAttributes(name); + int nx = (Integer) attributes.get(TopoAttributes.NX); + int ny = (Integer) attributes.get(TopoAttributes.NY); + double llLat = MapUtil.correctLat((Float) attributes + .get(TopoAttributes.LL_LAT)); + double llLon = MapUtil.correctLon((Float) attributes + .get(TopoAttributes.LL_LON)); + double urLat = MapUtil.correctLat((Float) attributes + .get(TopoAttributes.UR_LAT)); + double urLon = MapUtil.correctLon((Float) attributes + .get(TopoAttributes.UR_LON)); + + // Create the CRS of the topo data + CoordinateReferenceSystem topoCrs = CRSCache.getInstance() + .getCoordinateReferenceSystem( + (String) attributes.get(TopoAttributes.CRS)); + + // Create the geometry of the topo data + GridGeometry2D topoGeom = createGridGeometry(topoCrs, new Coordinate( + llLon, llLat), new Coordinate(urLon, urLat), nx, ny); + + ReferencedEnvelope refEnv = new ReferencedEnvelope( + inGeom.getEnvelope2D(), inCrs); + refEnv = refEnv.transform(topoCrs, true); + + DirectPosition upperCorner = topoGeom.getCRSToGrid2D( + PixelOrientation.UPPER_LEFT).transform(refEnv.getUpperCorner(), + null); + DirectPosition lowerCorner = topoGeom.getCRSToGrid2D( + PixelOrientation.UPPER_LEFT).transform(refEnv.getLowerCorner(), + null); + + int minx = (int) Math.floor(Math.min(lowerCorner.getOrdinate(0), + upperCorner.getOrdinate(0))); + int maxx = (int) Math.ceil(Math.max(upperCorner.getOrdinate(0), + lowerCorner.getOrdinate(0))); + int miny = (int) Math.floor(Math.min(upperCorner.getOrdinate(1), + lowerCorner.getOrdinate(1))); + int maxy = (int) Math.ceil(Math.max(lowerCorner.getOrdinate(1), + upperCorner.getOrdinate(1))); + + if ("world".equals(name)) { + if (minx - DATA_MARGIN < 0 || miny - DATA_MARGIN < 0 + || maxx + DATA_MARGIN >= nx || maxy + DATA_MARGIN >= ny) { + /* + * TODO: Have to do quite a bit more for minimal world + * projection subset. Just load the whole thing for now. + */ + minx = miny = 0; + maxx = nx; + maxy = ny; + } + } else { + if (minx - DATA_MARGIN >= 0) { + minx -= DATA_MARGIN; + } else { + minx = 0; + } + + if (miny - DATA_MARGIN >= 0) { + miny -= DATA_MARGIN; + } else { + miny = 0; + } + + if (maxx + DATA_MARGIN <= nx) { + maxx += DATA_MARGIN; + } else { + maxx = nx; + } + + if (maxy + DATA_MARGIN <= ny) { + maxy += DATA_MARGIN; + } else { + maxy = ny; + } + } + + double[] input = new double[] { minx, miny, maxx, maxy }; + double[] output = new double[input.length]; + + topoGeom.getGridToCRS(PixelInCell.CELL_CORNER).transform(input, 0, + output, 0, input.length / 2); + + DirectPosition dpUpper = new DirectPosition2D(Math.max(output[0], + output[2]), Math.max(output[1], output[3])); + DirectPosition dpLower = new DirectPosition2D(Math.min(output[0], + output[2]), Math.min(output[1], output[3])); + + Coordinate upperCoordinate = new Coordinate(dpUpper.getCoordinate()[0], + dpUpper.getCoordinate()[1]); + Coordinate lowerCoordinate = new Coordinate(dpLower.getCoordinate()[0], + dpLower.getCoordinate()[1]); + + Envelope tempEnv = new Envelope(upperCoordinate, lowerCoordinate); + ReferencedEnvelope correctedRefEnv = new ReferencedEnvelope(tempEnv, + topoCrs); + + int slabNx = maxx - minx; + int slabNy = maxy - miny; + + // The topo data does not intersect the desired region, so return + if (slabNx < 0 || slabNy < 0) { + if (finalData == null) { + finalData = new float[coverageNx * coverageNy]; + Arrays.fill(finalData, Float.NaN); + } + return finalData; + } + + // Add one to each of the maxx and maxy since getting slab is exclusive + // of the final point + float[][] slabData = this.to2DArray(slabNx, slabNy, + this.getSlab(name, minx, miny, maxx, maxy)); + + // Create the coverage object from the data and the geometry + GridCoverage2D topoCoverage = factory.create("coverage", slabData, + correctedRefEnv); + // Reproject the data into the requested CRS and geometry + float[] f1 = null; + try { + f1 = simpleResample(topoCoverage, slabData, inGeom, name, minx, + miny); + } catch (Exception e) { + statusHandler.error("rasample failed", e); + throw e; + } + + if (finalData == null) { + finalData = f1; + } else { + for (int idx = 0; idx < f1.length; idx++) { + if (Float.isNaN(finalData[idx]) || finalData[idx] <= DATA_FILL) { + finalData[idx] = f1[idx]; + } + } + } + JAI.getDefaultInstance().getTileCache().flush(); + return finalData; + } + + float[] simpleResample(GridCoverage2D sourceGC, float[][] sourceData, + GridGeometry2D targetGG, String pfx, int minx, int miny) { + int sourceWidth = sourceGC.getGridGeometry().getGridRange2D() + .getSpan(0); + int sourceHeight = sourceGC.getGridGeometry().getGridRange2D() + .getSpan(1); + int targetWidth = targetGG.getGridRange2D().getSpan(0); + int targetHeight = targetGG.getGridRange2D().getSpan(1); + float[] output = new float[targetWidth * targetHeight]; + Arrays.fill(output, Float.NaN); + + ArrayList transforms = new ArrayList(); + ArrayList toGeoXforms = new ArrayList(); + ArrayList sourceToGeoXforms = new ArrayList(); + + MathTransform targetGtoCRS = targetGG + .getGridToCRS(PixelInCell.CELL_CENTER); + MathTransform sourceCRStoG = sourceGC.getGridGeometry().getCRSToGrid2D( + PixelOrientation.CENTER); + CoordinateReferenceSystem targetCRS = targetGG + .getCoordinateReferenceSystem(); + CoordinateReferenceSystem sourceCRS = sourceGC + .getCoordinateReferenceSystem(); + + transforms.add(targetGtoCRS); + if (!CRS.equalsIgnoreMetadata(sourceCRS, targetCRS)) { + GeographicCRS sourceGeoCRS = null; + GeographicCRS targetGeoCRS = null; + if (sourceCRS instanceof ProjectedCRS) { + sourceGeoCRS = ((ProjectedCRS) sourceCRS).getBaseCRS(); + } + if (targetCRS instanceof ProjectedCRS) { + targetGeoCRS = ((ProjectedCRS) targetCRS).getBaseCRS(); + } + try { + transforms.add(CRS.findMathTransform(targetCRS, targetGeoCRS, + true)); + toGeoXforms.addAll(transforms); + if (CRS.equalsIgnoreMetadata(sourceGeoCRS, targetGeoCRS)) { + // nothing... + } else { + transforms.add(CRS.findMathTransform(targetGeoCRS, + sourceGeoCRS)); + } + transforms.add(CRS.findMathTransform(sourceGeoCRS, sourceCRS, + true)); + sourceToGeoXforms.add(0, + CRS.findMathTransform(sourceCRS, sourceGeoCRS)); + } catch (FactoryException e) { + // TODO: log + return output; + } + } + transforms.add(sourceCRStoG); + sourceToGeoXforms.add(0, + sourceGC.getGridGeometry() + .getGridToCRS(PixelInCell.CELL_CENTER)); + + MathTransform mt; + try { + mt = concatenateTransforms(transforms); + } catch (FactoryException e1) { + // TODO: log + return output; + } + + double[] coord = new double[2]; + + /* + * Output index. Assumes we iterate top-left to bottom-right in + * row-major order. + */ + int oi = 0; + for (int y = 0; y < targetHeight; ++y) { + for (int x = 0; x < targetWidth; ++x, ++oi) { + coord[0] = x; + coord[1] = y; + try { + mt.transform(coord, 0, coord, 0, 1); + } catch (TransformException e) { + continue; + } + + // Integer cell coordinates of upper-left cell of the 2x2 cell + // sample area + int sulx = (int) coord[0]; + int suly = (int) coord[1]; + + double fx = coord[0] - sulx; + double fy = coord[1] - suly; + + double tv = 0; // sum of weighted valid values + double tw = 0; // sum of valid weights + float v0; + double w0; + if (sulx >= 0 && suly >= 0 && sulx < sourceWidth - 1 + && suly < sourceHeight - 1) { + if (valid(v0 = fix(sourceData[suly][sulx]))) { + w0 = (1 - fx) * (1 - fy); + tv += v0 * w0; + tw += w0; + } + if (valid(v0 = fix(sourceData[suly][sulx + 1]))) { + w0 = (fx) * (1 - fy); + tv += v0 * w0; + tw += w0; + } + if (valid(v0 = fix(sourceData[suly + 1][sulx]))) { + w0 = (1 - fx) * (fy); + tv += v0 * w0; + tw += w0; + } + if (valid(v0 = fix(sourceData[suly + 1][sulx + 1]))) { + w0 = (fx) * (fy); + tv += v0 * w0; + tw += w0; + } + } else { + if (isValidCoord(sulx, suly, sourceWidth, sourceHeight) + && valid(v0 = fix(sourceData[suly][sulx]))) { + w0 = (1 - fx) * (1 - fy); + tv += v0 * w0; + tw += w0; + } + if (isValidCoord(sulx + 1, suly, sourceWidth, sourceHeight) + && valid(v0 = fix(sourceData[suly][sulx + 1]))) { + w0 = (fx) * (1 - fy); + tv += v0 * w0; + tw += w0; + } + if (isValidCoord(sulx, suly + 1, sourceWidth, sourceHeight) + && valid(v0 = fix(sourceData[suly + 1][sulx]))) { + w0 = (1 - fx) * (fy); + tv += v0 * w0; + tw += w0; + } + if (isValidCoord(sulx + 1, suly + 1, sourceWidth, + sourceHeight) + && valid(v0 = fix(sourceData[suly + 1][sulx + 1]))) { + w0 = (fx) * (fy); + tv += v0 * w0; + tw += w0; + } + } + if (tw != 0) { + output[oi] = (float) (tv / tw); + } + } + } + + return output; + + } + + private static final boolean isValidCoord(int ulx, int uly, int nx, int ny) { + return ulx >= 0 && uly >= 0 && ulx < nx && uly < ny; + } + + private static final boolean valid(float v) { + return !Float.isNaN(v) && v > DATA_FILL; + } + + // A1: passes N -9999 to test_grhi_remap, setting + // all source -9999 values to 0. + private static float fix(float v) { + return v > DATA_FILL ? v : 0; + } + + private MathTransform concatenateTransforms( + ArrayList transforms) throws FactoryException { + Hints hints = new Hints(); + final CoordinateOperationFactory factory = ReferencingFactoryFinder + .getCoordinateOperationFactory(hints); + final MathTransformFactory mtFactory; + if (factory instanceof AbstractCoordinateOperationFactory) { + mtFactory = ((AbstractCoordinateOperationFactory) factory) + .getMathTransformFactory(); + } else { + mtFactory = ReferencingFactoryFinder.getMathTransformFactory(hints); + } + + MathTransform mt = null; + for (MathTransform mti : transforms/* + * int i = 0; i < transforms.size(); + * ++i + */) { + if (mt == null) + mt = mti; + else { + mt = mtFactory.createConcatenatedTransform(mt, mti); + } + } + + return mt != null ? mt : IdentityTransform.create(2); + } + + /** + * Reads the raw data from the topo files + * + * @param name + * The name of the topo data set + * @param llLat + * The lower left latitude + * @param llLon + * The lower left longitude + * @param urLat + * The upper right latitude + * @param urLon + * The upper right longitude + * @param latCenter + * The central latitude + * @param lonCenter + * The central longitude + * @param nx + * The number of x axis points + * @param ny + * The number of y axis points + * @throws Exception + * If the data cannot be read + */ + private void readTopoFile(String name) throws Exception { + + Map dataAttributes = TopoAttributes.getAttributes(name); + int nx = (Integer) dataAttributes.get(TopoAttributes.NX); + int ny = (Integer) dataAttributes.get(TopoAttributes.NY); + long[] sizes = new long[] { nx, ny }; + + // Store the data + FloatDataRecord dataRec = new FloatDataRecord(name, "/", null, 2, sizes); + dataRec.setFillValue(Float.NaN); + + sTopoDataStore.createDataset(dataRec); + + // Create the new input stream from which to read + FileInputStream in = new FileInputStream(FILE_PREFIX + name + + "Topo.dat"); + + // Create a byte buffer to store the read data + ByteBuffer bb = ByteBuffer.allocate(2); + bb.order(ByteOrder.BIG_ENDIAN); + + byte[] bbuf = new byte[nx * 2]; + int index = 0; + int rowIndex = 0; + + // Create an array to hold the data read + float[] rawData = new float[nx]; + + sizes[1] = 1; + // Read in the data + while (in.available() > 0) { + if (in.read(bbuf) == -1) { + break; + } + for (int i = 0; i < nx * 2; i += 2) { + bb.clear(); + bb.put(bbuf[i]); + bb.put(bbuf[i + 1]); + rawData[index] = bb.getShort(0); + + index++; + if (index == nx) { + FloatDataRecord row = new FloatDataRecord(name, "/", + rawData, 2, sizes); + row.setMinIndex(new long[] { 0, rowIndex }); + sTopoDataStore.addDataRecord(row, sp); + sTopoDataStore.store(); + index = 0; + rowIndex++; + } + } + } + + FloatDataRecord attributeSet = new FloatDataRecord("attr" + name, "/", + new float[] { 0 }); + attributeSet.setDataAttributes(dataAttributes); + sTopoDataStore.addDataRecord(attributeSet, sp); + sTopoDataStore.store(); + in.close(); + } + + /** + * Creates a grid geometry object from the provided information + * + * @param crs + * The coordinate reference system + * @param llCoord + * The lower left coordinate + * @param urCoord + * The upper right coordinate + * @param nx + * The x axis points + * @param ny + * The y axis points + * @return The generated geometry + * @throws TransformException + * @throws MismatchedDimensionException + * @throws FactoryException + * @throws GribException + * If the geometry cannot be created + */ + private GridGeometry2D createGridGeometry(CoordinateReferenceSystem crs, + Coordinate llCoord, Coordinate urCoord, int nx, int ny) + throws MismatchedDimensionException, TransformException, + FactoryException { + MathTransform WGS84toPROJCRS = MapUtil.getTransformFromLatLon(crs); + + GeneralEnvelope envelope = new GeneralEnvelope(2); + + DirectPosition ll = WGS84toPROJCRS.transform(new DirectPosition2D( + llCoord.x, llCoord.y), null); + + DirectPosition ur = WGS84toPROJCRS.transform(new DirectPosition2D( + urCoord.x, urCoord.y), null); + + envelope.setRange(0, Math.min(ll.getOrdinate(0), ur.getOrdinate(0)), + Math.max(ll.getOrdinate(0), ur.getOrdinate(0))); + envelope.setRange(1, Math.min(ll.getOrdinate(1), ur.getOrdinate(1)), + Math.max(ll.getOrdinate(1), ur.getOrdinate(1))); + + envelope.setCoordinateReferenceSystem(crs); + + GridToEnvelopeMapper mapper = new GridToEnvelopeMapper(); + mapper.setEnvelope(envelope); + mapper.setGridRange(new GeneralGridEnvelope(new int[] { 1, 1 }, + new int[] { nx, ny }, false)); + mapper.setPixelAnchor(PixelInCell.CELL_CENTER); + mapper.setReverseAxis(new boolean[] { false, true }); + MathTransform mt = mapper.createTransform(); + + return new GridGeometry2D(PixelInCell.CELL_CORNER, mt, envelope, null); + } + + /** + * Retrieves a slab of data from a data set and returns a float array + * containing the data + * + * @param name + * The name of the data set to get the data slab from + * @param minX + * The starting x offset + * @param minY + * The starting y offset + * @param maxX + * The ending x offset + * @param maxY + * The endgin y offset + * @return The extracted slab of data + * @throws StorageException + * @throws FileNotFoundException + * If the data slab cannot be read + */ + private float[] getSlab(String name, int minX, int minY, int maxX, int maxY) + throws FileNotFoundException, StorageException { + return ((FloatDataRecord) sTopoDataStore.retrieve( + "/", + name, + Request.buildSlab(new int[] { minX, minY }, new int[] { maxX, + maxY }))).getFloatData(); + + } + + /** + * Utility method to flip a 1-D array into a 2-D array + * + * @param nx + * The x axis points + * @param ny + * The y axis points + * @param data + * The 1-D data array + * @return The 2-D data array + */ + private float[][] to2DArray(int nx, int ny, float[] data) { + float[][] matrix = new float[ny][nx]; + + for (int i = 0; i < nx; i++) { + for (int j = 0; j < ny; j++) { + matrix[j][i] = data[j * nx + i]; + } + } + return matrix; + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/topo/TopoAttributes.java b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/topo/TopoAttributes.java new file mode 100644 index 0000000000..ffe6468b68 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/topo/TopoAttributes.java @@ -0,0 +1,189 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.uf.edex.plugin.grid.topo; + +import java.util.HashMap; +import java.util.Map; + +import org.geotools.referencing.operation.DefaultMathTransformFactory; +import org.opengis.parameter.ParameterValueGroup; +import org.opengis.referencing.crs.CoordinateReferenceSystem; + +import com.raytheon.uf.common.geospatial.MapUtil; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; + +/** + * Static class used for holding the attributes of the static topo data + * + *
+ * SOFTWARE HISTORY
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 11/09/2010   6394        bphillip    Initial creation
+ * 
+ * + * @author bphillip + * @version 1.0 + */ +public class TopoAttributes { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(TopoAttributes.class); + + /** Lower left latitude attribute name */ + public static final String LL_LAT = "llLat"; + + /** Lower left longitude attribute name */ + public static final String LL_LON = "llLon"; + + /** Upper right latitude attribute name */ + public static final String UR_LAT = "urLat"; + + /** Upper right longitude attribute name */ + public static final String UR_LON = "urLon"; + + /** Nx attribute name */ + public static final String NX = "nx"; + + /** Ny attribute name */ + public static final String NY = "ny"; + + /** Central meridian attribute name */ + public static final String CENTRAL_MERIDIAN = "central_meridian"; + + /** Latitude of origin attribute name */ + public static final String LAT_OF_ORIGIN = "latOfOrigin"; + + /** CRS attribute name */ + public static final String CRS = "CRS"; + + /** Map containing the attributes for the static topo data */ + public static Map> attributeMap = new HashMap>(); + + static { + createAttributeMap("ak", 61.968945f, 150.32922f, 47.7384f, -128.74811f, + 4270, 2800, -150f, 90f); + createAttributeMap("carib", 26.831362f, -75.716293f, 8.909350f, + -56.794250f, 2271, 2151, 0f, 0f); + createAttributeMap("us", 16.114336f, -127.13067f, 51.825356f, + -49.03707f, 6138, 4610, -100f, 45f); + createAttributeMap("pac", -34.99583f, 120.004166f, 39.995834f, + -120.004166f, 14400, 9000, 0f, 0f); + createAttributeMap("world", -89.979164f, -180.0f, 89.979164f, 180.0f, + 8642, 4320, 0f, 0f); + + } + + /** + * Retrieves the attributes for a static topo data set + * + * @param name + * The name of the static topo data set + * @return The attribute for the requested data set + */ + public static Map getAttributes(String name) { + return attributeMap.get(name); + } + + /** + * Creates an attribute map with the provided parameters + * + * @param name + * The name of the static topo data set + * @param llLat + * The lower left latitude + * @param llLon + * The lower left longitude + * @param urLat + * The upper right latitude + * @param urLon + * The upper right longitude + * @param nx + * Number of points on the x axis + * @param ny + * Number of points on the y axis + * @param central_meridian + * The central meridian + * @param latOfOrigin + * The latitude of origin + */ + private static void createAttributeMap(String name, float llLat, + float llLon, float urLat, float urLon, int nx, int ny, + float central_meridian, float latOfOrigin) { + + Map attributes = new HashMap(); + attributes.put(LL_LAT, new Float(llLat)); + attributes.put(LL_LON, new Float(llLon)); + attributes.put(UR_LAT, new Float(urLat)); + attributes.put(UR_LON, new Float(urLon)); + attributes.put(NX, new Integer(nx)); + attributes.put(NY, new Integer(ny)); + attributes.put(CENTRAL_MERIDIAN, new Float(central_meridian)); + attributes.put(LAT_OF_ORIGIN, new Float(latOfOrigin)); + if (name.equals("us")) { + try { + attributes.put( + CRS, + initUSProjectionData("US", latOfOrigin, + central_meridian).toWKT()); + } catch (Exception e) { + statusHandler.handle(Priority.INFO, "Error creating US CRS"); + } + } else if (name.equals("ak")) { + attributes.put( + CRS, + MapUtil.constructStereographic(6371200.0, 6371200.0, + latOfOrigin, central_meridian).toWKT()); + } else { + attributes.put( + CRS, + MapUtil.constructEquidistantCylindrical(6371200.0, + 6371200.0, 0, 0).toWKT()); + } + + attributeMap.put(name, attributes); + + } + + /** + * Initializes the CRS for the us data set + * + * @param name + * The name + * @param latCenter + * The central latitude + * @param lonCenter + * The central longitude + * @return The constructed CRS + * @throws Exception + */ + private static CoordinateReferenceSystem initUSProjectionData(String name, + float latCenter, float lonCenter) throws Exception { + ParameterValueGroup parameters = new DefaultMathTransformFactory() + .getDefaultParameters("Lambert_Azimuthal_Equal_Area"); + parameters.parameter("semi_major").setValue(6371200.0); + parameters.parameter("semi_minor").setValue(6371200.0); + parameters.parameter("latitude_of_center").setValue(latCenter); + parameters.parameter("longitude_of_center").setValue(lonCenter); + return MapUtil.constructProjection(name, parameters); + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/utility/common_static/base/path/gridPathKeys.xml b/edexOsgi/com.raytheon.uf.edex.plugin.grid/utility/common_static/base/path/gridPathKeys.xml new file mode 100644 index 0000000000..5e7905ca42 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/utility/common_static/base/path/gridPathKeys.xml @@ -0,0 +1,7 @@ + + + + info.datasetId + 0 + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/utility/common_static/base/purge/gridPurgeRules.xml b/edexOsgi/com.raytheon.uf.edex.plugin.grid/utility/common_static/base/purge/gridPurgeRules.xml new file mode 100644 index 0000000000..94ca1d220a --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/utility/common_static/base/purge/gridPurgeRules.xml @@ -0,0 +1,1246 @@ + + + + + + + grid + default + + 2 + + + + + + + grid + info.datasetId=ETA + + 2 + + + + + + grid + info.datasetId=RUC + + 8 + + + + + + grid + info.datasetId=AVN + + 2 + + + + + + grid + info.datasetId=LAPS + + 30 + + + + + + grid + info.datasetId=NGM + + 2 + + + + + + grid + info.datasetId=MRF + + 2 + + + + + + grid + info.datasetId=MSAS + + 24 + + + + + + grid + info.datasetId=GFS201 + + 2 + + + + + + grid + info.datasetId=mrfNH + + 2 + + + + + + grid + info.datasetId=GFS213 + + 2 + + + + + + grid + info.datasetId=NGM213 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=NGM202 + + 2 + + + + + + grid + info.datasetId=AVN211 + + 2 + + + + + + grid + info.datasetId=mesoEta212 + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=mesoEta215 + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=ENSEMBLE + + 2 + + + + grid + info.datasetId=ENSEMBLE37 + + 2 + + + + grid + info.datasetId=ENSEMBLE38 + + 2 + + + + grid + info.datasetId=ENSEMBLE39 + + 2 + + + + grid + info.datasetId=ENSEMBLE40 + + 2 + + + + grid + info.datasetId=ENSEMBLE41 + + 2 + + + + grid + info.datasetId=ENSEMBLE42 + + 2 + + + + grid + info.datasetId=ENSEMBLE43 + + 2 + + + + grid + info.datasetId=ENSEMBLE44 + + 2 + + + + + + grid + info.datasetId=ETA212 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=MRF203 + + 3 + + + + + + grid + info.datasetId=AVN203 + + 3 + + + + + + grid + info.datasetId=MRF204 + + 3 + + + + + + grid + info.datasetId=MRF205 + + 3 + + + + + + grid + info.datasetId=NGM207 + + 3 + + + + + + grid + info.datasetId=NAM207 + + 3 + + + + + + grid + info.datasetId=ECMF-NorthernHemisphere + + 2 + + + + grid + info.datasetId=ECMF1 + + 2 + + + + grid + info.datasetId=ECMF2 + + 2 + + + + grid + info.datasetId=ECMF3 + + 2 + + + + grid + info.datasetId=ECMF4 + + 2 + + + + grid + info.datasetId=ECMF5 + + 2 + + + + grid + info.datasetId=ECMF6 + + 2 + + + + grid + info.datasetId=ECMF7 + + 2 + + + + grid + info.datasetId=ECMF8 + + 2 + + + + grid + info.datasetId=ECMF9 + + 2 + + + + grid + info.datasetId=ECMF10 + + 2 + + + + grid + info.datasetId=ECMF11 + + 2 + + + + grid + info.datasetId=ECMF12 + + 2 + + + + + + grid + info.datasetId=UKMET-NorthernHemisphere + + 2 + + + + grid + info.datasetId=UKMET37 + + 2 + + + + grid + info.datasetId=UKMET38 + + 2 + + + + grid + info.datasetId=UKMET39 + + 2 + + + + grid + info.datasetId=UKMET40 + + 2 + + + + grid + info.datasetId=UKMET41 + + 2 + + + + grid + info.datasetId=UKMET42 + + 2 + + + + grid + info.datasetId=UKMET43 + + 2 + + + + grid + info.datasetId=UKMET44 + + 2 + + + + + + grid + info.datasetId=AVN-NorthernHemisphere + + 2 + + + + grid + info.datasetId=AVN37 + + 2 + + + + grid + info.datasetId=AVN38 + + 2 + + + + grid + info.datasetId=AVN39 + + 2 + + + + grid + info.datasetId=AVN40 + + 2 + + + + grid + info.datasetId=AVN41 + + 2 + + + + grid + info.datasetId=AVN42 + + 2 + + + + grid + info.datasetId=AVN43 + + 2 + + + + grid + info.datasetId=AVN44 + + 2 + + + + + + grid + info.datasetId=GWW233 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=RFCqpf + + 5 + + + + + + grid + info.datasetId=RUC236 + + 8 + + + + + + grid + info.datasetId=AVN225 + + 3 + + + + + + grid + info.datasetId=WNAWAVE238 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=mesoEta216 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=mesoEta217 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=ETA218 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=ETA242 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=HPCqpf + + 5 + + + + + + grid + info.datasetId=ENPWAVE253 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=HPCdelta + + 4 + + + + + + grid + info.datasetId=HurWind226 + + 4 + + + + + + grid + info.datasetId=CPCoutlook211 + + 14 + + + + + + grid + info.datasetId=RTGSSTHR + + 2 + + + + + + grid + info.datasetId=NICICE + + 2 + + + + + + grid + info.datasetId=DGEX185 + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=HPCGuide + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=GFSGuide + + 8 + 00-00:15:00 + + + + + + grid + info.datasetId=GFS212 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=GFS160 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=GFS254 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=GFS161 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=MPE-Local + + 72 + + + + + + grid + info.datasetId=TPCWindProb + + 8 + 00-00:15:00 + + + + + + grid + info.datasetId=MOSGuide + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=QPE + + 72 + + + + grid + info.datasetId=QPE-TUA + + 72 + + + + grid + info.datasetId=QPE-ACR + + 72 + + + + grid + info.datasetId=QPE-STR + + 72 + + + + grid + info.datasetId=QPE-RSA + + 72 + + + + grid + info.datasetId=QPE-ORN + + 72 + + + + grid + info.datasetId=QPE-RHA + + 72 + + + + grid + info.datasetId=QPE-KRF + + 72 + + + + grid + info.datasetId=QPE-MSR + + 72 + + + + grid + info.datasetId=QPE-TAR + + 72 + + + + grid + info.datasetId=QPE-PTR + + 72 + + + + grid + info.datasetId=QPE-TIR + + 72 + + + + grid + info.datasetId=QPE-ALR + + 72 + + + + grid + info.datasetId=QPE-FWR + + 72 + + + + + + + + grid + info.datasetId=OPCWave180 + + 8 + 00-00:15:00 + + + + + + grid + info.datasetId=OPCWave181 + + 8 + 00-00:15:00 + + + + + + grid + info.datasetId=OPCWave182 + + 8 + 00-00:15:00 + + + + + + grid + info.datasetId=RTMA + + 24 + 00-00:15:00 + + + + + + grid + info.datasetId=SREF212 + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=RTGSST + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=GFSLAMPTstorm + + 24 + 00-00:15:00 + + + + + + grid + info.datasetId=ECMWF-HiRes + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=HPCqpfNDFD + + 42 + 00-00:15:00 + + + + + + grid + info.datasetId=NamDNG5 + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=TPCSurgeProb + + 3 + 00-00:15:00 + + + + + + grid + info.datasetId=HPE + + 00-12:00:00 + 00-00:15:00 + + + + + + grid + info.datasetId=BHPE + + 00-12:00:00 + 00-00:15:00 + + + + + + grid + info.datasetId=GlobalWave + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=AKWave10 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=AKWave4 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=EPWave10 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=WCWave10 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=WCWave4 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=WNAWave10 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=WNAWave4 + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=MOSGuide-AK + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=HI_RTMA + + 24 + + + + + + grid + info.datasetId=HiRes-ARW-East + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=HiRes-ARW-West + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=HiRes-ARW-AK + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=HiRes-ARW-HI + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=HiRes-ARW-SJU + + 1 + 00-00:15:00 + + + + + + + + grid + info.datasetId=HiRes-NMM-East + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=HiRes-NMM-West + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=HiRes-NMM-AK + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=HiRes-NMM-HI + + 2 + 00-00:15:00 + + + + + + grid + info.datasetId=HiRes-NMM-SJU + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=GRLKwave + + 1 + 00-00:15:00 + + + + + + grid + info.datasetId=CPCoutlook-Short + + 5 + 00-00:15:00 + + + + + + grid + info.datasetId=CPCoutlook-Medium + + 7 + 00-00:15:00 + + + + + + grid + info.datasetId=CPCoutlook-Short-AK + + 5 + 00-00:15:00 + + + + + + grid + info.datasetId=CPCoutlook-Medium-AK + + 7 + 00-00:15:00 + + + + + + grid + info.datasetId=SPCGuide + + 5 + 00-00:15:00 + +