Skip to content

Commit

Permalink
Started implementation of labeled datastore endpoint. Improvements to…
Browse files Browse the repository at this point in the history
… data models.
  • Loading branch information
Rui-Jesus committed Feb 23, 2024
1 parent 9ee9d25 commit 7cbff44
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,28 @@
*/
package pt.ua.dicoogle.core.mlprovider;

import org.dcm4che2.data.BasicDicomObject;
import org.dcm4che2.data.Tag;
import org.dcm4che2.data.TransferSyntax;
import org.dcm4che2.data.VR;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pt.ua.dicoogle.plugins.PluginController;
import pt.ua.dicoogle.sdk.datastructs.SearchResult;
import pt.ua.dicoogle.sdk.mlprovider.MLDataset;
import pt.ua.dicoogle.sdk.mlprovider.MLDicomDataset;
import pt.ua.dicoogle.sdk.mlprovider.MLImageDataset;
import pt.ua.dicoogle.sdk.datastructs.dim.BulkAnnotation;
import pt.ua.dicoogle.sdk.mlprovider.*;
import pt.ua.dicoogle.server.web.dicom.ROIExtractor;
import pt.ua.dicoogle.server.web.utils.cache.WSICache;

import java.util.HashMap;
import java.util.UUID;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

Expand Down Expand Up @@ -65,10 +75,12 @@ public MLDataset call() throws Exception {
switch (request.getDataType()){
case DICOM:
return new MLDicomDataset(request.getDimLevel(), request.getUids());
case IMAGE: // Not operational
throw new UnsupportedOperationException("Datastore requests for image objects is not supported");
/*
HashMap<String, String> extraFields = new HashMap<String, String>();
case IMAGE:
//throw new UnsupportedOperationException("Datastore requests for image objects is not supported");

HashMap<String, String> extraFields = new HashMap<>();

String path = this.ensureAndCreatePath();

extraFields.put("SOPInstanceUID", "SOPInstanceUID");
extraFields.put("SharedFunctionalGroupsSequence_PixelMeasuresSequence_PixelSpacing", "SharedFunctionalGroupsSequence_PixelMeasuresSequence_PixelSpacing");
Expand All @@ -80,6 +92,8 @@ public MLDataset call() throws Exception {
extraFields.put("ImageType", "ImageType");

MLImageDataset mlDataset = new MLImageDataset();
HashMap<ImageEntry, MLlabel> dataset = new HashMap<>();
Set<String> classes = new HashSet<>();

this.request.getDataset().entrySet().forEach((entry -> {
try {
Expand All @@ -88,18 +102,59 @@ public MLDataset call() throws Exception {
Iterable<SearchResult> results = controller
.query(controller.getQueryProvidersName(true).get(0), "SOPInstanceUID:" + entry.getKey(), extraFields).get();

int c = 0;
for (SearchResult image : results) {
//List<ImageROI> rois = (List<ImageROI>) roiExtractor.extractROI();

BasicDicomObject dcm = new BasicDicomObject();
dcm.putString(Tag.TransferSyntaxUID, VR.CS, "1.2.840.10008.1.2.4.50");

for(BulkAnnotation annotation: entry.getValue()){
BufferedImage roi = roiExtractor.extractROI(image.get("SOPInstanceUID").toString(), annotation);
String roiFileName = annotation.getLabel().getName() + c++;
classes.add(annotation.getLabel().getName());
File output = new File(path + File.separator + roiFileName + ".jpeg");
ImageIO.write(roi, "jpeg", output);
dataset.put(new ImageEntry(dcm, output.toURI()), annotation.getLabel());
}
}

} catch (InterruptedException | ExecutionException e) {
} catch (IOException | InterruptedException | ExecutionException e) {
logger.error("Error preparing datastore task", e);
}
}));

mlDataset.setMultiClass(classes.size() > 2);
mlDataset.setDataset(dataset);

return mlDataset;
*/
default:
return null;
}
}

