Skip to content

Commit

Permalink
Merge pull request #5 from qbicsoftware/feature/statistics
Browse files Browse the repository at this point in the history
Add space-based statistics
  • Loading branch information
wow-such-code authored Jul 16, 2024
2 parents 68a1e95 + 5f773a1 commit 46d461e
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

// main command with format specifiers for the usage help message
@Command(name = "openbis-scripts",
subcommands = { SampleHierarchyCommand.class, FindDatasetsCommand.class, UploadDatasetCommand.class },
subcommands = { SampleHierarchyCommand.class, FindDatasetsCommand.class,
UploadDatasetCommand.class, SpaceStatisticsCommand.class },
description = "A client software for querying openBIS.",
mixinStandardHelpOptions = true, versionProvider = ManifestVersionProvider.class)
public class CommandLineOptions {
Expand Down
31 changes: 21 additions & 10 deletions src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.Person;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import life.qbic.App;
import life.qbic.model.DatasetWithProperties;
import life.qbic.model.download.OpenbisConnector;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
Expand Down Expand Up @@ -45,12 +45,28 @@ public void run() {
.sorted(Comparator.comparing(
(DataSet d) -> d.getExperiment().getProject().getSpace().getCode())).collect(
Collectors.toList());
Map<String, String> properties = new HashMap<>();
if (!datasets.isEmpty()) {
Optional<String> patientID = openbis.findPropertyInSampleHierarchy("PATIENT_DKFZ_ID",
datasets.get(0).getExperiment().getIdentifier());
patientID.ifPresent(s -> properties.put("Patient ID", s));
}
List<DatasetWithProperties> datasetWithProperties = datasets.stream().map(dataSet -> {
DatasetWithProperties ds = new DatasetWithProperties(dataSet);
for (String key : properties.keySet()) {
ds.addProperty(key, properties.get(key));
}
return ds;
}).collect(Collectors.toList());
int datasetIndex = 0;
System.out.println();
System.out.printf("Found %s datasets for experiment %s:%n", datasets.size(), experimentCode);
for (DataSet dataSet : datasets) {
for (DatasetWithProperties dataSet : datasetWithProperties) {
datasetIndex++;
System.out.println("["+datasetIndex+"]");
for(String key : dataSet.getProperties().keySet()) {
System.out.println(key+ ": "+properties.get(key));
}
System.out.printf("ID: %s (%s)%n", dataSet.getCode(), dataSet.getExperiment().getIdentifier());
System.out.println("Type: "+dataSet.getType().getCode());
Person person = dataSet.getRegistrator();
Expand All @@ -62,9 +78,4 @@ public void run() {
}
}

private String getTimeStamp() {
final String PATTERN_FORMAT = "YYYY-MM-dd_HHmmss";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_FORMAT);
return LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).format(formatter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import life.qbic.model.Configuration;
import life.qbic.model.SampleTypeConnection;
import life.qbic.model.download.FileSystemWriter;
import life.qbic.model.download.ModelReporter;
import life.qbic.model.download.SummaryWriter;
import life.qbic.model.download.OpenbisConnector;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
Expand All @@ -38,10 +38,10 @@ public void run() {
List<String> summary = new ArrayList<>();
List<String> spaces = new ArrayList<>();
if(space!=null) {
summary.add("Querying samples in space: "+space+"...\n");
summary.add("Querying samples in space: "+space+"...");
spaces.add(space);
} else {
summary.add("Querying samples in all available spaces...\n");
summary.add("Querying samples in all available spaces...");
}
OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.getUser(), auth.getAS());
OpenbisConnector openbis = new OpenbisConnector(authentication);
Expand All @@ -55,13 +55,13 @@ public void run() {
System.out.println(s);
}
Path outputPath = Paths.get(Configuration.LOG_PATH.toString(),
"summary_model_"+getTimeStamp()+".txt");
"sample_model_summary"+getTimeStamp()+".txt");
if(outpath!=null) {
outputPath = Paths.get(outpath);
}
ModelReporter modelReporter = new FileSystemWriter(outputPath);
SummaryWriter summaryWriter = new FileSystemWriter(outputPath);
try {
modelReporter.reportSummary(summary);
summaryWriter.reportSummary(summary);
} catch (IOException e) {
throw new RuntimeException("Could not write summary file.");
}
Expand Down
135 changes: 135 additions & 0 deletions src/main/java/life/qbic/io/commandline/SpaceStatisticsCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package life.qbic.io.commandline;

import ch.ethz.sis.openbis.generic.OpenBIS;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import life.qbic.App;
import life.qbic.model.Configuration;
import life.qbic.model.download.FileSystemWriter;
import life.qbic.model.download.SummaryWriter;
import life.qbic.model.download.OpenbisConnector;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
import picocli.CommandLine.Option;

@Command(name = "statistics",
description = "lists the number of collections, sample objects and attached datasets (by type)"
+ "for one or all spaces accessible by the user")
public class SpaceStatisticsCommand implements Runnable {

@Option(arity = "1", paramLabel = "<space>", description = "optional openBIS spaces to filter samples", names = {"-s", "--space"})
private String space;
@Option(arity = "1", paramLabel = "<output file path>", description = "optional output path", names = {"-o", "--out"})
private String outpath;
@Option(arity = "0", description = "shows results for openBIS settings and material spaces. Ignored if a specific space is selected.",
names = {"--show-settings"})
private boolean allSpaces;
@Mixin
AuthenticationOptions auth = new AuthenticationOptions();

@Override
public void run() {
List<String> summary = new ArrayList<>();
List<String> blackList = new ArrayList<>(Arrays.asList("ELN_SETTINGS", "MATERIAL.GLOBAL"));
List<String> spaces = new ArrayList<>();
if (space != null) {
summary.add("Querying samples in space: " + space);
spaces.add(space);
} else {
summary.add("Querying samples in all available spaces...");
}
OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.getUser(), auth.getAS());
OpenbisConnector openbis = new OpenbisConnector(authentication);

if (spaces.isEmpty()) {
spaces = openbis.getSpaces();
if(!allSpaces) {
spaces.removeAll(blackList);
}
}

Map<String, Map<String, List<Experiment>>> experiments = openbis.getExperimentsByTypeAndSpace(spaces);
Map<String, Map<String, List<Sample>>> samples = openbis.getSamplesByTypeAndSpace(spaces);
Map<String, Map<String, List<DataSet>>> datasets = openbis.getDatasetsByTypeAndSpace(spaces);

for(String space : spaces) {
summary.add("-----");
summary.add("Summary for "+space);
summary.add("-----");
int numExps = 0;
if (experiments.containsKey(space)) {
numExps = experiments.get(space).values().stream().mapToInt(List::size).sum();
}
summary.add("Experiments ("+numExps+"):");
summary.add("");
if(!experiments.isEmpty()) {
Map<String, List<Experiment>> exps = experiments.get(space);
for (String type : exps.keySet()) {
summary.add(type + ": " + exps.get(type).size());
}
}
summary.add("");
int numSamples = 0;
if (samples.containsKey(space)) {
numSamples = samples.get(space).values().stream().mapToInt(List::size).sum();
}
summary.add("Samples ("+numSamples+"):");
summary.add("");
if(!samples.isEmpty()) {
Map<String, List<Sample>> samps = samples.get(space);
for (String type : samps.keySet()) {
summary.add(type + ": " + samps.get(type).size());
}
}
summary.add("");
int numData = 0;
if (datasets.containsKey(space)) {
numData = datasets.get(space).values().stream().mapToInt(List::size).sum();
}
summary.add("Attached datasets (" + numData + "):");
summary.add("");
if (datasets.get(space) != null) {
Map<String, List<DataSet>> dsets = datasets.get(space);
for (String dataType : dsets.keySet()) {
summary.add(dataType + ": " + dsets.get(dataType).size());
}
}

summary.add("");
}

for(String line : summary) {
System.out.println(line);
}

Path outputPath = Paths.get(Configuration.LOG_PATH.toString(),
"spaces_summary_"+getTimeStamp()+".txt");
if(outpath!=null) {
outputPath = Paths.get(outpath);
}
SummaryWriter summaryWriter = new FileSystemWriter(outputPath);
try {
summaryWriter.reportSummary(summary);
} catch (IOException e) {
throw new RuntimeException("Could not write summary file.");
}
}

private String getTimeStamp() {
final String PATTERN_FORMAT = "YYYY-MM-dd_HHmmss";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_FORMAT);
return LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).format(formatter).toString();
}
}
60 changes: 60 additions & 0 deletions src/main/java/life/qbic/model/DatasetWithProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package life.qbic.model;

import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.Person;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
* Wrapper class for openBIS DataSets that collects additional information, e.g. from samples,
* experiments etc. further up in the hierarchy.
*/
public class DatasetWithProperties {

private final DataSet dataset;
private final Map<String, String> properties;

public DatasetWithProperties(DataSet dataset) {
this.dataset = dataset;
this.properties = new HashMap<>();
}

public void addProperty(String key, String value) {
this.properties.put(key, value);
}

public String getProperty(String key) {
return properties.get(key);
}

public Map<String, String> getProperties() {
return properties;
}

public DataSet getDataset() {
return dataset;
}

public String getCode() {
return dataset.getCode();
}

public Experiment getExperiment() {
return dataset.getExperiment();
}

public DataSetType getType() {
return dataset.getType();
}

public Person getRegistrator() {
return dataset.getRegistrator();
}

public Date getRegistrationDate() {
return dataset.getRegistrationDate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*
* @author: Sven Fillinger, Andreas Friedrich
*/
public class FileSystemWriter implements ModelReporter {
public class FileSystemWriter implements SummaryWriter {

/**
* File that stores the summary report content for valid checksums.
Expand Down
Loading

0 comments on commit 46d461e

Please sign in to comment.