ffx.crystal.ReflectionList.java Source code

Java tutorial

Introduction

Here is the source code for ffx.crystal.ReflectionList.java

Source

/**
 * Title: Force Field X.
 *
 * Description: Force Field X - Software for Molecular Biophysics.
 *
 * Copyright: Copyright (c) Michael J. Schnieders 2001-2017.
 *
 * This file is part of Force Field X.
 *
 * Force Field X is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 3 as published by
 * the Free Software Foundation.
 *
 * Force Field X 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Linking this library statically or dynamically with other modules is making a
 * combined work based on this library. Thus, the terms and conditions of the
 * GNU General Public License cover the whole combination.
 *
 * As a special exception, the copyright holders of this library give you
 * permission to link this library with independent modules to produce an
 * executable, regardless of the license terms of these independent modules, and
 * to copy and distribute the resulting executable under terms of your choice,
 * provided that you also meet, for each linked independent module, the terms
 * and conditions of the license of that module. An independent module is a
 * module which is not derived from or based on this library. If you modify this
 * library, you may extend this exception to your version of the library, but
 * you are not obligated to do so. If you do not wish to do so, delete this
 * exception statement from your version.
 */
package ffx.crystal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.configuration.CompositeConfiguration;

import static org.apache.commons.math3.util.FastMath.PI;
import static org.apache.commons.math3.util.FastMath.cos;
import static org.apache.commons.math3.util.FastMath.floor;
import static org.apache.commons.math3.util.FastMath.max;
import static org.apache.commons.math3.util.FastMath.min;
import static org.apache.commons.math3.util.FastMath.rint;

/**
 * Class to represent a reflection list.
 *
 * @author Timothy D. Fenn
 *
 * @see
 * <a href="http://dx.doi.org/10.1107/S0021889802013420" target="_blank">
 * Cowtan, K. 2002. Generic representation and evaluation of properties as a
 * function of position in reciprocal space. J. Appl. Cryst. 35:655-663.
 * </a>
 *
 * @since 1.0
 */
public class ReflectionList {

    public final HashMap<String, HKL> hklmap = new HashMap<>();
    public final ArrayList<HKL> hkllist = new ArrayList<>();
    public final Crystal crystal;
    public final SpaceGroup spaceGroup;
    private final SpaceGroup.CrystalSystem crystalSystem;
    private final SpaceGroup.LaueSystem laueSystem;
    public final Resolution resolution;
    // for binning reflections based on resolution
    public int nbins = 10;
    public double hist[] = new double[1001];
    public double minres, maxres;

    /**
     * <p>
     * Constructor for ReflectionList.</p>
     *
     * @param crystal a {@link ffx.crystal.Crystal} object.
     * @param resolution a {@link ffx.crystal.Resolution} object.
     */
    public ReflectionList(Crystal crystal, Resolution resolution) {
        this(crystal, resolution, null);
    }

