private void initial() {
    NormalDistribution nd = new NormalDistribution();
    String[] seqList = this.sequence.split(";");
    for (String seq : seqList) {
      BaseIsotopomer bIso = new BaseIsotopomer(seq, this.isotopomerWidth);
      TIntDoubleMap chargeScaleMap = new TIntDoubleHashMap();
      int centralCharge = bIso.getCentralChargeState();
      int totalChargeState = (bIso.getMaxChargeState() - centralCharge) * 2;
      double step = 6.0 / totalChargeState;
      // calculate right side of the central charge state (inclusive) to 10+ charge
      double x = 0.0;
      for (int i = centralCharge; i > 8; i--) {
        double factor = nd.density(x);
        x += step;
        chargeScaleMap.put(i, factor);
      }

      // calculate left side of the central charge state (exclusive) to max charge
      x = step;
      for (int i = centralCharge + 1; i <= bIso.getMaxChargeState(); i++) {
        double factor = nd.density(x);
        x += step;
        chargeScaleMap.put(i, factor);
      }

      // build list of Isotopomer
      for (int charge : chargeScaleMap.keys()) {
        ChargedIsotopomer cIso = new ChargedIsotopomer(bIso, charge);
        isotopomerList.add(cIso);

        TDoubleDoubleMap tempPeakMap = cIso.getScaledPeakMap(chargeScaleMap.get(charge));

        for (double mz : tempPeakMap.keys()) {
          double intensity = peakMap.get(mz);
          if (intensity == peakMap.getNoEntryValue()) {
            peakMap.put(mz, tempPeakMap.get(mz));
          } else {
            peakMap.put(mz, intensity + tempPeakMap.get(mz));
          }
        }
      }
    }
  }
  /**
   * Create prefix residue mass spectrum (PRM spectrum) with subset of peak list from Ms2Query
   * peaklist based on their intensity values (higher intensity first). The output spectrum contains
   * double of number plus 2 peaks after inserting reverse peaks, start peak and whole mass.
   *
   * @param query Ms2Query from MgfReader
   * @param number number of peaks with large intensity values from original peak list
   */
  public PRMSpectrum(Ms2Query query, int number) {
    this.prmSpectrum = new ArrayList<>();

    int z = query.getPrecursorCharge();
    proteinMass = (query.getPrecursorMZ() * z) - (z * Constants.PROTON_MASS); // Neutral mass
    // String title = query.getTitle();

    TDoubleDoubleMap massToIntensity2dp =
        new TDoubleDoubleHashMap(); // This is for checking if we have duplication - use the mass at
                                    // 4dp with higher intensity, add intensity

    PeakList peakList =
        new PeakList(query.getPeakList()); // Convert Map<Double, Double> to TDoubleDoubleMap

    // Work on the top number
    TDoubleDoubleMap topNPeakList = peakList.getIntensePeaks(number);

    prmSpectrum.add(
        new PRMPeak(Double.parseDouble(df.format(0.0)), 50.0, 0)); // origin 0.0, forward
    prmSpectrum.add(
        new PRMPeak(
            Double.parseDouble(df.format(Constants.CTERM + Constants.HYDROGEN_MASS)),
            50.0,
            1)); // origin C term group needed for finding y ion series, reverse
    prmSpectrum.add(
        new PRMPeak(
            Double.parseDouble(df.format(proteinMass)), 50.0, 1)); // last y ion mass, reverse

    // Todo: check the following to FOR statements. What if pepMass=2500, mz=1250, then the
    // intensity at 1250 will be double counted?
    // Todo: It seems that the intensity will not be used in the output result.
    // first test for duplicate peaks, and include higher intensity ones
    // the mass in the peaklist is de-charged mass
    // Create forward PRM peak list
    for (double mz : topNPeakList.keys()) {

      // Todo: check if mz is +1 charged or other possible charged
      // Calculate mz (from mgf) and take the decimal formate set in df
      double decimalFormatMass = Double.parseDouble(df.format(mz - Constants.PROTON_MASS));

      // Get intensity value of mz
      double intensity = Double.parseDouble(df.format(topNPeakList.get(mz)));

      PRMPeak tempPeak = new PRMPeak(decimalFormatMass);
      // index of the first occurrence of the tempPeak in prmSpectrum, -1 if prmSpectrum doesn't
      // contain the element.
      int ind = prmSpectrum.indexOf(tempPeak);
      double newIntensity = 50.0;
      if (ind != -1) {
        // get the specific PRM peak by removing it from prmSpectrum
        PRMPeak rmPeak = prmSpectrum.remove(ind);
        double oldIntensity = rmPeak.getIntensity();
        newIntensity = oldIntensity + intensity;
      }

      prmSpectrum.add(
          new PRMPeak(
              decimalFormatMass, newIntensity, 0)); // Direction should be always 0 at this stage
    }

    // Now get the inverse mzs and check we are not duplicating
    // Create reverse PRM peak list
    for (double mz : topNPeakList.keys()) {

      // Calculate mz (from mgf) and take the decimal formate set in df
      double inverseFormatMass =
          Double.parseDouble(df.format(proteinMass - (mz - Constants.PROTON_MASS)));

      // Get intensity value of mz
      double intensity = Double.parseDouble(df.format(topNPeakList.get(mz)));

      if (massToIntensity2dp.containsKey(inverseFormatMass)) {
        intensity += massToIntensity2dp.get(inverseFormatMass);
      }
      PRMPeak tempPeak = new PRMPeak(inverseFormatMass);
      // index of the first occurrence of the tempPeak in prmSpectrum, -1 if prmSpectrum doesn't
      // contain the element.
      int ind = prmSpectrum.indexOf(tempPeak);
      double newIntensity = 50.0;
      if (ind != -1) {
        PRMPeak oldPeak = prmSpectrum.remove(ind);
        if (oldPeak.getDirection()
            != 1) { // if the direction of oldPeak is not reverse (it could be either 2 or 0), then
                    // new direction will be both (value 2).
          tempPeak.setDirection(2);
        } else {
          tempPeak.setDirection(1); // unneccessary?
        }
        double oldIntensity = oldPeak.getIntensity();
        newIntensity = oldIntensity + intensity;
      }

      prmSpectrum.add(new PRMPeak(inverseFormatMass, newIntensity, tempPeak.getDirection()));
    }

    Collections.sort(prmSpectrum, MASS_DESCENDING);
  }