Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugins/BIOP/ArgoLight_default_argoslide_params.csv
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ArgoSIM,false,5,100,21
ArgoSLJ488,false,15,660,45
ArgoSLG482,true,15,570,39
ArgoHM,false,15,660,45
4 changes: 2 additions & 2 deletions plugins/BIOP/ArgoLight_default_params.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
OMERO Host,omero-server-poc.epfl.ch
OMERO Host,omero-server-test.epfl.ch
OMERO Port,4064
ArgoSlides,ArgoSIM,ArgoSLJ488,ArgoSLG482
ArgoSlides,ArgoSIM,ArgoSLJ488,ArgoSLG482,ArgoHM
Root folder,D:\Remy\ArgoLight\new protocole\Raw Data
Saving folder,D:\Remy\ArgoLight\new protocole
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.scijava</groupId>
<artifactId>pom-scijava</artifactId>
<version>43.0.0</version>
<version>44.0.0</version>
<relativePath />
</parent>

Expand Down
213 changes: 143 additions & 70 deletions src/main/java/ch/epfl/biop/command/ArgoLightCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,14 @@
import loci.plugins.BF;
import loci.plugins.in.ImporterOptions;
import net.imagej.ImageJ;
import omero.gateway.exception.DSAccessException;
import org.scijava.Cancelable;
import org.scijava.command.Command;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import org.scijava.thread.ThreadService;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JRootPane;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog;
Expand All @@ -65,6 +49,9 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* This plugin runs image analysis pipeline on ArgoLight slide, pattern B, to measure the quality of objectives over
Expand All @@ -73,7 +60,15 @@
* or locally.
*/
@Plugin(type = Command.class, menuPath = "Plugins>BIOP>ArgoLight analysis tool")
public class ArgoLightCommand implements Command {
public class ArgoLightCommand implements Command, Cancelable {

@Parameter
private ThreadService threadService;
private final AtomicBoolean canceled = new AtomicBoolean(false);
private String cancelReason;
private Future<?> processingFuture;


private String userHost;
private String userPort;
private List<String> omeroMicroscopes = Collections.emptyList();
Expand All @@ -82,7 +77,7 @@ public class ArgoLightCommand implements Command {
private List<String> localMicroscopes = Collections.emptyList();
private List<String> userArgoSlides;
private String defaultArgoSlide;
private Map<String, List<String>> argoSlidesParameters = Collections.emptyMap();
private final Map<String, List<String>> argoSlidesParameters = new HashMap<>();
private String userRootFolder;
private String userSaveFolder;
private double userSigma;
Expand All @@ -95,7 +90,6 @@ public class ArgoLightCommand implements Command {
private boolean isDefaultThresholdMethod;
private boolean isDefaultParticleThresh;
private boolean isDefaultRingRadius;
private boolean startsProcessing = false;

private JDialog mainDialog;
private JDialog settingsDialog;
Expand Down Expand Up @@ -140,6 +134,7 @@ public class ArgoLightCommand implements Command {

final private Font stdFont = new Font("Calibri", Font.PLAIN, 17);
final private Font titleFont = new Font("Calibri", Font.BOLD, 22);

private enum CONNECTION_STATE{
CONNECTED("Disconnect"),
DISCONNECTED("Connect");
Expand Down Expand Up @@ -238,7 +233,8 @@ private void runProcessing(boolean isOmeroRetriever, String omeroFolderName, boo
List<String> argoParams = argoSlidesParameters.get(argoSlide);

// run analysis
if (nImages > 0)
if (nImages > 0) {
checkCanceled();
Processing.run(retriever, saveHeatMaps, sender,
isDefaultSigma ? defaultSigma : userSigma,
isDefaultMedianRadius ? defaultMedianRadius : userMedianRadius,
Expand All @@ -248,8 +244,9 @@ private void runProcessing(boolean isOmeroRetriever, String omeroFolderName, boo
argoSlide,
Integer.parseInt(argoParams.get(argoSpacingPos)),
Integer.parseInt(argoParams.get(argoFoVPos)),
Integer.parseInt(argoParams.get(argoNRingsPos)));
else {
Integer.parseInt(argoParams.get(argoNRingsPos)),
ArgoLightCommand.this);
} else {
IJLogger.warn("Parent container : "+rawTarget + ", microscope " + microscope + " does not contain any images");
showWarningMessage("No Images", "<html> Parent container : "+rawTarget + ", microscope '" + microscope + "', does not contain any images." +
"<p>" +
Expand All @@ -267,13 +264,7 @@ private void runProcessing(boolean isOmeroRetriever, String omeroFolderName, boo
} catch (Exception e){
finalPopupMessage = false;
IJLogger.error("Unexpected issue occurred", e);
} finally {
if(this.client.isConnected()) {
this.client.disconnect();
IJLogger.info("Disconnected from OMERO ");
}
}
IJLogger.info("ArgoLight Analysis Tool exited");

if(finalPopupMessage) {
showInfoMessage("Processing Done", "All images have been analyzed and results saved");
Expand All @@ -292,6 +283,32 @@ private boolean connectToOmero(Client client, String username, char[] password){
}
}

@Override
public boolean isCanceled() {
return canceled.get();
}

@Override
public void cancel(String reason) {
this.cancelReason = reason;
this.canceled.set(true);

if (processingFuture != null) {
processingFuture.cancel(true);
}
IJLogger.warn("Processing cancelled: " + reason);
}

@Override
public String getCancelReason() {
return cancelReason;
}

public void checkCanceled() {
if (canceled.get()) {
throw new CancellationException(cancelReason);
}
}

/**
* build the main user interface
Expand Down Expand Up @@ -691,6 +708,8 @@ private void createGui(){
// change the default button (when pressing enter with the keyboard)
omeroPane.getRootPane().setDefaultButton(bOk);
cbProject.requestFocus();
}else{
return;
}
}else{
if (this.client.isConnected()) {
Expand Down Expand Up @@ -730,34 +749,89 @@ private void createGui(){
cbProject.setSelectedItem(omeroProjects);
});

bOk.addActionListener(e->{
startsProcessing = true;
mainDialog.dispose();
JButton bCancel = new JButton("Cancel");
bCancel.setFont(stdFont);
bCancel.addActionListener(e->{
if(bCancel.getText().equals("Cancel")) {
mainDialog.dispose();
if (this.client.isConnected()) {
this.client.disconnect();
IJLogger.info("Disconnected from OMERO ");
}
IJLogger.info("ArgoLight Analysis Tool exited");
}else{
cancel("Aborted by user !");
}
});

char[] password = tfPassword.getPassword();
bOk.addActionListener(e->{
// freeze UI
cbMicroscope.setEnabled(false);
cbArgoSlide.setEnabled(false);
bArgoSlideSettings.setEnabled(false);
bLivePreview.setEnabled(false);
chkSaveHeatMap.setEnabled(false);
chkAllImages.setEnabled(false);
rbOmeroSender.setEnabled(false);
rbLocalSender.setEnabled(false);
rbOmeroRetriever.setEnabled(false);
rbLocalRetriever.setEnabled(false);
cbProject.setEnabled(false);
rbOmeroDataset.setEnabled(false);
rbOmeroProject.setEnabled(false);
bGeneralSettings.setEnabled(false);
bProcessingSettings.setEnabled(false);
bConnectToOmero.setEnabled(false);
bOk.setEnabled(false);
bCancel.setText("Abort");

String folderName;
if(rbOmeroProject.isSelected() && rbOmeroRetriever.isSelected())
folderName = (String)cbDataset.getSelectedItem();
else folderName = (String)cbProject.getSelectedItem();

runProcessing(rbOmeroRetriever.isSelected(),
folderName,
rbOmeroProject.isSelected(),
tfRootFolder.getText(),
((String)cbMicroscope.getSelectedItem()),
((String)cbArgoSlide.getSelectedItem()),
rbOmeroSender.isSelected(),
tfSavingFolder.getText(),
chkSaveHeatMap.isSelected(),
chkAllImages.isSelected(),
chkRemovePreviousRun.isSelected());
});

JButton bCancel = new JButton("Cancel");
bCancel.setFont(stdFont);
bCancel.addActionListener(e->{
mainDialog.dispose();
// send processing in another thread to get the Logs in the log window
processingFuture = threadService.run(() -> {
canceled.set(false);
try {
runProcessing(rbOmeroRetriever.isSelected(),
folderName,
rbOmeroProject.isSelected(),
tfRootFolder.getText(),
((String) cbMicroscope.getSelectedItem()),
((String) cbArgoSlide.getSelectedItem()),
rbOmeroSender.isSelected(),
tfSavingFolder.getText(),
chkSaveHeatMap.isSelected(),
chkAllImages.isSelected(),
chkRemovePreviousRun.isSelected());
} catch (CancellationException e1) {
IJLogger.warn("Processing stopped by user.");
}

// release UI
SwingUtilities.invokeLater(() -> {
cbMicroscope.setEnabled(true);
cbArgoSlide.setEnabled(true);
bArgoSlideSettings.setEnabled(true);
bLivePreview.setEnabled(true);
chkSaveHeatMap.setEnabled(true);
chkAllImages.setEnabled(true);
rbOmeroSender.setEnabled(true);
rbLocalSender.setEnabled(true);
rbOmeroRetriever.setEnabled(true);
rbLocalRetriever.setEnabled(true);
cbProject.setEnabled(true);
rbOmeroDataset.setEnabled(true);
rbOmeroProject.setEnabled(true);
bGeneralSettings.setEnabled(true);
bProcessingSettings.setEnabled(true);
bConnectToOmero.setEnabled(true);
bOk.setEnabled(true);
bCancel.setText("Cancel");
});
});
});

// build everything together
Expand Down Expand Up @@ -1003,7 +1077,7 @@ private void createGui(){
omeroPane.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
mainDialog.getContentPane().add(omeroPane);
mainDialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
mainDialog.setResizable(false);
mainDialog.setResizable(true);

if (JDialog.isDefaultLookAndFeelDecorated()) {
boolean supportsWindowDecorations =
Expand All @@ -1024,13 +1098,11 @@ private void createGui(){
mainDialog.setVisible(true);
mainDialog.dispose();

if(!startsProcessing) {
if (this.client.isConnected()) {
this.client.disconnect();
IJLogger.info("Disconnected from OMERO ");
}
IJLogger.info("ArgoLight Analysis Tool exited");
if (this.client.isConnected()) {
this.client.disconnect();
IJLogger.info("Disconnected from OMERO ");
}
IJLogger.info("ArgoLight Analysis Tool exited");
}


Expand Down Expand Up @@ -1146,7 +1218,7 @@ private void createArgoSettingsPane(String argoSlide){

// replace old values
argoSlidesParameters.clear();
argoSlidesParameters = newMap;
argoSlidesParameters.putAll(newMap);
}
}

Expand Down Expand Up @@ -1249,8 +1321,9 @@ else if(!userSelectedFile.getAbsolutePath().endsWith(".csv"))
if(readyToSave) {
String argoSlidesList = String.join(",", argoSettings.keySet());
tfArgoslide.setText(argoSlidesList);
argoSlidesParameters = tempMap;
saveArgoSlideParams();
argoSlidesParameters.clear();
argoSlidesParameters.putAll(tempMap);
saveArgoSlideParams(tempMap);
setDefaultArgoParams();
}else{
showErrorMessage("ArgoSlide settings", "The provided CSV is not correctly formatted. " +
Expand Down Expand Up @@ -2328,7 +2401,7 @@ private void setDefaultArgoParams(){

// replace old parameters
argoSlidesParameters.clear();
argoSlidesParameters = cleanArgoSlides;
argoSlidesParameters.putAll(cleanArgoSlides);
}

/**
Expand Down Expand Up @@ -2526,17 +2599,18 @@ private Map<String, List<String>> saveUserDefinedArgoSlideParams(String argoSli
argoslideParamList.add(String.valueOf(argoFov));
argoslideParamList.add(String.valueOf(argoNRings));
tempMap.put(argoSlide, argoslideParamList);
argoSlidesParameters = tempMap;

return saveArgoSlideParams();
saveArgoSlideParams(tempMap);

return tempMap;
}

/**
* Write a csv file containing all user-defined ArgoSlides parameters
*
* @return
*/
private Map<String, List<String>> saveArgoSlideParams() {
private void saveArgoSlideParams(Map<String, List<String>> argoSlidesParametersMap) {
File directory = new File(folderName);

if(!directory.exists())
Expand All @@ -2546,8 +2620,8 @@ private Map<String, List<String>> saveArgoSlideParams() {
File file = new File(directory.getAbsoluteFile() + File.separator + argoSlideFileName);
// write the file
BufferedWriter buffer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8));
for(String argoSlideKey : argoSlidesParameters.keySet()){
String argoSlideParamCSV = String.join(",", argoSlidesParameters.get(argoSlideKey));
for(String argoSlideKey : argoSlidesParametersMap.keySet()){
String argoSlideParamCSV = String.join(",", argoSlidesParametersMap.get(argoSlideKey));
buffer.write(argoSlideKey+","+ argoSlideParamCSV + "\n");
}
// close the file
Expand All @@ -2556,7 +2630,6 @@ private Map<String, List<String>> saveArgoSlideParams() {
} catch (IOException e) {
showWarningMessage("CSV writing","Couldn't write the csv for ArgoSlide parameters.");
}
return argoSlidesParameters;
}

public static void main(String... args){
Expand Down
Loading