Skip to content

Commit 1dc6944

Browse files
committed
Add plugin to find neighbouring spots in different channels
Refactors the FindFoci optimiser Parameters class to a new class for shared functionality of converting parameters to/from a string.
1 parent ea27c10 commit 1dc6944

5 files changed

Lines changed: 835 additions & 196 deletions

File tree

src/main/java/uk/ac/sussex/gdsc/ij/foci/FindFociOptimiser_PlugIn.java

Lines changed: 16 additions & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484
import javax.swing.WindowConstants;
8585
import org.apache.commons.lang3.ArrayUtils;
8686
import uk.ac.sussex.gdsc.core.annotation.Nullable;
87-
import uk.ac.sussex.gdsc.core.data.VisibleForTesting;
8887
import uk.ac.sussex.gdsc.core.ij.BufferedTextWindow;
8988
import uk.ac.sussex.gdsc.core.ij.ImageJUtils;
9089
import uk.ac.sussex.gdsc.core.ij.SimpleImageJTrackProgress;
@@ -139,7 +138,7 @@ public class FindFociOptimiser_PlugIn implements PlugIn {
139138
*/
140139
private static final int SORT_RMSD = 8;
141140

142-
private static final Pattern TAB_PATTERN = Pattern.compile("\t");
141+
static final Pattern TAB_PATTERN = Pattern.compile("\t");
143142
private static final Pattern POINTS_PATTERN = Pattern.compile("[, \t]+");
144143
/** The maximum errors when reading a file. */
145144
private static final int MAX_ERROR = 5;
@@ -204,7 +203,7 @@ public class FindFociOptimiser_PlugIn implements PlugIn {
204203
private int combinations;
205204

206205
private final Object2IntOpenHashMap<String> idMap = new Object2IntOpenHashMap<>();
207-
private final Int2ObjectOpenHashMap<Parameters> optionsMap = new Int2ObjectOpenHashMap<>();
206+
private final Int2ObjectOpenHashMap<FindFociParameters> optionsMap = new Int2ObjectOpenHashMap<>();
208207

209208
private final SoftLock lock = new SoftLock();
210209

@@ -559,15 +558,15 @@ private static class Result {
559558
static final int RMSD = 9;
560559

561560
int id;
562-
Parameters options;
561+
FindFociParameters options;
563562
int count;
564563
int tp;
565564
int fp;
566565
int fn;
567566
long time;
568567
double[] metrics = new double[10];
569568

570-
Result(int id, Parameters options, int count, int tp, int fp, int fn, long time, double beta,
569+
Result(int id, FindFociParameters options, int count, int tp, int fp, int fn, long time, double beta,
571570
double rmsd) {
572571
this.id = id;
573572
this.options = options;
@@ -761,179 +760,6 @@ private static <T extends Enum<?>> int compare(T value1, T value2, int[] result)
761760
}
762761
}
763762

764-
/**
765-
* A class to allow conversion of optimised parameters to and from a {@link String}.
766-
*/
767-
@VisibleForTesting
768-
static class Parameters {
769-
private static final String SPACER = " : ";
770-
771-
/** The processor options. */
772-
final FindFociProcessorOptions processorOptions;
773-
/** The cached parameter string. */
774-
private String parameterString;
775-
776-
/**
777-
* Instantiates a new parameters.
778-
*
779-
* @param processorOptions the processor options
780-
*/
781-
Parameters(FindFociProcessorOptions processorOptions) {
782-
this.processorOptions = processorOptions.copy();
783-
}
784-
785-
/**
786-
* Creates the string representation of the parameters (the value is computed once and cached).
787-
*
788-
* @return the string representation of the parameters.
789-
*/
790-
@Override
791-
public String toString() {
792-
String result = parameterString;
793-
if (result == null) {
794-
parameterString = result = createParametersString();
795-
}
796-
return result;
797-
}
798-
799-
/**
800-
* Convert the FindFoci parameters into a text representation.
801-
*
802-
* @return the string
803-
*/
804-
String createParametersString() {
805-
// Output results
806-
final StringBuilder sb = new StringBuilder();
807-
// Field 1
808-
sb.append(processorOptions.getGaussianBlur()).append('\t');
809-
// Field 2
810-
sb.append(processorOptions.getBackgroundMethod().getDescription());
811-
if (backgroundMethodHasStatisticsMode(processorOptions.getBackgroundMethod())) {
812-
sb.append(" (").append(processorOptions.getStatisticsMethod().getDescription())
813-
.append(") ");
814-
}
815-
sb.append(SPACER);
816-
if (backgroundMethodHasParameter(processorOptions.getBackgroundMethod())) {
817-
sb.append(IJ.d2s(processorOptions.getBackgroundParameter(), 2));
818-
} else {
819-
sb.append(processorOptions.getThresholdMethod().getDescription());
820-
}
821-
sb.append('\t');
822-
// Field 3
823-
sb.append(processorOptions.getMaxPeaks()).append('\t');
824-
// Field 4
825-
sb.append(processorOptions.getMinSize());
826-
if (processorOptions.isOption(AlgorithmOption.MINIMUM_ABOVE_SADDLE)) {
827-
sb.append(" >saddle");
828-
if (processorOptions.isOption(AlgorithmOption.CONTIGUOUS_ABOVE_SADDLE)) {
829-
sb.append(" conn");
830-
}
831-
}
832-
sb.append('\t');
833-
// Field 5
834-
sb.append(processorOptions.getSearchMethod().getDescription());
835-
if (searchMethodHasParameter(processorOptions.getSearchMethod())) {
836-
sb.append(SPACER).append(IJ.d2s(processorOptions.getSearchParameter(), 2));
837-
}
838-
sb.append('\t');
839-
// Field 6
840-
sb.append(processorOptions.getPeakMethod().getDescription()).append(SPACER);
841-
sb.append(IJ.d2s(processorOptions.getPeakParameter(), 2)).append('\t');
842-
// Field 7
843-
sb.append(processorOptions.getSortMethod().getDescription()).append('\t');
844-
// Field 8
845-
sb.append(processorOptions.getCentreMethod().getDescription());
846-
if (centreMethodHasParameter(processorOptions.getCentreMethod())) {
847-
sb.append(SPACER).append(IJ.d2s(processorOptions.getCentreParameter(), 2));
848-
}
849-
sb.append('\t');
850-
return sb.toString();
851-
}
852-
853-
/**
854-
* Convert the FindFoci text representation into Parameters.
855-
*
856-
* @param text the parameters text
857-
* @return the options
858-
* @throws IllegalArgumentException if the argument could not be parsed
859-
*/
860-
static Parameters fromString(String text) {
861-
final String[] fields = TAB_PATTERN.split(text);
862-
try {
863-
final FindFociProcessorOptions processorOptions = new FindFociProcessorOptions(true);
864-
// Field 1
865-
processorOptions.setGaussianBlur(Double.parseDouble(fields[0]));
866-
// Field 2 - Divided by a spacer
867-
int index = fields[1].indexOf(SPACER);
868-
final String backgroundMethod = fields[1].substring(0, index);
869-
final String backgroundOption = fields[1].substring(index + SPACER.length());
870-
index = backgroundMethod.indexOf('(');
871-
if (index != -1) {
872-
final int first = index + 1;
873-
final int last = backgroundMethod.indexOf(')', first);
874-
processorOptions.setBackgroundMethod(
875-
BackgroundMethod.fromDescription(backgroundMethod.substring(0, index - 1)));
876-
processorOptions.setStatisticsMethod(
877-
StatisticsMethod.fromDescription(backgroundMethod.substring(first, last)));
878-
} else {
879-
processorOptions.setBackgroundMethod(BackgroundMethod.fromDescription(backgroundMethod));
880-
}
881-
if (backgroundMethodHasParameter(processorOptions.getBackgroundMethod())) {
882-
processorOptions.setBackgroundParameter(Double.parseDouble(backgroundOption));
883-
} else {
884-
processorOptions.setThresholdMethod(ThresholdMethod.fromDescription(backgroundOption));
885-
}
886-
// Field 3
887-
processorOptions.setMaxPeaks(Integer.parseInt(fields[2]));
888-
// Field 4
889-
index = fields[3].indexOf(' ');
890-
if (index > 0) {
891-
processorOptions.setOption(AlgorithmOption.MINIMUM_ABOVE_SADDLE, true);
892-
if (fields[3].contains("conn")) {
893-
processorOptions.setOption(AlgorithmOption.CONTIGUOUS_ABOVE_SADDLE, true);
894-
}
895-
fields[3] = fields[3].substring(0, index);
896-
}
897-
processorOptions.setMinSize(Integer.parseInt(fields[3]));
898-
// Field 5
899-
index = fields[4].indexOf(SPACER);
900-
if (index != -1) {
901-
processorOptions
902-
.setSearchParameter(Double.parseDouble(fields[4].substring(index + SPACER.length())));
903-
fields[4] = fields[4].substring(0, index);
904-
}
905-
processorOptions.setSearchMethod(SearchMethod.fromDescription(fields[4]));
906-
// Field 6
907-
index = fields[5].indexOf(SPACER);
908-
processorOptions.setPeakMethod(PeakMethod.fromDescription(fields[5].substring(0, index)));
909-
processorOptions
910-
.setPeakParameter(Double.parseDouble(fields[5].substring(index + SPACER.length())));
911-
// Field 7
912-
processorOptions.setSortMethod(SortMethod.fromDescription(fields[6]));
913-
// Field 8
914-
index = fields[7].indexOf(SPACER);
915-
if (index != -1) {
916-
processorOptions
917-
.setCentreParameter(Double.parseDouble(fields[7].substring(index + SPACER.length())));
918-
fields[7] = fields[7].substring(0, index);
919-
}
920-
processorOptions.setCentreMethod(CentreMethod.fromDescription(fields[7]));
921-
922-
return new Parameters(processorOptions);
923-
} catch (final NullPointerException | NumberFormatException | IndexOutOfBoundsException ex) {
924-
// NPE will be thrown if the enum cannot parse the description because null
925-
// will be passed to the setter.
926-
throw new IllegalArgumentException(
927-
"Error converting parameters to FindFoci options: " + text, ex);
928-
}
929-
}
930-
931-
private static boolean centreMethodHasParameter(CentreMethod centreMethod) {
932-
return (centreMethod == CentreMethod.CENTRE_OF_MASS_SEARCH
933-
|| centreMethod == CentreMethod.GAUSSIAN_SEARCH);
934-
}
935-
}
936-
937763
/**
938764
* The Class OptimisationWorker.
939765
*/
@@ -1138,7 +964,7 @@ private int createId(String parameters) {
1138964
if (id == 0) {
1139965
id = idMap.size() + 1;
1140966
// Ensure we have options for every ID
1141-
optionsMap.put(id, Parameters.fromString(parameters));
967+
optionsMap.put(id, FindFociParameters.fromString(parameters));
1142968
idMap.put(parameters, id);
1143969
}
1144970
return id;
@@ -1354,7 +1180,7 @@ private void runSingleMode(ImagePlus imp) {
13541180
IJ.log("Top result = "
13551181
+ IJ.d2s(results.get(0).metrics[getSortIndex(settings.resultsSortMethod)], 4));
13561182

1357-
final Parameters bestOptions = results.get(0).options;
1183+
final FindFociParameters bestOptions = results.get(0).options;
13581184

13591185
final AssignedPoint[] predictedPoints = showResult(imp, mask, bestOptions,
13601186
settings.showScoreImages, settings.matchSearchMethod, settings.matchSearchDistance);
@@ -1415,7 +1241,7 @@ private static String getShortTitle(String title) {
14151241
* @param imp the imp
14161242
*/
14171243
private void checkOptimisationSpace(OptimiserResult result, ImagePlus imp) {
1418-
final Parameters bestOptions = result.results.get(0).options;
1244+
final FindFociParameters bestOptions = result.results.get(0).options;
14191245
if (bestOptions == null) {
14201246
return;
14211247
}
@@ -1796,7 +1622,7 @@ private static double getTop(double[] score) {
17961622
// Get the results
17971623
// The analysis time is not included in the speed-up factor
17981624
final long start = System.nanoTime();
1799-
final Parameters runOptions = new Parameters(processorOptions);
1625+
final FindFociParameters runOptions = new FindFociParameters(processorOptions);
18001626
final Result result = analyseResults(id, roiPoints,
18011627
peakResults.results, distanceThreshold, runOptions, time,
18021628
settings.beta, distanceFunction);
@@ -1880,7 +1706,7 @@ private void saveResults(ImagePlus imp, ImagePlus mask, ArrayList<Result> result
18801706
return;
18811707
}
18821708

1883-
final Parameters bestOptions = results.get(0).options;
1709+
final FindFociParameters bestOptions = results.get(0).options;
18841710

18851711
final FindFociOptions options = new FindFociOptions();
18861712
options.getOptions().clear();
@@ -1937,7 +1763,7 @@ private void saveResults(ImagePlus imp, ImagePlus mask, ArrayList<Result> result
19371763
}
19381764
}
19391765

1940-
private static synchronized void addFindFociCommand(BufferedWriter out, Parameters bestOptions,
1766+
private static synchronized void addFindFociCommand(BufferedWriter out, FindFociParameters bestOptions,
19411767
String maskTitle) throws IOException {
19421768
if (bestOptions == null) {
19431769
return;
@@ -2023,7 +1849,7 @@ private static double getDistanceThreshold(ImagePlus imp, int matchSearchMethod,
20231849
}
20241850

20251851
@Nullable
2026-
private static AssignedPoint[] showResult(ImagePlus imp, ImagePlus mask, Parameters parameters,
1852+
private static AssignedPoint[] showResult(ImagePlus imp, ImagePlus mask, FindFociParameters parameters,
20271853
boolean showScoreImages, int matchSearchMethod, double matchSearchDistance) {
20281854
if (imp == null) {
20291855
return null;
@@ -2675,12 +2501,12 @@ private double getBackgroundLimit(BackgroundMethod backgroundMethod) {
26752501
: backgroundParameterMax;
26762502
}
26772503

2678-
private static boolean backgroundMethodHasStatisticsMode(BackgroundMethod backgroundMethod) {
2504+
static boolean backgroundMethodHasStatisticsMode(BackgroundMethod backgroundMethod) {
26792505
return backgroundMethod != BackgroundMethod.NONE
26802506
&& backgroundMethod != BackgroundMethod.ABSOLUTE;
26812507
}
26822508

2683-
private static boolean backgroundMethodHasParameter(BackgroundMethod backgroundMethod) {
2509+
static boolean backgroundMethodHasParameter(BackgroundMethod backgroundMethod) {
26842510
return !EnumSet
26852511
.of(BackgroundMethod.NONE, BackgroundMethod.MEAN, BackgroundMethod.AUTO_THRESHOLD)
26862512
.contains(backgroundMethod);
@@ -2730,7 +2556,7 @@ private double getSearchLimit(SearchMethod searchMethod) {
27302556
return searchMethodHasParameter(searchMethod) ? searchParameterMin : searchParameterMax;
27312557
}
27322558

2733-
private static boolean searchMethodHasParameter(SearchMethod searchMethod) {
2559+
static boolean searchMethodHasParameter(SearchMethod searchMethod) {
27342560
return searchMethod != SearchMethod.ABOVE_BACKGROUND;
27352561
}
27362562

@@ -2965,7 +2791,7 @@ public void mouseClicked(MouseEvent event) {
29652791
return bw;
29662792
}
29672793

2968-
private BufferedWriter createResultsFile(Parameters bestOptions, ImagePlus imp, ImagePlus mask,
2794+
private BufferedWriter createResultsFile(FindFociParameters bestOptions, ImagePlus imp, ImagePlus mask,
29692795
String resultFile) {
29702796
BufferedWriter out = null;
29712797
try {
@@ -3054,7 +2880,7 @@ private static String createResultsHeader(boolean withScore, boolean milliSecond
30542880
}
30552881

30562882
private static Result analyseResults(int id, AssignedPoint[] roiPoints,
3057-
List<FindFociResult> resultsArray, double distanceThreshold, Parameters options, long time,
2883+
List<FindFociResult> resultsArray, double distanceThreshold, FindFociParameters options, long time,
30582884
double beta, ToDoubleBiFunction<Coordinate, Coordinate> edges) {
30592885
// Extract results for analysis
30602886
final Coordinate[] predictedPoints = extractedPredictedPoints(resultsArray);

0 commit comments

Comments
 (0)