001/* 002 * Copyright (c) 2018 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2018-07-24 17:31:17 +0000 (Tue, 24 Jul 2018) $' 007 * '$Revision: 34707 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029package org.kepler.gis.actor.calc; 030 031import java.io.IOException; 032import java.util.ArrayList; 033 034import org.geotools.coverage.grid.GridCoverage2D; 035import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader; 036import org.kepler.gis.data.RasterToken; 037 038import it.geosolutions.jaiext.range.Range.DataType; 039import ptolemy.actor.TypedAtomicActor; 040import ptolemy.actor.TypedIOPort; 041import ptolemy.actor.parameters.PortParameter; 042import ptolemy.data.StringToken; 043import ptolemy.data.expr.StringParameter; 044import ptolemy.data.type.BaseType; 045import ptolemy.kernel.CompositeEntity; 046import ptolemy.kernel.util.Attribute; 047import ptolemy.kernel.util.IllegalActionException; 048import ptolemy.kernel.util.NameDuplicationException; 049import ptolemy.kernel.util.SingletonAttribute; 050 051/** Raster calculator using Jiffle. Add an input port for each input 052 * raster, and refer to the raster in the jiffle script using the 053 * corresponding name of the port. The name of the output raster 054 * in the script is "dest". 055 * 056 * Jiffle language reference: 057 * 058 * https://github.com/geosolutions-it/jai-ext/wiki/Jiffle---language-summary 059 * 060 * @author Daniel Crawl 061 * @version $Id: JiffleRasterCalculator.java 34707 2018-07-24 17:31:17Z crawl $ 062 */ 063public class JiffleRasterCalculator extends TypedAtomicActor { 064 065 public JiffleRasterCalculator(CompositeEntity container, String name) 066 throws IllegalActionException, NameDuplicationException { 067 super(container, name); 068 069 script = new PortParameter(this, "script"); 070 script.setStringMode(true); 071 script.setTypeEquals(BaseType.STRING); 072 script.getPort().setTypeEquals(BaseType.STRING); 073 new SingletonAttribute(script.getPort(), "_showName"); 074 075 outType = new StringParameter(this, "outType"); 076 outType.addChoice("byte"); 077 outType.addChoice("double"); 078 outType.addChoice("float"); 079 outType.addChoice("integer"); 080 outType.addChoice("long"); 081 outType.addChoice("short"); 082 outType.addChoice("unsigned short"); 083 outType.setToken("double"); 084 085 output = new TypedIOPort(this, "output", false, true); 086 output.setTypeEquals(RasterToken.RASTER); 087 } 088 089 @Override 090 public void attributeChanged(Attribute attribute) throws IllegalActionException { 091 if(attribute == outType) { 092 String val = outType.stringValue(); 093 if(val == null || val.isEmpty()) { 094 throw new IllegalActionException(this, "Must specify output type."); 095 } 096 DataType type = DataType.valueOf(val.toUpperCase()); 097 if(type == null) { 098 throw new IllegalActionException(this, "Invalid output type."); 099 } 100 _outputType = type; 101 } else { 102 super.attributeChanged(attribute); 103 } 104 } 105 106 @Override 107 public void fire() throws IllegalActionException { 108 109 super.fire(); 110 111 script.update(); 112 String scriptStr = ((StringToken)script.getToken()).stringValue(); 113 if(scriptStr == null || scriptStr.trim().isEmpty()) { 114 throw new IllegalActionException(this, "Must specify jiffle script."); 115 } 116 117 JiffleProcess process = new JiffleProcess(); 118 119 ArrayList<String> names = new ArrayList<String>(); 120 ArrayList<GridCoverage2D> coverages = new ArrayList<GridCoverage2D>(); 121 122 for(TypedIOPort input: this.inputPortList()) { 123 if(input.numberOfSources() > 0 && input != script.getPort()) { 124 names.add(input.getName()); 125 RasterToken token = (RasterToken) input.get(0); 126 GridCoverage2D coverage = (GridCoverage2D) token.coverageValue(); 127 if(coverage == null) { 128 AbstractGridCoverage2DReader reader = token.reader(); 129 if(reader == null) { 130 throw new IllegalActionException(this, "File rasters not supported. Use RasterReader first."); 131 } 132 try { 133 coverage = reader.read(null); 134 } catch (IllegalArgumentException | IOException e) { 135 throw new IllegalActionException(this, e, 136 "Error getting reading coverage for raster."); 137 } 138 } 139 coverages.add(coverage); 140 } 141 } 142 143 GridCoverage2D outputCoverage = null; 144 try { 145 outputCoverage = process.execute( 146 coverages.toArray(new GridCoverage2D[coverages.size()]), 147 scriptStr, 148 null, 149 names.toArray(new String[names.size()]), 150 _outputType, 151 null); 152 } catch (Exception e) { 153 throw new IllegalActionException(this, e, 154 "Error running jiffle process."); 155 } 156 157 output.broadcast(new RasterToken(outputCoverage)); 158 159 } 160 161 @Override 162 public void preinitialize() throws IllegalActionException { 163 164 super.preinitialize(); 165 166 for(TypedIOPort input: this.inputPortList()) { 167 if(input != script.getPort()) { 168 input.setTypeEquals(RasterToken.RASTER); 169 } 170 } 171 172 } 173 174 /** The jiffle script. */ 175 public PortParameter script; 176 177 /** Raster output data type. */ 178 public StringParameter outType; 179 180 /** Raster output. */ 181 public TypedIOPort output; 182 183 private DataType _outputType; 184 185}