org.openscience.jvxl.Jvxl.java Source code

Java tutorial

Introduction

Here is the source code for org.openscience.jvxl.Jvxl.java

Source

/* $RCSfile$
 * $Author: nicove $
 * $Date: 2007-03-25 06:09:49 -0500 (Sun, 25 Mar 2007) $
 * $Revision: 7221 $
 *
 * Copyright (C) 2000-2005  The Jmol Development Team
 *
 * Contact: jmol-developers@lists.sf.net
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.openscience.jvxl;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.HelpFormatter;
import org.jmol.jvxl.readers.SurfaceGenerator;
import org.jmol.util.Logger;
import javajs.util.P4;
import javajs.util.PT;

public class Jvxl {

    private final static String VERSION = "JVXL.java Version 1.0";

    public static void main(String[] args) {

        boolean blockData = false;
        int fileIndex = Integer.MAX_VALUE;
        String inputFile = null;
        String mapFile = null;
        String outputFile = null;

        float cutoff = Float.NaN;
        boolean isPositiveOnly = false;

        P4 plane = null;

        boolean bicolor = false;
        boolean reverseColor = false;
        float min = Float.NaN;
        float max = Float.NaN;

        Options options = new Options();
        options.addOption("h", "help", false, "give this help page");

        /*
         *  examples: 
         *  
         *  jvxl ch3cl-density.cub --min=0.0 --max=0.2 --map ch3cl-esp.cub
         *  jvxl ethene-HOMO.cub --bicolor --output ethene.jvxl
         *  jvxl d_orbitals.jvxl --index 2 --phase yz
         *  jvxl d_orbitals.jvxl --map sets
         *  jvxl --plane xy  --min=0.0 --max=0.2 --map data/ch3cl-density.cub 
         */

        // file options
        options.addOption("B", "blockdata", false, "multiple cube data are in blocks, not interspersed");

        options.addOption("P", "progressive", false, "create JVXL+ progressive X low-to-high format");

        OptionBuilder.withLongOpt("file");
        OptionBuilder.withDescription("file containing surface data");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("f"));

        OptionBuilder.withLongOpt("index");
        OptionBuilder.withDescription("index of surface in file (starting with 1)");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("i"));

        OptionBuilder.withLongOpt("plane");
        OptionBuilder.withDescription("plane: x, y, z, xy, xz, yz, z2, x2-y2, or {a,b,c,d}");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("p"));

        OptionBuilder.withLongOpt("map");
        OptionBuilder.withDescription("file containing data to map onto the surface or \"sets\"");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("m"));

        OptionBuilder.withLongOpt("output");
        OptionBuilder.withDescription("JVXL output file");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("o"));

        // surface options

        OptionBuilder.withLongOpt("cutoff");
        OptionBuilder.withDescription("isosurface cutoff value");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("c"));

        // color mapping options

        options.addOption("b", "bicolor", false, "bicolor map (orbital)");
        options.addOption("r", "reversecolor", false, "reverse color");

        OptionBuilder.withLongOpt("colorScheme");
        OptionBuilder.withDescription("VRML color scheme: bw, wb, roygb, bgyor, rwb, bwr, low, high");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("s"));

        OptionBuilder.withLongOpt("phase");
        OptionBuilder.withDescription("color by phase: x, y, z, xy, xz, yz, z2, x2-y2");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("F"));

        OptionBuilder.withLongOpt("min");
        OptionBuilder.withDescription("color absolute minimum value");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("n"));

        OptionBuilder.withLongOpt("max");
        OptionBuilder.withDescription("color absolute maximum value");
        OptionBuilder.withValueSeparator('=');
        OptionBuilder.hasArg();
        options.addOption(OptionBuilder.create("x"));

        CommandLine line = null;
        try {
            CommandLineParser parser = new PosixParser();
            line = parser.parse(options, args);
        } catch (ParseException exception) {
            Logger.error("Unexpected exception: " + exception.toString());
        }

        if (line.hasOption("h")) {
            HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("Jvxl", options);
            return;
        }

        args = line.getArgs();
        if (args.length > 0) {
            inputFile = args[0];
        }

        // files 

        blockData = (line.hasOption("B"));

        if (line.hasOption("i")) {
            fileIndex = PT.parseInt(line.getOptionValue("i"));
        }

        if (line.hasOption("f")) {
            inputFile = line.getOptionValue("f");
        }

        if (line.hasOption("m")) {
            mapFile = line.getOptionValue("m");
        }

        if (line.hasOption("p")) {
            plane = getPlane(line.getOptionValue("p"));
            if (plane == null) {
                Logger.error("invalid plane");
                return;
            }
            Logger.info("using plane " + plane);
            if (mapFile == null)
                mapFile = inputFile;
            if (inputFile == null)
                inputFile = mapFile;
        }

        if (line.hasOption("o")) {
            outputFile = line.getOptionValue("o");
        } else {
            outputFile = inputFile;
            if (outputFile.indexOf(".") < 0)
                outputFile += ".";
            String sIndex = (fileIndex == Integer.MAX_VALUE ? "" : "_" + fileIndex);
            if (sIndex.length() == 0 && outputFile.indexOf(".jvxl") >= 0)
                sIndex += "_new";
            outputFile = outputFile.substring(0, outputFile.lastIndexOf(".")) + sIndex + ".jvxl";
        }

        // Process more command line arguments
        // these are also passed to vwr

        bicolor = (line.hasOption("b"));
        reverseColor = (line.hasOption("r"));

        if (bicolor && mapFile != null) {
            Logger.warn("--map option ignored; incompatible with --bicolor");
            mapFile = null;
        }

        if (line.hasOption("c")) {
            String s = line.getOptionValue("c");
            if (s.indexOf("+") == 0) {
                isPositiveOnly = true;
                s = s.substring(1);
            }
            cutoff = PT.parseFloat(s);
        }

        if (line.hasOption("n")) {
            if (bicolor)
                Logger.warn("--min option ignored; incompatible with --bicolor");
            else
                min = PT.parseFloat(line.getOptionValue("n"));
        }

        if (line.hasOption("x")) {
            if (bicolor)
                Logger.warn("--max option ignored; incompatible with --bicolor");
            else
                max = PT.parseFloat(line.getOptionValue("x"));
        }

        //    if (line.hasOption("P")) {
        //      phase = line.getOptionValue("P");
        //    }

        boolean progressive = line.hasOption("P");

        // compose the surface

        SurfaceGenerator sg = new SurfaceGenerator(null, null, null, null);

        // input file

        sg.version = VERSION;
        if (blockData)
            sg.setProp("blockData", Boolean.TRUE, null);
        if (!Float.isNaN(cutoff))
            sg.setProp(isPositiveOnly ? "cutoffPositive" : "cutoff", Float.valueOf(cutoff), null);
        if (bicolor)
            sg.setProp("sign", null, null);
        if (reverseColor)
            sg.setProp("reverseColor", null, null);
        //if (phase != null)
        //sg.setProp("phase", phase);

        if (progressive)
            sg.setProp("progressive", null, null);

        if (plane != null)
            sg.setProp("plane", plane, null);
        else {
            if (fileIndex != Integer.MAX_VALUE)
                sg.setProp("fileIndex", Integer.valueOf(fileIndex), null);
            Object t = FileReader.getBufferedReaderOrErrorMessageFromName(inputFile);
            if (t instanceof String) {
                Logger.error((String) t);
                return;
            }
            BufferedReader br = (BufferedReader) t;
            sg.setProp("readFile", br, null);
            try {
                br.close();
            } catch (Exception e) {
                //
            }
        }

        sg.setProp("title", line.toString(), null);

        //color scheme is only for VMRL

        //if (colorScheme != null) {
        // ColorEncoder ce = new ColorEncoder(null);
        // ce.setColorScheme(colorScheme, false);
        // sg.setProp("colorScheme", ce);
        // }
        if (!Float.isNaN(min))
            sg.setProp("red", Float.valueOf(min), null);
        if (!Float.isNaN(max))
            sg.setProp("blue", Float.valueOf(max), null);
        if (mapFile != null) {
            Object t = FileReader.getBufferedReaderOrErrorMessageFromName(mapFile);
            if (t instanceof String) {
                Logger.error((String) t);
                return;
            }
            BufferedReader br2 = (BufferedReader) t;
            sg.setProp("mapColor", br2, null);
            try {
                br2.close();
            } catch (Exception e) {
                //
            }
        }

        writeFile(outputFile, (String) sg.getProperty("jvxlFileData", 0));
        Logger.info((String) sg.getProperty("jvxlFileInfo", 0));
        Logger.info("\ncreated " + outputFile);
    }

    static void writeFile(String fileName, String text) {
        try {
            FileOutputStream os = new FileOutputStream(fileName);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os), 8192);
            bw.write(text);
            bw.close();
            os = null;
        } catch (IOException e) {
            Logger.error("IO Exception: " + e.toString());
        }
    }

    static P4 getPlane(String str) {
        if (str.equalsIgnoreCase("xy"))
            return P4.new4(0, 0, 1, 0);
        if (str.equalsIgnoreCase("xz"))
            return P4.new4(0, 1, 0, 0);
        if (str.equalsIgnoreCase("yz"))
            return P4.new4(1, 0, 0, 0);
        if (str.indexOf("x=") == 0) {
            return P4.new4(1, 0, 0, -PT.parseFloat(str.substring(2)));
        }
        if (str.indexOf("y=") == 0) {
            return P4.new4(0, 1, 0, -PT.parseFloat(str.substring(2)));
        }
        if (str.indexOf("z=") == 0) {
            return P4.new4(0, 0, 1, -PT.parseFloat(str.substring(2)));
        }
        if (str.indexOf("{") == 0) {
            str = str.replace(',', ' ');
            int[] next = new int[1];
            return P4.new4(PT.parseFloatNext(str, next), PT.parseFloatNext(str, next), PT.parseFloatNext(str, next),
                    PT.parseFloatNext(str, next));
        }
        return null;
    }
}

