Commit 4042b4da authored by Piotr Gawron's avatar Piotr Gawron
Browse files

adding of reference genomes implemented

parent e3306207
......@@ -127,7 +127,7 @@ public interface ReferenceGenomeConnector {
* @param version
* version of the reference genome
* @throws IOException
* thrown when there is a problem with removeing file
* thrown when there is a problem with removing file
*/
void removeGenomeVersion(MiriamData organism, String version) throws IOException;
......@@ -135,7 +135,7 @@ public interface ReferenceGenomeConnector {
* Returns url to the file that describes reference genome.
*
* @param organism
* organism of redference genome
* organism of reference genome
* @param version
* version of the reference genome
* @return url to the file that describes reference genome
......
......@@ -387,6 +387,7 @@ public class UcscReferenceGenomeConnector extends AbstractReferenceGenomeConnect
String remotePath = getGenomePath(organism, version);
FTPFile[] files = ftp.listFiles(remotePath);
for (FTPFile ftpFile : files) {
logger.debug(ftpFile.getName());
if (ftpFile.getName().endsWith(".2bit")) {
if (filename != null) {
logger.warn("More than one 2bit file found in a folder: " + remotePath + ". Using first: " + filename);
......
......@@ -448,6 +448,24 @@ ServerConnector.getReferenceGenomeUrl = function (queryParams, filterParams) {
}
};
/**
*
* @param {Object} queryParams
* @param {string} queryParams.version
* @param {Annotation} queryParams.organism
* @param {string} queryParams.type
* @param {Object} filterParams
*
* @returns {string}
*/
ServerConnector.getAvailableGenomeUrlsUrl = function (queryParams, filterParams) {
return this.getApiUrl({
type: "genomics/taxonomies/" + queryParams.organism.getResource() + "/genomeTypes/" + queryParams.type + "/versions/" + queryParams.version
+ ":getAvailableRemoteUrls",
params: filterParams
});
};
/**
*
* @param {Object} queryParams
......@@ -792,8 +810,8 @@ ServerConnector.getUsersUrl = function (queryParams, filterParams) {
/**
*
* @param {Object} queryParams
* @param {Object} filterParams
* @param {Object} [queryParams]
* @param {Object} [filterParams]
*
* @returns {string}
*/
......@@ -2077,6 +2095,45 @@ ServerConnector.getReferenceGenome = function (params) {
}
};
/**
*
* @param {Object} params
* @param {string} params.version
* @param {Annotation} params.organism
* @param {string} params.type
*
* @returns {Promise<string[]>}
*/
ServerConnector.getAvailableGenomeUrls = function (params) {
var self = this;
var filterParams = {};
return self.sendGetRequest(self.getAvailableGenomeUrlsUrl(params, filterParams)).then(function (content) {
var result = [];
var raw = JSON.parse(content);
for (var i = 0; i < raw.length; i++) {
result.push(raw[i].url);
}
return result;
});
};
/**
*
* @param {ReferenceGenome} genome
* @returns {Promise<ReferenceGenome>}
*/
ServerConnector.addReferenceGenome = function (genome) {
var self = this;
var data = {
organismId: genome.getOrganism().getResource(),
type: genome.getType(),
version: genome.getVersion(),
sourceUrl: genome.getSourceUrl()
};
return self.sendPostRequest(self.getReferenceGenomesUrl(), data);
};
/**
*
* @param {Object} params
......
......@@ -3,6 +3,7 @@
var Promise = require("bluebird");
var AbstractGuiElement = require('../AbstractGuiElement');
var Annotation = require('../../map/data/Annotation');
var GuiConnector = require('../../GuiConnector');
var Functions = require('../../Functions');
......@@ -175,6 +176,19 @@ EditGenomeDialog.prototype.createGeneralTabContent = function () {
});
result.appendChild(table);
$(table).on("change", "[name='genomeOrganismSelect']", function () {
return self._fillTypeSelect(self.getReferenceGenome(), self.getSelectedOrganism());
});
$(table).on("change", "[name='genomeTypeSelect']", function () {
return self._fillVersionSelect(self.getReferenceGenome(), self.getSelectedOrganism(), self.getSelectedType());
});
$(table).on("change", "[name='genomeVersionSelect']", function () {
return self._fillUrl(self.getReferenceGenome(), self.getSelectedOrganism(), self.getSelectedType(), self.getSelectedVersion());
});
var menuRow = Functions.createElement({
type: "div",
className: "minerva-menu-row",
......@@ -217,7 +231,12 @@ EditGenomeDialog.prototype.onSaveClicked = function () {
if (!self.isNew()) {
return self.callListeners("onSave");
} else {
return self.getServerConnector().updateReferenceGenome(self.getReferenceGenome()).then(function () {
var genome = self.getReferenceGenome();
genome.setSourceUrl(self.getSourceUrl());
genome.setOrganism(self.getSelectedOrganism());
genome.setType(self.getSelectedType());
genome.setVersion(self.getSelectedVersion());
return self.getServerConnector().addReferenceGenome(genome).then(function () {
return self.callListeners("onSave");
});
}
......@@ -232,6 +251,7 @@ EditGenomeDialog.prototype._fillOrganismSelect = function (genome) {
var self = this;
return self.getServerConnector().getReferenceGenomeOrganisms().then(function (organisms) {
var genomeOrganismSelect = $("[name=genomeOrganismSelect]", self.getElement());
genomeOrganismSelect.empty();
var selectedOrganism;
if (self.isNew()) {
selectedOrganism = organisms[0];
......@@ -255,7 +275,7 @@ EditGenomeDialog.prototype._fillOrganismSelect = function (genome) {
}));
});
genomeOrganismSelect.val(selectedOrganism.getResource());
return selectedOrganism;
return self._fillTypeSelect(genome, selectedOrganism);
});
};
......@@ -271,6 +291,8 @@ EditGenomeDialog.prototype._fillTypeSelect = function (genome, selectedOrganism)
return self.getServerConnector().getReferenceGenomeTypes({organism: selectedOrganism}).then(function (types) {
var genomeTypeSelect = $("[name=genomeTypeSelect]", self.getElement());
genomeTypeSelect.empty();
var selectedType;
if (self.isNew()) {
selectedType = types[0].type;
......@@ -289,7 +311,7 @@ EditGenomeDialog.prototype._fillTypeSelect = function (genome, selectedOrganism)
}));
});
genomeTypeSelect.val(selectedType);
return selectedType;
return self._fillVersionSelect(genome, selectedOrganism, selectedType);
})
};
......@@ -307,8 +329,9 @@ EditGenomeDialog.prototype._fillVersionSelect = function (genome, selectedOrgani
organism: selectedOrganism,
type: selectedType
}).then(function (versions) {
var genomeVersionSelect = $("[name=genomeVersionSelect]", self.getElement());
genomeVersionSelect.empty();
var selectedVersion;
if (self.isNew()) {
selectedVersion = versions[0].version;
......@@ -327,9 +350,52 @@ EditGenomeDialog.prototype._fillVersionSelect = function (genome, selectedOrgani
}));
});
genomeVersionSelect.val(selectedVersion);
return self._fillUrl(genome, selectedOrganism, selectedType, selectedVersion);
})
};
/**
*
* @param {ReferenceGenome} genome
* @param {Annotation} organism
* @param {string} type
* @param {string} version
* @returns {Promise}
* @private
*/
EditGenomeDialog.prototype._fillUrl = function (genome, organism, type, version) {
var self = this;
var genomeSourceUrlInput = $("[name=genomeSourceUrl]", self.getElement());
var genomeLocalUrlInput = $("[name=genomeLocalUrl]", self.getElement());
var genomeProgressInput = $("[name=genomeProgress]", self.getElement());
genomeLocalUrlInput.prop("disabled", true);
genomeProgressInput.val(genome.getDownloadProgressStatus());
genomeProgressInput.prop("disabled", true);
if (!self.isNew()) {
genomeSourceUrlInput.val(genome.getSourceUrl());
genomeSourceUrlInput.prop("disabled", true);
genomeLocalUrlInput.val(genome.getLocalUrl());
} else {
genomeSourceUrlInput.prop("disabled", false);
genomeLocalUrlInput.val("");
return self.getServerConnector().getAvailableGenomeUrls({
organism: organism,
type: type,
version: version
}).then(function (urls) {
if (urls.length > 0) {
genomeSourceUrlInput.val(urls[0]);
} else {
genomeSourceUrlInput.val("");
}
})
}
return Promise.resolve();
}
;
/**
*
......@@ -364,27 +430,7 @@ EditGenomeDialog.prototype.init = function () {
dataTable.clear().rows.add(data).draw();
var selectedOrganism, selectedType;
return self._fillOrganismSelect(genome).then(function (organism) {
selectedOrganism = organism;
return self._fillTypeSelect(genome, selectedOrganism);
}).then(function (type) {
selectedType = type;
return self._fillVersionSelect(genome, selectedOrganism, selectedType);
}).then(function (version) {
var genomeSourceUrlInput = $("[name=genomeSourceUrl]", self.getElement());
genomeSourceUrlInput.val(genome.getSourceUrl());
genomeSourceUrlInput.prop("disabled", true);
var genomeLocalUrlInput = $("[name=genomeLocalUrl]", self.getElement());
genomeLocalUrlInput.val(genome.getLocalUrl());
genomeLocalUrlInput.prop("disabled", true);
var genomeProgressInput = $("[name=genomeProgress]", self.getElement());
genomeProgressInput.val(genome.getDownloadProgressStatus());
genomeProgressInput.prop("disabled", true);
});
return self._fillOrganismSelect(genome);
};
EditGenomeDialog.prototype.destroy = function () {
......@@ -427,4 +473,45 @@ EditGenomeDialog.prototype.close = function () {
$(self.getElement()).dialog("close");
};
/**
*
* @returns {Annotation}
*/
EditGenomeDialog.prototype.getSelectedOrganism = function () {
var self = this;
return new Annotation({
resource: ($("[name='genomeOrganismSelect']", self.getElement()).val()).toString(),
link: '',
id: 0,
type: ''
})
};
/**
*
* @returns {string}
*/
EditGenomeDialog.prototype.getSelectedType = function () {
var self = this;
return ($("[name='genomeTypeSelect']", self.getElement()).val()).toString();
};
/**
*
* @returns {string}
*/
EditGenomeDialog.prototype.getSelectedVersion = function () {
var self = this;
return ($("[name='genomeVersionSelect']", self.getElement()).val()).toString();
};
/**
*
* @returns {string}
*/
EditGenomeDialog.prototype.getSourceUrl = function () {
var self = this;
return ($("[name='genomeSourceUrl']", self.getElement()).val()).toString();
};
module.exports = EditGenomeDialog;
......@@ -13,45 +13,70 @@ var chai = require('chai');
var assert = chai.assert;
var expect = chai.expect;
/**
*
* @param {ReferenceGenome} genome
* @returns {EditGenomeDialog}
*/
function createDialog(genome) {
return new EditGenomeDialog({
element: testDiv,
referenceGenome: genome,
customMap: null,
serverConnector: ServerConnector
});
}
describe('EditGenomeDialog', function () {
describe('init', function () {
it('new genome', function () {
var dialog;
var project;
var genome = new ReferenceGenome();
return ServerConnector.getProject().then(function (result) {
project = result;
dialog = new EditGenomeDialog({
element: testDiv,
project: project,
referenceGenome: genome,
customMap: null,
serverConnector: ServerConnector
});
return dialog.init();
}).then(function () {
dialog.destroy();
var dialog = createDialog(genome);
return dialog.init().then(function () {
return dialog.destroy();
});
});
});
it('on organism change', function () {
var genome = new ReferenceGenome();
var dialog = createDialog(genome);
return dialog.init().then(function () {
var element = $("[name='genomeOrganismSelect']")[0];
return helper.triggerJqueryEvent(element, "change");
}).then(function () {
return dialog.destroy();
});
});
it('on type change', function () {
var genome = new ReferenceGenome();
var dialog = createDialog(genome);
return dialog.init().then(function () {
var element = $("[name='genomeTypeSelect']")[0];
return helper.triggerJqueryEvent(element, "change");
}).then(function () {
return dialog.destroy();
});
});
it('on version change', function () {
var genome = new ReferenceGenome();
var dialog = createDialog(genome);
return dialog.init().then(function () {
var element = $("[name='genomeVersionSelect']")[0];
return helper.triggerJqueryEvent(element, "change");
}).then(function () {
return dialog.destroy();
});
});
describe('click cancel', function () {
it('new genome', function () {
var dialog;
var project;
var genome = new ReferenceGenome();
return ServerConnector.getProject().then(function (result) {
project = result;
dialog = new EditGenomeDialog({
element: testDiv,
project: project,
referenceGenome: genome,
customMap: null,
serverConnector: ServerConnector
});
return dialog.init();
}).then(function () {
var dialog = createDialog(genome);
return dialog.init().then(function () {
return dialog.open();
}).then(function () {
return $("[name=cancelGenome]", testDiv)[0].onclick();
......@@ -64,13 +89,12 @@ describe('EditGenomeDialog', function () {
describe('click save', function () {
it('existing genome', function () {
var dialog;
return ServerConnector.getReferenceGenome({organism:"9606", type:"UCSC",version:"hg38"}).then(function (genome) {
dialog = new EditGenomeDialog({
element: testDiv,
referenceGenome: genome,
customMap: null,
serverConnector: ServerConnector
});
return ServerConnector.getReferenceGenome({
organism: "9606",
type: "UCSC",
version: "hg38"
}).then(function (genome) {
dialog = createDialog(genome);
return dialog.init();
}).then(function () {
return dialog.open();
......@@ -80,6 +104,19 @@ describe('EditGenomeDialog', function () {
dialog.destroy();
});
});
it('new genome', function () {
helper.loginAsAdmin();
var genome = new ReferenceGenome();
var dialog = createDialog(genome);
return dialog.init().then(function () {
return dialog.open();
}).then(function () {
return $("[name=saveGenome]", testDiv)[0].onclick();
}).then(function () {
dialog.destroy();
});
});
});
});
[{"url":"ftp://hgdownload.cse.ucsc.edu/goldenPath/hg18/bigZips/hg18.2bit"}]
\ No newline at end of file
[{"url":"ftp://hgdownload.cse.ucsc.edu/goldenPath/hg18/bigZips/hg18.2bit"}]
\ No newline at end of file
......@@ -6,13 +6,16 @@ import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javassist.tools.rmi.ObjectNotFoundException;
import lcsb.mapviewer.annotation.services.genome.ReferenceGenomeConnectorException;
import lcsb.mapviewer.api.BaseController;
import lcsb.mapviewer.api.QueryException;
import lcsb.mapviewer.common.Configuration;
......@@ -35,6 +38,17 @@ public class ReferenceGenomeController extends BaseController {
return referenceGenomeController.getReferenceGenome(token, organism, type, version);
}
@RequestMapping(value = "/genomics/taxonomies/{organismId}/genomeTypes/{type}/versions/{version}:getAvailableRemoteUrls", method = {
RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
public List<Map<String, Object>> getRemoteUrls(//
@CookieValue(value = Configuration.AUTH_TOKEN) String token, //
@PathVariable(value = "organismId") String organism, //
@PathVariable(value = "type") String type, //
@PathVariable(value = "version") String version//
) throws SecurityException, QueryException, ObjectNotFoundException {
return referenceGenomeController.getRemoteUrls(token, organism, type, version);
}
@RequestMapping(value = "/genomics/taxonomies/", method = { RequestMethod.GET }, produces = {
MediaType.APPLICATION_JSON_VALUE })
public List<Map<String, Object>> getGenomeTaxonomies(//
......@@ -43,6 +57,15 @@ public class ReferenceGenomeController extends BaseController {
return referenceGenomeController.getReferenceGenomeTaxonomies(token);
}
@RequestMapping(value = "/genomics/", method = { RequestMethod.POST }, produces = {
MediaType.APPLICATION_JSON_VALUE })
public Map<String, Object> addGenome(//
@RequestBody MultiValueMap<String, Object> formData, //
@CookieValue(value = Configuration.AUTH_TOKEN) String token //
) throws SecurityException, QueryException, IOException, ReferenceGenomeConnectorException {
return referenceGenomeController.addReferenceGenome(formData, token);
}
@RequestMapping(value = "/genomics/taxonomies/{organismId}/genomeTypes/", method = { RequestMethod.GET }, produces = {
MediaType.APPLICATION_JSON_VALUE })
public List<Map<String, Object>> getGenomeTaxonomyTypes(//
......@@ -68,8 +91,9 @@ public class ReferenceGenomeController extends BaseController {
) throws SecurityException, QueryException, ObjectNotFoundException {
return referenceGenomeController.getReferenceGenomes(token);
}
@RequestMapping(value = "/genomics/{genomeId}/", method = { RequestMethod.DELETE }, produces = { MediaType.APPLICATION_JSON_VALUE })
@RequestMapping(value = "/genomics/{genomeId}/", method = { RequestMethod.DELETE }, produces = {
MediaType.APPLICATION_JSON_VALUE })
public Map<String, Object> removeGenome(//
@PathVariable(value = "genomeId") String genomeId, //
@CookieValue(value = Configuration.AUTH_TOKEN) String token //
......
......@@ -2,6 +2,7 @@ package lcsb.mapviewer.api.genomics;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
......@@ -13,6 +14,7 @@ import java.util.TreeMap;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MultiValueMap;
import lcsb.mapviewer.annotation.cache.BigFileCache;
import lcsb.mapviewer.annotation.services.genome.ReferenceGenomeConnectorException;
......@@ -25,7 +27,6 @@ import lcsb.mapviewer.model.map.layout.ReferenceGenome;
import lcsb.mapviewer.model.map.layout.ReferenceGenomeGeneMapping;
import lcsb.mapviewer.model.map.layout.ReferenceGenomeType;
import lcsb.mapviewer.model.user.PrivilegeType;
import lcsb.mapviewer.model.user.User;
import lcsb.mapviewer.services.SecurityException;
import lcsb.mapviewer.services.interfaces.IReferenceGenomeService;
......@@ -69,6 +70,30 @@ public class ReferenceGenomeRestImpl extends BaseRestImpl {
}
}
public List<Map<String, Object>> getRemoteUrls(String token, String organismId, String type, String version)
throws SecurityException, QueryException, ObjectNotFoundException {
MiriamData organism = null;
if (organismId != null && !organismId.isEmpty()) {
organism = new MiriamData(MiriamType.TAXONOMY, organismId);
} else {
throw new QueryException("Unknown taxonomy organism: " + organismId);
}
try {
ReferenceGenomeType genomeType = ReferenceGenomeType.valueOf(type);
String url = referenceGenomeService.getUrlForGenomeVersion(genomeType, organism, version);
List<Map<String, Object>> result = new ArrayList<>();
if (url != null) {
Map<String, Object> row = new TreeMap<>();
row.put("url", url);
result.add(row);
}
return result;
} catch (IllegalArgumentException e) {
throw new QueryException("Cannot find type: " + type);
}
}
private Map<String, Object> genomeToMap(ReferenceGenome genome) {
Map<String, Object> result = new TreeMap<>();
result.put("organism", super.createAnnotation(genome.getOrganism()));
......@@ -190,4 +215,29 @@ public class ReferenceGenomeRestImpl extends BaseRestImpl {
return okStatus();