Skip to content

Commit

Permalink
Merge pull request #94 from molgenis/fix/empty_format
Browse files Browse the repository at this point in the history
Fix: missing value for format fields is an empty string rather than a…
  • Loading branch information
dennishendriksen authored Oct 10, 2024
2 parents 47ef665 + 4bfa134 commit 00831ed
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ private Object getNestedVepValue(Field field) {
String separator = Pattern.quote(nestedField.getParent().getSeparator().toString());
int index = nestedField.getIndex();
String parentId = nestedField.getParent().getId();
List<String> infoValues = VcfUtils.getInfoAsStringList(variantContext, parentId);
List<String> infoValues = VcfUtils.getInfoAsStringList(variantContext, parentId, VCFConstants.MISSING_VALUE_v4);
if (!infoValues.isEmpty()) {
String singleValue = infoValues.get(0);
String[] split = singleValue.split(separator, -1);
Expand Down
69 changes: 40 additions & 29 deletions src/main/java/org/molgenis/vcf/decisiontree/utils/VcfUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ private VcfUtils() {

public static Integer getInfoAsInteger(VariantContext variantContext, Field field) {
Object value = variantContext.getAttribute(field.getId());
return getVcfValueAsInteger(value);
String missingValue = getMissingValue(field);
return getVcfValueAsInteger(value, missingValue);
}

public static List<Integer> getInfoAsIntegerList(VariantContext variantContext, Field field) {
List<Integer> integerValues;

String missingValue = getMissingValue(field);
Object value = variantContext.getAttribute(field.getId());
if (value == null) {
integerValues = List.of();
Expand All @@ -44,15 +46,15 @@ public static List<Integer> getInfoAsIntegerList(VariantContext variantContext,
if (size == 0) {
integerValues = emptyList();
} else if (size == 1) {
integerValues = singletonList(getVcfValueAsInteger(objectValues.get(0)));
integerValues = singletonList(getVcfValueAsInteger(objectValues.get(0), missingValue));
} else {
integerValues = new ArrayList<>(objectValues.size());
for (Object objValue : objectValues) {
integerValues.add(getVcfValueAsInteger(objValue));
integerValues.add(getVcfValueAsInteger(objValue, missingValue));
}
}
} else if (value instanceof String stringValue) {
integerValues = singletonList(getInfoStringValueAsInteger(stringValue));
integerValues = singletonList(getInfoStringValueAsInteger(stringValue, missingValue));
} else {
throw new TypeConversionException(value, Integer.class);
}
Expand All @@ -61,24 +63,24 @@ public static List<Integer> getInfoAsIntegerList(VariantContext variantContext,
}

private static @Nullable
Integer getVcfValueAsInteger(@Nullable Object objValue) {
Integer getVcfValueAsInteger(@Nullable Object objValue, String missingValue) {
Integer intValue;
if (objValue == null) {
intValue = null;
} else if (objValue instanceof Integer integer) {
intValue = integer;
} else if (objValue instanceof String stringValue) {
intValue = getInfoStringValueAsInteger(stringValue);
intValue = getInfoStringValueAsInteger(stringValue, missingValue);
} else {
throw new TypeConversionException(objValue, Integer.class);
}
return intValue;
}

private static @Nullable
Integer getInfoStringValueAsInteger(String infoStrValue) {
Integer getInfoStringValueAsInteger(String infoStrValue, String missingValue) {
Integer intValue;
if (infoStrValue.equals(VCFConstants.MISSING_VALUE_v4)) {
if (infoStrValue.equals(missingValue)) {
intValue = null;
} else {
intValue = Integer.valueOf(infoStrValue);
Expand All @@ -88,11 +90,13 @@ Integer getInfoStringValueAsInteger(String infoStrValue) {

public static Double getInfoAsDouble(VariantContext variantContext, Field field) {
Object value = variantContext.getAttribute(field.getId());
return getVcfValueAsDouble(value);
String missingValue = getMissingValue(field);
return getVcfValueAsDouble(value, missingValue);
}

public static List<Double> getInfoAsDoubleList(VariantContext variantContext, Field field) {
List<Double> doubleValues;
String missingValue = getMissingValue(field);

Object value = variantContext.getAttribute(field.getId());
if (value == null) {
Expand All @@ -102,41 +106,45 @@ public static List<Double> getInfoAsDoubleList(VariantContext variantContext, Fi
if (size == 0) {
doubleValues = emptyList();
} else if (size == 1) {
doubleValues = singletonList(getVcfValueAsDouble(objectValues.get(0)));
doubleValues = singletonList(getVcfValueAsDouble(objectValues.get(0), missingValue));
} else {
doubleValues = new ArrayList<>(objectValues.size());
for (Object objValue : objectValues) {
doubleValues.add(getVcfValueAsDouble(objValue));
doubleValues.add(getVcfValueAsDouble(objValue, missingValue));
}
}
} else if (value instanceof String string) {
doubleValues = singletonList(getInfoStringValueAsDouble(string));
doubleValues = singletonList(getInfoStringValueAsDouble(string, missingValue));
} else {
throw new TypeConversionException(value, Double.class);
}

return doubleValues;
}

private static String getMissingValue(Field field) {
return field.getFieldType() == FORMAT ? "" : VCFConstants.MISSING_VALUE_v4;
}

private static @Nullable
Double getVcfValueAsDouble(@Nullable Object objValue) {
Double getVcfValueAsDouble(@Nullable Object objValue, String missingValue) {
Double doubleValue;
if (objValue == null) {
doubleValue = null;
} else if (objValue instanceof Double doubleVal) {
doubleValue = doubleVal;
} else if (objValue instanceof String string) {
doubleValue = getInfoStringValueAsDouble(string);
doubleValue = getInfoStringValueAsDouble(string, missingValue);
} else {
throw new TypeConversionException(objValue, Double.class);
}
return doubleValue;
}

private static @Nullable
Double getInfoStringValueAsDouble(String infoStrValue) {
Double getInfoStringValueAsDouble(String infoStrValue, String missingValue) {
Double doubleValue;
if (infoStrValue.equals(VCFConstants.MISSING_VALUE_v4)) {
if (infoStrValue.equals(missingValue)) {
doubleValue = null;
} else {
doubleValue = Double.valueOf(infoStrValue);
Expand All @@ -146,19 +154,21 @@ Double getInfoStringValueAsDouble(String infoStrValue) {

public static String getInfoAsString(VariantContext variantContext, Field field) {
Object value = variantContext.getAttribute(field.getId());
return getVcfValueAsString(value);
String missingValue = getMissingValue(field);
return getVcfValueAsString(value, missingValue);
}

public static List<String> getInfoAsStringList(VariantContext variantContext, Field field) {
List<String> strValues;
String id = field.getId();
String missingValue = getMissingValue(field);

strValues = getInfoAsStringList(variantContext, id);
strValues = getInfoAsStringList(variantContext, id, missingValue);

return strValues;
}

public static List<String> getInfoAsStringList(VariantContext variantContext, String id) {
public static List<String> getInfoAsStringList(VariantContext variantContext, String id, String missingValue) {
List<String> strValues;
Object value = variantContext.getAttribute(id);
if (value == null) {
Expand All @@ -168,15 +178,15 @@ public static List<String> getInfoAsStringList(VariantContext variantContext, St
if (size == 0) {
strValues = emptyList();
} else if (size == 1) {
strValues = singletonList(getVcfValueAsString(objectValues.get(0)));
strValues = singletonList(getVcfValueAsString(objectValues.get(0), missingValue));
} else {
strValues = new ArrayList<>(objectValues.size());
for (Object objValue : objectValues) {
strValues.add(getVcfValueAsString(objValue));
strValues.add(getVcfValueAsString(objValue, missingValue));
}
}
} else if (value instanceof String string) {
strValues = singletonList(getInfoStringValueAsString(string));
strValues = singletonList(getInfoStringValueAsString(string, missingValue));
} else {
throw new TypeConversionException(value, String.class);
}
Expand All @@ -185,22 +195,22 @@ public static List<String> getInfoAsStringList(VariantContext variantContext, St
}

private static @Nullable
String getVcfValueAsString(@Nullable Object objValue) {
String getVcfValueAsString(@Nullable Object objValue, String missingValue) {
String strValue;
if (objValue == null) {
strValue = null;
} else if (objValue instanceof String string) {
strValue = getInfoStringValueAsString(string);
strValue = getInfoStringValueAsString(string, missingValue);
} else {
throw new TypeConversionException(objValue, String.class);
}
return strValue;
}

private static @Nullable
String getInfoStringValueAsString(String infoStrValue) {
String getInfoStringValueAsString(String infoStrValue, String missingValue) {
String stringValue;
if (infoStrValue.equals(VCFConstants.MISSING_VALUE_v4)) {
if (infoStrValue.equals(missingValue)) {
stringValue = null;
} else {
stringValue = infoStrValue;
Expand Down Expand Up @@ -241,18 +251,19 @@ public static Object getTypedVcfValue(Field field, String stringValue, String se
public static Object getTypedVcfValue(Field field, String stringValue) {
Object typedValue;
ValueType valueType = field.getValueType();
String missingValue = getMissingValue(field);
switch (valueType) {
case INTEGER:
typedValue = VcfUtils.getVcfValueAsInteger(stringValue);
typedValue = VcfUtils.getVcfValueAsInteger(stringValue, missingValue);
break;
case FLAG:
typedValue = VcfUtils.getVcfValueAsBoolean(stringValue);
break;
case FLOAT:
typedValue = VcfUtils.getVcfValueAsDouble(stringValue);
typedValue = VcfUtils.getVcfValueAsDouble(stringValue, missingValue);
break;
case CHARACTER, STRING:
typedValue = VcfUtils.getVcfValueAsString(stringValue);
typedValue = VcfUtils.getVcfValueAsString(stringValue, missingValue);
break;
default:
throw new UnexpectedEnumException(valueType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.List;
import org.junit.jupiter.api.Test;
import org.molgenis.vcf.decisiontree.filter.model.FieldImpl;
import org.molgenis.vcf.decisiontree.filter.model.FieldType;

class VcfUtilsTest {

Expand Down Expand Up @@ -299,14 +300,29 @@ void getInfoAsDoubleListSingletonString() {
@Test
void getInfoAsDoubleListSingletonStringMissing() {
String key = "my_key";
FieldImpl field = when(mock(FieldImpl.class).getId()).thenReturn(key).getMock();
FieldImpl field = mock(FieldImpl.class);
when(field.getId()).thenReturn(key);
when(field.getFieldType()).thenReturn(FieldType.INFO);
List<String> values = singletonList(".");
VariantContext variantContext =
when(mock(VariantContext.class).getAttribute(key)).thenReturn(values).getMock();

assertEquals(singletonList(null), VcfUtils.getInfoAsDoubleList(variantContext, field));
}

@Test
void getFormatAsDoubleListSingletonStringMissing() {
String key = "my_key";
FieldImpl field = mock(FieldImpl.class);
when(field.getId()).thenReturn(key);
when(field.getFieldType()).thenReturn(FieldType.FORMAT);
List<String> values = singletonList("");
VariantContext variantContext =
when(mock(VariantContext.class).getAttribute(key)).thenReturn(values).getMock();

assertEquals(singletonList(null), VcfUtils.getInfoAsDoubleList(variantContext, field));
}

@Test
void getInfoAsDoubleListNull() {
String key = "my_key";
Expand Down

0 comments on commit 00831ed

Please sign in to comment.