public JComplex generateF0(JVector Q, int Z, JComplex energyFormFactor) {
    JComplex f0 = new JComplex(0, 0);

    double fTemp = elementConstants[Z - 1][9];

    for (int i = 1; i < 5; i++) {
      double ai = elementConstants[Z - 1][i];
      double bi = elementConstants[Z - 1][i + 4];

      fTemp += ai * Math.exp(-1 * bi * Math.pow((Q.length()) / (4 * Math.PI), 2));
    }

    f0 = JComplex.add(energyFormFactor, fTemp);

    return f0;
  }
  /**
   * This method searches through the "sf" folder which contains the complex scattering factors at a
   * number of energies in eV for the desired energy. These files were obtained from the Berkeley
   * National Lab. url http://henke.lbl.gov/optical_constants/asf.html The files that will be
   * searched only have energy values between 10eV and 30keV. If a selection of > 30keV is made then
   * a complex value of Z + 0*i will be returned.
   *
   * @param energyOrWavelength set to 0 for an Energy in eV input. set to 1 for a wavelength in
   *     Angstroms input
   * @param findMe The energy or wavelength that is to be found in the list
   * @param Z The number of electrons in the element
   * @return The complex scattering factor for the desired energy or wavelength
   * @throws Exception If the energyOrWavelength toggle is < 0 or > 1 then an exception is thrown.
   *     If Z < 0 or > 92 an exception is thrown. If E < 10 eV or lambda > 1238.174 Angstroms an
   *     exception is thrown
   */
  public JComplex getComplexF(int energyOrWavelength, double findMe, int Z) throws Exception {
    /* make sure the input is 0 or 1 */
    if (energyOrWavelength < 0 || energyOrWavelength > 1)
      throw new Exception(
          "Your selection of "
              + energyOrWavelength
              + " does not fall within the constraints."
              + "\nIf you want energy, set the energyOrWavelength value to 0.\nIf you want wavelength, set the energyOrWavelength value to 1.");

    /* make sure the 0 < Z < 92 */
    if (Z < 0 || Z > 92)
      throw new Exception(
          "Your selection of "
              + Z
              + " does not fall within the current number of elements.  Please choose a Z such that 0 < Z < 92");

    /* Declare the file reader */
    FileReader fr = null;

    /* define Planck's constant in terms of eV*s */
    double h = 4.13566733e-15;

    /* define the speed of light in terms of Angstroms / second */
    double c = 2.99792458e18;

    /* If the user passes in a wavelength (energyOrWavelength == 1), convert the wavelength to an energy in eV */
    double energyDesired;
    if (energyOrWavelength != 0) energyDesired = h * c / findMe;
    else energyDesired = findMe;

    /* Check to make sure that the energy or wavelength passed in is within the parameters available to this method. */
    if (energyDesired < 10)
      throw new Exception(
          "Your choice of an energy or wavelength of "
              + energyDesired
              + " is too low. \nPlease choose an energy such that "
              + "E > 10eV or a wavelength such that lambda < 1238.174 Angstroms.");

    /* If the energy that is passed in is greater than 30keV or less than .413 Angstroms, return a real scattering value of the Z value and 0 for the complex scattering.
     * This is a reasonable approximation.  If more exact numbers are needed, please reference http://www.nist.gov/physlab/data/ffast/index.cfm */
    if (energyDesired > 30000) return new JComplex(Z, 0);

    /* get the abbreviation for the element based on the index i and make it lower case */
    String abbreviation = elementNameAbbrev[Z - 1][0].toLowerCase();

    /* find the location of the program by creating a new file "." and getting the path.  Then take the substring that includes the path less the file name */
    String findLocation = (new File(".").getAbsolutePath());

    findLocation = findLocation.substring(0, findLocation.length() - 1);

    /* Initialize the file reader */
    try {
      fr = new FileReader(new File(findLocation + "/sf/" + abbreviation + ".nff"));
    } catch (FileNotFoundException e) {
      System.out.println("Cannot find the .nff files");
      e.printStackTrace();
    }

    /* Declare a new scanner to parse the file 'name.nff' */
    Scanner s = new Scanner(fr);

    /* skip the first line of the file */
    if (s.next().compareTo("E(eV)") == 0) s.nextLine();

    /* declare two variables to hold the current and previous values of the energy to compare them */
    double energyCurrent = 0;
    double energyPrevious = 0;

    /* declare two JComplex numbers to hold the current and previous values of the complex scattering factors */
    JComplex current = new JComplex(0., 0.);
    JComplex previous = new JComplex(0., 0.);

    /* if findMe is between two energies then take a percentage of the surrounding energies or wavelengths */
    double howMuchOf1 = 0;
    double howMuchOf2 = 0;

    /* declare a boolean toggle to break out of the while loop */
    boolean found = false;

    /* Loop through the file as long as the desired energy has not been found*/
    while (found == false) {
      /* set the previous energy value to what used to be the current energy value */
      energyPrevious = energyCurrent;

      /* set the previous scattering factor to what used to be the current scattering factor */
      previous.setRe(current.getRe());
      previous.setIm(current.getIm());

      /* read energy */
      energyCurrent = Double.valueOf(s.next());

      /* read real and imaginary parts of the scattering factor */
      current.setRe(Double.valueOf(s.next()));
      current.setIm(Double.valueOf(s.next()));

      /* test the current energy value to the target energy value */
      if (energyCurrent > energyDesired) {
        /* get out of the loop */
        found = true;

        /* how far away is the first energy */
        howMuchOf1 =
            Math.abs(energyPrevious - energyDesired)
                / (Math.abs(energyPrevious - energyDesired)
                    + Math.abs(energyCurrent - energyDesired));

        /* how far away is the second energy */
        howMuchOf2 =
            Math.abs(energyCurrent - energyDesired)
                / (Math.abs(energyPrevious - energyDesired)
                    + Math.abs(energyCurrent - energyDesired));
      }

      if (found == false) s.nextLine();
    }

    previous = JComplex.multiply(previous, howMuchOf1);

    /* set the second complex scattering factor to be how far away from the second energy your selection is times
    the complex scattering factor at the second energy */
    current = JComplex.multiply(current, howMuchOf2);

    /* Test to see if the first complex scattering factor is near an absorption edge */
    if (previous.getRe() < -1 * Z) previous.setRe(0);

    /* Test to see if the second complex scattering factor is near an absorption edge */
    if (current.getRe() < -1 * Z) current.setRe(0);

    /* return the complex scattering factor to be how far away from the bracketing energies your selection is times
    the complex scattering factor */
    return JComplex.add(previous, current);
  }