From 12731b5a7264e0a67a0d9880a7504804f83c0939 Mon Sep 17 00:00:00 2001 From: Jules Jacobsen Date: Tue, 13 Feb 2024 10:09:56 +0000 Subject: [PATCH] Alter Frequency to be able to represent both percentage frequency values and fractional frequencies i.e. AF = AC/AN with a hom count. Alter FrequencyData to work with Frequency for representing AF, AC, AN and HOM counts Alter FrequencyData 'get' prefixed methods to remove the 'get' e.g. getMaxFreqForPopulation() is now maxFreqForPopulation(), getScore() -> frequencyScore(), frequencyData.getKnownFrequencies() -> frequencyData.frequencies() --- .../util/InheritanceModeAnnotator.java | 4 +- .../util/acmg/Acmg2015EvidenceAssigner.java | 4 +- .../core/genome/dao/SvFrequencyDao.java | 2 +- .../core/model/AlleleProtoAdaptor.java | 12 +- .../core/model/VariantEvaluation.java | 2 +- .../core/model/frequency/Frequency.java | 77 ++++-- .../core/model/frequency/FrequencyData.java | 230 +++++++++--------- .../core/writers/TsvVariantResultsWriter.java | 10 +- .../src/main/resources/templates/results.html | 8 +- .../filters/FrequencyDataProviderTest.java | 4 +- .../core/genome/TestVariantDataService.java | 4 +- .../genome/VariantFactoryPerformanceTest.java | 2 +- .../genome/dao/ClinVarDaoMvStoreTest.java | 2 +- .../genome/dao/FrequencyDaoMvStoreTest.java | 6 +- .../core/model/AlleleProtoAdaptorTest.java | 25 +- .../model/frequency/FrequencyDataTest.java | 120 +++++---- .../core/model/frequency/FrequencyTest.java | 26 +- .../src/main/resources/templates/results.html | 8 +- 18 files changed, 317 insertions(+), 229 deletions(-) diff --git a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/analysis/util/InheritanceModeAnnotator.java b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/analysis/util/InheritanceModeAnnotator.java index da9c862d0..413eacdd7 100644 --- a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/analysis/util/InheritanceModeAnnotator.java +++ b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/analysis/util/InheritanceModeAnnotator.java @@ -150,10 +150,10 @@ private List getCompatibleVariantsUnderFrequencyThreshold(Lis // float maxFreq = frequencyData.maxFreqIgnoring(Set.of(LOCAL, ESP)) // float maxFreq = frequencyData.maxFreqFrom(Set.of(LOCAL, ESP)) FrequencyData frequencyData = variantEvaluation.getFrequencyData(); - if (frequencyData.getMaxFreq() <= maxFreqForMode || variantEvaluation.isWhiteListed()) { + if (frequencyData.maxFreq() <= maxFreqForMode || variantEvaluation.isWhiteListed()) { compatibleVariants.add(variantEvaluation); } else { - logger.debug("FAIL variant freq {} >= {} (maxFreq for MOI) {}", frequencyData.getMaxFreq(), maxFreqForMode, variantEvaluation); + logger.debug("FAIL variant freq {} >= {} (maxFreq for MOI) {}", frequencyData.maxFreq(), maxFreqForMode, variantEvaluation); } } return compatibleVariants; diff --git a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/analysis/util/acmg/Acmg2015EvidenceAssigner.java b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/analysis/util/acmg/Acmg2015EvidenceAssigner.java index 653aa9856..410aae62e 100644 --- a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/analysis/util/acmg/Acmg2015EvidenceAssigner.java +++ b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/analysis/util/acmg/Acmg2015EvidenceAssigner.java @@ -134,7 +134,7 @@ public AcmgEvidence assignVariantAcmgEvidence(VariantEvaluation variantEvaluatio // AlleleProto.AlleleKey alleleKey = AlleleProtoAdaptor.toAlleleKey(variantEvaluation); AlleleProto.AlleleKey alleleKey = variantEvaluation.alleleKey(); boolean isBa1ExcludedVariant = variantEvaluation.getGenomeAssembly() == GenomeAssembly.HG19 ? HG19_BA1_EXCLUSION_VARIANTS.contains(alleleKey) : HG38_BA1_EXCLUSION_VARIANTS.contains(alleleKey); - if (!isBa1ExcludedVariant && frequencyData.getMaxFreqForPopulation(FrequencySource.NON_FOUNDER_POPS) >= 5.0) { + if (!isBa1ExcludedVariant && frequencyData.maxFreqForPopulation(FrequencySource.NON_FOUNDER_POPS) >= 5.0) { acmgEvidenceBuilder.add(BA1); // BA1 is supposed to be used as a filtering criterion where no other evidence need be considered. return acmgEvidenceBuilder.build(); @@ -436,7 +436,7 @@ private void assignPM2(AcmgEvidence.Builder acmgEvidenceBuilder, FrequencyData f // allow local frequency occurrences as these are unverifiable as to their size or content. Also do not use isRepresentedInDatabase() // as this will exclude anything with an rsID which could be a ClinVar variant not seen in any population database. boolean absentFromDatabase = frequencyData.isEmpty() || (frequencyData.size() == 1 && frequencyData.containsFrequencySource(FrequencySource.LOCAL)); - boolean atVeryLowFrequencyIfRecessive = modeOfInheritance.isRecessive() && frequencyData.getMaxFreqForPopulation(FrequencySource.NON_FOUNDER_POPS) < 0.01f; + boolean atVeryLowFrequencyIfRecessive = modeOfInheritance.isRecessive() && frequencyData.maxFreqForPopulation(FrequencySource.NON_FOUNDER_POPS) < 0.01f; if (absentFromDatabase || atVeryLowFrequencyIfRecessive) { acmgEvidenceBuilder.add(PM2, Evidence.SUPPORTING); } diff --git a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/genome/dao/SvFrequencyDao.java b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/genome/dao/SvFrequencyDao.java index b073d261c..79ce139b2 100644 --- a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/genome/dao/SvFrequencyDao.java +++ b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/genome/dao/SvFrequencyDao.java @@ -96,7 +96,7 @@ private FrequencyData mapToFrequencyData(List topMatches) { } SvResult first = topMatches.get(0); Frequency frequency = toFrequency(first); - if (first.an < 10 || frequency.getFrequency() == 0) { + if (first.an < 10 || frequency.frequency() == 0) { // Don't report poorly defined frequencies return FrequencyData.of(first.id()); } diff --git a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/AlleleProtoAdaptor.java b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/AlleleProtoAdaptor.java index 22541b9aa..d9e12d579 100644 --- a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/AlleleProtoAdaptor.java +++ b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/AlleleProtoAdaptor.java @@ -130,9 +130,15 @@ private static void parseFrequencyData(FrequencyData.Builder frequencyDataBuilde for (int i = 0; i < freqsCount; i++) { AlleleProto.Frequency frequency = alleleProperties.getFrequencies(i); var freqSource = toFreqSource(frequency.getFrequencySource()); - var freq = Frequency.percentageFrequency(frequency.getAc(), frequency.getAn()); - var hom = frequency.getHom(); - frequencyDataBuilder.addFrequency(freqSource, freq, hom); + int an = frequency.getAn(); + if (an == 0) { + float af = frequency.getFrequency(); + frequencyDataBuilder.addFrequency(freqSource, af); + } else { + int ac = frequency.getAc(); + int hom = frequency.getHom(); + frequencyDataBuilder.addFrequency(freqSource, ac, an, hom); + } } } diff --git a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/VariantEvaluation.java b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/VariantEvaluation.java index 5bbd57336..b2b82e94a 100644 --- a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/VariantEvaluation.java +++ b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/VariantEvaluation.java @@ -356,7 +356,7 @@ public float getVariantScore() { * @return a score between 0 and 1 */ public float getFrequencyScore() { - return whiteListed ? 1f : frequencyData.getScore(); + return whiteListed ? 1f : frequencyData.frequencyScore(); } /** diff --git a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/frequency/Frequency.java b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/frequency/Frequency.java index e4c1e83f7..3cfb51d33 100644 --- a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/frequency/Frequency.java +++ b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/frequency/Frequency.java @@ -36,62 +36,93 @@ public class Frequency { private final FrequencySource source; private final float value; + private final int ac; + private final int an; + private final int homs; public static Frequency of(FrequencySource source, float value) { - return new Frequency(source, value); + return new Frequency(source, value, 0, 0, 0); } - private Frequency(FrequencySource source, float value) { + public static Frequency of(FrequencySource source, int ac, int an, int homs) { + if (an <= 0 || ac > an || homs > ac) { + throw new IllegalArgumentException(source + " AN must be > 0, AC must be < AN and HOM must be < AC. Got AC=" + ac + ", AN=" + an + ", hom=" + homs); + } + return new Frequency(source, percentageFrequency(ac, an), ac, an, homs); + } + + // package private to work with FrequencyData *ONLY* where allele frequency has already been calculated and input + // values have already been validated + static Frequency of(FrequencySource source, float af, int ac, int an, int homs) { + return new Frequency(source, af, ac, an, homs); + } + + private Frequency(FrequencySource source, float value, int ac, int an, int homs) { this.source = source; this.value = value; + this.ac = ac; + this.an = an; + this.homs = homs; + } + + public FrequencySource source() { + return source; } - public float getFrequency() { + public float frequency() { return value; } - public FrequencySource getSource() { - return source; + public int ac() { + return ac; + } + + public int an() { + return an; + } + + public int homs() { + return homs; } - + public boolean isOverThreshold(float threshold) { return value > threshold; } /** - * Returns the frequency of ac/an as a percentage value. + * Returns the frequency of ac/an as a percentage frequency. * * @param ac Allele Count - the number of observed alleles. * @param an Allele Number - size of the population in which the AC was observed. - * @return the frequency of ac/an as a percentage value in the range 0..100 + * @return the frequency of ac/an as a percentage frequency in the range 0..100 */ public static float percentageFrequency(int ac, int an) { return 100f * (ac / (float) an); } + @Override - public int hashCode() { - return Objects.hash(source, value); + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Frequency frequency = (Frequency) o; + return Float.compare(value, frequency.value) == 0 && ac == frequency.ac && an == frequency.an && homs == frequency.homs && source == frequency.source; } @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Frequency)) { - return false; - } - Frequency other = (Frequency) o; - if (source != other.source) { - return false; - } - return Float.compare(other.value, value) == 0; + public int hashCode() { + return Objects.hash(source, value, ac, an, homs); } + @Override public String toString() { - return "Frequency{" + source + "=" + value + '}'; + return "Frequency{" + source + + '=' + value + (an > 0 ? formatAcAn() : "") + + '}'; } + private String formatAcAn() { + return "(" + ac + '|' + an + '|' + homs + ')'; + } } diff --git a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyData.java b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyData.java index 0ef1238f5..d0142b355 100644 --- a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyData.java +++ b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyData.java @@ -36,15 +36,17 @@ public class FrequencyData { private static final String VCF_EMPTY_VALUE = "."; - private static final FrequencyData EMPTY_DATA = new FrequencyData("", List.of()); + private static final FrequencyData EMPTY_DATA = new FrequencyData("", new FrequencySource[0], new float[0]); private static final int NUM_FREQ_SOURCES = FrequencySource.values().length; // offsets for data array // [SOURCE, SOURCE, SOURCE] - // [FREQ, HOM, FREQ, HOM, FREQ, HOM] - private static final int WORD_SIZE = 2; + // [AF, AC, AN, HOM, AF, AC, AN, HOM, AF, AC, AN, HOM] + private static final int WORD_SIZE = 4; private static final int FREQ_OFFSET = 0; - private static final int HOM_OFFSET = 1; + private static final int AC_OFFSET = 1; + private static final int AN_OFFSET = 2; + private static final int HOM_OFFSET = 3; private static final float VERY_RARE_SCORE = 1f; private static final float NOT_RARE_SCORE = 0f; @@ -54,13 +56,14 @@ public class FrequencyData { private final int size; private final FrequencySource[] sources; private final float[] data; + private final int maxSource; - public static FrequencyData of(String rsId, Collection frequencies) { - return validate(rsId, frequencies); + public static FrequencyData empty() { + return EMPTY_DATA; } public static FrequencyData of(Collection frequencies) { - return validate("", frequencies); + return of("", frequencies); } public static FrequencyData of(String rsId, Frequency frequency) { @@ -79,72 +82,45 @@ public static FrequencyData of(Frequency frequency) { return of(List.of(frequency)); } - public static FrequencyData empty() { - return EMPTY_DATA; - } - - private static FrequencyData validate(String rsId, Collection frequencies) { + public static FrequencyData of(String rsId, Collection frequencies) { Objects.requireNonNull(frequencies, "frequency data cannot be null"); - if (isEmptyValue(rsId) && frequencies.isEmpty()) { + String rsIdValue = isEmptyValue(rsId) ? "" : rsId; + if (rsIdValue.isEmpty() && frequencies.isEmpty()) { return FrequencyData.empty(); } - + Builder builder = FrequencyData.builder(); + builder.rsId(rsIdValue); for (Frequency frequency : frequencies) { Objects.requireNonNull(frequency, "frequency data cannot contain null element"); + builder.addFrequency(frequency.source(), frequency.frequency(), frequency.ac(), frequency.an(), frequency.homs()); } - return new FrequencyData(rsId == null ? "" : rsId, frequencies); + return builder.build(); } private static boolean isEmptyValue(String id) { return id == null || id.isEmpty() || VCF_EMPTY_VALUE.equals(id); } - private FrequencyData(String rsId, Collection frequencies) { - this.rsId = rsId; - // use natural ordering by FrequencySource - this class is a kind of EnumMap, but we're using primitives to store - // the values. This means that duplicated FrequencySource will be overwritten. In practice this shouldn't happen - // as they are extracted from a map instance. - Frequency[] sorted = orderByFrequencySource(frequencies); - this.size = countNotNullFrequencies(sorted); - this.sources = new FrequencySource[size]; - this.data = new float[size * WORD_SIZE]; - - int pos = 0; - for (Frequency entry : sorted) { - if (entry != null) { - this.sources[pos] = entry.getSource(); - this.data[pos * WORD_SIZE + FREQ_OFFSET] = entry.getFrequency(); - this.data[pos * WORD_SIZE + HOM_OFFSET] = 0f; - pos++; - } - } - } - private FrequencyData(String rsId, FrequencySource[] sources, float[] data) { this.rsId = rsId; this.size = sources.length; this.sources = sources; this.data = data; + this.maxSource = findMaxSource(); } - private Frequency[] orderByFrequencySource(Collection frequencies) { - Frequency[] sorted = new Frequency[NUM_FREQ_SOURCES]; - for (Frequency frequency : frequencies) { - FrequencySource frequencySource = frequency.getSource(); - sorted[frequencySource.ordinal()] = frequency; - } - return sorted; - } - - private int countNotNullFrequencies(Frequency[] sorted) { - int notNull = 0; - for (Frequency frequency : sorted) { - if (frequency != null) { - notNull++; + private int findMaxSource() { + float max = 0.0f; + int source = -1; + for(int i = 0; i < this.size; ++i) { + float value = freq(i); + if (value > max) { + max = value; + source = i; } } - return notNull; + return source; } /** @@ -174,29 +150,44 @@ public boolean isEmpty() { * @since 13.3.0 */ public boolean containsFrequencySource(FrequencySource frequencySource) { - int i = Arrays.binarySearch(sources, frequencySource); + int i = frequencySourceIndex(frequencySource); return i >= 0; } - public String getRsId() { - return rsId; + @Nullable + public Frequency frequencyForSource(FrequencySource source) { + int i = frequencySourceIndex(source); + return i < 0 ? null : frequency(i); } - @Nullable - public Frequency getFrequencyForSource(FrequencySource source) { - int i = Arrays.binarySearch(sources, source); - // , homs(i) - return i < 0 ? null : Frequency.of(sources[i], freq(i)); + private int frequencySourceIndex(FrequencySource frequencySource) { + return Arrays.binarySearch(sources, frequencySource); + } + + private Frequency frequency(int i) { + return Frequency.of(sources[i], freq(i), ac(i), an(i), homs(i)); } private float freq(int i) { return data[i * WORD_SIZE + FREQ_OFFSET]; } + private int ac(int i) { + return (int) data[i * WORD_SIZE + AC_OFFSET]; + } + + private int an(int i) { + return (int) data[i * WORD_SIZE + AN_OFFSET]; + } + private int homs(int i) { return (int) data[i * WORD_SIZE + HOM_OFFSET]; } + public String getRsId() { + return rsId; + } + /** * @return true if this variant is at all represented in dbSNP or ESP data, * regardless of frequency. That is, if the variant has an RS id in dbSNP or @@ -265,10 +256,10 @@ public boolean hasGnomadData() { * Returns the highest frequency in percent for a given set of {@link FrequencySource}. * * @param frequencySources to find the highest frequency for - * @return the population frequency as a percentage value i.e. 0.001 == 0.1% + * @return the population frequency as a percentage frequency i.e. 0.001 == 0.1% * @since 13.3.3 */ - public float getMaxFreqForPopulation(Set frequencySources) { + public float maxFreqForPopulation(Set frequencySources) { float max = 0f; for (int i = 0; i < size; i++) { FrequencySource freqSource = this.sources[i]; @@ -285,36 +276,31 @@ public boolean hasKnownFrequency() { } /** - * This function tests whether or not this {@code FrequencyData} object contains a {@code Frequency} object which has - * a frequency greater than the maximum frequency provided. This method does not check any ranges so it is advised - * that the user checks the frequency type in advance of calling this method. By default exomiser expresses the - * frequencies as a percentage value. + * This function tests if this {@code FrequencyData} object contains a {@code Frequency} object which has + * a frequency greater than the maximum frequency provided. This method does not check any ranges, so it is advised + * that the user checks the frequency type in advance of calling this method. By default, exomiser expresses the + * frequencies as a percentage frequency. * * @param maxFreq the maximum frequency threshold against which the {@code Frequency} objects are tested - * @return true if the object contains a {@code Frequency} over the provided percentage value, otherwise returns false. + * @return true if the object contains a {@code Frequency} over the provided percentage frequency, otherwise returns false. * @since 10.1.0 */ public boolean hasFrequencyOverPercentageValue(float maxFreq) { - for (int i = 0; i < size; i++) { - if (freq(i) > maxFreq) { - return true; - } - } - return false; + return maxFreq() > maxFreq; } /** * Returns a list of {@code Frequency} objects. If there is no known frequency data then an empty list will be returned. - * This method will return a mutable copy of the underlying data. + * This method will return an immutable copy of the underlying data. * - * @return a mutable copy of the {@code Frequency} data + * @return an immutable copy of the {@code Frequency} data */ - public List getKnownFrequencies() { - List freqs = new ArrayList<>(size); + public List frequencies() { + Frequency[] freqs = new Frequency[size]; for (int i = 0; i < size; i++) { - freqs.add(Frequency.of(sources[i], freq(i))); + freqs[i] = frequency(i); } - return freqs; + return List.of(freqs); } /** @@ -324,12 +310,8 @@ public List getKnownFrequencies() { * @return */ @JsonIgnore - public float getMaxFreq() { - float max = 0f; - for (int i = 0; i < size; i++) { - max = Math.max(max, freq(i)); - } - return max; + public float maxFreq() { + return maxSource == -1 ? 0f : freq(maxSource); } /** @@ -339,35 +321,19 @@ public float getMaxFreq() { */ @JsonIgnore @Nullable - public Frequency getMaxFrequency() { - if (this.size == 0) { - return null; - } - float max = 0.0f; - int maxSource = 0; - - for(int i = 0; i < this.size; ++i) { - float value = freq(i); - if (value > max) { - max = value; - maxSource = i; - } - } - - return Frequency.of(this.sources[maxSource], max); + public Frequency maxFrequency() { + return this.size == 0 ? null : frequency(maxSource); } /** - * @return returns a numerical value that is closer to one, the rarer + * @return returns a numerical frequency that is closer to one, the rarer * the variant is. If a variant is not entered in any of the data * sources, it returns one (highest score). Otherwise, it identifies the * maximum MAF in any of the databases, and returns a score that depends on * the MAF. Note that the frequency is expressed as a percentage. */ - public float getScore() { - - float max = getMaxFreq(); - + public float frequencyScore() { + float max = maxFreq(); if (max <= 0) { return VERY_RARE_SCORE; } else if (max > 2) { @@ -406,7 +372,13 @@ public String toString() { sb.append(", "); } first = false; - sb.append(sources[i]).append('=').append(freq(i)); + sb.append(sources[i]).append('=').append(freq(i)) + .append("(") + .append(ac(i)).append("|") + .append(an(i)).append("|") + .append(homs(i)) + .append(")") + ; } sb.append('}'); return "FrequencyData{" + "rsId=" + rsId + ", knownFrequencies=" + sb + '}'; @@ -421,7 +393,7 @@ public Builder toBuilder() { Builder builder = new Builder(); builder.rsId(rsId); for (int i = 0; i < sources.length; i++) { - builder.addFrequency(sources[i], freq(i), homs(i)); + builder.addFrequency(sources[i], freq(i), ac(i), an(i), homs(i)); } return builder; } @@ -446,15 +418,42 @@ public Builder rsId(String rsId) { } /** - * * @param frequencySource - * @param frequency the frequency of the variant as a percentage value. + * @param frequency the frequency of the variant as a percentage frequency. + * @return + */ + public Builder addFrequency(FrequencySource frequencySource, float frequency) { + Objects.requireNonNull(frequencySource); + if (frequency > 100f || frequency < 0f) { + throw new IllegalArgumentException(frequencySource + " must have a frequency in range 0-100%! Got " + frequency); + } + return addFrequency(frequencySource, frequency, 0, 0, 0); + } + + public Builder addFrequency(FrequencySource frequencySource, int ac, int an, int homCount) { + Objects.requireNonNull(frequencySource); + if (an <= 0 || ac > an || homCount > ac) { + throw new IllegalArgumentException(frequencySource + " AN must be > 0, AC must be < AN and HOM must be < AC. Got AC=" + ac + ", AN=" + an + ", hom=" + homCount); + } + float af = Frequency.percentageFrequency(ac, an); + return addFrequency(frequencySource, af, ac, an, homCount); + } + + /** + * PRIVATE method for use when converting the final {@link FrequencyData} back into a Builder. Do not expose as it + * will require checking that the frequency = AC / AN * 100 or calculating the frequency + * @param frequencySource + * @param frequency + * @param ac + * @param an * @param homCount * @return */ - public Builder addFrequency(FrequencySource frequencySource, float frequency, int homCount) { - frequencySources[frequencySource.ordinal()] = Objects.requireNonNull(frequencySource); + private Builder addFrequency(FrequencySource frequencySource, float frequency, int ac, int an, int homCount) { + frequencySources[frequencySource.ordinal()] = frequencySource; frequencyData[frequencySource.ordinal() * WORD_SIZE + FREQ_OFFSET] = frequency; + frequencyData[frequencySource.ordinal() * WORD_SIZE + AC_OFFSET] = ac; + frequencyData[frequencySource.ordinal() * WORD_SIZE + AN_OFFSET] = an; frequencyData[frequencySource.ordinal() * WORD_SIZE + HOM_OFFSET] = homCount; return this; } @@ -495,7 +494,7 @@ public Builder mergeFrequencyData(FrequencyData frequencyData) { return this; } for (int i = 0; i < frequencyData.sources.length; i++) { - this.addFrequency(frequencyData.sources[i], frequencyData.freq(i), frequencyData.homs(i)); + this.addFrequency(frequencyData.sources[i], frequencyData.freq(i), frequencyData.ac(i), frequencyData.an(i), frequencyData.homs(i)); } return this; } @@ -506,15 +505,18 @@ public FrequencyData build() { if (isEmptyValue(rsId) && size == 0) { return FrequencyData.empty(); } - var sources = new FrequencySource[size]; var data = new float[size * WORD_SIZE]; int dataPos = 0; - for (FrequencySource source : FrequencySource.values()) { + FrequencySource[] values = FrequencySource.values(); + for (int i = 0, valuesLength = values.length; i < valuesLength; i++) { + FrequencySource source = values[i]; if (frequencySources[source.ordinal()] != null) { sources[dataPos] = source; data[dataPos * WORD_SIZE + FREQ_OFFSET] = frequencyData[source.ordinal() * WORD_SIZE + FREQ_OFFSET]; + data[dataPos * WORD_SIZE + AC_OFFSET] = frequencyData[source.ordinal() * WORD_SIZE + AC_OFFSET]; + data[dataPos * WORD_SIZE + AN_OFFSET] = frequencyData[source.ordinal() * WORD_SIZE + AN_OFFSET]; data[dataPos * WORD_SIZE + HOM_OFFSET] = frequencyData[source.ordinal() * WORD_SIZE + HOM_OFFSET]; dataPos++; } diff --git a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/writers/TsvVariantResultsWriter.java b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/writers/TsvVariantResultsWriter.java index 5a258901c..19d0bb5db 100644 --- a/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/writers/TsvVariantResultsWriter.java +++ b/exomiser-core/src/main/java/org/monarchinitiative/exomiser/core/writers/TsvVariantResultsWriter.java @@ -171,10 +171,10 @@ private List buildVariantRecord(int rank, VariantEvaluation ve, GeneScor fields.add(geneConstraint == null ? "" : geneConstraint.loeuf()); fields.add(geneConstraint == null ? "" : geneConstraint.loeufLower()); fields.add(geneConstraint == null ? "" : geneConstraint.loeufUpper()); - Frequency maxFreq = frequencyData.getMaxFrequency(); - fields.add(maxFreq == null ? "" : maxFreq.getSource()); - fields.add(maxFreq == null ? "" : maxFreq.getFrequency()); - fields.add(toVcfFreqInfo(frequencyData.getKnownFrequencies())); + Frequency maxFreq = frequencyData.maxFrequency(); + fields.add(maxFreq == null ? "" : maxFreq.source()); + fields.add(maxFreq == null ? "" : maxFreq.frequency()); + fields.add(toVcfFreqInfo(frequencyData.frequencies())); PathogenicityScore maxPath = pathogenicityData.getMostPathogenicScore(); fields.add(maxPath == null ? "" : maxPath.getSource()); fields.add(maxPath == null ? "" : maxPath.getScore()); @@ -193,7 +193,7 @@ private String toVcfAcmgInfo(AcmgEvidence acmgEvidence) { } private String toVcfFreqInfo(List frequencies) { return frequencies.stream() - .map(frequency -> frequency.getSource() + "=" + frequency.getFrequency()) + .map(frequency -> frequency.source() + "=" + frequency.frequency()) .collect(joining(",")); } diff --git a/exomiser-core/src/main/resources/templates/results.html b/exomiser-core/src/main/resources/templates/results.html index 9b99b30f1..87060587b 100644 --- a/exomiser-core/src/main/resources/templates/results.html +++ b/exomiser-core/src/main/resources/templates/results.html @@ -390,8 +390,8 @@

Variant Score: Frequency Score: 0.95-->
Frequency Data:
-
No frequency data
-
No frequency data
+
1000Genomes: 0.02%
@@ -531,8 +531,8 @@

Variant Score: Frequency Score: 0.95-->
Frequency Data:
-
No frequency data
-
No frequency data
+
1000Genomes: 0.02%
diff --git a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/filters/FrequencyDataProviderTest.java b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/filters/FrequencyDataProviderTest.java index cc9495996..1ad93c675 100644 --- a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/filters/FrequencyDataProviderTest.java +++ b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/filters/FrequencyDataProviderTest.java @@ -120,7 +120,7 @@ public void testFrequencyDataOnlyContainsSpecifiedSourcesOneSourceSpecifiedAllDa VariantDataService variantDataService = TestVariantDataService.builder().put(variant, variantFrequencyData).build(); - instance = new FrequencyDataProvider(variantDataService, EnumSet.of(espAll.getSource()), new KnownVariantFilter()); + instance = new FrequencyDataProvider(variantDataService, EnumSet.of(espAll.source()), new KnownVariantFilter()); instance.runFilter(variant); assertThat(variant.getFrequencyData(), equalTo(FrequencyData.of(RS_ID, espAll))); @@ -135,7 +135,7 @@ public void testFrequencyDataOnlyContainsSpecifiedSourcesTwoSourcesSpecifiedAllD VariantDataService variantDataService = TestVariantDataService.builder().put(variant, variantFrequencyData).build(); - instance = new FrequencyDataProvider(variantDataService, EnumSet.of(espAll.getSource(), exacAfr.getSource()), new KnownVariantFilter()); + instance = new FrequencyDataProvider(variantDataService, EnumSet.of(espAll.source(), exacAfr.source()), new KnownVariantFilter()); instance.runFilter(variant); assertThat(variant.getFrequencyData(), equalTo(FrequencyData.of(RS_ID, espAll, exacAfr))); diff --git a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/TestVariantDataService.java b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/TestVariantDataService.java index d43991786..1db781f68 100644 --- a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/TestVariantDataService.java +++ b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/TestVariantDataService.java @@ -99,9 +99,9 @@ public boolean variantIsWhiteListed(Variant variant) { public FrequencyData getVariantFrequencyData(Variant variant, Set frequencySources) { FrequencyData allFrequencyData = expectedFrequencyData.getOrDefault(variant, FrequencyData.empty()); - List wanted = allFrequencyData.getKnownFrequencies() + List wanted = allFrequencyData.frequencies() .stream() - .filter(frequency -> frequencySources.contains(frequency.getSource())) + .filter(frequency -> frequencySources.contains(frequency.source())) .collect(Collectors.toList()); return FrequencyData.of(allFrequencyData.getRsId(), wanted); diff --git a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/VariantFactoryPerformanceTest.java b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/VariantFactoryPerformanceTest.java index 5ea3614f0..ca6d11ed5 100644 --- a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/VariantFactoryPerformanceTest.java +++ b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/VariantFactoryPerformanceTest.java @@ -179,7 +179,7 @@ private Consumer printVariant() { variantEvaluation.getTranscriptAnnotations().get(0).getAccession(), variantEvaluation.getTranscriptAnnotations().get(0).getHgvsCdna(), variantEvaluation.getVariantScore(), - variantEvaluation.getFrequencyScore(), variantEvaluation.getFrequencyData().getMaxFreq(), + variantEvaluation.getFrequencyScore(), variantEvaluation.getFrequencyData().maxFreq(), variantEvaluation.getPathogenicityScore(), variantEvaluation.getPathogenicityData().getPredictedPathogenicityScores() ); } diff --git a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/dao/ClinVarDaoMvStoreTest.java b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/dao/ClinVarDaoMvStoreTest.java index 57d969aea..30c549b0e 100644 --- a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/dao/ClinVarDaoMvStoreTest.java +++ b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/dao/ClinVarDaoMvStoreTest.java @@ -279,7 +279,7 @@ void manualDataExplorer() { if (frequencyData.isEmpty()) { System.out.println("\t-"); } else { - frequencyData.getKnownFrequencies().forEach(freq -> System.out.println("\t" + freq.getSource() + "=" + freq.getFrequency())); + frequencyData.frequencies().forEach(freq -> System.out.println("\t" + freq.source() + "=" + freq.frequency())); } System.out.println("Pathogenicity scores:"); diff --git a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/dao/FrequencyDaoMvStoreTest.java b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/dao/FrequencyDaoMvStoreTest.java index f59f6a13e..1c278711c 100644 --- a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/dao/FrequencyDaoMvStoreTest.java +++ b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/genome/dao/FrequencyDaoMvStoreTest.java @@ -87,13 +87,13 @@ public void getFrequencyDataWithFrequencies() throws Exception { AlleleKey key = AlleleProtoAdaptor.toAlleleKey(variant); AlleleProperties properties = AlleleProperties.newBuilder().setRsId("rs54321") .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.KG, 4, 1000)) - .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.ESP_AA, 3, 6000)) + .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.ESP_AA, 3, 6000, 1)) .build(); FrequencyDao instance = newInstanceWithData(Map.of(key, properties)); assertThat(instance.getFrequencyData(variant), equalTo(FrequencyData.of("rs54321", - Frequency.of(FrequencySource.THOUSAND_GENOMES, 0.4f), - Frequency.of(FrequencySource.ESP_AA, 0.05f)))); + Frequency.of(FrequencySource.THOUSAND_GENOMES, 4, 1000, 0), + Frequency.of(FrequencySource.ESP_AA, 3, 6000, 1)))); } } \ No newline at end of file diff --git a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/AlleleProtoAdaptorTest.java b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/AlleleProtoAdaptorTest.java index 5543daa69..36b427dd9 100644 --- a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/AlleleProtoAdaptorTest.java +++ b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/AlleleProtoAdaptorTest.java @@ -66,17 +66,34 @@ public void generateAlleleKey() { public void testToFreqData() { AlleleProperties alleleProperties = AlleleProperties.newBuilder() // 100f * (ac / (float) an); - .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.KG, 4, 1000)) - .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.TOPMED, 200, 400000)) + .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.GNOMAD_E_ASJ, 4, 1000)) + .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.GNOMAD_E_EAS, 200, 400000, 1)) .build(); assertThat(AlleleProtoAdaptor.toFrequencyData(alleleProperties), equalTo(FrequencyData.of( - Frequency.of(FrequencySource.THOUSAND_GENOMES, 0.4f), - Frequency.of(FrequencySource.TOPMED, 0.05f)) + Frequency.of(FrequencySource.GNOMAD_E_ASJ, 4, 1000, 0), + Frequency.of(FrequencySource.GNOMAD_E_EAS, 200, 400000, 1)) ) ); } + @Test + public void testToFreqDataNoAnType() { + AlleleProperties alleleProperties = AlleleProperties.newBuilder() + // 100f * (ac / (float) an); + .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.KG, 0.001f)) + .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.TOPMED, 0.002f)) + .addFrequencies(AlleleData.frequencyOf(AlleleProto.FrequencySource.GNOMAD_E_EAS, 200, 400000, 1)) + .build(); + assertThat(AlleleProtoAdaptor.toFrequencyData(alleleProperties), + equalTo(FrequencyData.of( + Frequency.of(FrequencySource.THOUSAND_GENOMES, 0.001f), + Frequency.of(FrequencySource.TOPMED, 0.002f), + Frequency.of(FrequencySource.GNOMAD_E_EAS, 200, 400000, 1)) + ) + ); + } + @Test public void testToPathDataSift() { AlleleProperties alleleProperties = AlleleProperties.newBuilder() diff --git a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyDataTest.java b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyDataTest.java index 4e8ea6db4..ccc9faea2 100644 --- a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyDataTest.java +++ b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyDataTest.java @@ -63,7 +63,7 @@ public class FrequencyDataTest { @Test public void testEmptyData() { assertThat(EMPTY_DATA.getRsId(), equalTo("")); - assertThat(EMPTY_DATA.getKnownFrequencies().isEmpty(), is(true)); + assertThat(EMPTY_DATA.frequencies().isEmpty(), is(true)); assertThat(EMPTY_DATA.isRepresentedInDatabase(), is(false)); } @@ -114,37 +114,37 @@ public void testGetRsId() { @Test public void testGetNonExistentFrequency() { - assertThat(EMPTY_DATA.getFrequencyForSource(THOUSAND_GENOMES), equalTo(null)); + assertThat(EMPTY_DATA.frequencyForSource(THOUSAND_GENOMES), equalTo(null)); } @Test public void testGetDbSnpMaf() { - assertThat(FREQUENCY_DATA.getFrequencyForSource(THOUSAND_GENOMES), equalTo(DBSNP_PASS)); + assertThat(FREQUENCY_DATA.frequencyForSource(THOUSAND_GENOMES), equalTo(DBSNP_PASS)); } @Test public void testGetEspEaMaf() { - assertThat(FREQUENCY_DATA.getFrequencyForSource(ESP_EA), equalTo(ESP_EA_PASS)); + assertThat(FREQUENCY_DATA.frequencyForSource(ESP_EA), equalTo(ESP_EA_PASS)); } @Test public void testGetEspAaMaf() { - assertThat(FREQUENCY_DATA.getFrequencyForSource(ESP_AA), equalTo(ESP_AA_PASS)); + assertThat(FREQUENCY_DATA.frequencyForSource(ESP_AA), equalTo(ESP_AA_PASS)); } @Test public void testGetEspAllMaf() { - assertThat(FREQUENCY_DATA.getFrequencyForSource(ESP_ALL), equalTo(ESP_ALL_PASS)); + assertThat(FREQUENCY_DATA.frequencyForSource(ESP_ALL), equalTo(ESP_ALL_PASS)); } @Test public void testGetFrequencyForUnavailableSource() { - assertThat(FREQUENCY_DATA.getFrequencyForSource(GNOMAD_E_NFE), equalTo(null)); + assertThat(FREQUENCY_DATA.frequencyForSource(GNOMAD_E_NFE), equalTo(null)); } @Test public void testGetFrequencyForUnavailableSourceBefore() { - assertThat(FREQUENCY_DATA.getFrequencyForSource(UNKNOWN), equalTo(null)); + assertThat(FREQUENCY_DATA.frequencyForSource(UNKNOWN), equalTo(null)); } @Test @@ -231,7 +231,7 @@ public void testHasKnownFrequencyTrue() { @Test public void testGetKnownFrequenciesNoFrequencyData() { - assertThat(EMPTY_DATA.getKnownFrequencies(), equalTo(Collections.emptyList())); + assertThat(EMPTY_DATA.frequencies(), equalTo(Collections.emptyList())); } @Test @@ -243,7 +243,7 @@ public void testGetKnownFrequencies() { expResult.add(ESP_EA_PASS); expResult.add(ESP_ALL_PASS); - assertThat(instance.getKnownFrequencies(), equalTo(expResult)); + assertThat(instance.frequencies(), equalTo(expResult)); } @Test @@ -255,15 +255,14 @@ public void testGetKnownFrequenciesIsImmutable() { expResult.add(ESP_ALL_PASS); //try and add another score to the instance post-construction - instance.getKnownFrequencies().add(ESP_EA_PASS); + assertThrows(UnsupportedOperationException.class, () -> instance.frequencies().add(ESP_EA_PASS)); - assertThat(instance.getKnownFrequencies(), equalTo(expResult)); + assertThat(instance.frequencies(), equalTo(expResult)); } @Test public void testGetMaxFreqWhenNoData() { - float maxFreq = 0.0f; - assertThat(EMPTY_DATA.getMaxFreq(), equalTo(maxFreq)); + assertThat(EMPTY_DATA.maxFreq(), equalTo(0.0f)); } @Test @@ -271,21 +270,21 @@ public void testGetMaxFreqWithData() { float maxFreq = 89.5f; Frequency maxFrequency = Frequency.of(UNKNOWN, maxFreq); FrequencyData instance = FrequencyData.of(RS_ID, DBSNP_PASS, maxFrequency, ESP_AA_PASS, ESP_EA_PASS); - assertThat(instance.getMaxFreq(), equalTo(maxFreq)); + assertThat(instance.maxFreq(), equalTo(maxFreq)); } @Test public void testGetMaxFrequencyWhenNoData() { - assertThat(EMPTY_DATA.getMaxFrequency(), equalTo(null)); + assertThat(EMPTY_DATA.maxFrequency(), equalTo(null)); } @Test public void testGetMaxFrequencyWithData() { - Frequency maxFrequency = Frequency.of(GNOMAD_E_OTH, 89.5f); + Frequency maxFrequency = Frequency.of(GNOMAD_E_OTH, 89, 100, 5); Frequency minFrequency = Frequency.of(GNOMAD_G_AFR, 0.0002f); Frequency midFrequency = Frequency.of(GNOMAD_E_AMR, 25.5f); FrequencyData instance = FrequencyData.of(RS_ID, minFrequency, maxFrequency, midFrequency); - assertThat(instance.getMaxFrequency(), equalTo(maxFrequency)); + assertThat(instance.maxFrequency(), equalTo(maxFrequency)); } @Test @@ -300,7 +299,7 @@ public void testHasFrequencyOverPercentageValue() { @Test public void testGetScoreReallyRareVariant() { - assertThat(EMPTY_DATA.getScore(), equalTo(1f)); + assertThat(EMPTY_DATA.frequencyScore(), equalTo(1f)); } @Test @@ -308,7 +307,7 @@ public void testGetScoreCommonVariant() { float maxFreq = 100.0f; Frequency maxFrequency = Frequency.of(THOUSAND_GENOMES, maxFreq); FrequencyData instance = FrequencyData.of(RS_ID, maxFrequency); - assertThat(instance.getScore(), equalTo(0f)); + assertThat(instance.frequencyScore(), equalTo(0f)); } @Test @@ -316,15 +315,15 @@ public void testGetScoreRareVariant() { float maxFreq = 0.1f; Frequency maxFrequency = Frequency.of(UNKNOWN, maxFreq); FrequencyData instance = FrequencyData.of(maxFrequency); - assertThat(instance.getScore(), equalTo(0.9857672f)); + assertThat(instance.frequencyScore(), equalTo(0.9857672f)); } @Test void testBuilderEquivalentToStaticConstructor() { FrequencyData actual = FrequencyData.builder() .rsId("rs12345") - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_AFR, 0.0005f) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .build(); FrequencyData expected = FrequencyData.of("rs12345", Frequency.of(GNOMAD_E_AFR, 0.0005f), Frequency.of(GNOMAD_E_AMR, 0.0002f)); @@ -334,10 +333,10 @@ void testBuilderEquivalentToStaticConstructor() { @Test void testBuilder() { FrequencyData instance = FrequencyData.builder() - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_AFR, 0.0005f) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .build(); - assertThat(instance.getKnownFrequencies(), equalTo(List.of(Frequency.of(GNOMAD_E_AFR, 0.0005f), Frequency.of(GNOMAD_E_AMR, 0.0002f)))); + assertThat(instance.frequencies(), equalTo(List.of(Frequency.of(GNOMAD_E_AFR, 0.0005f), Frequency.of(GNOMAD_E_AMR, 0.0002f)))); } @Test @@ -357,8 +356,8 @@ void testBuilderIsEmpty() { @Test void testToBuilder() { FrequencyData frequencyData = FrequencyData.builder() - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_AFR, 0.0005f) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .build(); FrequencyData instance = frequencyData.toBuilder().build(); @@ -369,8 +368,8 @@ void testToBuilder() { @Test void testBuilderRetainSourcesEmpty() { FrequencyData instance = FrequencyData.builder() - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_AFR, 0.0005f) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .filterSources(Set.of()) .build(); assertThat(instance, equalTo(FrequencyData.empty())); @@ -379,13 +378,13 @@ void testBuilderRetainSourcesEmpty() { @Test void testBuilderRetainSources() { FrequencyData instance = FrequencyData.builder() - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_AFR, 0.0005f) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .filterSources(Set.of(GNOMAD_E_AMR)) .build(); FrequencyData expected = FrequencyData.builder() - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .build(); assertThat(instance, equalTo(expected)); @@ -394,7 +393,7 @@ void testBuilderRetainSources() { @Test void testBuilderRetainSourcesAllRemoved() { FrequencyData instance = FrequencyData.builder() - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) + .addFrequency(GNOMAD_E_AFR, 0.0005f) .filterSources(Set.of(GNOMAD_E_SAS)) .build(); assertThat(instance, equalTo(FrequencyData.empty())); @@ -403,14 +402,14 @@ void testBuilderRetainSourcesAllRemoved() { @Test void testBuilderMergeEmpty() { FrequencyData instance = FrequencyData.builder() - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_AFR, 0.0005f) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .mergeFrequencyData(FrequencyData.empty()) .build(); FrequencyData expected = FrequencyData.builder() - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) + .addFrequency(GNOMAD_E_AMR, 0.0002f) + .addFrequency(GNOMAD_E_AFR, 0.0005f) .build(); assertThat(instance, equalTo(expected)); @@ -419,7 +418,7 @@ void testBuilderMergeEmpty() { @Test void testBuilderMergeNewFrequencyIntoEmpty() { FrequencyData toMerge = FrequencyData.builder() - .addFrequency(GNOMAD_E_EAS, 0.0001f, 1) + .addFrequency(GNOMAD_E_EAS, 0.0001f) .build(); FrequencyData instance = FrequencyData.builder() @@ -427,7 +426,7 @@ void testBuilderMergeNewFrequencyIntoEmpty() { .build(); FrequencyData expected = FrequencyData.builder() - .addFrequency(GNOMAD_E_EAS, 0.0001f, 1) + .addFrequency(GNOMAD_E_EAS, 0.0001f) .build(); assertThat(instance, equalTo(expected)); @@ -436,19 +435,21 @@ void testBuilderMergeNewFrequencyIntoEmpty() { @Test void testBuilderMergeNewFrequency() { FrequencyData toMerge = FrequencyData.builder() - .addFrequency(GNOMAD_E_EAS, 0.0001f, 1) + .addFrequency(GNOMAD_E_EAS, 0.0001f) + .addFrequency(GNOMAD_G_AMI, 1, 200, 1) .build(); FrequencyData instance = FrequencyData.builder() - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_AFR, 0.0005f) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .mergeFrequencyData(toMerge) .build(); FrequencyData expected = FrequencyData.builder() - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) - .addFrequency(GNOMAD_E_AFR, 0.0005f, 0) - .addFrequency(GNOMAD_E_EAS, 0.0001f, 1) + .addFrequency(GNOMAD_E_AMR, 0.0002f) + .addFrequency(GNOMAD_E_AFR, 0.0005f) + .addFrequency(GNOMAD_E_EAS, 0.0001f) + .addFrequency(GNOMAD_G_AMI, 1, 200, 1) .build(); assertThat(instance, equalTo(expected)); @@ -457,20 +458,37 @@ void testBuilderMergeNewFrequency() { @Test void testBuilderMergeSameFrequency() { FrequencyData toMerge = FrequencyData.builder() - .addFrequency(GNOMAD_E_EAS, 0.0001f, 1) + .addFrequency(GNOMAD_E_EAS, 0.0001f) .build(); FrequencyData instance = FrequencyData.builder() - .addFrequency(GNOMAD_E_EAS, 0.0005f, 0) - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) + .addFrequency(GNOMAD_E_EAS, 0.0005f) + .addFrequency(GNOMAD_E_AMR, 0.0002f) .mergeFrequencyData(toMerge) .build(); FrequencyData expected = FrequencyData.builder() - .addFrequency(GNOMAD_E_AMR, 0.0002f, 0) - .addFrequency(GNOMAD_E_EAS, 0.0001f, 1) + .addFrequency(GNOMAD_E_AMR, 0.0002f) + .addFrequency(GNOMAD_E_EAS, 0.0001f) .build(); assertThat(instance, equalTo(expected)); } + + @Test + void floatArray() { + var data = new float[4]; + var ac = 110; + var an = 10000; + var hom = 10; + var af = Frequency.percentageFrequency(ac, an); + System.out.println("AF=" + af); + data[0] = (float) ac; + data[1] = (float) an; + data[2] = (float) hom; + data[3] = (float) af; + System.out.println("dataAF=" + data[3]); + assertThat(Frequency.percentageFrequency((int) data[0], (int) data[1]), equalTo((float) data[3])); + } + } diff --git a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyTest.java b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyTest.java index 18cfa3d42..60490be39 100644 --- a/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyTest.java +++ b/exomiser-core/src/test/java/org/monarchinitiative/exomiser/core/model/frequency/FrequencyTest.java @@ -40,21 +40,33 @@ public class FrequencyTest { @Test - public void testfrequencyOnlyConstructor(){ + public void testFrequencyOnlyConstructor(){ float frequency = 1.0f; Frequency instance = Frequency.of(UNKNOWN, frequency); - assertThat(instance.getFrequency(), equalTo(frequency)); - assertThat(instance.getSource(), equalTo(FrequencySource.UNKNOWN)); + assertThat(instance.frequency(), equalTo(frequency)); + assertThat(instance.source(), equalTo(FrequencySource.UNKNOWN)); + assertThat(instance.ac(), equalTo(0)); + assertThat(instance.an(), equalTo(0)); + assertThat(instance.homs(), equalTo(0));} + + @Test + public void testFrequencyAcAnHomConstructor(){ + Frequency instance = Frequency.of(UNKNOWN, 2, 200, 1); + assertThat(instance.frequency(), equalTo(1.0f)); + assertThat(instance.source(), equalTo(FrequencySource.UNKNOWN)); + assertThat(instance.ac(), equalTo(2)); + assertThat(instance.an(), equalTo(200)); + assertThat(instance.homs(), equalTo(1)); } @Test - public void testfrequencySourceInConstructor(){ + public void testFrequencySourceInConstructor(){ float frequency = 1.0f; FrequencySource source = EXAC_NON_FINNISH_EUROPEAN; Frequency instance = Frequency.of(source, frequency); - assertThat(instance.getFrequency(), equalTo(frequency)); - assertThat(instance.getSource(), equalTo(source)); + assertThat(instance.frequency(), equalTo(frequency)); + assertThat(instance.source(), equalTo(source)); } @Test @@ -106,5 +118,7 @@ public void testToString() { float frequency = 1.0f; Frequency instance = Frequency.of(UNKNOWN, frequency); assertThat(instance.toString(), equalTo(String.format(Locale.UK, "Frequency{UNKNOWN=%s}", frequency))); + + assertThat(Frequency.of(GNOMAD_E_AFR, 100, 2000, 1).toString(), equalTo("Frequency{GNOMAD_E_AFR=5.0(100|2000|1)}")); } } diff --git a/exomiser-web/src/main/resources/templates/results.html b/exomiser-web/src/main/resources/templates/results.html index 5ebebb8c4..191c3bb65 100644 --- a/exomiser-web/src/main/resources/templates/results.html +++ b/exomiser-web/src/main/resources/templates/results.html @@ -308,10 +308,10 @@

Analyzed samples

- + - + @@ -569,8 +569,8 @@

Variant Score: Frequency Score: 0.95-->
Frequency Data:
-
No frequency data
-
No frequency data
+
1000Genomes: 0.02%