Skip to content

Commit

Permalink
implement first seek use cases
Browse files Browse the repository at this point in the history
  • Loading branch information
wow-such-code committed Oct 7, 2024
1 parent c41c6aa commit 3ec62fd
Show file tree
Hide file tree
Showing 16 changed files with 899 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

// main command with format specifiers for the usage help message
@Command(name = "openbis-scripts",
subcommands = {SampleHierarchyCommand.class, FindDatasetsCommand.class,
subcommands = {SampleHierarchyCommand.class, TransferSampleTypesToSeekCommand.class,
DownloadPetabCommand.class, UploadPetabResultCommand.class, UploadDatasetCommand.class,
SpaceStatisticsCommand.class, TransferDataToSeekCommand.class},
SpaceStatisticsCommand.class, TransferDataToSeekCommand.class, FindDatasetsCommand.class},
description = "A client software for querying openBIS.",
mixinStandardHelpOptions = true, versionProvider = ManifestVersionProvider.class)
public class CommandLineOptions {
Expand Down
103 changes: 51 additions & 52 deletions src/main/java/life/qbic/io/commandline/TransferDataToSeekCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import life.qbic.App;
import life.qbic.model.AssayWithQueuedAssets;
import life.qbic.model.OpenbisExperimentWithDescendants;
import life.qbic.model.OpenbisSeekTranslator;
import life.qbic.model.SeekStructure;
import life.qbic.model.isa.SeekStructure;
import life.qbic.model.download.OpenbisConnector;
import life.qbic.model.download.SEEKConnector;
import life.qbic.model.download.SEEKConnector.AssetToUpload;
Expand Down Expand Up @@ -65,21 +69,21 @@ public class TransferDataToSeekCommand implements Runnable {
AuthenticationOptions auth = new AuthenticationOptions();
OpenbisConnector openbis;
SEEKConnector seek;
OpenbisSeekTranslator translator = new OpenbisSeekTranslator();
OpenbisSeekTranslator translator;

@Override
public void run() {
System.out.println("auth...");
System.out.println("Connecting to openBIS...");

OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(),
auth.getAS(), auth.getDSS());
System.out.println("openbis...");

openbis = new OpenbisConnector(authentication);

boolean isSample = false;
boolean isDataSet = false;
System.out.println("search for experiment...");

System.out.println("Searching for specified object in openBIS...");

boolean isExperiment = experimentExists(objectID);
if (!isExperiment && sampleExists(objectID)) {
Expand All @@ -96,32 +100,15 @@ public void run() {
objectID);
return;
}
System.out.println("Searching done...");
/*
if (isExperiment) {
if (seekNode != null && !seekNode.contains("assays")) {
System.out.printf(
"Seek node %s does not correspond to the provided openBIS experiment identifier. "
+ "Please select an assay node.%n", objectID);
return;
}
}
if (isSample) {
if (seekNode != null && !seekNode.contains("samples")) {
System.out.printf(
"Seek node %s does not correspond to the provided openBIS sample identifier. "
+ "Please select a sample node.%n", objectID);
return;
}
}
*/
System.out.println("Search successful.");
System.out.println("Connecting to SEEK...");

byte[] httpCredentials = Base64.encodeBase64(
(auth.getSeekUser() + ":" + new String(auth.getSeekPassword())).getBytes());
try {
seek = new SEEKConnector(auth.getSeekURL(), httpCredentials, "Default Project",
seek = new SEEKConnector(auth.getSeekURL(), httpCredentials, "seek_test",
"lisym default study");
translator = seek.getTranslator();
} catch (URISyntaxException | IOException | InterruptedException e) {
throw new RuntimeException(e);
}
Expand All @@ -147,13 +134,22 @@ public void run() {
*/
try {
System.out.println("Collecting information from openBIS...");
OpenbisExperimentWithDescendants experiment = openbis.getExperimentWithDescendants(objectID);
String assayID = getAssayIDForOpenBISExperiment(experiment.getExperiment());
List<String> blacklist = parseBlackList(blacklistFile);
if(assayID.isBlank()) {
createNewNodes(experiment, blacklist);
System.out.println("Trying to find existing corresponding assay in SEEK...");
Optional<String> assayID = getAssayIDForOpenBISExperiment(experiment.getExperiment());
assayID.ifPresent(x -> System.out.println("Found assay with id "+assayID.get()));
Set<String> blacklist = parseBlackList(blacklistFile);
System.out.println("Translating openBIS property codes to SEEK names...");
Map<String, String> sampleTypesToIds = seek.getSampleTypeNamesToIDs();
System.out.println("Creating SEEK structure...");
SeekStructure nodeWithChildren = translator.translate(experiment, sampleTypesToIds, blacklist);
if(assayID.isEmpty()) {
System.out.println("Creating new nodes...");
createNewNodes(nodeWithChildren);
} else {
updateNodes(experiment, assayID, blacklist);
System.out.println("Updating nodes...");
updateNodes(nodeWithChildren, assayID.get());
}
} catch (URISyntaxException | InterruptedException | IOException e) {
throw new RuntimeException(e);
Expand Down Expand Up @@ -187,42 +183,46 @@ public void run() {
System.out.println("Done");
}

private List<String> parseBlackList(String blacklistFile) {
List<String> result = new ArrayList<>();
private Set<String> parseBlackList(String blacklistFile) {
if(blacklistFile == null) {
return result;
return new HashSet<>();
}
// trim whitespace, skip empty lines
try (Stream<String> lines = Files.lines(Paths.get(blacklistFile))
.map(String::trim)
.filter(s -> !s.isBlank())) {
return lines.collect(Collectors.toList());

Set<String> codes = lines.collect(Collectors.toSet());

for(String code : codes) {
if(!OpenbisConnector.datasetCodePattern.matcher(code).matches()) {
throw new RuntimeException("Invalid dataset code: " + code+". Please make sure to use valid"
+ " dataset codes in the blacklist file.");
}
}
return codes;
} catch (IOException e) {
throw new RuntimeException(blacklistFile+" could not be found or read.");
}
}

private void updateNodes(OpenbisExperimentWithDescendants experiment, String assayID, List<String> blacklist) {
System.err.println("updating nodes of assay "+assayID);
SeekStructure nodeWithChildren = translator.translate(experiment, blacklist);
private void updateNodes(SeekStructure nodeWithChildren, String assayID) {
String updatedEndpoint = seek.updateNode(nodeWithChildren, assayID, transferData);
System.out.printf("%s was successfully updated.%n", endpoint);
System.out.printf("%s was successfully updated.%n", updatedEndpoint);
}

private void createNewNodes(OpenbisExperimentWithDescendants experiment, List<String> blacklist)
private void createNewNodes(SeekStructure nodeWithChildren)
throws URISyntaxException, IOException, InterruptedException {
System.err.println("creating new nodes");
SeekStructure nodeWithChildren = translator.translate(experiment, blacklist);
List<AssetToUpload> assetsToUpload = seek.createNode(nodeWithChildren, transferData);
AssayWithQueuedAssets assetsOfAssayToUpload = seek.createNode(nodeWithChildren, transferData);
if(transferData) {
for(AssetToUpload asset : assetsToUpload) {
for(AssetToUpload asset : assetsOfAssayToUpload.getAssets()) {
System.out.printf("Streaming file %s from openBIS to SEEK...%n", asset.getFilePath());
String fileURL = seek.uploadStreamContent(asset.getBlobEndpoint(),
() -> openbis.streamDataset(asset.getDataSetCode(), asset.getFilePath()));
System.out.printf("File stored here: %s%n", fileURL);
}
}
System.out.printf("%s was successfully created.%n", endpoint);
System.out.printf("%s was successfully created.%n", assetsOfAssayToUpload.getAssayEndpoint());
}

private boolean sampleExists(String objectID) {
Expand All @@ -237,7 +237,7 @@ private boolean experimentExists(String experimentID) {
return openbis.experimentExists(experimentID);
}

private String getAssayIDForOpenBISExperiment(Experiment experiment)
private Optional<String> getAssayIDForOpenBISExperiment(Experiment experiment)
throws URISyntaxException, IOException, InterruptedException {
// the perm id is unique and afaik not used by scientists. it is highly unlikely that it would
// "accidentally" be part of another title or description. however, care should be taken here,
Expand All @@ -246,12 +246,12 @@ private String getAssayIDForOpenBISExperiment(Experiment experiment)
String permID = experiment.getPermId().getPermId();
List<String> assayIDs = seek.searchAssaysContainingKeyword(permID);
if(assayIDs.isEmpty()) {
return "";
return Optional.empty();
}
if(assayIDs.size() == 1) {
return assayIDs.get(0);
return Optional.of(assayIDs.get(0));
}
throw new RuntimeException("Search term "+permID+ " was found in more than one assay: "+assayIDs);
throw new RuntimeException("Experiment identifier "+permID+ " was found in more than one assay: "+assayIDs);
}

private void sendDatasetToSeek(String datasetCode, String assayID)
Expand All @@ -265,8 +265,7 @@ private void sendDatasetToSeek(String datasetCode, String assayID)
}
DataSet dataset = datasets.get(0);
List<DataSetFile> files = openbis.getDatasetFiles(dataset);
List<AssetToUpload> assets = seek.createAssets(files, dataset.getType().getCode(),
Arrays.asList(assayID));
List<AssetToUpload> assets = seek.createAssets(files, Arrays.asList(assayID));
for(AssetToUpload asset : assets) {
System.out.printf("Streaming file %s from openBIS to SEEK...%n", asset.getFilePath());
String fileURL = seek.uploadStreamContent(asset.getBlobEndpoint(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package life.qbic.io.commandline;

import ch.ethz.sis.openbis.generic.OpenBIS;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.SampleType;
import java.io.IOException;
import java.net.URISyntaxException;
import life.qbic.App;
import life.qbic.model.OpenbisSeekTranslator;
import life.qbic.model.SampleTypesAndMaterials;
import life.qbic.model.download.OpenbisConnector;
import life.qbic.model.download.SEEKConnector;
import org.apache.commons.codec.binary.Base64;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;

@Command(name = "sample-type-transfer",
description =
"Transfers sample types from openBIS to SEEK.")
public class TransferSampleTypesToSeekCommand implements Runnable {
@Mixin
AuthenticationOptions auth = new AuthenticationOptions();
OpenbisConnector openbis;
SEEKConnector seek;
OpenbisSeekTranslator translator;

@Override
public void run() {
System.out.println("auth...");

OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(),
auth.getAS(), auth.getDSS());
System.out.println("openbis...");

openbis = new OpenbisConnector(authentication);

byte[] httpCredentials = Base64.encodeBase64(
(auth.getSeekUser() + ":" + new String(auth.getSeekPassword())).getBytes());
try {
seek = new SEEKConnector(auth.getSeekURL(), httpCredentials, "seek_test",
"lisym default study");
translator = seek.getTranslator();
} catch (URISyntaxException | IOException | InterruptedException e) {
throw new RuntimeException(e);
}

SampleTypesAndMaterials types = openbis.getSampleTypesWithMaterials();

try {
for(SampleType type : types.getSampleTypes()) {
System.err.println("creating "+type.getCode());
String sampleTypeId = seek.createSampleType(translator.translate(type));
System.err.println("created "+sampleTypeId);
}
} catch (URISyntaxException | IOException | InterruptedException e) {
throw new RuntimeException(e);
}

System.out.println("Done");
}

}
23 changes: 23 additions & 0 deletions src/main/java/life/qbic/model/AssayWithQueuedAssets.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package life.qbic.model;

import java.util.List;
import life.qbic.model.download.SEEKConnector.AssetToUpload;

public class AssayWithQueuedAssets {

private String assayEndpoint;
private List<AssetToUpload> assetsToUpload;

public AssayWithQueuedAssets(String assayEndpoint, List<AssetToUpload> assetsToUpload) {
this.assayEndpoint = assayEndpoint;
this.assetsToUpload = assetsToUpload;
}

public String getAssayEndpoint() {
return assayEndpoint;
}

public List<AssetToUpload> getAssets() {
return assetsToUpload;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ public class OpenbisExperimentWithDescendants {
private Experiment experiment;
private List<Sample> samples;
private List<DatasetWithProperties> datasets;
private Map<DataSetPermId, List<DataSetFile>> datasetCodeToFiles;
private Map<String, List<DataSetFile>> datasetCodeToFiles;

public OpenbisExperimentWithDescendants(Experiment experiment, List<Sample> samples,
List<DatasetWithProperties> datasets, Map<DataSetPermId, List<DataSetFile>> datasetCodeToFiles) {
List<DatasetWithProperties> datasets, Map<String, List<DataSetFile>> datasetCodeToFiles) {
this.experiment = experiment;
this.samples = samples;
this.datasets = datasets;
Expand Down
Loading

0 comments on commit 3ec62fd

Please sign in to comment.