    /**
     * <p>
     * Constructor for ReflectionList.</p>
     *
     * @param crystal a {@link ffx.crystal.Crystal} object.
     * @param resolution a {@link ffx.crystal.Resolution} object.
     * @param properties a
     * {@link org.apache.commons.configuration.CompositeConfiguration} object.
     */
    public ReflectionList(Crystal crystal, Resolution resolution, CompositeConfiguration properties) {
        this.crystal = crystal;
        spaceGroup = crystal.spaceGroup;
        crystalSystem = spaceGroup.crystalSystem;
        laueSystem = spaceGroup.laueSystem;
        this.resolution = resolution;

        int hmax = (int) (this.crystal.a / this.resolution.resolutionLimit());
        int kmax = (int) (this.crystal.b / this.resolution.resolutionLimit());
        int lmax = (int) (this.crystal.c / this.resolution.resolutionLimit());

        minres = Double.POSITIVE_INFINITY;
        maxres = Double.NEGATIVE_INFINITY;
        int n = 0;

        HKL hkl = new HKL();
        for (int h = -hmax; h <= hmax; h++) {
            hkl.h(h);
            for (int k = -kmax; k <= kmax; k++) {
                hkl.k(k);
                for (int l = -lmax; l <= lmax; l++) {
                    hkl.l(l);

                    double res = Crystal.invressq(this.crystal, hkl);
                    getepsilon(hkl);
                    if (SpaceGroup.checkLaueRestrictions(laueSystem, h, k, l) && resolution.inInverseResSqRange(res)
                            && !HKL.sys_abs(hkl)) {
                        minres = min(res, minres);
                        maxres = max(res, maxres);
                        String s = ("" + h + "_" + k + "_" + l).intern();
                        hklmap.put(s, new HKL(hkl.h(), hkl.k(), hkl.l(), hkl.epsilon(), hkl.allowed));
                        n++;
                    }
                }
            }
        }

        n = 0;
        for (Map.Entry ei : hklmap.entrySet()) {
            Object key = ei.getKey();
            HKL ih = (HKL) ei.getValue();

            ih.index(n);
            hkllist.add(ih);
            n++;
        }

        /*
         * set up the resolution bins
         * first build a histogram
         */
        for (HKL ih : hkllist) {
            double r = (Crystal.invressq(this.crystal, ih) - minres) / (maxres - minres);
            int i = (int) (min(r, 0.999) * 1000.0);
            hist[i + 1] += 1.0;
        }

        // convert to cumulative histogram
        for (int i = 1; i < hist.length; i++) {
            hist[i] += hist[i - 1];
        }
        for (int i = 0; i < hist.length; i++) {
            hist[i] /= hist[hist.length - 1];
        }

        // assign each reflection to a bin in the range (0-nbins)
        setResolutionBins(properties);
    }

    /**
     * <p>
     * Constructor for ReflectionList.</p>
     *
     * @param a a double.
     * @param b a double.
     * @param c a double.
     * @param alpha a double.
     * @param beta a double.
     * @param gamma a double.
     * @param sg a {@link java.lang.String} object.
     * @param resolution a double.
     */
    public ReflectionList(double a, double b, double c, double alpha, double beta, double gamma, String sg,
            double resolution) {
        this(new Crystal(a, b, c, alpha, beta, gamma, sg), new Resolution(resolution));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return " Reflection list with " + this.hkllist.size() + " reflections, spacegroup "
                + this.spaceGroup.shortName + " resolution limit: " + resolution.resolutionLimit();
    }

    /**
     * <p>
     * findSymHKL</p>
     *
     * @param hkl a {@link ffx.crystal.HKL} object.
     * @param mate a {@link ffx.crystal.HKL} object.
     * @return a boolean.
     */
    public boolean findSymHKL(HKL hkl, HKL mate) {
        return findSymHKL(hkl, mate, false);
    }

    /**
     * <p>
     * findSymHKL</p>
     *
     * @param h a int.
     * @param k a int.
     * @param l a int.
     * @param mate a {@link ffx.crystal.HKL} object.
     * @return a boolean.
     */
    public boolean findSymHKL(int h, int k, int l, HKL mate) {
        return findSymHKL(new HKL(h, k, l), mate, false);
    }

    /**
     * <p>
     * findSymHKL</p>
     *
     * @param h a int.
     * @param k a int.
     * @param l a int.
     * @param mate a {@link ffx.crystal.HKL} object.
     * @param transpose a boolean.
     * @return a boolean.
     */
    public boolean findSymHKL(int h, int k, int l, HKL mate, boolean transpose) {
        return findSymHKL(new HKL(h, k, l), mate, transpose);
    }

