/** Get info string for a specific allele */ public String getInfo(String key, String allele) { if (info == null) parseInfo(); // Get INFO value String infoStr = info.get(key); if (infoStr == null) return null; // Split INFO value and match it to allele String infos[] = infoStr.split(","); // INFO fields having number type 'R' (all alleles) should have one value for reference as well. // So in those cases we must skip the first value int firstAltIndex = 0; VcfHeaderInfo vcfInfo = getVcfInfo(key); if (vcfInfo != null && vcfInfo.isNumberAllAlleles()) { firstAltIndex = 1; // Are we looking for 'REF' information? if (ref.equalsIgnoreCase(allele)) return infos[0]; } // Find ALT matching allele for (int i = 0, j = firstAltIndex; (i < alts.length) && (j < infos.length); i++, j++) if (alts[i].equalsIgnoreCase(allele)) return infos[j]; return null; }
/** Check info field Note: We report the first error we find */ String checkInfo(String infoName) { if (infoName.isEmpty()) return ""; VcfHeaderInfo vcfInfo = getVcfInfo(infoName); if (vcfInfo == null) return "Cannot find header for INFO field '" + infoName + "'"; // Split INFO value and match it to allele String valsStr = getInfo(infoName); if (valsStr == null) return ""; // INFO field not present, nothing to do // Check values String values[] = valsStr.split(","); for (String val : values) if (!VcfEntry.isValidInfoValue(val)) return "INFO filed '" + infoName + "' has an invalid value '" + val + "' (no spaces, tabs, '=' or ';' are allowed)"; // Check number of INFO elements if (vcfInfo.isNumberNumber() && vcfInfo.getNumber() != values.length) { VcfInfoType type = vcfInfo.getVcfInfoType(); if (type == VcfInfoType.Flag && values.length == 1) ; // OK, flags must have one or zero values else return "INFO filed '" + infoName + "' has 'Number=" + vcfInfo.getNumber() + "' in header, but it contains '" + values.length + "' elements."; } if (vcfInfo.isNumberAllAlleles() && values.length != (alts.length + 1)) return "INFO filed '" + infoName + "' has 'Number=R' in header, but it contains '" + values.length + "' elements when there are '" + alts.length + "' alleles (it should have '" + (alts.length + 1) + "' elements)."; if (vcfInfo.isNumberAllAlleles() && values.length != alts.length) return "INFO filed '" + infoName + "' has 'Number=A' in header, but it contains '" + values.length + "' elements when there are '" + alts.length + "' alleles."; return ""; }
/** * Add a "key=value" tuple the info field * * @param key : INFO key name * @param value : Can be null if it is a boolean field. */ public void addInfo(String key, String value) { if (!isValidInfoKey(key)) throw new RuntimeException( "Illegal INFO key / name. Key: \"" + key + "\" does not match regular expression ^[A-Za-z_][0-9A-Za-z_.]*$"); if (!isValidInfoValue(value)) throw new RuntimeException( "No white-space, semi-colons, or equals-signs are permitted in INFO field values. Name:\"" + key + "\" Value:\"" + value + "\""); // Remove previous 'key' for INFO field? removeInfo(key); // Is this a 'flag'? boolean isFlag = false; VcfHeader vcfHeader = vcfFileIterator.getVcfHeader(); if (vcfHeader != null) { VcfHeaderInfo vcfHeaderInfo = vcfFileIterator.getVcfHeader().getVcfInfo(key); isFlag = (vcfHeaderInfo != null) && (vcfHeaderInfo.getVcfInfoType() == VcfInfoType.Flag); } // Add to info hash (if available) if (info != null) info.put(key, value); // Append value to infoStr String addInfoStr = key + (value != null && !isFlag ? "=" + value : ""); // String to append if ((infoStr == null) || infoStr.isEmpty()) infoStr = addInfoStr; else { if (!infoStr.endsWith(SUB_FIELD_SEP)) infoStr += SUB_FIELD_SEP; // Do we need to add a semicolon? infoStr += addInfoStr; // Add info string } }
/** Get Info number for a given ID */ public VcfInfoType getVcfInfoNumber(String id) { VcfHeaderInfo vcfInfo = vcfFileIterator.getVcfHeader().getVcfInfo(id); if (vcfInfo == null) return null; return vcfInfo.getVcfInfoType(); }