V2_0.java [src/java/m/windgen] Revision: default  Date:
package m.windgen;

import csip.Config;
import static csip.Config.CSIP_DATA_DIR;
import csip.api.server.Executable;
import csip.ModelDataService;
import csip.api.server.ServiceException;
import csip.annotations.*;
import static csip.annotations.ResourceType.*;
import csip.utils.ZipFiles;
import interpolation.Interpolation;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

import javax.ws.rs.*;
import static m.wepsModelConstants.*;
import static m.windgen.interpolate.V1_0.WindBoundaryFileName;
import static m.windgen.interpolate.V1_0.WindInterpDefOutputname;

/**
 * This implements the CSIP WINDGEN service.
 *
 * @author od, mh
 */
@Name("windgen")
@Description("wind station data (Windgen) utility with integrated interpolation")
@VersionInfo("2.0")
@Path("m/windgen/2.0")
@Polling(first = 2000, next = 1000)

@Resource(file = "/bin/lin-amd64/wind_gen5", id = "windgen5", type = EXECUTABLE)
@Resource(file = "/bin/lin-amd64/interpolate", id = "interpolateExeLin64ID", type = EXECUTABLE)
@Resource(file = "/bin/lin-amd64/interp_wdb", id = "interp_wdb", type = EXECUTABLE)
@Resource(file = "/data/windgenData111522.zip", id = "windgenDataID", type = ARCHIVE)

//@Resource(file = "*stdout.txt *stderr.txt *wdb", type = OUTPUT)

/*
    windgenData111522.zip includes:
        interpolation_boundary.pol
        windgen.idx
        windgen_NRCS.idx
        windgen.wdb
*/

public class V2_0 extends ModelDataService {

    public static final String WindDBFileName = "windgen.wdb";
    public static final String WindIdxFileName = "windgen.idx";
    public static final String WindIdxNrcsFileName = "windgen_NRCS.idx";
    
    public static final String INTERPOLATE_URL = "m/interpolate/1.0";
    
    
    Executable windgen;
    String parmOutputFile;
    
    // Reminder: add new date to json as well
    static final String serviceUpdateStr = "05/10/2023";


    @Override
    public void doProcess() throws Exception {
        
        windgen = resources().getExe("windgen5");

        parmOutputFile = parameter().getString(PARMITEMOUTPUTFILE, "win_gen_d.win");
        String parmOutputFileParm = "-o" + workspace().getDir() + "/" + parmOutputFile;

        // default to the internal file path
        String parmDBFilePath = Config.getString(CSIP_DATA_DIR);
        if (parameter().has(PARMITEMDATAFILE)) {
            // default, if parm PARMITEMDATAFILE is used, is external file
            parmDBFilePath = workspace().getDir().getAbsolutePath();
        }
        String parmDBFileName = parmDBFilePath + "/" + parameter().getString(PARMITEMDATAFILE, WindDBFileName);
        
        if (!(new File(parmDBFileName).exists())) {
            throw new ServiceException("File does not exist, filename=" + parmDBFileName);
        }
        String parmDBFile = "-f" + parmDBFileName;

        int wBAN = parameter().getInt("WBANnum", 999999);
        
        if (parameter().has(PARMITEMWEPSLAT)) {
            double lat = parameter().getDouble(PARMITEMWEPSLAT);
            double lon = parameter().getDouble(PARMITEMWEPSLON);
            
//            String url = request().getCodebase();
//            url += INTERPOLATE_URL;
//            fetchWindStation(lat, lon, url);

            File newDataFile = getWindStation(lat, lon, parmDBFileName);
            
            wBAN = 999999;
            parmDBFile = "-f" + newDataFile.getAbsolutePath();
        }
        
        String parmWBAN = "-s" + wBAN;
        String parmStartYear = "-b" + parameter().getInt("startyear", 1);
        String parmDuration = "-y" + parameter().getInt("duration", 1);
        String parmStationIndex = parameter().has("stationIndex") ? "-x" + parameter().getInt("stationIndex") : "";
        String parmRandSeed = parameter().has("randSeed") ? "-r" + parameter().getInt("randSeed") : "";
        String parmStormDuration = parameter().has("stormDuration") ? "-u" + parameter().getInt("stormDuration") : "";
        String parmStormBuild = parameter().has("stormBuild") ? "-d" + parameter().getInt("stormBuild") : "";
        String parmLongOutput = parameter().has("longOutput") && parameter().getBoolean("longOutput") ? "-l" : "";

        windgen.setArguments(
                parmOutputFileParm,
                parmDBFile,
                parmWBAN,
                parmStartYear,
                parmDuration,
                parmStationIndex,
                parmRandSeed,
                parmStormDuration,
                parmStormBuild,
                parmLongOutput
        );

        int ret = windgen.exec();
        if (ret != 0) {
            throw new ServiceException("Error executing: " + windgen);
        }
    }
    
