Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TASK-5278 - Add haploid calls treatment parameter to family-qc and relatedness #2466

Open
wants to merge 10 commits into
base: release-3.x.x
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
package org.opencb.opencga.analysis.family.qc;

import org.apache.commons.lang3.StringUtils;
import org.opencb.biodata.models.clinical.qc.RelatednessReport;
import org.opencb.commons.datastore.core.QueryOptions;
import org.opencb.opencga.analysis.AnalysisUtils;
import org.opencb.opencga.analysis.individual.qc.IndividualQcUtils;
import org.opencb.opencga.analysis.tools.OpenCgaTool;
import org.opencb.opencga.analysis.tools.OpenCgaToolScopeStudy;
import org.opencb.opencga.analysis.variant.relatedness.RelatednessAnalysis;
import org.opencb.opencga.catalog.exceptions.CatalogException;
import org.opencb.opencga.catalog.utils.CatalogFqn;
Expand All @@ -32,7 +33,10 @@
import org.opencb.opencga.core.models.family.FamilyQualityControl;
import org.opencb.opencga.core.models.family.FamilyUpdateParams;
import org.opencb.opencga.core.models.study.Study;
import org.opencb.opencga.core.models.variant.FamilyQcAnalysisParams;
import org.opencb.opencga.core.models.variant.MutationalSignatureAnalysisParams;
import org.opencb.opencga.core.tools.annotations.Tool;
import org.opencb.opencga.core.tools.annotations.ToolParams;
import org.opencb.opencga.core.tools.variant.FamilyQcAnalysisExecutor;

import java.nio.file.Path;
Expand All @@ -43,62 +47,78 @@
import static org.opencb.opencga.core.models.study.StudyPermissions.Permissions.WRITE_FAMILIES;

