PageRenderTime 63ms CodeModel.GetById 15ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/alaspatial/src/main/java/org/ala/spatial/util/AnalysisJobMaxent.java

http://alageospatialportal.googlecode.com/
Java | 719 lines | 519 code | 101 blank | 99 comment | 100 complexity | f1422eb8530b751654661e2dee7d748c MD5 | raw file
  1/**
  2 * ************************************************************************
  3 * Copyright (C) 2010 Atlas of Living Australia All Rights Reserved.
  4 *
  5 * The contents of this file are subject to the Mozilla Public License Version
  6 * 1.1 (the "License"); you may not use this file except in compliance with the
  7 * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 11 * the specific language governing rights and limitations under the License.
 12 * *************************************************************************
 13 */
 14package org.ala.spatial.util;
 15
 16import java.io.BufferedReader;
 17import java.io.BufferedWriter;
 18import java.io.File;
 19import java.io.FileInputStream;
 20import java.io.FileReader;
 21import java.io.FileWriter;
 22import java.io.IOException;
 23import java.io.InputStreamReader;
 24import java.io.PrintWriter;
 25import java.io.RandomAccessFile;
 26import java.util.Arrays;
 27import java.util.Hashtable;
 28import org.ala.layers.client.Client;
 29import org.ala.layers.dao.LayerDAO;
 30import org.ala.layers.dto.Field;
 31import org.ala.layers.dto.Layer;
 32import org.ala.layers.intersect.Grid;
 33import org.ala.layers.intersect.SimpleRegion;
 34import org.ala.spatial.analysis.index.LayerFilter;
 35import org.ala.spatial.analysis.maxent.MaxentServiceImpl;
 36import org.ala.spatial.analysis.maxent.MaxentSettings;
 37import org.apache.commons.io.IOUtils;
 38
 39/**
 40 *
 41 * @author Adam
 42 */
 43public class AnalysisJobMaxent extends AnalysisJob {
 44
 45    long[] stageTimes;
 46    String currentPath;
 47    String taxon;
 48    String area;
 49    String envlist;
 50    String txtTestPercentage;
 51    String chkJackknife;
 52    String chkResponseCurves;
 53    LayerFilter[] envelope;
 54    SimpleRegion region;
 55    int cells;
 56    int speciesCount;
 57    String resolution;
 58    String[] envnameslist;
 59
 60    public AnalysisJobMaxent(String pid, String currentPath_, String taxon_, String envlist_, SimpleRegion region_, LayerFilter[] filter_, String txtTestPercentage_, String chkJackknife_, String chkResponseCurves_, String resolution_) {
 61        super(pid);
 62        currentPath = currentPath_;
 63        taxon = taxon_;
 64        region = region_;
 65        envelope = filter_;
 66        txtTestPercentage = txtTestPercentage_;
 67        chkJackknife = chkJackknife_;
 68        chkResponseCurves = chkResponseCurves_;
 69        envlist = envlist_;
 70        resolution = resolution_;
 71        envnameslist = envlist.split(":");
 72        System.out.println("ENVLIST*** " + envlist);
 73
 74
 75        //TODO: remove rough estimate
 76        if (region != null) {
 77            cells = (int) Math.ceil(region.getWidth() / Double.parseDouble(resolution)
 78                    * region.getHeight() / Double.parseDouble(resolution));
 79        } else {
 80            cells = 1000000; //or something
 81        }
 82        //cells = GridCutter.countCells(region, envelope);
 83
 84//        SamplingService ss = SamplingService.newForLSID(taxon);
 85//        double[] p = ss.sampleSpeciesPoints(taxon, region, null);
 86//        if (p != null) {
 87//            speciesCount = p.length / 2;
 88//        }
 89        //TODO: dynamic species count
 90        speciesCount = 10000;
 91
 92        stageTimes = new long[4];
 93        setStage(0);
 94        setProgress(0);
 95    }
 96
 97    @Override
 98    public void run() {
 99
100        try {
101            setCurrentState(RUNNING);
102            setStage(0);
103
104            // dump the species data to a file
105            setProgress(0, "dumping species data");
106
107//            SamplingService ss = SamplingService.newForLSID(taxon);
108//
109//            StringBuffer removedSpecies = new StringBuffer();
110//            double[] points = ss.sampleSpeciesPointsMinusSensitiveSpecies(taxon, region, null, removedSpecies);
111//
112//            if (points == null) {
113//                setProgress(1, "failed: No occurrence points found in selection region");
114//                setCurrentState(FAILED);
115//                setMessage("No species selected.\nHint: Make sure your active area includes species occurrences");
116//
117//                return;
118//            }
119//
120//            StringBuffer sbSpecies = new StringBuffer();
121//            // get the header
122//            sbSpecies.append("species, longitude, latitude");
123//            sbSpecies.append(System.getProperty("line.separator"));
124//            for (int i = 0; i < points.length; i += 2) {
125//                sbSpecies.append("species, " + points[i] + ", " + points[i + 1]);
126//                sbSpecies.append(System.getProperty("line.separator"));
127//            }
128
129            setProgress(0, "preparing input files and run parameters");
130
131            String cutDataPath = GridCutter.cut2(envnameslist, resolution, region, envelope, null);
132
133            System.out.println("CUTDATAPATH: " + region + " " + cutDataPath);
134
135            MaxentSettings msets = new MaxentSettings();
136            msets.setMaxentPath(AlaspatialProperties.getAnalysisMaxentCmd());
137            msets.setRandomTestPercentage(Integer.parseInt(txtTestPercentage));
138            msets.setEnvPath(cutDataPath);          //use (possibly) cut layers
139
140            String ctxVarToggler = "";
141            for (int l = 0; l < envnameslist.length; l++) {
142                if (Client.getLayerDao().getLayerByName(envnameslist[l]) != null && Client.getLayerDao().getLayerByName(envnameslist[l]).getType().equals("contextual")) {
143                    ctxVarToggler += envnameslist[l] + " ";
144                } else if (envnameslist[l].startsWith("aloc_")) {
145                    ctxVarToggler += envnameslist[l] + " ";
146                }
147            }
148            msets.setEnvVarToggler(ctxVarToggler);
149            msets.setEnvList(Arrays.asList(envnameslist.clone()));
150
151            //msets.setSpeciesFilepath(setupSpecies(sbSpecies.toString(), currentPath + "output" + File.separator + "maxent" + File.separator + getName() + File.separator));
152            msets.setSpeciesFilepath(currentPath + "output" + File.separator + "maxent" + File.separator + getName() + File.separator + "species_points.csv");
153            msets.setOutputPath(currentPath + "output" + File.separator + "maxent" + File.separator + getName() + File.separator);
154            if (chkJackknife != null) {
155                msets.setDoJackknife(true);
156            }
157            if (chkResponseCurves != null) {
158                msets.setDoResponsecurves(true);
159            }
160
161            MaxentServiceImpl maxent = new MaxentServiceImpl();
162            maxent.setMaxentSettings(msets);
163
164            System.out.println("To run: " + msets.toString());
165
166            setStage(1);
167
168            setProgress(0, "running Maxent");
169
170            int exitValue = maxent.process(this);
171            System.out.println("Completed: " + exitValue);
172
173            setProgress(1, "Maxent finished with exit value=" + exitValue);
174
175            setStage(2);
176
177            setProgress(0, "exporting results");
178
179            Hashtable htProcess = new Hashtable();
180
181            String[] imgExtensions = {".png", "_only.png", "_only_thumb.png", "_thumb.png"};
182
183            if (isCancelled()) {
184                //
185            } else if (exitValue == 0) {
186
187                // check if there is an error
188                String maxentError = getMaxentError(new File(msets.getOutputPath() + "maxent.log"), 2);
189                if (maxentError != null) {
190                    System.out.println("Has error, sending maxent error message");
191                    setProgress(1, "failed: " + maxentError);
192                    setCurrentState(FAILED);
193                    if (maxentError.equals("Warning: Skipping species because it has 0 test samples")) {
194                        setMessage("Warning: Skipping species because it has 0 test samples." + (msets.getRandomTestPercentage() > 0 ? "\nHint: Try to set the test percetage to '0'" : ""));
195                    } else if (maxentError.equals("No species selected")) {
196                        setMessage("No species selected.\nHint: Make sure your active area includes species occurrences");
197                    }
198                } else {
199                    // rename the env filenames to their display names
200                    String pth_plots = currentPath + "output" + File.separator + "maxent" + File.separator + getName() + File.separator + "plots" + File.separator;
201                    String pth = currentPath + "output" + File.separator + "maxent" + File.separator + getName() + File.separator;
202//                for (int ei = 0; ei < envnameslist.length; ei++) {
203//                    readReplace(pth + "species.html", ".*?\\b"+envpathlist[ei]+"\\b.*?", Layers.layerNameToDisplayName(envnameslist[ei].replace(" ", "_")) + "("+envnameslist[ei]+")" );
204//                    for (int j = 0; j < imgExtensions.length; j++) {
205//                        try {
206//                            FileUtils.moveFile(
207//                                    new File(pth_plots + "species_" + envpathlist[ei] + imgExtensions[j]),
208//                                    new File(pth_plots + "species_" + Layers.layerNameToDisplayName(envnameslist[ei].replace(" ", "_")) + "("+envnameslist[ei]+")" + imgExtensions[j]));
209//                        } catch (Exception ex) {
210//                        }
211//                    }
212//                }
213
214//                //remove species image path in output species.html
215//                readReplaceBetween(pth + "species.html", "<HR><H2>Pictures of the model", "<HR>","<HR>");
216//                readReplace(pth + "species.html", "<a href = \"plots/\"> <img src=\"plots/\" width=600></a>", "see map window");
217//                readReplace(pth + "species.html", "plots\\\\", "plots/");
218//
219//                readReplace(pth + "species.html", "<a href = \"species_samplePredictions.csv\">The prediction strength at the training and (optionally) test presence sites</a><br>", "");
220                    String input = getInputs();
221//                    String sciname = input.substring(input.indexOf("scientificName:") + 15, input.indexOf(";", input.indexOf("scientificName:") + 15));
222//                    String scirank = input.substring(input.indexOf("taxonRank:") + 10, input.indexOf(";", input.indexOf("taxonRank:") + 10));
223                    readReplace(pth + "species.html", "Maxent model for species", "Maxent model for " + taxon);
224
225                    String paramlist = "Model reference number: " + getName()
226                            + "<br>Species: " + taxon //+ " (" + scirank + ")"
227                            + "<br>Layers: <ul>";
228
229                    LayerDAO layerDao = Client.getLayerDao();
230                    for (int ei = 0; ei < envnameslist.length; ei++) {
231                        System.out.println("LAYER NAME: " + envnameslist[ei]);
232                        Layer lyr = layerDao.getLayerByName(envnameslist[ei]);
233                        if (lyr != null) {
234                            paramlist += "<li>" + lyr.getDisplayname() + " (" + envnameslist[ei] + ")</li>";
235                        } else {
236                            if (envnameslist[ei].startsWith("aloc_")) {
237                                paramlist += "<li>Classification (" + envnameslist[ei].split("_")[1] + ")</li>";
238                            } else {
239                                paramlist += "<li>" + envnameslist[ei] + "</li>";
240                            }
241                        }
242                    }
243                    paramlist += "</ul>";
244
245                    readReplace(pth + "species.html", "end of this page.<br>", "end of this page.<br><p>" + paramlist + "</p>");
246                    readReplace(pth + "species.html", msets.getOutputPath(), "");
247                    readReplaceBetween(pth + "species.html", "Command line", "<br>", "");
248                    readReplaceBetween(pth + "species.html", "Command line", "<br>", "");
249
250                    // replace the summary
251                    readReplace(pth + "species.html", "This page contains some analysis of the Maxent model for", "This <a href='http://www.cs.princeton.edu/~schapire/maxent/'>Maxent</a> v3.3.3e predictive model for");
252                    readReplace(pth + "species.html", ", created", " was created");
253                    readReplace(pth + "species.html", " using Maxent version 3.3.3e.", ".");
254                    readReplace(pth + "species.html", "If you would like to do further analyses, the raw data used here is linked to at the end of this page", "Links at the bottom of this page to the raw data may be used for further analysis");
255
256                    if (chkResponseCurves != null) {
257                        StringBuffer sbTable = new StringBuffer();
258                        String[] ctxlist = msets.getEnvVarToggler().split(" ");
259                        if (msets.getEnvVarToggler().length() > 0) {
260                            sbTable.append("<pre>");
261                            for (String ctx : ctxlist) {
262                                if (ctx.startsWith("aloc_")) {
263                                    continue;
264                                }
265                                sbTable.append("<span style='font-weight: bold; text-decoration: underline'>" + ctx + " legend</span><br />");
266                                //sbTable.append(IOUtils.toString(new FileInputStream(/*TabulationSettings.environmental_data_path + ctx + ".txt"*/"")));
267                                sbTable.append(IOUtils.toString(new FileInputStream(GridCutter.getLayerPath(resolution, ctx) + ".txt")));
268                                sbTable.append("<br /><br />");
269                            }
270                            sbTable.append("</pre>");
271                            readReplace(pth + "species.html", "<br><HR><H2>Analysis of variable contributions</H2><br>", sbTable.toString() + "<br><HR><H2>Analysis of variable contributions</H2><br>");
272                        }
273                    }
274
275                    readReplaceBetween(pth + "species.html", "<br>Click <a href=species_explain.bat", "memory.<br>", "");
276                    readReplaceBetween(pth + "species.html", "(A link to the Explain", "additive models.)", "");
277
278                    StringBuffer removedSpecies = new StringBuffer();
279                    try {
280                        BufferedReader br = new BufferedReader(new FileReader(
281                                currentPath + "output" + File.separator + "maxent" + File.separator + getName() + File.separator + "Prediction_removedSpecies.txt"));
282                        String s;
283                        while ((s = br.readLine()) != null) {
284                            removedSpecies.append(s);
285                        }
286                        br.close();
287                    } catch (Exception e) {
288                    }
289                    if (removedSpecies.length() > 0) {
290                        String header = "'Sensitive species' have been masked out of the model. See: http://www.ala.org.au/about/program-of-projects/sds/\r\n\r\nLSID,Species scientific name,Taxon rank";
291                        writeToFile(header + removedSpecies.toString(),
292                                currentPath + "output" + File.separator + "maxent" + File.separator + getName() + File.separator + "Prediction_maskedOutSensitiveSpecies.csv");
293
294                        String insertBefore = "<a href = \"species.asc\">The";
295                        String insertText = "<b><a href = \"Prediction_maskedOutSensitiveSpecies.csv\">'Sensitive species' masked out of the model</a></br></b>";
296                        readReplace(pth + "species.html", insertBefore, insertText + insertBefore);
297                    }
298
299//                //delete image
300//                FileUtils.deleteQuietly(new File(pth_plots + "species.png"));
301//                FileUtils.deleteQuietly(new File(pth + "species_samplePredictions.csv"));
302//                FileUtils.deleteQuietly(new File(pth + "maxent.log"));
303//                FileUtils.deleteQuietly(new File(msets.getSpeciesFilepath()));
304
305                    writeProjectionFile(msets.getOutputPath());
306
307                    // if generated successfully, then add it to geoserver
308                    String url = AlaspatialProperties.getGeoserverUrl() + "/rest/workspaces/ALA/coveragestores/maxent_" + getName() + "/file.arcgrid?coverageName=species_" + getName();
309                    String extra = "";
310                    String username = AlaspatialProperties.getGeoserverUsername();
311                    String password = AlaspatialProperties.getGeoserverPassword();
312
313                    // first zip up the file as it's going to be sent as binary
314                    //String ascZipFile = Zipper.zipFile(msets.getOutputPath() + "species.asc");
315                    String[] infiles = {msets.getOutputPath() + "species.asc", msets.getOutputPath() + "species.prj"};
316                    String ascZipFile = msets.getOutputPath() + "species.zip";
317                    Zipper.zipFiles(infiles, ascZipFile);
318
319                    // Upload the file to GeoServer using REST calls
320                    System.out.println("Uploading file: " + ascZipFile + " to \n" + url);
321                    UploadSpatialResource.loadResource(url, extra, username, password, ascZipFile);
322
323                    //Enable browser caching, FIX for zoom to extent required.
324//                    String data = "<coverage><metadata><entry key=\"cacheAgeMax\">3600</entry><entry key=\"cachingEnabled\">true</entry><entry key=\"dirName\">maxent_" + getName() + "_species</entry></metadata></coverage>";
325//                    url = (String) htGeoserver.get("geoserver_url") + "/rest/workspaces/ALA/coveragestores/maxent_" + getName() + "/coverages/maxent_" + getName() + ".xml";
326//                    UploadSpatialResource.assignSld(url, extra, username, password, data);
327
328                    htProcess.put("status", "success"); ///
329                    htProcess.put("pid", getName());
330                    htProcess.put("info", "/output/maxent/" + getName() + "/species.html");
331
332                    //convert .asc to .grd/.gri
333                    convertAscToDiva(msets.getOutputPath() + "species.asc", msets.getOutputPath() + getName());
334
335                    setStage(3);
336
337                    // generate the readme.txt file
338                    CitationService.generatePredictionReadme(msets.getOutputPath(), msets.getSpeciesFilepath().substring(msets.getSpeciesFilepath().lastIndexOf("points")));
339
340                    setProgress(1, "finished");
341
342                    setCurrentState(SUCCESSFUL);
343
344                    //write out infor for adjusting input parameters
345                    System.out.println("MAXENT:" + cells + "," + envnameslist.length + " " + speciesCount + " " + (stageTimes[1] - stageTimes[0]) + " " + (stageTimes[2] - stageTimes[0]) + " " + (stageTimes[3] - stageTimes[2]));
346                }
347            } else {
348                System.out.println("Failed 1");
349                setProgress(1, "failed");
350                setCurrentState(FAILED);
351            }
352        } catch (Exception e) {
353            e.printStackTrace();
354            System.out.println("Failed with exception: " + e.getMessage());
355            setProgress(1, "failed: " + e.getMessage());
356            setCurrentState(FAILED);
357            setMessage("Error processing your Prediction request. Please try again or if problem persists, contact the Administrator.\n\nPlease quote the Prediction ID: " + getName());
358        }
359    }
360
361    @Override
362    public long getEstimate() {
363        if (getProgress() == 0) {
364            return 0;
365        }
366
367        long progTime;
368        synchronized (progress) {
369            progTime = progressTime;
370        }
371        long timeRemaining = 0;
372        long t1 = 0, t2 = 0, t3 = 0;
373
374        if (stage <= 0) { //data load; 0 to 0.2
375            t1 += (cells * AlaspatialProperties.getAnalysisMaxentEstimateMult0()) * envnameslist.length; //default
376            t1 = t1 + progTime - stageTimes[0];
377        }
378        if (stage <= 1) { //running; 0.2 to 0.9
379            t2 += (cells * AlaspatialProperties.getAnalysisMaxentEstimateMult1()) * envnameslist.length; //default
380            if (stage == 1) {
381                t2 = t2 + progTime - stageTimes[1];
382            }
383        }
384        if (stage > 1) { //data export + done
385            t3 += 5000 * AlaspatialProperties.getAnalysisMaxentEstimateMult2(); //default
386            if (stage == 2) {
387                t3 = t3 + progTime - stageTimes[2];
388            }
389        }
390
391        timeRemaining = t1 + t2 + t3;
392
393        return timeRemaining; //smoothEstimate(timeRemaining);
394    }
395
396    @Override
397    public void setProgress(double d) {
398        if (stage == 0) { //data load; 0 to 0.2
399            progress = d / 5.0;
400        } else if (stage == 1) { //running; 0.2 to 0.9
401            progress = 0.2 + 10 * d / 7.0;
402        } else { //exporting/done
403            progress = 0.9 + d / 10.0;
404        }
405        super.setProgress(progress);
406    }
407
408    @Override
409    public double getProgress() {
410        //return expected progress since cannot track internals
411
412        long currentTime = System.currentTimeMillis();
413
414        long progTime;
415        synchronized (progress) {
416            progTime = progressTime;
417        }
418
419        long t1 = 0, t2 = 0, t3 = 0;
420        double d1, d2, d3;
421
422        //progress is [time passed] / [time expected]
423        if (stage <= 0) { //data load; 0 to 0.2
424            t1 += (cells * AlaspatialProperties.getAnalysisMaxentEstimateMult0()) * envnameslist.length; //default
425            d1 = (currentTime - stageTimes[0]) / (double) t1;
426            if (d1 > 0.9) {
427                d1 = 0.9;
428            }
429            d1 *= 0.2; //range limit
430        } else {
431            d1 = 0.2;
432        }
433        if (stage <= 1) { //running; 0.2 to 0.9
434            t2 += (cells * AlaspatialProperties.getAnalysisMaxentEstimateMult1()) * envnameslist.length; //default
435            if (stage == 1) {
436                d2 = (currentTime - stageTimes[1]) / (double) t2;
437            } else {
438                d2 = 0;
439            }
440            if (d2 > 0.9) {
441                d2 = 0.9;
442            }
443            d2 *= 0.7; //range limit
444        } else {
445            d2 = 0.7;
446        }
447        if (stage > 1) { //data export + done
448            t3 += 5000 * AlaspatialProperties.getAnalysisMaxentEstimateMult2(); //default
449            if (stage == 2) {
450                d3 = (currentTime - stageTimes[2]) / (double) t3;
451            } else {
452                d3 = 0;
453            }
454            if (d3 > 0.9) {
455                d3 = 0.9;
456            }
457            d3 *= 0.1; //range limit
458        } else {
459            d3 = 0.1;
460        }
461
462        return d1 + d2 + d3;
463    }
464
465    @Override
466    public String getStatus() {
467        if (getProgress() < 1) {
468            String msg;
469            if (stage == 0) { //data load; 0 to 0.2
470                msg = "Data preparation, ";
471            } else if (stage == 1) { //seeding; 0.2 to 0.9
472                msg = "Running, ";
473            } else {    //transforming data; 0.9 to 1.0
474                msg = "Exporting results, ";
475            }
476            return msg + "est remaining: " + getEstimateInMinutes() + " min";
477        } else {
478            if (stage == -1) {
479                return "not started, est: " + getEstimateInMinutes() + " min";
480            } else {
481                return "finished, total run time=" + Math.round(getRunTime() / 1000) + "s";
482            }
483        }
484    }
485
486    @Override
487    public void setStage(int i) {
488        super.setStage(i);
489        if (i < 4) {
490            stageTimes[i] = System.currentTimeMillis();
491        }
492    }
493
494    public void setCells(int i) {
495        cells = i;
496    }
497
498    public String toString() {
499        StringBuffer sb = new StringBuffer();
500        sb.append(getName());
501        sb.append("; Maxent");
502        sb.append("; state=").append(getCurrentState());
503        sb.append("; status=").append(getStatus());
504        sb.append("; grid cell count=").append(cells);
505        sb.append("; number of layers=").append(envnameslist.length);
506
507        return sb.toString();
508    }
509
510    static public void readReplace(String fname, String oldPattern, String replPattern) {
511        String line;
512        StringBuffer sb = new StringBuffer();
513        try {
514            FileInputStream fis = new FileInputStream(fname);
515            BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
516            while ((line = reader.readLine()) != null) {
517                line = line.replaceAll(oldPattern, replPattern);
518                sb.append(line + "\n");
519            }
520            reader.close();
521            BufferedWriter out = new BufferedWriter(new FileWriter(fname));
522            out.write(sb.toString());
523            out.close();
524        } catch (Throwable e) {
525            System.err.println("*** exception ***");
526            e.printStackTrace(System.out);
527        }
528    }
529
530    public void readReplaceBetween(String fname, String startOldText, String endOldText, String replText) {
531        String line;
532        StringBuffer sb = new StringBuffer();
533        try {
534            FileInputStream fis = new FileInputStream(fname);
535            BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
536            while ((line = reader.readLine()) != null) {
537                sb.append(line + "\n");
538            }
539            int start, end;
540            start = sb.indexOf(startOldText);
541            if (start >= 0) {
542                end = sb.indexOf(endOldText, start + 1);
543                sb.replace(start, end + endOldText.length(), replText);
544            }
545            reader.close();
546            BufferedWriter out = new BufferedWriter(new FileWriter(fname));
547            out.write(sb.toString());
548            out.close();
549        } catch (Throwable e) {
550            System.err.println("*** exception ***");
551            e.printStackTrace(System.out);
552        }
553    }
554
555    private String setupSpecies(String speciesList, String outputpath) {
556        try {
557            File fDir = new File(outputpath);
558            fDir.mkdir();
559
560            //File spFile = File.createTempFile("points_", ".csv", fDir);
561            File spFile = new File(fDir, "species_points.csv");
562            PrintWriter spWriter = new PrintWriter(new BufferedWriter(new FileWriter(spFile)));
563
564            //spWriter.write("spname, longitude, latitude \n");
565            spWriter.write(speciesList);
566            spWriter.close();
567
568            return spFile.getAbsolutePath();
569        } catch (IOException ex) {
570            //Logger.getLogger(MaxentServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
571            System.out.println("error writing species file:");
572            ex.printStackTrace(System.out);
573        }
574
575        return null;
576    }
577
578    private void writeToFile(String text, String filename) {
579        try {
580            FileWriter fw = new FileWriter(filename);
581            fw.append(text);
582            fw.close();
583        } catch (Exception e) {
584            e.printStackTrace();
585        }
586    }
587
588    private void writeProjectionFile(String outputpath) {
589        try {
590            File fDir = new File(outputpath);
591            fDir.mkdir();
592
593            PrintWriter spWriter = new PrintWriter(new BufferedWriter(new FileWriter(outputpath + "species.prj")));
594
595            StringBuffer sbProjection = new StringBuffer();
596            sbProjection.append("GEOGCS[\"WGS 84\", ").append("\n");
597            sbProjection.append("    DATUM[\"WGS_1984\", ").append("\n");
598            sbProjection.append("        SPHEROID[\"WGS 84\",6378137,298.257223563, ").append("\n");
599            sbProjection.append("            AUTHORITY[\"EPSG\",\"7030\"]], ").append("\n");
600            sbProjection.append("        AUTHORITY[\"EPSG\",\"6326\"]], ").append("\n");
601            sbProjection.append("    PRIMEM[\"Greenwich\",0, ").append("\n");
602            sbProjection.append("        AUTHORITY[\"EPSG\",\"8901\"]], ").append("\n");
603            sbProjection.append("    UNIT[\"degree\",0.01745329251994328, ").append("\n");
604            sbProjection.append("        AUTHORITY[\"EPSG\",\"9122\"]], ").append("\n");
605            sbProjection.append("    AUTHORITY[\"EPSG\",\"4326\"]] ").append("\n");
606
607            //spWriter.write("spname, longitude, latitude \n");
608            spWriter.write(sbProjection.toString());
609            spWriter.close();
610
611        } catch (IOException ex) {
612            //Logger.getLogger(MaxentServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
613            System.out.println("error writing species file:");
614            ex.printStackTrace(System.out);
615        }
616    }
617
618    public String getImage() {
619        return "output/maxent/" + getName() + "/plots/species_hidden.png";
620    }
621
622    AnalysisJob copy() {
623        return new AnalysisJobMaxent(String.valueOf(System.currentTimeMillis()),
624                currentPath, taxon, envlist, region, envelope, txtTestPercentage, chkJackknife, chkResponseCurves, resolution);
625    }
626
627    private String getMaxentError(File file, int count) {
628        try {
629            RandomAccessFile rf = new RandomAccessFile(file, "r");
630
631
632            // first check if maxent threw a 'No species selected' error
633            String nosp = rf.readLine(); // first line: date/time
634            nosp = rf.readLine(); // second line: maxent version
635            nosp = rf.readLine(); // third line: "No species selected"
636            if (nosp.equals("No species selected")) {
637                return "No species selected";
638            }
639
640            long flen = file.length() - 1;
641            int nlcnt = -1;
642            StringBuilder lines = new StringBuilder();
643            while (nlcnt != count) {
644                rf.seek(flen--);
645                char c = (char) rf.read();
646                lines.append(c);
647                if (c == '\n') {
648                    nlcnt++;
649                }
650
651            }
652            String line = lines.reverse().toString();
653            if (line.contains("Warning: Skipping species because it has 0 test samples")) {
654                return "Warning: Skipping species because it has 0 test samples";
655            }
656
657            rf.close();
658        } catch (Exception e) {
659            System.out.println("Unable to read lines");
660            e.printStackTrace(System.out);
661        }
662
663        // return false anyways
664        return null;
665    }
666
667    private void convertAscToDiva(String asc, String grd) {
668        try {
669            //read asc
670            BufferedReader br = new BufferedReader(new FileReader(asc));
671            String s;
672
673            //maxent output grid is:
674            s = br.readLine();
675            int ncols = Integer.parseInt(s.replace("ncols", "").trim());
676
677            s = br.readLine();
678            int nrows = Integer.parseInt(s.replace("nrows", "").trim());
679
680            s = br.readLine();
681            double lng1 = Double.parseDouble(s.replace("xllcorner", "").trim());
682
683            s = br.readLine();
684            double lat1 = Double.parseDouble(s.replace("yllcorner", "").trim());
685
686            s = br.readLine();
687            double div = Double.parseDouble(s.replace("cellsize", "").trim());
688
689            s = br.readLine();
690            double nodata = Double.parseDouble(s.replace("NODATA_value", "").trim());
691
692            double[] data = new double[ncols * nrows];
693            for (int i = 0; i < ncols * nrows; i++) {
694                data[i] = Double.NaN;
695            }
696            int r = 0;
697            while ((s = br.readLine()) != null) {
698                String[] row = s.split(" ");
699                for (int i = 0; i < row.length && i < ncols; i++) {
700                    double v = Double.parseDouble(row[i]);
701                    if (v != nodata) {
702                        data[r * ncols + i] = v;
703                    }
704                }
705                r++;
706                if (r == nrows) {
707                    break;
708                }
709            }
710            br.close();
711
712            Grid g = new Grid(null);
713            g.writeGrid(grd, data, lng1, lat1, lng1 + ncols * div, lat1 + nrows * div, div, div, nrows, ncols);
714
715        } catch (Exception e) {
716            e.printStackTrace();
717        }
718    }
719}