class FileReader {

    FileReader() {

    }

    static Object getBufferedReaderOrErrorMessageFromName(String name) {
        Object t = getInputStreamOrErrorMessageFromName(name);
        if (t instanceof String)
            return t;
        try {
            BufferedInputStream bis = new BufferedInputStream((InputStream) t, 8192);
            InputStream is = bis;
            return new BufferedReader(new InputStreamReader(is));
        } catch (Exception ioe) {
            return ioe.getMessage();
        }
    }

    private static Object getInputStreamOrErrorMessageFromName(String name) {
        String errorMessage = null;
        try {
            Logger.info("opening " + name);
            File file = new File(name);
            int length = (int) file.length();
            InputStream in = new FileInputStream(file);
            return new MonitorInputStream(in, length);
        } catch (Exception e) {
            errorMessage = "" + e;
        }
        return errorMessage;
    }
}

class MonitorInputStream extends FilterInputStream {
    int length;
    int position;
    int markPosition;
    int readEventCount;
    long timeBegin;

    MonitorInputStream(InputStream in, int length) {
        super(in);
        this.length = length;
        this.position = 0;
        timeBegin = System.currentTimeMillis();
    }

    @Override
    public int read() throws IOException {
        ++readEventCount;
        int nextByte = super.read();
        if (nextByte >= 0)
            ++position;
        return nextByte;
    }

    @Override
    public int read(byte[] b) throws IOException {
        ++readEventCount;
        int cb = super.read(b);
        if (cb > 0)
            position += cb;
        return cb;
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        ++readEventCount;
        int cb = super.read(b, off, len);
        if (cb > 0)
            position += cb;
        return cb;
    }

    @Override
    public long skip(long n) throws IOException {
        long cb = super.skip(n);
        // this will only work in relatively small files ... 2Gb
        position = (int) (position + cb);
        return cb;
    }

    @Override
    public synchronized void mark(int readlimit) {
        super.mark(readlimit);
        markPosition = position;
    }

    @Override
    public synchronized void reset() throws IOException {
        position = markPosition;
        super.reset();
    }

    int getPosition() {
        return position;
    }

    int getLength() {
        return length;
    }

    int getPercentageRead() {
        return position * 100 / length;
    }

    int getReadingTimeMillis() {
        return (int) (System.currentTimeMillis() - timeBegin);
    }
}