@Tool(id = FamilyQcAnalysis.ID, resource = Enums.Resource.FAMILY, description = FamilyQcAnalysis.DESCRIPTION)
public class FamilyQcAnalysis extends OpenCgaTool {
public class FamilyQcAnalysis extends OpenCgaToolScopeStudy {

public static final String ID = "family-qc";
public static final String DESCRIPTION = "Run quality control (QC) for a given family. It computes the relatedness scores among the"
+ " family members";
+ " family members";

public static final String RELATEDNESS_STEP = "relatedness";

private String studyId;
private String familyId;
private String relatednessMethod;
@ToolParams
private FamilyQcAnalysisParams familyQcParams = new FamilyQcAnalysisParams();

private String relatednessMaf;
private String haploidCallMode;
private Map<String, Map<String, Float>> relatednessThresholds;

private Family family;

@Override
protected void check() throws Exception {
super.check();
setUpStorageEngineExecutor(studyId);
setUpStorageEngineExecutor(study);

if (StringUtils.isEmpty(studyId)) {
if (StringUtils.isEmpty(study)) {
throw new ToolException("Missing study ID.");
}

// Check permissions
try {
JwtPayload jwtPayload = catalogManager.getUserManager().validateToken(token);
CatalogFqn studyFqn = CatalogFqn.extractFqnFromStudy(studyId, jwtPayload);
CatalogFqn studyFqn = CatalogFqn.extractFqnFromStudy(study, jwtPayload);
String organizationId = studyFqn.getOrganizationId();
String userId = jwtPayload.getUserId(organizationId);

Study study = catalogManager.getStudyManager().get(studyId, QueryOptions.empty(), token).first();
catalogManager.getAuthorizationManager().checkStudyPermission(organizationId, study.getUid(), userId, WRITE_FAMILIES);
Study auxStudy = catalogManager.getStudyManager().get(study, QueryOptions.empty(), token).first();
catalogManager.getAuthorizationManager().checkStudyPermission(organizationId, auxStudy.getUid(), userId, WRITE_FAMILIES);
} catch (CatalogException e) {
throw new ToolException(e);
}

// Sanity check
if (StringUtils.isEmpty(familyId)) {
if (StringUtils.isEmpty(familyQcParams.getFamily())) {
throw new ToolException("Missing family ID.");
}

family = IndividualQcUtils.getFamilyById(studyId, familyId, catalogManager, token);
family = IndividualQcUtils.getFamilyById(study, familyQcParams.getFamily(), catalogManager, token);
if (family == null) {
throw new ToolException("Family '" + familyId + "' not found.");
throw new ToolException("Family '" + familyQcParams.getFamily() + "' not found.");
}

// As relatedness is the only QC to compute, it is mandatory
if (StringUtils.isEmpty(relatednessMethod)) {
relatednessMethod = "PLINK/IBD";
}
// Check MAF
relatednessMaf = familyQcParams.getRelatednessMaf();
if (StringUtils.isEmpty(relatednessMaf)) {
relatednessMaf = RelatednessAnalysis.MAF_DEFAULT_VALUE;
}

// Check haploid call mode
haploidCallMode = familyQcParams.getHaploidCallMode();
if (StringUtils.isEmpty(haploidCallMode)) {
haploidCallMode = RelatednessReport.HAPLOID_CALL_MODE_DEFAUT_VALUE;
} else {
switch (haploidCallMode) {
case RelatednessReport.HAPLOID_CALL_MODE_HAPLOID_VALUE:
case RelatednessReport.HAPLOID_CALL_MODE_MISSING_VALUE:
case RelatednessReport.HAPLOID_CALL_MODE_REF_VALUE:
break;
default:
throw new ToolException("Invalid haploid call value '" + haploidCallMode + "', accepted values are: "
+ RelatednessReport.HAPLOID_CALL_MODE_HAPLOID_VALUE + ", " + RelatednessReport.HAPLOID_CALL_MODE_MISSING_VALUE
+ " and " + RelatednessReport.HAPLOID_CALL_MODE_REF_VALUE);
}
}

Path thresholdsPath = getOpencgaHome().resolve("analysis").resolve(FamilyQcAnalysis.ID).resolve("relatedness_thresholds.csv");
relatednessThresholds = AnalysisUtils.parseRelatednessThresholds(thresholdsPath);
}
Expand All @@ -120,10 +140,10 @@ protected void run() throws ToolException {
FamilyQcAnalysisExecutor executor = getToolExecutor(FamilyQcAnalysisExecutor.class);

// Set up executor
executor.setStudyId(studyId)
executor.setStudyId(study)
.setFamily(family)
.setRelatednessMethod(relatednessMethod)
.setRelatednessMaf(relatednessMaf)
.setHaploidCallMode(haploidCallMode)
.setRelatednessThresholds(relatednessThresholds)
.setRelatednesResourcePath(getOpencgaHome().resolve("analysis/resources").resolve(RelatednessAnalysis.ID))
.setQualityControl(qualityControl);
Expand All @@ -135,47 +155,29 @@ protected void run() throws ToolException {
try {
qualityControl = executor.getQualityControl();
if (qualityControl != null) {
catalogManager.getFamilyManager().update(getStudyId(), familyId, new FamilyUpdateParams().setQualityControl(qualityControl),
catalogManager.getFamilyManager().update(study, familyQcParams.getFamily(), new FamilyUpdateParams().setQualityControl(qualityControl),
QueryOptions.empty(), token);
}
} catch (CatalogException e) {
throw new ToolException(e);
}
}

public String getStudyId() {
return studyId;
}

public FamilyQcAnalysis setStudyId(String studyId) {
this.studyId = studyId;
return this;
}

public String getFamilyId() {
return familyId;
}

public FamilyQcAnalysis setFamilyId(String familyId) {
this.familyId = familyId;
return this;
}

public String getRelatednessMethod() {
return relatednessMethod;
public String getRelatednessMaf() {
return relatednessMaf;
}

public FamilyQcAnalysis setRelatednessMethod(String relatednessMethod) {
this.relatednessMethod = relatednessMethod;
public FamilyQcAnalysis setRelatednessMaf(String relatednessMaf) {
this.relatednessMaf = relatednessMaf;
return this;
}

public String getRelatednessMaf() {
return relatednessMaf;
public String getHaploidCallMode() {
return haploidCallMode;
}

public FamilyQcAnalysis setRelatednessMaf(String relatednessMaf) {
this.relatednessMaf = relatednessMaf;
public FamilyQcAnalysis setHaploidCallMode(String haploidCallMode) {
this.haploidCallMode = haploidCallMode;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ private void runRelatedness() throws ToolException {

if (CollectionUtils.isNotEmpty(qualityControl.getRelatedness())) {
for (RelatednessReport relatedness : qualityControl.getRelatedness()) {
if (relatednessMethod.equals(relatedness.getMethod()) && relatednessMaf.equals(relatedness.getMaf())) {
if (IBDComputation.PLINK_IBD_METHOD.equals(relatedness.getMethod()) && relatednessMaf.equals(relatedness.getMaf())) {
// Nothing to update
addWarning("Skipping relatedness analysis: it was already computed for method '" + relatednessMethod + "' and MAF '"
+ relatednessMaf + "'");
addWarning("Skipping relatedness analysis: it was already computed for method '" + IBDComputation.PLINK_IBD_METHOD
+ "' and MAF '" + relatednessMaf + "'");
qualityControl = null;
return;
}
Expand Down Expand Up @@ -113,7 +113,7 @@ private void runRelatedness() throws ToolException {

// Run IBD/IBS computation using PLINK in docker
RelatednessReport report = IBDComputation.compute(getStudyId(), getFamily(), sampleIds, getRelatednessMaf(),
getRelatednessThresholds(), getRelatednesResourcePath(), getOutDir(), getVariantStorageManager(), getToken());
getHaploidCallMode(), getRelatednessThresholds(), getRelatednesResourcePath(), getOutDir(), getVariantStorageManager(), getToken());

// Sanity check
if (report == null) {
Expand Down
Loading