private void computeLCMs() { final ChemicalElement first = weights.get(0); first.setL(1); first.setLcm(first.getIntegerMass()); for (int i = 1; i < weights.size(); i++) { final ChemicalElement weight = weights.get(i); int temp = first.getIntegerMass() / gcd(first.getIntegerMass(), weight.getIntegerMass()); weight.setL(temp); weight.setLcm(temp * weight.getIntegerMass()); } }
private void afterFindingADecomposition() { if (minValues != null) { for (int j = 0; j < minValues.length; ++j) { buffer[j] -= minValues[j]; } } ++i; // "return" from recursion flagWhile = true; // in this recursion-depth we are in the while-loop, cause the next recursion (the one we just exited) was called m[i - 1] -= weights.get(i).getLcm(); // execute the rest of the while buffer[i] += weights.get(i).getL(); }
private void discretizeMasses() { // compute integer masses for (final ChemicalElement weight : weights) { weight.setIntegerMass((int) (weight.getMass() / precision)); } }
m[i - 1] -= weights.get(i).getLcm(); // execute the rest of the while buffer[i] += weights.get(i).getL(); } else { if (flagWhile) { if (j[i] < weights.get(i).getL() && m[i] - j[i] * weights.get(i).getIntegerMass() >= 0) { buffer[i] = j[i]; m[i - 1] = m[i] - j[i] * weights.get(i).getIntegerMass(); r[i] = m[i - 1] % a; m[i - 1] -= weights.get(i).getLcm(); // execute the rest of the while buffer[i] += weights.get(i).getL();
private void computeErrors() { this.minError = 0d; this.maxError = 0d; for (ChemicalElement weight : weights) { final double error = (precision * weight.getIntegerMass() - weight.getMass()) / weight.getMass(); minError = Math.min(minError, error); maxError = Math.max(maxError, error); } }
private void divideByGCD() { if (weights.size() > 0) { int d = gcd(weights.get(0).getIntegerMass(), weights.get(1).getIntegerMass()); for (int i = 2; i < weights.size(); ++i) { d = gcd(d, weights.get(i).getIntegerMass()); if (d == 1) return; } precision *= d; for (ChemicalElement weight : weights) { weight.setIntegerMass(weight.getIntegerMass() / d); } } }
/** * @param allowedIsotopes array of the elements of the alphabet */ RangeMassDecomposer(IIsotope[] allowedIsotopes) { this.ERTs = null; this.precision = findOptimalPrecision(); final int n = allowedIsotopes.length; this.weights = new ArrayList<>(n); this.elements = new IIsotope[allowedIsotopes.length]; for (IIsotope allowedIsotope : allowedIsotopes) { weights.add(new ChemicalElement(allowedIsotope, allowedIsotope.getExactMass())); } Collections.sort(weights); for (int i = 0; i < n; ++i) { elements[i] = weights.get(i).getOwner(); } }
if (boundaries != null) { for (int i = 0; i < boundsarray.length; i++) { IIsotope el = weights.get(i).getOwner(); int max = boundaries.getIsotopeCountMax(el); int min = boundaries.getIsotopeCountMin(el); minValues[i] = min; if (minValues[i] > 0) { final double reduceWeightBy = weights.get(i).getMass() * min; cfrom -= reduceWeightBy; cto -= reduceWeightBy;
DecompIterator(int[][] ERT, int minIntegerMass, int maxIntegerMass, double minDoubleMass, double maxDoubleMass, int[] minValues, int[] maxValues, List<ChemicalElement> weights) { this.ERT = ERT; this.minDoubleMass = minDoubleMass; this.maxDoubleMass = maxDoubleMass; this.buffer = new int[weights.size()]; if (minValues != null) { boolean allZero = true; for (int k : minValues) if (k > 0) allZero = false; if (!allZero) this.minValues = minValues; else this.minValues = null; } else this.minValues = null; this.maxValues = maxValues; this.weights = weights; k = weights.size(); j = new int[k]; m = new int[k]; lbound = new int[k]; r = new int[k]; flagWhile = false; // flag whether we are in the while-loop or not a = weights.get(0).getIntegerMass(); // Init for (int i = 1; i < k; ++i) { lbound[i] = Integer.MAX_VALUE; // this is just to ensure, that lbound < m in the first iteration } i = k - 1; m[i] = maxIntegerMass; // m[i] corresponds to M, m[i-1] ^= m this.rewind = false; this.deviation = maxIntegerMass - minIntegerMass; this.ERTdev = Integer.highestOneBit(deviation); }
IIsotope getCharacterAt(int index) { return weights.get(index).getOwner(); } }
private boolean checkCompomere() { if (minValues != null) { for (int j = 0; j < minValues.length; ++j) { buffer[j] += minValues[j]; } } // calculate mass of decomposition double exactMass = 0; for (int j = 0; j < buffer.length; ++j) { exactMass += buffer[j] * weights.get(j).getMass(); } return exactMass >= minDoubleMass && exactMass <= maxDoubleMass; }
private void calcERT() { int firstLongVal = weights.get(0).getIntegerMass(); int[][] ERT = new int[firstLongVal][weights.size()]; int d, r, n, argmin; d = gcd(firstLongVal, weights.get(j).getIntegerMass()); for (int p = 0; p < d; p++) { // Need to start d Round Robin loops if (p == 0) { n += weights.get(j).getIntegerMass(); if (n < 0) { throw new ArithmeticException("Integer overflow occurs. DECOMP cannot calculate decompositions for the given alphabet as it exceeds the 32 bit integer space. Please use a smaller precision value.");
/** * This method does not work for Round Robin as the algorithm only enumerates formulas which really have the * searched mass range (except for false positives due to rounding errors). As the exact number of molecular formulas * with a given mass is unknown (calculating it is as expensive as enumerating them) there is no way to give a * progress number. Therefore, the method returns just 0 if it's enumerating and 1 if it's done. */ @Override public double getFinishedPercentage() { if (done) return 1d; final int[] lastDecomposition = this.lastDecomposition; if (lastDecomposition == null) return 0; double result = 0.0; double remainingPerc = 1.0; for (int i = lastDecomposition.length - 1; i >= 0; i--) { double max = mfRange.getIsotopeCountMax(decomposer.weights.get(i).getOwner()); if (i > 0) max += 1.0; result += remainingPerc * ((double) lastDecomposition[i] / max); remainingPerc /= max; } return result; }
/** * Check if a mass is decomposable. This is done in constant time (especially: it is very very very fast!). * But it doesn't check if there is a valid decomposition. Therefore, even if the method returns true, * all decompositions may be invalid for the given validator or given bounds. * #decompose(mass) uses this function before starting the decomposition, therefore this method should only * be used if you don't want to start the decomposition algorithm. * * @return true if the mass is decomposable, ignoring bounds or any additional filtering rule */ boolean maybeDecomposable(double from, double to) { init(); final int[][][] ERTs = this.ERTs; final int[] minmax = new int[2]; //normal version seems to be faster, because it returns after first hit integerBound(from, to, minmax); final int a = weights.get(0).getIntegerMass(); for (int i = minmax[0]; i <= minmax[1]; ++i) { final int r = i % a; if (i >= ERTs[0][r][weights.size() - 1]) return true; } return false; }