    /**
     * <p>
     * findSymHKL</p>
     *
     * @param hkl a {@link ffx.crystal.HKL} object.
     * @param mate a {@link ffx.crystal.HKL} object.
     * @param transpose a boolean.
     * @return a boolean.
     */
    public boolean findSymHKL(HKL hkl, HKL mate, boolean transpose) {
        int nsym = spaceGroup.numPrimitiveSymEquiv;

        for (int i = 0; i < nsym; i++) {
            if (transpose) {
                crystal.applyTransSymRot(hkl, mate, spaceGroup.symOps.get(i));
            } else {
                crystal.applySymRot(hkl, mate, spaceGroup.symOps.get(i));
            }
            if (SpaceGroup.checkLaueRestrictions(laueSystem, mate.h(), mate.k(), mate.l())) {
                return false;
            }
            if (SpaceGroup.checkLaueRestrictions(laueSystem, -mate.h(), -mate.k(), -mate.l())) {
                mate.h(-mate.h());
                mate.k(-mate.k());
                mate.l(-mate.l());
                return true;
            }
        }

        mate.h(hkl.h());
        mate.k(hkl.k());
        mate.l(hkl.l());
        return false;
    }

    /**
     * <p>
     * getHKL</p>
     *
     * @param h a int.
     * @param k a int.
     * @param l a int.
     * @return a {@link ffx.crystal.HKL} object.
     */
    public HKL getHKL(int h, int k, int l) {
        String s = ("" + h + "_" + k + "_" + l);
        return hklmap.get(s);
    }

    /**
     * <p>
     * getHKL</p>
     *
     * @param hkl a {@link ffx.crystal.HKL} object.
     * @return a {@link ffx.crystal.HKL} object.
     */
    public HKL getHKL(HKL hkl) {
        return getHKL(hkl.h(), hkl.k(), hkl.l());
    }

    /**
     * <p>
     * hasHKL</p>
     *
     * @param h a int.
     * @param k a int.
     * @param l a int.
     * @return a boolean.
     */
    public boolean hasHKL(int h, int k, int l) {
        String s = ("" + h + "_" + k + "_" + l);
        return hklmap.containsKey(s);
    }

    /**
     * <p>
     * hasHKL</p>
     *
     * @param hkl a {@link ffx.crystal.HKL} object.
     * @return a boolean.
     */
    public boolean hasHKL(HKL hkl) {
        return hasHKL(hkl.h(), hkl.k(), hkl.l());
    }

    private void getepsilon(HKL hkl) {
        int epsilon = 1;
        int allowed = 255;

        int nsym = spaceGroup.symOps.size();
        for (int i = 1; i < nsym; i++) {
            HKL mate = new HKL();
            crystal.applySymRot(hkl, mate, spaceGroup.symOps.get(i));
            double shift = Crystal.sym_phase_shift(hkl, spaceGroup.symOps.get(i));

            if (mate.equals(hkl)) {
                if (cos(shift) > 0.999) {
                    epsilon++;
                } else {
                    allowed = 0;
                    epsilon = 0;
                    break;
                }
            } else if (mate.equals(HKL.neg(hkl))) {
                // centric reflection
                allowed = (int) rint(Crystal.mod(-0.5 * shift, PI) / (PI / HKL.ndiv));
            }
        }
        if (hkl.h() == 0 && hkl.k() == 0 && hkl.l() == 0) {
            allowed = 0;
        }

        hkl.epsilon(epsilon);
        hkl.allowed(allowed);
    }

    /**
     * <p>
     * ordinal</p>
     *
     * @param s a double.
     * @return a double.
     */
    public double ordinal(double s) {
        double r = (s - minres) / (maxres - minres);
        r = min(r, 0.999) * 1000.0;
        int i = (int) r;
        r -= floor(r);
        return ((1.0 - r) * hist[i] + r * hist[i + 1]);
    }

    private void setResolutionBins() {
        setResolutionBins(null);
    }

    private void setResolutionBins(CompositeConfiguration properties) {
        if (properties != null) {
            nbins = properties.getInt("nbins", 10);
        }
        double nbinsd = (double) nbins;
        for (HKL ih : hkllist) {
            int bin = (int) (nbinsd * ordinal(Crystal.invressq(this.crystal, ih)));
            ih.bin = min(bin, nbins - 1);
        }
    }
}