/** * Resolve a sequence of ties, using the configured {@link TiesStrategy}. The input <code>ranks * </code> array is expected to take the same value for all indices in <code>tiesTrace</code>. The * common value is recoded according to the tiesStrategy. For example, if ranks = * <5,8,2,6,2,7,1,2>, tiesTrace = <2,4,7> and tiesStrategy is MINIMUM, ranks will be unchanged. * The same array and trace with tiesStrategy AVERAGE will come out <5,8,3,6,3,7,1,3>. * * @param ranks array of ranks * @param tiesTrace list of indices where <code>ranks</code> is constant -- that is, for any i and * j in TiesTrace, <code> ranks[i] == ranks[j] * </code> */ private void resolveTie(double[] ranks, List<Integer> tiesTrace) { // constant value of ranks over tiesTrace final double c = ranks[tiesTrace.get(0)]; // length of sequence of tied ranks final int length = tiesTrace.size(); switch (tiesStrategy) { case AVERAGE: // Replace ranks with average fill(ranks, tiesTrace, (2 * c + length - 1) / 2d); break; case MAXIMUM: // Replace ranks with maximum values fill(ranks, tiesTrace, c + length - 1); break; case MINIMUM: // Replace ties with minimum fill(ranks, tiesTrace, c); break; case RANDOM: // Fill with random integral values in [c, c + length - 1] Iterator<Integer> iterator = tiesTrace.iterator(); long f = FastMath.round(c); while (iterator.hasNext()) { // No advertised exception because args are guaranteed valid ranks[iterator.next()] = randomData.nextLong(f, f + length - 1); } break; case SEQUENTIAL: // Fill sequentially from c to c + length - 1 // walk and fill iterator = tiesTrace.iterator(); f = FastMath.round(c); int i = 0; while (iterator.hasNext()) { ranks[iterator.next()] = f + i++; } break; default: // this should not happen unless TiesStrategy enum is changed throw new MathInternalError(); } }
/** * Create the objects needed for linear transformation. * * <p>Each {@link org.orekit.propagation.semianalytical.dsst.utilities.hansenHansenTesseralLinear * HansenTesseralLinear} uses a fixed value for s and j. Since j varies from -maxJ to +maxJ and s * varies from -maxDegree to +maxDegree, a 2 * maxDegree + 1 x 2 * maxJ + 1 matrix of objects * should be created. The size of this matrix can be reduced by taking into account the expression * (2.7.3-2). This means that is enough to create the objects for positive values of j and all * values of s. * * @param meanOnly create only the objects required for the mean contribution */ private void createHansenObjects(final boolean meanOnly) { // Allocate the two dimensional array this.hansenObjects = new HansenTesseralLinear[2 * maxDegree + 1][jMax + 1]; if (meanOnly) { // loop through the resonant orders for (int m : resOrders) { // Compute the corresponding j term final int j = FastMath.max(1, (int) FastMath.round(ratio * m)); // Compute the sMin and sMax values final int sMin = FastMath.min(maxEccPow - j, maxDegree); final int sMax = FastMath.min(maxEccPow + j, maxDegree); // loop through the s values for (int s = 0; s <= sMax; s++) { // Compute the n0 value final int n0 = FastMath.max(FastMath.max(2, m), s); // Create the object for the pair j,s this.hansenObjects[s + maxDegree][j] = new HansenTesseralLinear(maxDegree, s, j, n0, maxHansen); if (s > 0 && s <= sMin) { // Also create the object for the pair j, -s this.hansenObjects[maxDegree - s][j] = new HansenTesseralLinear(maxDegree, -s, j, n0, maxHansen); } } } } else { // create all objects for (int j = 0; j <= jMax; j++) { for (int s = -maxDegree; s <= maxDegree; s++) { // Compute the n0 value final int n0 = FastMath.max(2, FastMath.abs(s)); this.hansenObjects[s + maxDegree][j] = new HansenTesseralLinear(maxDegree, s, j, n0, maxHansen); } } } }
/** * Get the resonant and non-resonant tesseral terms in the central body spherical harmonic field. * * @param resonantOnly extract only resonant terms */ private void getResonantAndNonResonantTerms(final boolean resonantOnly) { // Compute natural resonant terms final double tolerance = 1. / FastMath.max(MIN_PERIOD_IN_SAT_REV, MIN_PERIOD_IN_SECONDS / orbitPeriod); // Search the resonant orders in the tesseral harmonic field resOrders.clear(); nonResOrders.clear(); for (int m = 1; m <= maxOrder; m++) { final double resonance = ratio * m; int jRes = 0; final int jComputedRes = (int) FastMath.round(resonance); if (jComputedRes > 0 && jComputedRes <= jMax && FastMath.abs(resonance - jComputedRes) <= tolerance) { // Store each resonant index and order resOrders.add(m); jRes = jComputedRes; } if (!resonantOnly && !mDailiesOnly && m <= maxOrderTesseralSP) { // compute non resonant orders in the tesseral harmonic field final List<Integer> listJofM = new ArrayList<Integer>(); // for the moment we take only the pairs (j,m) with |j| <= maxDegree + maxEccPow (from |s-j| // <= maxEccPow and |s| <= maxDegree) for (int j = -jMax; j <= jMax; j++) { if (j != 0 && j != jRes) { listJofM.add(j); } } nonResOrders.put(m, listJofM); } } }
/** * Computes the potential U derivatives. * * <p>The following elements are computed from expression 3.3 - (4). * * <pre> * dU / da * dU / dh * dU / dk * dU / dλ * dU / dα * dU / dβ * dU / dγ * </pre> * * @param date current date * @return potential derivatives * @throws OrekitException if an error occurs */ private double[] computeUDerivatives(final AbsoluteDate date) throws OrekitException { // Potential derivatives double dUda = 0.; double dUdh = 0.; double dUdk = 0.; double dUdl = 0.; double dUdAl = 0.; double dUdBe = 0.; double dUdGa = 0.; // Compute only if there is at least one resonant tesseral if (!resOrders.isEmpty()) { // Gmsj and Hmsj polynomials final GHmsjPolynomials ghMSJ = new GHmsjPolynomials(k, h, alpha, beta, I); // GAMMAmns function final GammaMnsFunction gammaMNS = new GammaMnsFunction(fact, gamma, I); // R / a up to power degree final double[] roaPow = new double[maxDegree + 1]; roaPow[0] = 1.; for (int i = 1; i <= maxDegree; i++) { roaPow[i] = roa * roaPow[i - 1]; } // SUM over resonant terms {j,m} for (int m : resOrders) { // Resonant index for the current resonant order final int j = FastMath.max(1, (int) FastMath.round(ratio * m)); // Phase angle final double jlMmt = j * lm - m * theta; final double sinPhi = FastMath.sin(jlMmt); final double cosPhi = FastMath.cos(jlMmt); // Potential derivatives components for a given resonant pair {j,m} double dUdaCos = 0.; double dUdaSin = 0.; double dUdhCos = 0.; double dUdhSin = 0.; double dUdkCos = 0.; double dUdkSin = 0.; double dUdlCos = 0.; double dUdlSin = 0.; double dUdAlCos = 0.; double dUdAlSin = 0.; double dUdBeCos = 0.; double dUdBeSin = 0.; double dUdGaCos = 0.; double dUdGaSin = 0.; // s-SUM from -sMin to sMax final int sMin = FastMath.min(maxEccPow - j, maxDegree); final int sMax = FastMath.min(maxEccPow + j, maxDegree); for (int s = 0; s <= sMax; s++) { // Compute the initial values for Hansen coefficients using newComb operators this.hansenObjects[s + maxDegree][j].computeInitValues(e2, chi, chi2); // n-SUM for s positive final double[][] nSumSpos = computeNSum(date, j, m, s, maxDegree, roaPow, ghMSJ, gammaMNS); dUdaCos += nSumSpos[0][0]; dUdaSin += nSumSpos[0][1]; dUdhCos += nSumSpos[1][0]; dUdhSin += nSumSpos[1][1]; dUdkCos += nSumSpos[2][0]; dUdkSin += nSumSpos[2][1]; dUdlCos += nSumSpos[3][0]; dUdlSin += nSumSpos[3][1]; dUdAlCos += nSumSpos[4][0]; dUdAlSin += nSumSpos[4][1]; dUdBeCos += nSumSpos[5][0]; dUdBeSin += nSumSpos[5][1]; dUdGaCos += nSumSpos[6][0]; dUdGaSin += nSumSpos[6][1]; // n-SUM for s negative if (s > 0 && s <= sMin) { // Compute the initial values for Hansen coefficients using newComb operators this.hansenObjects[maxDegree - s][j].computeInitValues(e2, chi, chi2); final double[][] nSumSneg = computeNSum(date, j, m, -s, maxDegree, roaPow, ghMSJ, gammaMNS); dUdaCos += nSumSneg[0][0]; dUdaSin += nSumSneg[0][1]; dUdhCos += nSumSneg[1][0]; dUdhSin += nSumSneg[1][1]; dUdkCos += nSumSneg[2][0]; dUdkSin += nSumSneg[2][1]; dUdlCos += nSumSneg[3][0]; dUdlSin += nSumSneg[3][1]; dUdAlCos += nSumSneg[4][0]; dUdAlSin += nSumSneg[4][1]; dUdBeCos += nSumSneg[5][0]; dUdBeSin += nSumSneg[5][1]; dUdGaCos += nSumSneg[6][0]; dUdGaSin += nSumSneg[6][1]; } } // Assembly of potential derivatives componants dUda += cosPhi * dUdaCos + sinPhi * dUdaSin; dUdh += cosPhi * dUdhCos + sinPhi * dUdhSin; dUdk += cosPhi * dUdkCos + sinPhi * dUdkSin; dUdl += cosPhi * dUdlCos + sinPhi * dUdlSin; dUdAl += cosPhi * dUdAlCos + sinPhi * dUdAlSin; dUdBe += cosPhi * dUdBeCos + sinPhi * dUdBeSin; dUdGa += cosPhi * dUdGaCos + sinPhi * dUdGaSin; } dUda *= -moa / a; dUdh *= moa; dUdk *= moa; dUdl *= moa; dUdAl *= moa; dUdBe *= moa; dUdGa *= moa; } return new double[] {dUda, dUdh, dUdk, dUdl, dUdAl, dUdBe, dUdGa}; }
public void process(String mgfFile, PeakProcessorChain<PeakAnnotation> aChain, double scoreLimit) throws IOException { MgfReader reader = new MgfReader(new File(mgfFile)); String core = FilePathUtil.removeExtension(mgfFile); PrintWriter log = new PrintWriter(core + "_log.csv"); log.println("Scan1,Mz1,Charge1,Scan2,Mz2,Charge2,DeltaCount,NewMz,PeakCount,FilterPeakCount"); MgfWriter writer = new MgfWriter(new File(core + "_pair.mgf")); List<MsnSpectrum> specList = loadMgf(reader, aChain); PeakListExtractor extractor = new PeakListExtractor(iMs2Tol); HashMap<Integer, SpectrumSpectrumMatch> map = new HashMap<>(); double labelDelta = iHeavyMod.getMolecularMass() - iLightMod.getMolecularMass(); double maxDelta = labelDelta * iMaxModCount; for (int lId = 0; lId < specList.size(); lId++) { MsnSpectrum lSpec = specList.get(lId); Peak lPeak = lSpec.getPrecursor(); for (int hId = lId + 1; hId < specList.size(); hId++) { MsnSpectrum hSpec = specList.get(hId); Peak hPeak = hSpec.getPrecursor(); double delta = hPeak.getMass() - lPeak.getMass(); if (iMs1Tol.check(maxDelta, delta).equals(Location.LARGER)) break; if (iMs1Tol.check(labelDelta, delta).equals(Location.SMALLER)) continue; if (iChargeTol.isPresent()) { int deltaE = iChargeTol.get(); int lightE = lPeak.getCharge(); int heavyE = hPeak.getCharge(); if (Math.abs(lightE - heavyE) > deltaE) break; } if (iIntensityTol.isPresent()) { double deltaIn = iIntensityTol.get(); double lightI = lPeak.getIntensity(); double heavyI = hPeak.getIntensity(); if (Math.abs(Math.log(lightI / heavyI)) > Math.log(deltaIn)) break; } if (iTimeTol.isPresent()) { double lightT = lSpec.getRetentionTimes().getFirst().getTime(); double heavyT = hSpec.getRetentionTimes().getFirst().getTime(); int deltaTime = iTimeTol.get(); if (Math.abs(lightT - heavyT) > deltaTime) break; } for (int mCount = iMaxModCount; mCount > 0; mCount--) { if (!iMs1Tol.withinTolerance(mCount * labelDelta, delta)) continue; double lBaseIn = lSpec.getBasePeakIntensity(); double hBaseIn = hSpec.getBasePeakIntensity(); MsnSpectrum lFilterSpec = lSpec.copy(new ThresholdFilter<>(lBaseIn * 0.01)); MsnSpectrum hFilterSpec = hSpec.copy(new ThresholdFilter<>(hBaseIn * 0.01)); HashMap<Integer, Integer> filterMatch = extractor.getMatchPeaks(lFilterSpec, hFilterSpec, labelDelta, mCount); if (filterMatch.size() < scoreLimit) break; HashMap<Integer, Integer> pairPeaksIndex = extractor.getMatchPeaks(lSpec, hSpec, labelDelta, mCount); MsnSpectrum peaks = new MsnSpectrum(); for (Entry<Integer, Integer> entry : pairPeaksIndex.entrySet()) { double lightMz = lSpec.getMz(entry.getKey()); double heavyMz = hSpec.getMz(entry.getValue()); double intensity = lSpec.getIntensity(entry.getKey()); int count = (int) (FastMath.round((heavyMz - lightMz) / labelDelta)); if (count != 0) { lightMz = lightMz - count * iLightMod.getMolecularMass(); } peaks.add(lightMz, intensity); } double newMz = lPeak.getMz() - mCount * iLightMod.getMolecularMass() / lPeak.getCharge(); Peak rPeak = Peak.noIntensity(newMz, lPeak.getCharge()); peaks.setPrecursor(rPeak); log.print(lSpec.getScanNumbers().getFirst().getValue() + ","); log.print(lPeak.getMz() + ","); log.print(lPeak.getCharge() + ","); log.print(hSpec.getScanNumbers().getFirst().getValue() + ","); log.print(hPeak.getMz() + ","); log.print(hPeak.getCharge() + ","); log.print(mCount + ","); log.print(newMz + ","); log.print(pairPeaksIndex.size() + ","); log.print(filterMatch.size() + "\n"); SpectrumSpectrumMatch aMatch = new SpectrumSpectrumMatch(lSpec.getComment(), hSpec.getComment()); aMatch.setFirstPrecursorPeak(lPeak); aMatch.setSecondPrecursorPeak(hPeak); aMatch.setFirstRetentionTime(lSpec.getRetentionTimes().getFirst()); aMatch.setSecondRetentionTime(hSpec.getRetentionTimes().getFirst()); aMatch.setFirstScanNumber(lSpec.getScanNumbers().getFirst()); aMatch.setSecondScanNumber(hSpec.getScanNumbers().getFirst()); aMatch.setCommonPeaks(peaks); aMatch.setLabelDelta(mCount); aMatch.setMatchCount(peaks.size()); if (map.containsKey(lId)) { SpectrumSpectrumMatch spectrumSpectrumMatch = map.get(lId); if (spectrumSpectrumMatch.getMatchCount() < peaks.size()) { map.put(lId, aMatch); } } else { map.put(lId, aMatch); } break; } } } for (SpectrumSpectrumMatch match : map.values()) { MsnSpectrum spec = match.getCommonPeaks(); spec.setComment(String.valueOf(match.getLabelDelta().get())); spec.addScanNumber(match.getFirstScanNumber()); spec.addScanNumber(match.getSecondScanNumber()); spec.addRetentionTime(match.getFirstRetentionTime()); spec.addRetentionTime(match.getSecondRetentionTime()); writer.write(spec); } writer.close(); log.close(); }