    private File getWindStation(double lat, double lon, String parmDBFile) throws Exception {
    File interpOutputFile;
    
    Executable interpolate = resources().getExe("interpolateExeLin64ID");
    Executable interp_wdb = resources().getExe("interp_wdb");
    Interpolation interp = new Interpolation(interpolate, interp_wdb, workspace().getDir(), LOG);

    Boolean isNRCS = parameter().getBoolean(PARMITEMISNRCS, false);
    String idxFileName = (isNRCS) ? WindIdxNrcsFileName : WindIdxFileName;

    String dataPath = Config.getString(CSIP_DATA_DIR);
    String parmIdxFile = dataPath + "/" + idxFileName;
    String parmPolygonFile = dataPath + "/" + WindBoundaryFileName;
    
    interpOutputFile = interp.interpolate(lat, lon, parmIdxFile, parmPolygonFile, WindInterpDefOutputname);
    
    File parmWdbFile = interp.createInterpolatedWdb(interpOutputFile.getName(), parmDBFile, 
                null, null, null, null, null, null, null, null, null, "windgen-interpolated.wdb");
    
    return parmWdbFile;
    
    }
    
//    private void fetchWindStation(double lat, double lon, String url) throws Exception {
//        ModelDataServiceCall resInterp = new ModelDataServiceCall()
//            .put(PARMITEMWEPSLAT, lat)
//            .put(PARMITEMWEPSLON, lon)
//            .url(url)
//            .withDefaultLogger()
//            .call();
//
//        if (resInterp.serviceFinished()) {
//            resInterp.download("weights.txt", workspace().getFile("weights.txt"));
////            createInterpolatedWdb ();
//            
//            ModelDataServiceCall resWdb = new ModelDataServiceCall()
//                .put(PARMITEMWEPSLAT, lat)
//                .put(PARMITEMWEPSLON, lon)
//                .url(url)
//                .withDefaultLogger()
//                .call();
//
//            if (resWdb.serviceFinished()) {
//                resWdb.download("weights.txt", workspace().getFile("weights.txt"));
//            } else {
//                throw new ServiceException("Wind service error: " + resWdb.getError());
//            }
//        } else {
//            throw new ServiceException("Wind service error: " + resInterp.getError());
//        }
//    }
    

    @Override
    protected void postProcess() throws Exception {
        metainfo().put(PARMOUTUPDATED, serviceUpdateStr);

        File winResFile = new File(workspace().getDir() + "/" + parmOutputFile);
        File[] windFiles = workspace().getDir().listFiles( (File file) -> 
            file.getName().startsWith("wind_gen") ||
            file.getName().endsWith(parmOutputFile)
        );
        
        File[] interpFiles = workspace().getDir().listFiles( (File file) -> 
            !file.getName().startsWith("win_gen") &&
            !file.getName().startsWith("wind_gen")
        );
        File interpzFile = new File(workspace().getDir(),"interpolate.zip");
        if (interpFiles.length > 0) {
            ZipFiles.zip(interpzFile, interpFiles);
        }
        
        boolean zipResults = (parameter().has("zipResults")) ? parameter().getBoolean("zipResults") : false;
        if (zipResults) {
            File zFile = new File(workspace().getDir(),"results.zip");
            
            ArrayList<File> zFilesList = new ArrayList();
            zFilesList.addAll(Arrays.asList(windFiles));
            if (interpFiles.length > 0) {
                zFilesList.add(interpzFile);
            }

            try {
                ZipFiles.zip(zFile, zFilesList);
                results().put(zFile);
            } catch (IOException e) {
            }
        } else {
            results().put(windFiles);
            if (interpzFile.exists()) {
                results().put(interpzFile);
            }
        }
    }
}