Skip to content

Commit

Permalink
Merge pull request #1012 from opencb/TASK-7049
Browse files Browse the repository at this point in the history
TASK-7049 - Liftover analysis
  • Loading branch information
jmjuanes authored Mar 6, 2025
2 parents a99e5e9 + 200d5bd commit d154928
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/core/clients/opencga/api/Variant.js
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ export default class Variant extends OpenCGAParentClass {
}

/** BCFtools liftover plugin maps coordinates from assembly 37 to 38.
* @param {Object} data - BCFtools +liftover plugin params.
* @param {Object} data - BCFtools +liftover plugin parameters.
* @param {Object} [params] - The Object containing the following optional parameters:
* @param {String} [params.study] - study.
* @param {String} [params.jobId] - Job ID. It must be a unique string within the study. An ID will be autogenerated automatically if not
Expand Down
8 changes: 8 additions & 0 deletions src/sites/iva/conf/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,14 @@ const SUITE = {
{
id: "bcftools",
name: "BCFtools",
acronym: "BC",
description: "",
icon: "",
visibility: "public"
},
{
id: "liftover",
name: "LiftOver",
acronym: "GT",
description: "",
icon: "",
Expand Down
10 changes: 10 additions & 0 deletions src/sites/iva/iva-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import "../../webcomponents/variant/analysis/mendelian-error-analysis.js";
import "../../webcomponents/variant/analysis/sample-qc-analysis.js";
import "../../webcomponents/variant/analysis/individual-qc-analysis.js";
import "../../webcomponents/variant/analysis/family-qc-analysis.js";
import "../../webcomponents/variant/analysis/liftover-analysis.js";
import "../../webcomponents/variant/analysis/knockout-analysis.js";
import "../../webcomponents/variant/analysis/opencga-plink-analysis.js";
import "../../webcomponents/variant/analysis/opencga-gatk-analysis.js";
Expand Down Expand Up @@ -219,6 +220,7 @@ class IvaApp extends LitElement {
"mendelian-error",
"plink",
"gatk",
"liftover",
"bcftools",
"variant-export",
"variant-stats-exporter",
Expand Down Expand Up @@ -1929,6 +1931,14 @@ class IvaApp extends LitElement {
</div>
` : nothing}
${this.config.enabledComponents["liftover"] ? html`
<div class="container py-3" id="liftover-analysis">
<liftover-analysis
.opencgaSession="${this.opencgaSession}">
</liftover-analysis>
</div>
` : nothing}
${this.config.enabledComponents["bcftools"] ? html`
<div class="content p-3" id="bcftools-analysis">
<bcftools-analysis
Expand Down
180 changes: 180 additions & 0 deletions src/webcomponents/variant/analysis/liftover-analysis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import {LitElement, html, render} from "lit";
import UtilsNew from "../../../core/utils-new.js";
import AnalysisUtils from "../../commons/analysis/analysis-utils";
import "../../commons/forms/data-form.js";
import "../../commons/filters/catalog-search-autocomplete.js";

export default class LiftOverAnalysis extends LitElement {

constructor() {
super();

this.#init();
}

createRenderRoot() {
return this;
}

static get properties() {
return {
toolParams: {
type: Object,
},
opencgaSession: {
type: Object,
},
config: {
type: Object
},
};
}

#init() {
this.ANALYSIS_TOOL = "liftover";
this.ANALYSIS_TITLE = "LiftOver Analysis";
this.ANALYSIS_DESCRIPTION = "Liftover your VCF files from hg19 to hg38 (GRCH38 for Ensembl or HG38 for NCBI).";

this.DEFAULT_TOOLPARAMS = {
targetAssembly: "GRCh38",
};
// Make a deep copy to avoid modifying default object.
this._toolParams = {
...UtilsNew.objectClone(this.DEFAULT_TOOLPARAMS)
};

this._config = this.getDefaultConfig();
}

update(changedProperties) {
if (changedProperties.has("toolParams")) {
this._toolParams = {
...UtilsNew.objectClone(this.DEFAULT_TOOLPARAMS),
...this.toolParams,
};
}
if (changedProperties.has("config")) {
// Note: this.config is merged with the default config in the AnalysisUtils.getAnalysisConfiguration method.
this._config = this.getDefaultConfig();
}
super.update(changedProperties);
}

check() {
return null;
}

onFieldChange() {
this._toolParams = {...this._toolParams};
this.requestUpdate();
}

onSubmit() {
const toolParams = {
files: this._toolParams.files.split(","),
targetAssembly: this._toolParams.targetAssembly,
outdir: this._toolParams.outdir || "",
};
const params = {
study: this.opencgaSession.study.fqn,
...AnalysisUtils.fillJobParams(this._toolParams, this.ANALYSIS_TOOL),
};

AnalysisUtils.submit(
this.ANALYSIS_TITLE,
this.opencgaSession.opencgaClient.variants()
.runLiftover(toolParams, params),
this,
);
}

onClear() {
this._toolParams = {
...UtilsNew.objectClone(this.DEFAULT_TOOLPARAMS),
};
this.requestUpdate();
}

render() {
return html`
<data-form
.data="${this._toolParams}"
.config="${this._config}"
@fieldChange="${e => this.onFieldChange(e)}"
@clear="${this.onClear}"
@submit="${this.onSubmit}">
</data-form>
`;
}

getDefaultConfig() {
const params = [
{
title: "Input Parameters",
elements: [
{
title: "VCF File",
required: true,
field: "files",
type: "custom",
display: {
render: (files, dataFormFilterChange) => {
return html `
<catalog-search-autocomplete
.value="${files}"
.resource="${"FILE"}"
.query="${{format: "VCF"}}"
.opencgaSession="${this.opencgaSession}"
.config="${{multiple: true}}"
@filterChange="${e => dataFormFilterChange(e.detail.value)}">
</catalog-search-autocomplete>
`;
}
}
},
{
title: "Target Assembly",
field: "targetAssembly",
type: "select",
required: true,
allowedValues: ["GRCh38", "hg38"],
display: {
helpMessage: "Target assembly for lift over.",
},
},
{
title: "Output Directory",
field: "outdir",
type: "custom",
display: {
render: (outdir, dataFormFilterChange) => {
return html`
<catalog-search-autocomplete
.value="${outdir}"
.resource="${"DIRECTORY"}"
.opencgaSession="${this.opencgaSession}"
.config="${{multiple: false}}"
@filterChange="${e => dataFormFilterChange(e.detail.value)}">
</catalog-search-autocomplete>
`;
},
helpMessage: "Destination path where the lifted-over VCF files will be stored. If left empty, the VCF files will be stored in the job folder.",
},
},
],
}
];

return AnalysisUtils.getAnalysisConfiguration(
this.ANALYSIS_TOOL,
this.ANALYSIS_TITLE,
this.ANALYSIS_DESCRIPTION,
params,
this.check(),
this.config,
);
}

}

customElements.define("liftover-analysis", LiftOverAnalysis);

0 comments on commit d154928

Please sign in to comment.