private String ensureAndCreatePath(){
Path datasetsFolder = Paths.get("datasets");
// Check if the folder exists
if (!Files.exists(datasetsFolder)) {
try {
Files.createDirectories(datasetsFolder);
System.out.println("Datasets folder didn't exist, creating one.");
} catch (Exception e) {
System.err.println("Failed to create datasets folder: " + e.getMessage());
}
}

Path datasetFolder = Paths.get("datasets" + File.separator + System.currentTimeMillis());

if (!Files.exists(datasetFolder)) {
try {
Files.createDirectories(datasetFolder);
} catch (Exception e) {
System.err.println("Failed to create dataset folder: " + e.getMessage());
}
}

return datasetFolder.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -863,16 +863,18 @@ public Task<MLDataset> datastore(final DatastoreRequest datasetRequest) {
String uuid = UUID.randomUUID().toString();
Task<MLDataset> prepareTask =
new Task<>("MLPrepareDatastoreTask" + uuid, new PrepareDatastoreTask(this, datasetRequest));
MLProviderInterface mlInterface = getMachineLearningProviderByName(datasetRequest.getProvider(), true);
if (mlInterface == null) {
logger.error("MLProvider with name {} not found", datasetRequest.getProvider());
prepareTask.cancel(true);
return prepareTask;
}

prepareTask.onCompletion(() -> {
MLProviderInterface mlInterface = getMachineLearningProviderByName(datasetRequest.getProvider(), true);
if (mlInterface == null) {
logger.error("MLProvider with name {} not found", prepareTask.getName());
} else {
try {
mlInterface.dataStore(prepareTask.get());
} catch (InterruptedException | ExecutionException e) {
logger.error("Task {} failed execution", prepareTask.getName(), e);
}
try {
mlInterface.dataStore(prepareTask.get());
} catch (InterruptedException | ExecutionException e) {
logger.error("Task {} failed execution", prepareTask.getName(), e);
}
});
logger.debug("Fired prepare dataset task with uuid {}", uuid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
package pt.ua.dicoogle.sdk.datastructs.dim;

import pt.ua.dicoogle.sdk.mlprovider.MLlabel;

import java.util.Arrays;
import java.util.List;

Expand Down Expand Up @@ -69,7 +71,7 @@ public enum CoordinateType {

private AnnotationType annotationType;

private String label;
private MLlabel label;

private List<Point2D> points;

Expand Down Expand Up @@ -99,11 +101,11 @@ public void setAnnotationType(AnnotationType annotationType) {
this.annotationType = annotationType;
}

public String getLabel() {
public MLlabel getLabel() {
return label;
}

public void setLabel(String label) {
public void setLabel(MLlabel label) {
this.label = label;
}

Expand Down
16 changes: 12 additions & 4 deletions sdk/src/main/java/pt/ua/dicoogle/sdk/datastructs/dim/ImageROI.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ private FileType(String s, String mimeType) {

private double y;

private int width;
private double width;

private int height;
private double height;

private String sopInstanceUID;

Expand All @@ -67,6 +67,14 @@ public ImageROI(String sopInstanceUID, int x, int y, int width, int height) {
this.height = height;
}

public ImageROI(String sopInstanceUID, double x, double y, double width, double height, URI roi) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.uriROI = roi;
}

public double getX() {
return x;
}
Expand All @@ -91,15 +99,15 @@ public void setSopInstanceUID(String sopInstanceUID) {
this.sopInstanceUID = sopInstanceUID;
}

public int getWidth() {
public double getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}

public int getHeight() {
public double getHeight() {
return height;
}

Expand Down
68 changes: 68 additions & 0 deletions sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/ImageEntry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/
*
* This file is part of Dicoogle/dicoogle-sdk.
*
* Dicoogle/dicoogle-sdk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dicoogle/dicoogle-sdk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dicoogle. If not, see <http://www.gnu.org/licenses/>.
*/
package pt.ua.dicoogle.sdk.mlprovider;

import org.dcm4che2.data.DicomObject;

import java.net.URI;
import java.util.Objects;

/**
* Used to map the metadata of regions of interest.
*/
public class ImageEntry {

private DicomObject object;

private URI file;

public ImageEntry(DicomObject object, URI file) {
this.object = object;
this.file = file;
}

public DicomObject getObject() {
return object;
}

public void setObject(DicomObject object) {
this.object = object;
}

public URI getFile() {
return file;
}

public void setFile(URI file) {
this.file = file;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ImageEntry that = (ImageEntry) o;
return object.equals(that.object) && file.equals(that.file);
}

@Override
public int hashCode() {
return Objects.hash(file);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ public class MLCSVDataset extends MLDataset {

private InputStream csvFile;

public MLCSVDataset(){
super("", MLDataType.CSV);
}
}
22 changes: 22 additions & 0 deletions sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/MLDataset.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,26 @@ public abstract class MLDataset {

protected String name;

protected MLDataType dataType;

public MLDataset(String name, MLDataType dataType) {
this.name = name;
this.dataType = dataType;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public MLDataType getDataType() {
return dataType;
}

public void setDataType(MLDataType dataType) {
this.dataType = dataType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ public class MLDicomDataset extends MLDataset {
private List<String> dimUIDs;

public MLDicomDataset(DimLevel level){
super("", MLDataType.DICOM);
this.level = level;
dimUIDs = new ArrayList<>();
}

public MLDicomDataset(DimLevel level, List<String> dimUIDs){
super("", MLDataType.DICOM);
this.level = level;
this.dimUIDs = dimUIDs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,32 @@
*/
package pt.ua.dicoogle.sdk.mlprovider;

import java.net.URI;
import java.util.HashMap;
import java.util.List;

/**
* An ML dataset of image objects.
* Optionally an array of labels can be given to create a labelled dataset.
*/
public class MLImageDataset extends MLDataset {

private HashMap<URI, List<MLlabel>> dataset;
private HashMap<ImageEntry, MLlabel> dataset;

private boolean multiClass;

public HashMap<URI, List<MLlabel>> getDataset() {
public MLImageDataset() {
super("name", MLDataType.IMAGE);
}

public MLImageDataset(HashMap<ImageEntry, MLlabel> dataset) {
super("", MLDataType.IMAGE);
this.dataset = dataset;
}

public HashMap<ImageEntry, MLlabel> getDataset() {
return dataset;
}

public void setDataset(HashMap<URI, List<MLlabel>> dataset) {
public void setDataset(HashMap<ImageEntry, MLlabel> dataset) {
this.dataset = dataset;
}

Expand Down
Loading

0 comments on commit 7cbff44

Please sign in to comment.