statusChangeListeners;
/**
*
@@ -104,6 +92,7 @@ public class SearchTask extends Accessible implements Runnable {
* @param curve the {@code ExperimentalData}
*/
public SearchTask(ExperimentalData curve) {
+ super();
this.statusChangeListeners = new CopyOnWriteArrayList<>();
this.listeners = new CopyOnWriteArrayList<>();
current = new Calculation(this);
@@ -114,23 +103,7 @@ public SearchTask(ExperimentalData curve) {
clear();
addListeners();
}
-
- /**
- * Update the best state. The instance of this class stores two objects of
- * the type IterativeState: the current state of the optimiser and the
- * global best state. Calling this method will check if a new global best is
- * found, and if so, this will store its parameters in the corresponding
- * variable. This will then be used at the final stage of running the search
- * task, comparing the converged result to the global best, and selecting
- * whichever has the lowest cost. Such routine is required due to the
- * possibility of some optimisers going uphill.
- */
- public void storeState() {
- if (best == null || best.getCost() > path.getCost()) {
- best = new IterativeState(path);
- }
- }
-
+
private void addListeners() {
InterpolationDataset.addListener(e -> {
if (current.getProblem() != null) {
@@ -171,218 +144,22 @@ private void addListeners() {
public void clear() {
stored = new ArrayList<>();
curve.resetRanges();
- buffer = new Buffer();
correlationBuffer.clear();
- buffer.setParent(this);
log = new Log(this);
initCorrelationTest();
initNormalityTest();
- this.path = null;
+ //this.path = null;
current.clear();
this.checkProblems(true);
}
-
- /**
- * This will use the current {@code DifferenceScheme} to solve the
- * {@code Problem} for this {@code SearchTask} and calculate the SSR value
- * showing how well (or bad) the calculated solution describes the
- * {@code ExperimentalData}.
- *
- * @return the value of SSR (sum of squared residuals).
- * @throws SolverException
- */
- public double solveProblemAndCalculateCost() throws SolverException {
- current.process();
- var rs = current.getOptimiserStatistic();
- rs.evaluate(this);
- return (double) rs.getStatistic().getValue();
- }
-
+
public List alteredParameters() {
- return activeParameters(this).stream().map(key -> this.numericProperty(key)).collect(Collectors.toList());
- }
-
- /**
- * Generates a search vector (= optimisation vector) using the search flags
- * set by the {@code PathSolver}.
- *
- * @return an {@code IndexedVector} with search parameters of this
- * {@code SearchTaks}
- * @see pulse.search.direction.PathSolver.getSearchFlags()
- * @see pulse.problem.statements.Problem.optimisationVector(List)
- */
- public ParameterVector searchVector() {
- var flags = ActiveFlags.getAllFlags();
- var keywords = activeParameters(this);
- var optimisationVector = new ParameterVector(keywords);
-
- current.getProblem().optimisationVector(optimisationVector, flags);
- curve.getRange().optimisationVector(optimisationVector, flags);
-
- return optimisationVector;
- }
-
- /**
- * Assigns the values of the parameters of this {@code SearchTask} to
- * {@code searchParameters}.
- *
- * @param searchParameters an {@code IndexedVector} with relevant search
- * parameters
- * @throws pulse.problem.schemes.solvers.SolverException
- * @see pulse.problem.statements.Problem.assign(IndexedVector)
- */
- public void assign(ParameterVector searchParameters) throws SolverException {
- current.getProblem().assign(searchParameters);
- curve.getRange().assign(searchParameters);
- }
-
- /**
- *
- * Runs this task if is either {@code READY} or {@code QUEUED}. Otherwise,
- * will do nothing. After making some preparatory steps, will initiate a
- * loop with successive calls to {@code PathSolver.iteration(this)}, filling
- * the buffer and notifying any data change listeners in parallel. This loop
- * will go on until either converging results are obtained, or a timeout is
- * reached, or if an execution error happens. Whether the run has been
- * successful will be determined by comparing the associated
- * R2 value with the {@code SUCCESS_CUTOFF}.
- *
- */
- @Override
- public void run() {
-
- current.setResult(null);
-
- /* check of status */
- switch (current.getStatus()) {
- case READY:
- case QUEUED:
- setStatus(IN_PROGRESS);
- break;
- default:
- return;
- }
-
- /* preparatory steps */
- current.getProblem().parameterListChanged(); // get updated list of parameters
-
- var optimiser = getInstance();
-
- path = optimiser.initState(this);
-
- var errorTolerance = (double) optimiser.getErrorTolerance().getValue();
- int bufferSize = (Integer) getSize().getValue();
- buffer.init();
- correlationBuffer.clear();
-
- /* search cycle */
- /* sets an independent thread for manipulating the buffer */
- List> bufferFutures = new ArrayList<>(bufferSize);
- var singleThreadExecutor = Executors.newSingleThreadExecutor();
-
- try {
- solveProblemAndCalculateCost();
- } catch (SolverException e1) {
- notifyFailedStatus(e1);
- }
-
- outer:
- do {
-
- bufferFutures.clear();
-
- for (var i = 0; i < bufferSize; i++) {
-
- try {
- for (boolean finished = false; !finished;) {
- finished = optimiser.iteration(this);
- }
- } catch (SolverException e) {
- notifyFailedStatus(e);
- break outer;
- }
-
- //if global best is better than the converged value
- if (best != null && best.getCost() < path.getCost()) {
- try {
- //assign the global best parameters
- assign(path.getParameters());
- //and try to re-calculate
- solveProblemAndCalculateCost();
- } catch (SolverException ex) {
- notifyFailedStatus(ex);
- }
- }
-
- final var j = i;
-
- bufferFutures.add(CompletableFuture.runAsync(() -> {
- buffer.fill(this, j);
- correlationBuffer.inflate(this);
- notifyDataListeners(new DataLogEntry(this));
- }, singleThreadExecutor));
-
- }
-
- bufferFutures.forEach(future -> future.join());
-
- } while (buffer.isErrorTooHigh(errorTolerance)
- && current.getStatus() == IN_PROGRESS);
-
- singleThreadExecutor.shutdown();
-
- if (current.getStatus() == IN_PROGRESS) {
- runChecks();
- }
-
- }
-
- private void runChecks() {
-
- if (!normalityTest.test(this)) { // first, check if the residuals are normally-distributed
- var status = FAILED;
- status.setDetails(ABNORMAL_DISTRIBUTION_OF_RESIDUALS);
- setStatus(status);
- } else {
-
- var test = correlationBuffer.test(correlationTest); // second, check there are no unexpected
- // correlations
- notifyDataListeners(new CorrelationLogEntry(this));
-
- if (test) {
- var status = AMBIGUOUS;
- status.setDetails(SIGNIFICANT_CORRELATION_BETWEEN_PARAMETERS);
- setStatus(status);
- } else {
- // lastly, check if the parameter values estimated in this procedure are
- // reasonable
-
- var properties = alteredParameters();
-
- if (properties.stream().anyMatch(np -> !np.validate())) {
- var status = FAILED;
- status.setDetails(PARAMETER_VALUES_NOT_SENSIBLE);
- setStatus(status);
- } else {
- current.getModelSelectionCriterion().evaluate(this);
- setStatus(DONE);
- }
-
- }
-
- }
- }
-
- public void notifyFailedStatus(SolverException e1) {
- var status = Status.FAILED;
- status.setDetails(Details.SOLVER_ERROR);
- status.setDetailedMessage(e1.getMessage());
- e1.printStackTrace();
- setStatus(status);
- }
+ return activeParameters().stream().map(key ->
+ this.numericProperty(key)).collect(Collectors.toList());
+ }
public void addTaskListener(DataCollectionListener toAdd) {
listeners.add(toAdd);
@@ -404,15 +181,7 @@ public void removeStatusChangeListeners() {
public String toString() {
return getIdentifier().toString();
}
-
- public ExperimentalData getExperimentalCurve() {
- return curve;
- }
-
- public IterativeState getIterativeState() {
- return path;
- }
-
+
/**
* Adopts the {@code curve} by this {@code SearchTask}.
*
@@ -427,28 +196,6 @@ public void setExperimentalCurve(ExperimentalData curve) {
}
- /**
- * Will return {@code true} if status could be updated.
- *
- * @param status the status of the task
- * @return {@code} true if status has been updated. {@code false} if the
- * status was already set to {@code status} previously, or if it could not
- * be updated at this time.
- * @see Calculation.setStatus()
- */
- public boolean setStatus(Status status) {
- Objects.requireNonNull(status);
-
- Status oldStatus = current.getStatus();
- boolean changed = current.setStatus(status)
- && (oldStatus != current.getStatus());
- if (changed) {
- notifyStatusListeners(new StateEntry(this, status));
- }
-
- return changed;
- }
-
/**
*
* Checks if this {@code SearchTask} is ready to be run.Performs basic check
@@ -465,7 +212,7 @@ public boolean setStatus(Status status) {
* @param updateStatus
*/
public void checkProblems(boolean updateStatus) {
- var status = current.getStatus();
+ var status = getStatus();
if (status == DONE) {
return;
@@ -484,7 +231,7 @@ public void checkProblems(boolean updateStatus) {
s.setDetails(MISSING_HEATING_CURVE);
} else if (pathSolver == null) {
s.setDetails(MISSING_OPTIMISER);
- } else if (buffer == null) {
+ } else if (getBuffer() == null) {
s.setDetails(MISSING_BUFFER);
} else if (!getInstance().compatibleWith(current.getOptimiserStatistic())) {
s.setDetails(INCOMPATIBLE_OPTIMISER);
@@ -516,24 +263,28 @@ private void notifyStatusListeners(StateEntry e) {
l.onStatusChange(e);
}
}
-
+
@Override
- public String describe() {
-
- var sb = new StringBuilder();
- sb.append(TaskManager.getManagerInstance().getSampleName());
- sb.append("_Task_");
- var extId = curve.getMetadata().getExternalID();
- if (extId < 0) {
- sb.append("IntID_").append(identifier.getValue());
- } else {
- sb.append("ExtID_").append(extId);
+ public void run() {
+ correlationBuffer.clear();
+ current.setResult(null);
+
+ /* check of status */
+ switch (getStatus()) {
+ case READY:
+ case QUEUED:
+ setStatus(IN_PROGRESS);
+ break;
+ default:
+ return;
}
-
- return sb.toString();
-
+
+ current.getProblem().parameterListChanged(); // get updated list of parameters
+ setDefaultOptimiser();
+
+ super.run();
}
-
+
/**
* If the current task is either {@code IN_PROGRESS}, {@code QUEUED}, or
* {@code READY}, terminates it by setting its status to {@code TERMINATED}.
@@ -541,39 +292,15 @@ public String describe() {
* running).
*/
public void terminate() {
- switch (current.getStatus()) {
+ switch (getStatus()) {
case IN_PROGRESS:
case QUEUED:
- case READY:
setStatus(AWAITING_TERMINATION);
break;
default:
}
}
- @Override
- public void set(NumericPropertyKeyword type, NumericProperty property) {
- // intentionally left blank
- }
-
- /**
- * A {@code SearchTask} is deemed equal to another one if it has the same
- * {@code ExperimentalData}.
- */
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
-
- if (!(o instanceof SearchTask)) {
- return false;
- }
-
- return curve.equals(((SearchTask) o).getExperimentalCurve());
-
- }
-
public NormalityTest getNormalityTest() {
return normalityTest;
}
@@ -595,22 +322,17 @@ public CorrelationBuffer getCorrelationBuffer() {
public CorrelationTest getCorrelationTest() {
return correlationTest;
}
-
- public Calculation getCurrentCalculation() {
- return current;
- }
-
+
public List getStoredCalculations() {
return this.stored;
- }
+ }
public void storeCalculation() {
var copy = new Calculation(current);
stored.add(copy);
- }
+ }
public void switchTo(Calculation calc) {
- current.setParent(null);
current = calc;
current.setParent(this);
var e = new TaskRepositoryEvent(TaskRepositoryEvent.State.TASK_MODEL_SWITCH, this.getIdentifier());
@@ -641,5 +363,191 @@ private void fireRepositoryEvent(TaskRepositoryEvent e) {
l.onTaskListChanged(e);
}
}
+
+ @Override
+ public boolean isInProgress() {
+ return getStatus() == IN_PROGRESS;
+ }
+
+ @Override
+ public void intermediateProcessing() {
+ correlationBuffer.inflate(this);
+ notifyDataListeners(new DataLogEntry(this));
+ }
+
+ @Override
+ public void onSolverException(SolverException e) {
+ setStatus(Status.troubleshoot(e));
+ }
+
+ /**
+ * Generates a search vector (= optimisation vector) using the search flags
+ * set by the {@code PathSolver}.
+ *
+ * @return an {@code IndexedVector} with search parameters of this
+ * {@code SearchTaks}
+ * @see pulse.search.direction.PathSolver.getSearchFlags()
+ * @see pulse.problem.statements.Problem.optimisationVector(List)
+ */
+ @Override
+ public ParameterVector searchVector() {
+ var ids = activeParameters().stream().map(id ->
+ new ParameterIdentifier(id)).collect(Collectors.toList());
+ var optimisationVector = new ParameterVector(ids);
+
+ current.getProblem().optimisationVector(optimisationVector);
+ curve.getRange().optimisationVector(optimisationVector);
+
+ return optimisationVector;
+ }
+
+ /**
+ * Assigns the values of the parameters of this {@code SearchTask} to
+ * {@code searchParameters}.
+ *
+ * @param searchParameters an {@code IndexedVector} with relevant search
+ * parameters
+ * @throws pulse.problem.schemes.solvers.SolverException
+ * @see pulse.problem.statements.Problem.assign(IndexedVector)
+ */
+ @Override
+ public void assign(ParameterVector searchParameters) throws SolverException {
+ current.getProblem().assign(searchParameters);
+ curve.getRange().assign(searchParameters);
+ }
+
+ @Override
+ public void postProcessing() {
+
+ if (!normalityTest.test(this)) { // first, check if the residuals are normally-distributed
+ var status = FAILED;
+ status.setDetails(ABNORMAL_DISTRIBUTION_OF_RESIDUALS);
+ setStatus(status);
+ } else {
+
+ var test = correlationBuffer.test(correlationTest); // second, check there are no unexpected
+ // correlations
+ notifyDataListeners(new CorrelationLogEntry(this));
+
+ if (test) {
+ var status = AMBIGUOUS;
+ status.setDetails(SIGNIFICANT_CORRELATION_BETWEEN_PARAMETERS);
+ setStatus(status);
+ } else {
+ // lastly, check if the parameter values estimated in this procedure are
+ // reasonable
+
+ var properties = this.getIterativeState().getParameters();
+
+ if (properties.findMalformedElements().size() > 0) {
+ var status = FAILED;
+ status.setDetails(PARAMETER_VALUES_NOT_SENSIBLE);
+ setStatus(status);
+ } else {
+ current.getModelSelectionCriterion().evaluate(this);
+ setStatus(DONE);
+ }
+
+ }
+
+ }
+ }
+
+
+ /**
+ * Finds what properties are being altered in the search of this SearchTask.
+ *
+ * @return a {@code List} of property types represented by
+ * {@code NumericPropertyKeyword}s
+ */
+ @Override
+ public List activeParameters() {
+ var flags = ActiveFlags.getAllFlags();
+ //problem dependent
+ var allActiveParams = ActiveFlags.selectActiveAndListed
+ (flags, current.getProblem());
+ //problem independent (lower/upper bound)
+ var listed = ActiveFlags.selectActiveAndListed
+ (flags, curve.getRange() );
+ allActiveParams.addAll(listed);
+ return allActiveParams;
+ }
+
+ /**
+ * Will return {@code true} if status could be updated.
+ *
+ * @param status the status of the task
+ * @return {@code} true if status has been updated. {@code false} if the
+ * status was already set to {@code status} previously, or if it could not
+ * be updated at this time.
+ * @see Calculation.setStatus()
+ */
+
+ public boolean setStatus(Status status) {
+ Objects.requireNonNull(status);
+
+ Status oldStatus = getStatus();
+ boolean changed = current.setStatus(status)
+ && (oldStatus != getStatus());
+ if (changed) {
+ notifyStatusListeners(new StateEntry(this, status));
+ }
+
+ return changed;
+ }
+
+ public Status getStatus() {
+ return current.getStatus();
+ }
+
+ @Override
+ public void set(NumericPropertyKeyword type, NumericProperty property) {
+ // intentionally left blank
+ }
+
+ /**
+ * A {@code SearchTask} is deemed equal to another one if it has the same
+ * {@code ExperimentalData}.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof SearchTask)) {
+ return false;
+ }
+
+ return curve.equals(((SearchTask) o).curve);
+
+ }
+
+ @Override
+ public String describe() {
+
+ var sb = new StringBuilder();
+ sb.append(TaskManager.getManagerInstance().getSampleName());
+ sb.append("_Task_");
+ var extId = curve.getMetadata().getExternalID();
+ if (extId < 0) {
+ sb.append("IntID_").append(identifier.getValue());
+ } else {
+ sb.append("ExtID_").append(extId);
+ }
+
+ return sb.toString();
+
+ }
+
+ @Override
+ public ExperimentalData getInput() {
+ return curve;
+ }
+
+ @Override
+ public Calculation getResponse() {
+ return current;
+ }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/pulse/tasks/TaskManager.java b/src/main/java/pulse/tasks/TaskManager.java
index f8801c2..358403d 100644
--- a/src/main/java/pulse/tasks/TaskManager.java
+++ b/src/main/java/pulse/tasks/TaskManager.java
@@ -95,14 +95,6 @@ private TaskManager() {
selectionListeners = new CopyOnWriteArrayList<>();
taskRepositoryListeners = new CopyOnWriteArrayList<>();
addHierarchyListener(statementListener);
- /*
- Calculate the half-time once data is loaded.
- */
- addTaskRepositoryListener((TaskRepositoryEvent e) -> {
- if (e.getState() == TaskRepositoryEvent.State.TASK_ADDED) {
- getTask(e.getId()).getExperimentalCurve().calculateHalfTime();
- }
- });
}
/**
@@ -123,35 +115,40 @@ public static TaskManager getManagerInstance() {
* @param t a {@code SearchTask} that will be executed
*/
public void execute(SearchTask t) {
- t.checkProblems(t.getCurrentCalculation().getStatus() != Status.DONE);
+ t.checkProblems(t.getStatus() != Status.DONE);
//try to start cmputation
// notify listeners computation is about to start
if (!t.setStatus(QUEUED)) {
return;
}
-
+
// notify listeners calculation started
notifyListeners(new TaskRepositoryEvent(TASK_SUBMITTED, t.getIdentifier()));
-
+
// run task t -- after task completed, write result and trigger listeners
CompletableFuture.runAsync(t).thenRun(() -> {
- var current = t.getCurrentCalculation();
+ Calculation current = (Calculation)t.getResponse();
var e = new TaskRepositoryEvent(TASK_FINISHED, t.getIdentifier());
- if (current.getStatus() == DONE) {
- current.setResult(new Result(t, ResultFormat.getInstance()));
- //notify listeners before the task is re-assigned
+ if (null == current.getStatus()) {
notifyListeners(e);
- t.storeCalculation();
}
- else if(current.getStatus() == AWAITING_TERMINATION) {
- t.setStatus(Status.TERMINATED);
- }
- else {
- notifyListeners(e);
+ else switch (current.getStatus()) {
+ case DONE:
+ current.setResult(new Result(t, ResultFormat.getInstance()));
+ //notify listeners before the task is re-assigned
+ notifyListeners(e);
+ t.storeCalculation();
+ break;
+ case AWAITING_TERMINATION:
+ t.setStatus(Status.TERMINATED);
+ break;
+ default:
+ notifyListeners(e);
+ break;
}
});
-
+
}
/**
@@ -174,7 +171,7 @@ public void notifyListeners(TaskRepositoryEvent e) {
public void executeAll() {
var queue = tasks.stream().filter(t -> {
- switch (t.getCurrentCalculation().getStatus()) {
+ switch (t.getStatus()) {
case IN_PROGRESS:
case EXECUTION_ERROR:
return false;
@@ -198,7 +195,7 @@ public void executeAll() {
*/
public boolean isTaskQueueEmpty() {
return !tasks.stream().anyMatch(t -> {
- var status = t.getCurrentCalculation().getStatus();
+ var status = t.getStatus();
return status == QUEUED || status == IN_PROGRESS;
});
}
@@ -262,7 +259,8 @@ public SampleName getSampleName() {
return null;
}
- return optional.get().getExperimentalCurve().getMetadata().getSampleName();
+ return ( (ExperimentalData) optional.get().getInput() )
+ .getMetadata().getSampleName();
}
/**
@@ -308,7 +306,8 @@ public SearchTask getTask(Identifier id) {
*/
public SearchTask getTask(int externalId) {
var o = tasks.stream().filter(t
- -> Integer.compare(t.getExperimentalCurve().getMetadata().getExternalID(),
+ -> Integer.compare( ( (ExperimentalData) t.getInput())
+ .getMetadata().getExternalID(),
externalId) == 0).findFirst();
return o.isPresent() ? o.get() : null;
}
@@ -340,7 +339,7 @@ public void generateTask(File file) {
curves.stream().forEach((ExperimentalData curve) -> {
var task = new SearchTask(curve);
addTask(task);
- var data = task.getExperimentalCurve();
+ var data = (ExperimentalData) task.getInput();
if (!data.isAcquisitionTimeSensible()) {
data.truncate();
}
@@ -374,7 +373,6 @@ public void generateTasks(List files) {
};
Executors.newSingleThreadExecutor().submit(loader);
-
}
/**
@@ -512,8 +510,8 @@ public String describe() {
public void evaluate() {
tasks.stream().forEach(t -> {
- var properties = t.getCurrentCalculation().getProblem().getProperties();
- var c = t.getExperimentalCurve();
+ var properties = ( (Calculation) t.getResponse() ).getProblem().getProperties();
+ var c = (ExperimentalData)t.getInput();
properties.useTheoreticalEstimates(c);
});
}
diff --git a/src/main/java/pulse/tasks/logs/CorrelationLogEntry.java b/src/main/java/pulse/tasks/logs/CorrelationLogEntry.java
index cacac2f..f6785bd 100644
--- a/src/main/java/pulse/tasks/logs/CorrelationLogEntry.java
+++ b/src/main/java/pulse/tasks/logs/CorrelationLogEntry.java
@@ -1,8 +1,8 @@
package pulse.tasks.logs;
+import pulse.math.ParameterIdentifier;
import static pulse.properties.NumericProperties.def;
-import pulse.properties.NumericPropertyKeyword;
import pulse.tasks.SearchTask;
import pulse.tasks.TaskManager;
import pulse.util.ImmutablePair;
@@ -32,16 +32,20 @@ public String toString() {
sb.append("Correlation table");
sb.append(" x | y | Correlation |
");
- for (ImmutablePair key : map.keySet()) {
+ for (ImmutablePair key : map.keySet()) {
sb.append("");
- sb.append(def(key.getFirst()).getAbbreviation(false));
+ sb.append(def(key.getFirst().getKeyword()).getAbbreviation(false));
+ if(key.getFirst().getIndex() > 0)
+ sb.append(" - ").append(key.getFirst().getIndex());
sb.append(" | ");
- sb.append(def(key.getSecond()).getAbbreviation(false));
+ sb.append(def(key.getSecond().getKeyword()).getAbbreviation(false));
+ if(key.getSecond().getIndex() > 0)
+ sb.append(" - ").append(key.getSecond().getIndex());
sb.append(" | ");
if (test.compareToThreshold(map.get(key))) {
sb.append("");
}
- sb.append("" + String.format("%3.2f", map.get(key)) + "");
+ sb.append("").append(String.format("%3.2f", map.get(key))).append("");
if (test.compareToThreshold(map.get(key))) {
sb.append("");
}
diff --git a/src/main/java/pulse/tasks/logs/DataLogEntry.java b/src/main/java/pulse/tasks/logs/DataLogEntry.java
index 8448b5f..2fad022 100644
--- a/src/main/java/pulse/tasks/logs/DataLogEntry.java
+++ b/src/main/java/pulse/tasks/logs/DataLogEntry.java
@@ -1,10 +1,11 @@
package pulse.tasks.logs;
import java.lang.reflect.InvocationTargetException;
-import java.util.Collections;
import java.util.List;
+import pulse.math.Parameter;
+import pulse.math.ParameterIdentifier;
+import pulse.properties.NumericProperties;
-import pulse.properties.NumericProperty;
import pulse.tasks.SearchTask;
import pulse.tasks.TaskManager;
import pulse.ui.Messages;
@@ -19,7 +20,7 @@
*/
public class DataLogEntry extends LogEntry {
- private List entry;
+ private List entry;
/**
* Creates a new {@code DataLogEntry} based on the current values of the
@@ -52,13 +53,14 @@ public DataLogEntry(SearchTask task) {
*/
private void fill() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
var task = TaskManager.getManagerInstance().getTask(getIdentifier());
-
- entry = task.alteredParameters();
- Collections.sort(entry, (p1, p2) -> p1.getDescriptor(false).compareTo(p2.getDescriptor(false)));
- entry.add(0, task.getIterativeState().getIteration());
+ entry = task.searchVector().getParameters();
+ var pval = task.getIterativeState().getIteration();
+ var pid = new Parameter(new ParameterIdentifier(pval.getType()));
+ pid.setValue( (int) pval.getValue() );
+ entry.add(0, pid);
}
- public List getData() {
+ public List getData() {
return entry;
}
@@ -83,13 +85,26 @@ public String toString() {
*/
sb.append("");
- for (NumericProperty p : entry) {
+ for (Parameter p : entry) {
sb.append("");
- sb.append(p.getAbbreviation(false));
+ var def = NumericProperties.def(p.getIdentifier().getKeyword());
+ boolean b = def.getValue() instanceof Integer;
+ Number val;
+ if(b) {
+ val = (int) Math.rint(p.getApparentValue());
+ } else{
+ val = p.getApparentValue();
+ }
+ def.setValue(val);
+ sb.append(def.getAbbreviation(false));
+ int index = p.getIdentifier().getIndex();
+ if(index > 0) {
+ sb.append(" - ").append(index);
+ }
sb.append(" | <");
sb.append(Messages.getString("DataLogEntry.FontTagNumber")); //$NON-NLS-1$
sb.append("");
- sb.append(p.formattedOutput());
+ sb.append(def.formattedOutput());
sb.append("");
sb.append(Messages.getString("DataLogEntry.FontTagClose")); //$NON-NLS-1$
sb.append(" |
");
diff --git a/src/main/java/pulse/tasks/logs/Log.java b/src/main/java/pulse/tasks/logs/Log.java
index c8780ba..5b51953 100644
--- a/src/main/java/pulse/tasks/logs/Log.java
+++ b/src/main/java/pulse/tasks/logs/Log.java
@@ -9,7 +9,6 @@
import pulse.tasks.SearchTask;
import pulse.tasks.TaskManager;
import pulse.tasks.listeners.LogEntryListener;
-import pulse.tasks.listeners.StatusChangeListener;
import pulse.ui.Messages;
import pulse.util.Group;
@@ -23,8 +22,8 @@ public class Log extends Group {
private List logEntries;
private LocalTime start;
private LocalTime end;
- private Identifier id;
- private List listeners;
+ private final Identifier id;
+ private final List listeners;
private static boolean verbose = false;
/**
@@ -49,38 +48,32 @@ public Log(SearchTask task) {
/**
* Do these actions each time data has been collected for this task.
*/
- if (task.getCurrentCalculation().getStatus() != Status.INCOMPLETE && verbose) {
+ if (task.getStatus() != Status.INCOMPLETE && verbose) {
logEntries.add(le);
notifyListeners(le);
}
});
- task.addStatusChangeListener(new StatusChangeListener() {
-
- /**
- * Do these actions every time the task status has changed.
- */
- @Override
- public void onStatusChange(StateEntry e) {
- logEntries.add(e);
-
- if (e.getStatus() == Status.IN_PROGRESS) {
- start = e.getTime();
- end = null;
- } else {
- end = e.getTime();
- }
-
- notifyListeners(e);
-
- if (e.getState() == Status.DONE) {
- logFinished();
- }
-
+ task.addStatusChangeListener((StateEntry e) -> {
+ logEntries.add(e);
+
+ if (e.getStatus() == Status.IN_PROGRESS) {
+ start = e.getTime();
+ end = null;
+ } else {
+ end = e.getTime();
}
-
- });
+
+ notifyListeners(e);
+
+ if (e.getState() == Status.DONE) {
+ logFinished();
+ }
+ } /**
+ * Do these actions every time the task status has changed.
+ */
+ );
}
@@ -92,15 +85,15 @@ private void notifyListeners(LogEntry logEntry) {
listeners.stream().forEach(l -> l.onNewEntry(logEntry));
}
- public List getListeners() {
+ public final List getListeners() {
return listeners;
}
- public void addListener(LogEntryListener l) {
+ public final void addListener(LogEntryListener l) {
listeners.add(l);
}
- public Identifier getIdentifier() {
+ public final Identifier getIdentifier() {
return id;
}
@@ -128,10 +121,12 @@ public String toString() {
sb.append(newLine);
sb.append(newLine);
- for (LogEntry le : logEntries) {
+ logEntries.stream().map(le -> {
sb.append(le);
+ return le;
+ }).forEachOrdered(_item -> {
sb.append(newLine);
- }
+ });
return sb.toString();
diff --git a/src/main/java/pulse/tasks/logs/Status.java b/src/main/java/pulse/tasks/logs/Status.java
index 87e226d..e2d7017 100644
--- a/src/main/java/pulse/tasks/logs/Status.java
+++ b/src/main/java/pulse/tasks/logs/Status.java
@@ -1,6 +1,9 @@
package pulse.tasks.logs;
import java.awt.Color;
+import java.util.Objects;
+import pulse.problem.schemes.solvers.SolverException;
+import pulse.problem.schemes.solvers.SolverException.SolverExceptionType;
/**
* An enum that represents the different states in which a {@code SearchTask}
@@ -130,5 +133,20 @@ public String getMessage() {
}
return sb.toString();
}
+
+ public static Status troubleshoot(SolverException e1) {
+ Objects.requireNonNull(e1, "Solver exception cannot be null when calling troubleshoot!");
+ Status status = null;
+ if(e1.getType() != SolverExceptionType.OPTIMISATION_TIMEOUT) {
+ status = Status.FAILED;
+ status.setDetails(Details.SOLVER_ERROR);
+ status.setDetailedMessage(e1.getMessage());
+ }
+ else {
+ status = Status.TIMEOUT;
+ status.setDetails(Details.MAX_ITERATIONS_REACHED);
+ }
+ return status;
+ }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/pulse/tasks/processing/Buffer.java b/src/main/java/pulse/tasks/processing/Buffer.java
index bcfbac0..e3a1684 100644
--- a/src/main/java/pulse/tasks/processing/Buffer.java
+++ b/src/main/java/pulse/tasks/processing/Buffer.java
@@ -13,7 +13,7 @@
import pulse.properties.NumericProperty;
import pulse.properties.NumericPropertyKeyword;
import pulse.properties.Property;
-import pulse.tasks.SearchTask;
+import pulse.search.GeneralTask;
import pulse.util.PropertyHolder;
/**
@@ -61,8 +61,9 @@ public void init() {
* @param t the {@code SearchTask}
* @param bufferElement the {@code bufferElement} which will be written over
*/
- public void fill(SearchTask t, int bufferElement) {
- statistic[bufferElement] = (double) t.getCurrentCalculation().getOptimiserStatistic().getStatistic().getValue();
+ public final void fill(GeneralTask t, int bufferElement) {
+ statistic[bufferElement] = (double) t.getResponse()
+ .getOptimiserStatistic().getStatistic().getValue();
data[bufferElement] = t.searchVector();
}
@@ -80,7 +81,7 @@ public boolean isErrorTooHigh(double errorTolerance) {
boolean result = false;
for (int i = 0; i < e.length && (!result); i++) {
- var index = data[0].getIndex(i);
+ var index = data[0].getParameters().get(i).getIdentifier().getKeyword();
final double av = average(index);
e[i] = variance(index) / (av * av);
@@ -105,7 +106,7 @@ public double average(NumericPropertyKeyword index) {
double av = 0;
for (ParameterVector v : data) {
- av += v.getParameterValue(index);
+ av += v.getParameterValue(index, 0);
}
return av / data.length;
@@ -142,7 +143,7 @@ public double variance(NumericPropertyKeyword index) {
double av = average(index);
for (ParameterVector v : data) {
- final double s = v.getParameterValue(index) - av;
+ final double s = v.getParameterValue(index, 0) - av;
sd += s * s;
}
@@ -188,7 +189,7 @@ public void set(NumericPropertyKeyword type, NumericProperty property) {
*/
@Override
public List listedTypes() {
- return new ArrayList(Arrays.asList(def(BUFFER_SIZE)));
+ return new ArrayList<>(Arrays.asList(def(BUFFER_SIZE)));
}
}
diff --git a/src/main/java/pulse/tasks/processing/CorrelationBuffer.java b/src/main/java/pulse/tasks/processing/CorrelationBuffer.java
index 31d3ef1..fc0c0f7 100644
--- a/src/main/java/pulse/tasks/processing/CorrelationBuffer.java
+++ b/src/main/java/pulse/tasks/processing/CorrelationBuffer.java
@@ -7,8 +7,10 @@
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
+import pulse.math.ParameterIdentifier;
import pulse.math.ParameterVector;
+import pulse.math.linear.Vector;
import pulse.properties.NumericPropertyKeyword;
import pulse.search.statistics.CorrelationTest;
import pulse.search.statistics.EmptyCorrelationTest;
@@ -18,9 +20,9 @@
public class CorrelationBuffer {
- private List params;
- private static Set> excludePairList;
- private static Set excludeSingleList;
+ private final List params;
+ private static final Set> excludePairList;
+ private static final Set excludeSingleList;
private final static double DEFAULT_THRESHOLD = 1E-3;
@@ -58,17 +60,18 @@ private void truncate(double threshold) {
for(i = 0; i < size - 1; i = i + 2) {
- ParameterVector diff = new ParameterVector( params.get(i), params.get(i + 1).subtract(params.get(i) ));
- if(diff.lengthSq()/params.get(i).lengthSq() < thresholdSq)
+ Vector vParams = params.get(i).toVector();
+ Vector vPlusOneParams = params.get(i + 1).toVector();
+ Vector vDiff = vPlusOneParams.subtract(vParams);
+ if(vDiff.lengthSq()/vParams.lengthSq() < thresholdSq)
break;
}
for(int j = size - 1; j > i; j--)
- params.remove(j);
-
+ params.remove(j);
}
- public Map, Double> evaluate(CorrelationTest t) {
+ public Map, Double> evaluate(CorrelationTest t) {
if (params.isEmpty()) {
throw new IllegalStateException("Zero number of entries in parameter list");
}
@@ -79,24 +82,40 @@ public Map, Double> evaluate(CorrelationTe
truncate(DEFAULT_THRESHOLD);
- var indices = params.get(0).getIndices();
- var map = indices.stream()
- .map(index -> new ImmutableDataEntry<>(index, params.stream().mapToDouble(v -> v.getParameterValue(index)).toArray()))
+ List indices = params.get(0).getParameters().stream()
+ .map(ps -> ps.getIdentifier()).collect(Collectors.toList());
+ Map map = indices.stream()
+ .map(index -> new ImmutableDataEntry<>(index, params.stream().mapToDouble(
+ v -> v.getParameterValue(index.getKeyword(), index.getIndex())).toArray()))
.collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
int indicesSize = indices.size();
- var correlationMap = new HashMap, Double>();
- ImmutablePair pair = null;
+ var correlationMap = new HashMap, Double>();
+ ImmutablePair pair;
for (int i = 0; i < indicesSize; i++) {
- if (!excludeSingleList.contains(indices.get(i))) {
+ var iKey = indices.get(i).getKeyword();
+
+ if (!excludeSingleList.contains(iKey)) {
+
for (int j = i + 1; j < indicesSize; j++) {
- pair = new ImmutablePair<>(indices.get(i), indices.get(j));
- if (!excludeSingleList.contains(indices.get(j)) && !excludePairList.contains(pair)) {
- correlationMap.put(pair, t.evaluate(map.get(indices.get(i)), map.get(indices.get(j))));
+
+ var jKey = indices.get(j).getKeyword();
+
+ pair = new ImmutablePair<>(iKey, jKey);
+
+ if (!excludeSingleList.contains(jKey)
+ && !excludePairList.contains(pair)) {
+
+ correlationMap.put(
+ new ImmutablePair<>(indices.get(i), indices.get(j)),
+ t.evaluate(map.get(indices.get(i)), map.get(indices.get(j))));
+
}
+
}
+
}
}
@@ -112,6 +131,8 @@ public boolean test(CorrelationTest t) {
return false;
}
+ var values = map.values();
+
return map.values().stream().anyMatch(d -> t.compareToThreshold(d));
}
diff --git a/src/main/java/pulse/tasks/processing/Result.java b/src/main/java/pulse/tasks/processing/Result.java
index 8350aed..626e292 100644
--- a/src/main/java/pulse/tasks/processing/Result.java
+++ b/src/main/java/pulse/tasks/processing/Result.java
@@ -1,5 +1,6 @@
package pulse.tasks.processing;
+import pulse.tasks.Calculation;
import pulse.tasks.SearchTask;
import pulse.ui.Messages;
@@ -28,7 +29,7 @@ public Result(SearchTask task, ResultFormat format) throws IllegalArgumentExcept
throw new IllegalArgumentException(Messages.getString("Result.NullTaskError"));
}
- setParent(task.getCurrentCalculation());
+ setParent((Calculation)task.getResponse());
format.getKeywords().stream().forEach(key -> addProperty(task.numericProperty(key)));
diff --git a/src/main/java/pulse/ui/Launcher.java b/src/main/java/pulse/ui/Launcher.java
index acadc0b..de97832 100644
--- a/src/main/java/pulse/ui/Launcher.java
+++ b/src/main/java/pulse/ui/Launcher.java
@@ -87,7 +87,7 @@ public static void main(String[] args) {
});
} else {
- System.out.println("An instance of PULsE is already running!");
+ System.out.println(Messages.getString("msg.running"));
}
}
diff --git a/src/main/java/pulse/ui/components/CalculationTable.java b/src/main/java/pulse/ui/components/CalculationTable.java
index 9d966b4..95c4ab1 100644
--- a/src/main/java/pulse/ui/components/CalculationTable.java
+++ b/src/main/java/pulse/ui/components/CalculationTable.java
@@ -4,6 +4,8 @@
import static pulse.ui.frames.MainGraphFrame.getChart;
import java.awt.Dimension;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
@@ -23,9 +25,11 @@ public class CalculationTable extends JTable {
private final static int HEADER_HEIGHT = 30;
private TaskTableRenderer taskTableRenderer;
+ private ExecutorService plotExecutor;
public CalculationTable() {
super();
+ plotExecutor = Executors.newSingleThreadExecutor();
setDefaultEditor(Object.class, null);
taskTableRenderer = new TaskTableRenderer();
this.setRowSelectionAllowed(true);
@@ -67,7 +71,7 @@ public void update(SearchTask t) {
}
public void identifySelection(SearchTask t) {
- int modelIndex = t.getStoredCalculations().indexOf(t.getCurrentCalculation());
+ int modelIndex = t.getStoredCalculations().indexOf(t.getResponse());
if (modelIndex > -1) {
this.getSelectionModel().setSelectionInterval(modelIndex, modelIndex);
}
@@ -81,10 +85,12 @@ public void initListeners() {
var task = TaskManager.getManagerInstance().getSelectedTask();
var id = convertRowIndexToModel(this.getSelectedRow());
if (!lsm.getValueIsAdjusting() && id > -1 && id < task.getStoredCalculations().size()) {
-
- task.switchTo(task.getStoredCalculations().get(id));
- getChart().plot(task, true);
-
+
+ plotExecutor.submit(() -> {
+ task.switchTo(task.getStoredCalculations().get(id));
+ getChart().plot(task, true);
+ });
+
}
});
diff --git a/src/main/java/pulse/ui/components/Chart.java b/src/main/java/pulse/ui/components/Chart.java
index 753b878..68dda2d 100644
--- a/src/main/java/pulse/ui/components/Chart.java
+++ b/src/main/java/pulse/ui/components/Chart.java
@@ -41,6 +41,7 @@
import pulse.input.IndexRange;
import pulse.input.Range;
import pulse.input.listeners.DataEvent;
+import pulse.problem.schemes.solvers.SolverException;
import pulse.properties.NumericProperties;
import static pulse.properties.NumericPropertyKeyword.LOWER_BOUND;
import static pulse.properties.NumericPropertyKeyword.UPPER_BOUND;
@@ -90,10 +91,9 @@ public void mouseDragged(MouseEvent e) {
}
SwingUtilities.invokeLater(() -> {
-
+
//process dragged events
- Range range = instance.getSelectedTask()
- .getExperimentalCurve().getRange();
+ Range range = ((ExperimentalData) (instance.getSelectedTask().getInput())).getRange();
double value = xCoord(e) / factor; //convert to seconds back from ms -- if needed
if (lowerMarker.getState() != MovableValueMarker.State.IDLE) {
@@ -107,7 +107,7 @@ public void mouseDragged(MouseEvent e) {
} else {
super.mouseDragged(e);
}
-
+
});
}
@@ -118,12 +118,13 @@ public void mouseDragged(MouseEvent e) {
//for each new task
var eventTask = instance.getTask(e.getId());
if (e.getState() == TaskRepositoryEvent.State.TASK_ADDED) {
+ var data = (ExperimentalData) eventTask.getInput();
//add passive data listener
- eventTask.getExperimentalCurve().addDataListener((DataEvent e1) -> {
+ data.addDataListener((DataEvent e1) -> {
//that will be triggered only when this task is selected
if (instance.getSelectedTask() == eventTask) {
//update marker values
- var segment = eventTask.getExperimentalCurve().getRange().getSegment();
+ var segment = data.getRange().getSegment();
lowerMarker.setValue(segment.getMinimum() * factor); //convert to ms -- if needed
upperMarker.setValue(segment.getMaximum() * factor); //convert to ms -- if needed
}
@@ -221,7 +222,7 @@ public void plot(SearchTask task, boolean extendedCurve) {
plot.setDataset(i, null);
}
- var rawData = task.getExperimentalCurve();
+ var rawData = (ExperimentalData) task.getInput();
var segment = rawData.getRange().getSegment();
adjustAxisLabel(segment.getMaximum());
@@ -239,7 +240,7 @@ public void plot(SearchTask task, boolean extendedCurve) {
lowerMarker = new MovableValueMarker(segment.getMinimum() * factor);
upperMarker = new MovableValueMarker(segment.getMaximum() * factor);
- final double margin = (lowerMarker.getValue() + upperMarker.getValue())/20.0;
+ final double margin = (lowerMarker.getValue() + upperMarker.getValue()) / 20.0;
//add listener to handle range adjustment
var lowerMarkerListener = new MouseOnMarkerListener(this, lowerMarker, upperMarker, margin);
@@ -251,7 +252,7 @@ public void plot(SearchTask task, boolean extendedCurve) {
plot.addDomainMarker(upperMarker);
plot.addDomainMarker(lowerMarker);
- var calc = task.getCurrentCalculation();
+ var calc = (Calculation) task.getResponse();
var problem = calc.getProblem();
if (problem != null) {
@@ -259,6 +260,15 @@ public void plot(SearchTask task, boolean extendedCurve) {
var solution = problem.getHeatingCurve();
var scheme = calc.getScheme();
+ if (solution != null && !solution.isFull()) {
+ try {
+ calc.process();
+ } catch (SolverException ex) {
+ System.out.println("Could not plot solution! See details in debug.");
+ ex.printStackTrace();
+ }
+ }
+
if (solution != null && scheme != null) {
var solutionDataset = new XYSeriesCollection();
@@ -298,7 +308,7 @@ public void plot(SearchTask task, boolean extendedCurve) {
public void plotSingle(HeatingCurve curve) {
requireNonNull(curve);
- var plot = chart.getXYPlot();
+ plot = chart.getXYPlot();
var classicDataset = new XYSeriesCollection();
@@ -339,6 +349,7 @@ public XYSeries residuals(Calculation calc) {
var problem = calc.getProblem();
var baseline = problem.getBaseline();
+ var time = calc.getOptimiserStatistic().getTimeSequence();
var residuals = calc.getOptimiserStatistic().getResiduals();
var size = residuals.size();
@@ -348,7 +359,7 @@ public XYSeries residuals(Calculation calc) {
var series = new XYSeries(format("Residuals (offset %3.2f)", offset));
for (var i = 0; i < size; i++) {
- series.add(factor * residuals.get(i)[0], (Number) (residuals.get(i)[1] + offset));
+ series.add(factor * time.get(i), (Number) (residuals.get(i) + offset));
}
return series;
diff --git a/src/main/java/pulse/ui/components/DataLoader.java b/src/main/java/pulse/ui/components/DataLoader.java
index d6b6539..34f9f97 100644
--- a/src/main/java/pulse/ui/components/DataLoader.java
+++ b/src/main/java/pulse/ui/components/DataLoader.java
@@ -15,12 +15,14 @@
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
+import pulse.input.ExperimentalData;
import pulse.input.InterpolationDataset;
import pulse.input.InterpolationDataset.StandartType;
import pulse.io.readers.MetaFilePopulator;
import pulse.io.readers.ReaderManager;
import pulse.problem.laser.NumericPulse;
+import pulse.tasks.Calculation;
import pulse.tasks.SearchTask;
import pulse.tasks.TaskManager;
import pulse.tasks.listeners.TaskRepositoryEvent;
@@ -99,7 +101,7 @@ public static void loadMetadataDialog() {
// attempt to fill metadata and problem
for (SearchTask task : instance.getTaskList()) {
- var data = task.getExperimentalCurve();
+ var data = (ExperimentalData) task.getInput();
try {
handler.populate(file, data.getMetadata());
@@ -109,7 +111,7 @@ public static void loadMetadataDialog() {
e.printStackTrace();
}
- var p = task.getCurrentCalculation().getProblem();
+ var p = ( (Calculation) task.getResponse() ).getProblem();
if (p != null) {
p.retrieveData(data);
}
@@ -146,7 +148,7 @@ public static void loadPulseDialog() {
if (task != null) {
pool.submit(() -> {
- var metadata = task.getExperimentalCurve().getMetadata();
+ var metadata = ((ExperimentalData) task.getInput()).getMetadata();
metadata.setPulseData(pulseData);
metadata.getPulseDescriptor()
.setSelectedDescriptor(
diff --git a/src/main/java/pulse/ui/components/LogPane.java b/src/main/java/pulse/ui/components/LogPane.java
index 0fb1716..5af4215 100644
--- a/src/main/java/pulse/ui/components/LogPane.java
+++ b/src/main/java/pulse/ui/components/LogPane.java
@@ -90,7 +90,7 @@ public void printAll() {
log.getLogEntries().stream().forEach(entry -> post(entry));
- if (task.getCurrentCalculation().getStatus() == DONE) {
+ if (task.getStatus() == DONE) {
printTimeTaken(log);
}
diff --git a/src/main/java/pulse/ui/components/ProblemTree.java b/src/main/java/pulse/ui/components/ProblemTree.java
index 54513d9..e4c2e0d 100644
--- a/src/main/java/pulse/ui/components/ProblemTree.java
+++ b/src/main/java/pulse/ui/components/ProblemTree.java
@@ -14,6 +14,7 @@
import pulse.problem.statements.Problem;
import pulse.problem.statements.ProblemComplexity;
+import pulse.tasks.Calculation;
import pulse.ui.components.controllers.ProblemCellRenderer;
import pulse.ui.components.listeners.ProblemSelectionEvent;
import pulse.ui.components.listeners.ProblemSelectionListener;
@@ -21,7 +22,7 @@
@SuppressWarnings("serial")
public class ProblemTree extends JTree {
- private List selectionListeners;
+ private final List selectionListeners;
public ProblemTree(List allProblems) {
super();
@@ -66,7 +67,7 @@ private void addListeners() {
});
instance.addSelectionListener(e -> {
- var current = instance.getSelectedTask().getCurrentCalculation().getProblem();
+ var current = ( (Calculation) instance.getSelectedTask().getResponse() ).getProblem();
// select appropriate problem type from list
setSelectedProblem(current);
@@ -108,7 +109,7 @@ public void setSelectedProblem(Problem p) {
});
}
- public void addProblemSelectionListener(ProblemSelectionListener l) {
+ public final void addProblemSelectionListener(ProblemSelectionListener l) {
selectionListeners.add(l);
}
diff --git a/src/main/java/pulse/ui/components/PulseMainMenu.java b/src/main/java/pulse/ui/components/PulseMainMenu.java
index 74aeeab..216770e 100644
--- a/src/main/java/pulse/ui/components/PulseMainMenu.java
+++ b/src/main/java/pulse/ui/components/PulseMainMenu.java
@@ -44,6 +44,7 @@
import pulse.search.statistics.NormalityTest;
import pulse.search.statistics.OptimiserStatistic;
import pulse.search.statistics.SumOfSquares;
+import pulse.tasks.Calculation;
import pulse.tasks.listeners.TaskRepositoryEvent;
import pulse.tasks.processing.Buffer;
import pulse.ui.components.listeners.ExitRequestListener;
@@ -244,7 +245,8 @@ private JMenu initAnalysisSubmenu() {
if (((AbstractButton) e.getItem()).isSelected()) {
var text = ((AbstractButton) e.getItem()).getText();
setSelectedOptimiserDescriptor(text);
- getManagerInstance().getTaskList().stream().forEach(t -> t.getCurrentCalculation().initOptimiser());
+ getManagerInstance().getTaskList().stream().forEach(t ->
+ ( (Calculation) t.getResponse() ).initOptimiser());
}
});
diff --git a/src/main/java/pulse/ui/components/RangeTextFields.java b/src/main/java/pulse/ui/components/RangeTextFields.java
index 47cacf1..a146e55 100644
--- a/src/main/java/pulse/ui/components/RangeTextFields.java
+++ b/src/main/java/pulse/ui/components/RangeTextFields.java
@@ -1,30 +1,15 @@
-/*
- * Copyright 2021 Artem Lunev .
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
package pulse.ui.components;
import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.text.DecimalFormat;
-import java.text.NumberFormat;
import java.text.ParseException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFormattedTextField;
import javax.swing.text.NumberFormatter;
+import pulse.input.ExperimentalData;
import pulse.input.Range;
import pulse.input.listeners.DataEvent;
import pulse.tasks.SearchTask;
@@ -36,7 +21,6 @@
/**
* Two JFormattedTextFields used to display the range of the currently
* selected task.
- * @author Artem Lunev
*/
public final class RangeTextFields {
@@ -69,7 +53,7 @@ public RangeTextFields() {
//when a new task is selected
instance.addSelectionListener((TaskSelectionEvent e) -> {
var task = instance.getSelectedTask();
- var segment = task.getExperimentalCurve().getRange().getSegment();
+ var segment = ( (ExperimentalData) task.getInput() ).getRange().getSegment();
//update the textfield values
lowerLimitField.setValue(segment.getMinimum());
upperLimitField.setValue(segment.getMaximum());
@@ -109,8 +93,8 @@ private NumberFormatter initFormatter() {
*/
private static boolean isEditValid(JFormattedTextField jtf, boolean upperBound) {
- Range range = TaskManager.getManagerInstance().getSelectedTask()
- .getExperimentalCurve().getRange();
+ Range range = ( (ExperimentalData) TaskManager.getManagerInstance().getSelectedTask()
+ .getInput() ).getRange();
double candidateValue = 0.0;
try {
@@ -195,10 +179,11 @@ public void focusLost(FocusEvent arg0) {
}
private void updateTextfieldsFromTask(SearchTask newTask) {
+ var data = (ExperimentalData) newTask.getInput();
//add data listeners in case when the range of the selected task is changed
- newTask.getExperimentalCurve().addDataListener((DataEvent e1) -> {
+ data.addDataListener((DataEvent e1) -> {
if (TaskManager.getManagerInstance().getSelectedTask() == newTask) {
- var segment = newTask.getExperimentalCurve().getRange().getSegment();
+ var segment = data.getRange().getSegment();
lowerLimitField.setValue(segment.getMinimum());
upperLimitField.setValue(segment.getMaximum());
}
diff --git a/src/main/java/pulse/ui/components/ResidualsChart.java b/src/main/java/pulse/ui/components/ResidualsChart.java
index 614d786..7a78ee2 100644
--- a/src/main/java/pulse/ui/components/ResidualsChart.java
+++ b/src/main/java/pulse/ui/components/ResidualsChart.java
@@ -30,10 +30,10 @@ public void plot(ResidualStatistic stat) {
var pulseDataset = new HistogramDataset();
pulseDataset.setType(HistogramType.RELATIVE_FREQUENCY);
- var residuals = stat.transformResiduals();
+ var residuals = stat.residualsArray();
if (residuals.length > 0) {
- pulseDataset.addSeries("H1", stat.transformResiduals(), binCount);
+ pulseDataset.addSeries("H1", residuals, binCount);
}
getPlot().setDataset(0, pulseDataset);
diff --git a/src/main/java/pulse/ui/components/ResultTable.java b/src/main/java/pulse/ui/components/ResultTable.java
index 520aa0e..d718926 100644
--- a/src/main/java/pulse/ui/components/ResultTable.java
+++ b/src/main/java/pulse/ui/components/ResultTable.java
@@ -17,6 +17,7 @@
import javax.swing.table.TableRowSorter;
import pulse.properties.NumericProperty;
+import pulse.tasks.Calculation;
import pulse.tasks.SearchTask;
import pulse.tasks.TaskManager;
import pulse.tasks.listeners.TaskRepositoryEvent;
@@ -77,35 +78,41 @@ public ResultTable(ResultFormat fmt) {
*/
TaskManager.getManagerInstance().addTaskRepositoryListener((TaskRepositoryEvent e) -> {
var t = instance.getTask(e.getId());
- switch (e.getState()) {
- case TASK_FINISHED:
- var r = t.getCurrentCalculation().getResult();
- var resultTableModel = (ResultTableModel) getModel();
- Objects.requireNonNull(r, "Task finished with a null result!");
- invokeLater(() -> resultTableModel.addRow(r));
- break;
- case TASK_REMOVED:
- case TASK_RESET:
- ((ResultTableModel) getModel()).removeAll(e.getId());
- getSelectionModel().clearSelection();
- break;
- case BEST_MODEL_SELECTED:
- for (var c : t.getStoredCalculations()) {
- if (c.getResult() != null && c != t.getCurrentCalculation()) {
- ((ResultTableModel) getModel()).remove(c.getResult());
+
+ if(t != null) {
+
+ var cc = (Calculation) t.getResponse();
+
+ switch (e.getState()) {
+ case TASK_FINISHED:
+ var r = cc.getResult();
+ var resultTableModel = (ResultTableModel) getModel();
+ Objects.requireNonNull(r, "Task finished with a null result!");
+ invokeLater(() -> resultTableModel.addRow(r));
+ break;
+ case TASK_REMOVED:
+ case TASK_RESET:
+ ((ResultTableModel) getModel()).removeAll(e.getId());
+ getSelectionModel().clearSelection();
+ break;
+ case BEST_MODEL_SELECTED:
+ for (var c : t.getStoredCalculations()) {
+ if (c.getResult() != null && c != cc) {
+ ((ResultTableModel) getModel()).remove(c.getResult());
+ }
}
- }
- this.select(t.getCurrentCalculation().getResult());
- break;
- case TASK_MODEL_SWITCH:
- var c = t.getCurrentCalculation();
- this.getSelectionModel().clearSelection();
- if (c != null && c.getResult() != null) {
- select(c.getResult());
- }
- break;
- default:
- break;
+ this.select(cc.getResult());
+ break;
+ case TASK_MODEL_SWITCH:
+ this.getSelectionModel().clearSelection();
+ if (cc != null && cc.getResult() != null) {
+ select(cc.getResult());
+ }
+ break;
+ default:
+ break;
+ }
+
}
});
diff --git a/src/main/java/pulse/ui/components/TaskPopupMenu.java b/src/main/java/pulse/ui/components/TaskPopupMenu.java
index d89e43d..5dc2c26 100644
--- a/src/main/java/pulse/ui/components/TaskPopupMenu.java
+++ b/src/main/java/pulse/ui/components/TaskPopupMenu.java
@@ -27,9 +27,11 @@
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
+import pulse.input.ExperimentalData;
import pulse.problem.schemes.solvers.Solver;
import pulse.problem.schemes.solvers.SolverException;
+import pulse.tasks.Calculation;
import pulse.tasks.TaskManager;
import pulse.tasks.listeners.TaskRepositoryEvent;
import pulse.tasks.processing.Result;
@@ -69,8 +71,9 @@ public TaskPopupMenu() {
getString("TaskTablePopupMenu.EmptySelection2"), //$NON-NLS-1$
getString("TaskTablePopupMenu.11"), ERROR_MESSAGE); //$NON-NLS-1$
} else {
+ var input = (ExperimentalData) t.getInput();
showMessageDialog(getWindowAncestor((Component) e.getSource()),
- t.getExperimentalCurve().getMetadata().toString(), "Metadata", PLAIN_MESSAGE);
+ input.getMetadata().toString(), "Metadata", PLAIN_MESSAGE);
}
});
@@ -78,14 +81,14 @@ public TaskPopupMenu() {
instance.addSelectionListener(event -> {
instance.getSelectedTask().checkProblems(false);
- var details = instance.getSelectedTask().getCurrentCalculation().getStatus().getDetails();
+ var details = instance.getSelectedTask().getStatus().getDetails();
itemShowStatus.setEnabled((details != null) & (details != NONE));
});
itemShowStatus.addActionListener((ActionEvent e) -> {
var t = instance.getSelectedTask();
if (t != null) {
- var d = t.getCurrentCalculation().getStatus().getDetails();
+ var d = t.getStatus().getDetails();
showMessageDialog(getWindowAncestor((Component) e.getSource()),
"This is due to " + d.toString() + "", "Problems with " + t, INFORMATION_MESSAGE);
}
@@ -100,7 +103,7 @@ public TaskPopupMenu() {
getString("TaskTablePopupMenu.ErrorTitle"), ERROR_MESSAGE); //$NON-NLS-1$
} else {
t.checkProblems(true);
- var status = t.getCurrentCalculation().getStatus();
+ var status = t.getStatus();
if (status == DONE) {
var dialogButton = YES_NO_OPTION;
@@ -115,7 +118,7 @@ public TaskPopupMenu() {
}
} else if (status != READY) {
showMessageDialog(getWindowAncestor((Component) e.getSource()),
- t.toString() + " is " + t.getCurrentCalculation().getStatus().getMessage(), //$NON-NLS-1$
+ t.toString() + " is " + t.getStatus().getMessage(), //$NON-NLS-1$
getString("TaskTablePopupMenu.TaskNotReady"), //$NON-NLS-1$
ERROR_MESSAGE);
} else {
@@ -136,7 +139,7 @@ public TaskPopupMenu() {
if (t == null) {
return;
}
- var current = t.getCurrentCalculation();
+ var current = (Calculation) t.getResponse();
if (current != null) {
var r = new Result(t, getInstance());
current.setResult(r);
@@ -175,8 +178,8 @@ public void plot(boolean extended) {
getString("TaskTablePopupMenu.11"), ERROR_MESSAGE); //$NON-NLS-1$
} else {
- var calc = t.getCurrentCalculation();
- var statusDetails = calc.getStatus().getDetails();
+ var calc = (Calculation) t.getResponse();
+ var statusDetails = t.getStatus().getDetails();
if (statusDetails == MISSING_HEATING_CURVE) {
diff --git a/src/main/java/pulse/ui/components/buttons/ExecutionButton.java b/src/main/java/pulse/ui/components/buttons/ExecutionButton.java
index 37b84d5..30ea042 100644
--- a/src/main/java/pulse/ui/components/buttons/ExecutionButton.java
+++ b/src/main/java/pulse/ui/components/buttons/ExecutionButton.java
@@ -50,12 +50,12 @@ public ExecutionButton() {
}
var problematicTask = instance.getTaskList().stream().filter(t -> {
t.checkProblems(true);
- return t.getCurrentCalculation().getStatus() == INCOMPLETE;
+ return t.getStatus() == INCOMPLETE;
}).findFirst();
if (problematicTask.isPresent()) {
var t = problematicTask.get();
showMessageDialog(getWindowAncestor((Component) e.getSource()),
- t + " is " + t.getCurrentCalculation().getStatus().getMessage(), "Problems found",
+ t + " is " + t.getStatus().getMessage(), "Problems found",
ERROR_MESSAGE);
} else {
instance.executeAll();
diff --git a/src/main/java/pulse/ui/components/controllers/InstanceCellEditor.java b/src/main/java/pulse/ui/components/controllers/InstanceCellEditor.java
index ac0c3bd..526823f 100644
--- a/src/main/java/pulse/ui/components/controllers/InstanceCellEditor.java
+++ b/src/main/java/pulse/ui/components/controllers/InstanceCellEditor.java
@@ -32,8 +32,10 @@ public Component getTableCellEditorComponent(JTable table, Object value, boolean
try {
descriptor.attemptUpdate(e.getItem());
} catch(NullPointerException npe) {
- System.out.println("Error updating " + descriptor.getDescriptor(false)
- + ". Cannot be set to " + e.getItem());
+ String text = "Error updating " + descriptor.getDescriptor(false)
+ + ". Cannot be set to " + e.getItem();
+ System.out.println(text);
+ npe.printStackTrace();
}
}
});
diff --git a/src/main/java/pulse/ui/components/models/ResultTableModel.java b/src/main/java/pulse/ui/components/models/ResultTableModel.java
index ffd35db..8592285 100644
--- a/src/main/java/pulse/ui/components/models/ResultTableModel.java
+++ b/src/main/java/pulse/ui/components/models/ResultTableModel.java
@@ -223,8 +223,7 @@ public void addRow(AbstractResult result) {
if (result instanceof Result) {
//result must have a valid ancestor!
- var ancestor = Objects.requireNonNull(
- result.specificAncestor(SearchTask.class),
+ var ancestor = Objects.requireNonNull(result.specificAncestor(SearchTask.class),
"Result " + result.toString() + " does not belong a SearchTask!");
//the ancestor then has the SearchTask type
@@ -232,8 +231,7 @@ public void addRow(AbstractResult result) {
//any old result asssociated withis this task
var oldResult = results.stream().filter(r
- -> r.specificAncestor(
- SearchTask.class) == parentTask).findAny();
+ -> r.specificAncestor(SearchTask.class) == parentTask).findAny();
//check the following only if the old result is present
if (oldResult.isPresent()) {
@@ -249,7 +247,8 @@ public void addRow(AbstractResult result) {
Status status = Status.DONE;
//better result than already present -- update table
- if (parentTask.getCurrentCalculation().isBetterThan(oldCalculation.get())) {
+ var c = (Calculation) parentTask.getResponse();
+ if (c.isBetterThan(oldCalculation.get())) {
remove(oldResultExisting);
status.setDetails(Details.BETTER_CALCULATION_RESULTS_THAN_PREVIOUSLY_OBTAINED);
parentTask.setStatus(status);
diff --git a/src/main/java/pulse/ui/components/models/TaskTableModel.java b/src/main/java/pulse/ui/components/models/TaskTableModel.java
index 77d51b8..86eef58 100644
--- a/src/main/java/pulse/ui/components/models/TaskTableModel.java
+++ b/src/main/java/pulse/ui/components/models/TaskTableModel.java
@@ -11,6 +11,8 @@
import static pulse.ui.Messages.getString;
import javax.swing.table.DefaultTableModel;
+import pulse.input.ExperimentalData;
+import pulse.tasks.Calculation;
import pulse.tasks.Identifier;
import pulse.tasks.SearchTask;
@@ -51,11 +53,12 @@ public TaskTableModel() {
}
public void addTask(SearchTask t) {
- var temperature = t.getExperimentalCurve()
+ var temperature = ( (ExperimentalData) t.getInput() )
.getMetadata().numericProperty(TEST_TEMPERATURE);
+ var calc = (Calculation) t.getResponse();
var data = new Object[]{t.getIdentifier(), temperature,
- t.getCurrentCalculation().getOptimiserStatistic().getStatistic(),
- t.getNormalityTest().getStatistic(), t.getCurrentCalculation().getStatus()};
+ calc.getOptimiserStatistic().getStatistic(),
+ t.getNormalityTest().getStatistic(), t.getStatus()};
invokeLater(() -> super.addRow(data));
@@ -68,7 +71,7 @@ public void addTask(SearchTask t) {
});
t.addTaskListener((LogEntry e) -> {
- setValueAt(t.getCurrentCalculation().getOptimiserStatistic()
+ setValueAt(calc.getOptimiserStatistic()
.getStatistic(), searchRow(t.getIdentifier()), SEARCH_STATISTIC_COLUMN);
});
diff --git a/src/main/java/pulse/ui/components/panels/ChartToolbar.java b/src/main/java/pulse/ui/components/panels/ChartToolbar.java
index 011d2f7..b4d5e54 100644
--- a/src/main/java/pulse/ui/components/panels/ChartToolbar.java
+++ b/src/main/java/pulse/ui/components/panels/ChartToolbar.java
@@ -26,6 +26,7 @@
import pulse.input.ExperimentalData;
import pulse.input.Range;
+import pulse.tasks.Calculation;
import pulse.tasks.TaskManager;
import pulse.ui.Messages;
import pulse.ui.components.RangeTextFields;
@@ -64,12 +65,13 @@ public final void initComponents() {
pdfBtn.addActionListener(e -> {
var task = TaskManager.getManagerInstance().getSelectedTask();
+ var calc = (Calculation) task.getResponse();
- if (task != null && task.getCurrentCalculation().getModelSelectionCriterion() != null) {
+ if (task != null && calc.getModelSelectionCriterion() != null) {
chFrame.setLocationRelativeTo(null);
chFrame.setVisible(true);
- chFrame.plot(task.getCurrentCalculation().getOptimiserStatistic());
+ chFrame.plot(calc.getOptimiserStatistic());
}
@@ -130,7 +132,7 @@ private void validateRange(double a, double b) {
return;
}
- var expCurve = task.getExperimentalCurve();
+ var expCurve = (ExperimentalData) task.getInput();
if (expCurve == null) {
return;
@@ -169,7 +171,7 @@ private void validateRange(double a, double b) {
// set range for all available experimental datasets
TaskManager.getManagerInstance().getTaskList()
.stream().forEach((aTask)
- -> setRange(aTask.getExperimentalCurve(), a, b)
+ -> setRange( (ExperimentalData) aTask.getInput(), a, b)
);
}
diff --git a/src/main/java/pulse/ui/components/panels/ProblemToolbar.java b/src/main/java/pulse/ui/components/panels/ProblemToolbar.java
index 0aeedc8..92e42ca 100644
--- a/src/main/java/pulse/ui/components/panels/ProblemToolbar.java
+++ b/src/main/java/pulse/ui/components/panels/ProblemToolbar.java
@@ -20,6 +20,7 @@
import pulse.problem.schemes.solvers.Solver;
import pulse.problem.schemes.solvers.SolverException;
+import pulse.tasks.Calculation;
import pulse.tasks.TaskManager;
import pulse.ui.components.buttons.LoaderButton;
import pulse.ui.frames.MainGraphFrame;
@@ -61,15 +62,16 @@ public static void plot(ActionEvent e) {
var t = instance.getSelectedTask();
- var calc = t.getCurrentCalculation();
+ var calc = (Calculation) t.getResponse();
t.checkProblems(true);
- var status = t.getCurrentCalculation().getStatus();
+ var status = t.getStatus();
if (status == INCOMPLETE && !status.checkProblemStatementSet()) {
getDefaultToolkit().beep();
- showMessageDialog(getWindowAncestor((Component) e.getSource()), calc.getStatus().getMessage(),
+ showMessageDialog(getWindowAncestor((Component) e.getSource()),
+ calc.getStatus().getMessage(),
getString("ProblemStatementFrame.ErrorTitle"), //$NON-NLS-1$
ERROR_MESSAGE);
diff --git a/src/main/java/pulse/ui/frames/HistogramFrame.java b/src/main/java/pulse/ui/frames/HistogramFrame.java
index f91f8a7..9debcdc 100644
--- a/src/main/java/pulse/ui/frames/HistogramFrame.java
+++ b/src/main/java/pulse/ui/frames/HistogramFrame.java
@@ -9,6 +9,7 @@
import javax.swing.JSlider;
import pulse.search.statistics.ResidualStatistic;
+import pulse.tasks.Calculation;
import pulse.tasks.TaskManager;
import pulse.ui.components.AuxPlotter;
import pulse.ui.components.ResidualsChart;
@@ -29,7 +30,9 @@ public HistogramFrame(AuxPlotter chart, int width, int height
getContentPane().add(panel, SOUTH);
slider.addChangeListener(e -> {
((ResidualsChart) chart).setBinCount(slider.getValue());
- plot(TaskManager.getManagerInstance().getSelectedTask().getCurrentCalculation().getOptimiserStatistic());
+ var c = (Calculation) TaskManager.getManagerInstance().getSelectedTask()
+ .getResponse();
+ plot(c.getOptimiserStatistic());
info.setText("Number of bins: " + slider.getValue());
});
}
diff --git a/src/main/java/pulse/ui/frames/MainGraphFrame.java b/src/main/java/pulse/ui/frames/MainGraphFrame.java
index fff33ec..e4400d4 100644
--- a/src/main/java/pulse/ui/frames/MainGraphFrame.java
+++ b/src/main/java/pulse/ui/frames/MainGraphFrame.java
@@ -4,8 +4,11 @@
import static java.awt.BorderLayout.LINE_END;
import static java.awt.BorderLayout.PAGE_END;
import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.swing.JInternalFrame;
+import pulse.problem.schemes.solvers.SolverException;
import pulse.tasks.TaskManager;
import pulse.tasks.logs.Status;
@@ -46,7 +49,7 @@ private void initComponents() {
public void plot() {
var task = TaskManager.getManagerInstance().getSelectedTask();
//do not plot tasks that are not finished
- if (task != null && task.getCurrentCalculation().getStatus() != Status.IN_PROGRESS) {
+ if (task != null && task.getStatus() != Status.IN_PROGRESS) {
Executors.newSingleThreadExecutor().submit(() -> chart.plot(task, false));
}
}
diff --git a/src/main/java/pulse/ui/frames/ProblemStatementFrame.java b/src/main/java/pulse/ui/frames/ProblemStatementFrame.java
index 41d5bbf..6acd7da 100644
--- a/src/main/java/pulse/ui/frames/ProblemStatementFrame.java
+++ b/src/main/java/pulse/ui/frames/ProblemStatementFrame.java
@@ -14,8 +14,10 @@
import java.awt.BorderLayout;
import java.awt.GridLayout;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
@@ -32,9 +34,11 @@
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreePath;
+import pulse.input.ExperimentalData;
import pulse.problem.schemes.DifferenceScheme;
import pulse.problem.statements.Problem;
+import pulse.tasks.Calculation;
import pulse.tasks.SearchTask;
import pulse.tasks.TaskManager;
import pulse.tasks.listeners.TaskSelectionEvent;
@@ -44,6 +48,7 @@
import pulse.ui.components.panels.ProblemToolbar;
import pulse.ui.components.panels.SettingsToolBar;
import pulse.ui.frames.TaskControlFrame.Mode;
+import pulse.ui.frames.dialogs.ProgressDialog;
@SuppressWarnings("serial")
public class ProblemStatementFrame extends JInternalFrame {
@@ -108,22 +113,25 @@ public ProblemStatementFrame() {
/*
* Scheme list and scroller
*/
- schemeSelectionList = new JList();
+ schemeSelectionList = new JList<>();
schemeSelectionList.setSelectionMode(SINGLE_SELECTION);
- schemeSelectionList.setModel(new DefaultListModel());
+ schemeSelectionList.setModel(new DefaultListModel<>());
schemeSelectionList.addListSelectionListener((ListSelectionEvent arg0) -> {
- if (TaskControlFrame.getInstance().getMode() != Mode.PROBLEM) {
- return;
- }
+ if (TaskControlFrame.getInstance().getMode() == Mode.PROBLEM) {
- var selectedValue = schemeSelectionList.getSelectedValue();
+ var selectedValue = schemeSelectionList.getSelectedValue();
+
+ if (selectedValue != null) {
+
+ if (arg0.getValueIsAdjusting() || !(selectedValue instanceof DifferenceScheme)) {
+ ((DefaultTableModel) schemeTable.getModel()).setRowCount(0);
+ } else {
+ changeSchemes(selectedValue);
+ }
+
+ }
- if (arg0.getValueIsAdjusting() || !(selectedValue instanceof DifferenceScheme)) {
- ((DefaultTableModel) schemeTable.getModel()).setRowCount(0);
- }
- else {
- changeSchemes(selectedValue);
}
});
@@ -195,7 +203,7 @@ public void setSelectionPath(TreePath path) {
//for all tasks
instance.getTaskList().stream().
//select the problem statement of the current calculation
- map(t -> t.getCurrentCalculation().getProblem())
+ map(t -> ((Calculation) t.getResponse()).getProblem())
//that is non-null
.filter(problem -> problem != null)
//for each problem, update its properties in a separete thread
@@ -215,13 +223,9 @@ public void update() {
}
private void update(SearchTask selectedTask) {
-
- if(selectedTask == null)
- return;
-
- var calc = selectedTask.getCurrentCalculation();
- var selectedProblem = selectedTask == null ? null : calc.getProblem();
- var selectedScheme = selectedTask == null ? null : calc.getScheme();
+ var calc = (Calculation) selectedTask.getResponse();
+ var selectedProblem = calc.getProblem();
+ var selectedScheme = calc.getScheme();
// problem
if (selectedProblem == null) {
@@ -237,95 +241,139 @@ private void update(SearchTask selectedTask) {
setSelectedElement(schemeSelectionList, selectedScheme);
schemeTable.setPropertyHolder(selectedScheme);
}
-
}
private void changeSchemes(DifferenceScheme newScheme) {
var instance = TaskManager.getManagerInstance();
var selectedTask = instance.getSelectedTask();
+
+ var schemeLoaderTracker = new ProgressDialog();
+ schemeLoaderTracker.setTitle("Initialising solution schemes...");
+ schemeLoaderTracker.setLocationRelativeTo(null);
+ schemeLoaderTracker.setAlwaysOnTop(true);
+
+ List> callableList;
+
if (instance.isSingleStatement()) {
- var callableList = instance.getTaskList().stream().map(t -> new Callable() {
+ callableList = instance.getTaskList().stream().map(t -> new Callable() {
@Override
public DifferenceScheme call() throws Exception {
changeScheme(t, newScheme);
- return t.getCurrentCalculation().getScheme();
+ schemeLoaderTracker.incrementProgress();
+ return ((Calculation) t.getResponse()).getScheme();
}
}).collect(Collectors.toList());
+ } else {
+ callableList = Arrays.asList(() -> {
+ changeScheme(selectedTask, newScheme);
+ return selectedTask.getResponse().getScheme();
+ });
+ }
+
+ schemeLoaderTracker.trackProgress(callableList.size() - 1);
+
+ CompletableFuture.runAsync(() -> {
try {
schemeListExecutor.invokeAll(callableList);
} catch (InterruptedException ex) {
- Logger.getLogger(ProblemStatementFrame.class.getName()).log(Level.SEVERE, null, ex);
+ ex.printStackTrace();
}
+ }).thenRun(() -> {
- } else {
- changeScheme(selectedTask, newScheme);
- }
- schemeTable.setPropertyHolder(selectedTask.getCurrentCalculation().getScheme());
- if (selectedTask.getCurrentCalculation().getProblem().getComplexity() == HIGH) {
- showMessageDialog(null, getString("complexity.warning"), "High complexity", INFORMATION_MESSAGE);
- }
+ var c = (Calculation) selectedTask.getResponse();
+ schemeTable.setPropertyHolder(c.getScheme());
+ if (c.getProblem().getComplexity() == HIGH) {
+ showMessageDialog(null, getString("complexity.warning"),
+ "High complexity", INFORMATION_MESSAGE);
+ }
+ Executors.newSingleThreadExecutor().submit(() -> ProblemToolbar.plot(null));
+ });
}
private void changeProblems(Problem newlySelectedProblem, Object source) {
var instance = TaskManager.getManagerInstance();
- var selectedTask = instance.getSelectedTask();
+ var task = instance.getSelectedTask();
+ var selectedCalc = ((Calculation) task.getResponse());
+
+ var problemLoaderTracker = new ProgressDialog();
+ problemLoaderTracker.setTitle("Changing problem statements...");
+ problemLoaderTracker.setLocationRelativeTo(null);
+ problemLoaderTracker.setAlwaysOnTop(true);
+
+ List> callableList;
if (source != instance) {
+ //apply to all tasks
if (instance.isSingleStatement()) {
- var callableList = instance.getTaskList().stream().map(t -> new Callable() {
+ callableList = instance.getTaskList().stream().map(t -> new Callable() {
@Override
public Problem call() throws Exception {
changeProblem(t, newlySelectedProblem);
- return t.getCurrentCalculation().getProblem();
+ var result = ((Calculation) t.getResponse()).getProblem();
+ problemLoaderTracker.incrementProgress();
+ return result;
}
}).collect(Collectors.toList());
+
+ } //apply only to this task
+ else {
+ callableList = Arrays.asList(() -> {
+ changeProblem(task, newlySelectedProblem);
+ return ((Calculation) task.getResponse()).getProblem();
+ });
+ }
+
+ problemLoaderTracker.trackProgress(callableList.size() - 1);
+
+ CompletableFuture.runAsync(() -> {
try {
problemListExecutor.invokeAll(callableList);
} catch (InterruptedException ex) {
- Logger.getLogger(ProblemStatementFrame.class.getName()).log(Level.SEVERE, null, ex);
+ ex.printStackTrace();
}
-
- } else {
- changeProblem(selectedTask, newlySelectedProblem);
}
+ ).thenRun(() -> {
+ problemTable.setPropertyHolder(selectedCalc.getProblem());
+ // after problem is selected for this task, show available difference schemes
+ var defaultModel = (DefaultListModel) (schemeSelectionList.getModel());
+ defaultModel.clear();
+ var schemes = newlySelectedProblem.availableSolutions();
+ schemes.forEach(s -> defaultModel.addElement(s));
+ selectDefaultScheme(schemeSelectionList, selectedCalc.getProblem());
+ schemeSelectionList.setToolTipText(null);
+ });
}
- problemTable.setPropertyHolder(selectedTask.getCurrentCalculation().getProblem());
- // after problem is selected for this task, show available difference schemes
- var defaultModel = (DefaultListModel) (schemeSelectionList.getModel());
- defaultModel.clear();
- var schemes = newlySelectedProblem.availableSolutions();
- schemes.forEach(s -> defaultModel.addElement(s));
- selectDefaultScheme(schemeSelectionList, selectedTask.getCurrentCalculation().getProblem());
- schemeSelectionList.setToolTipText(null);
-
- Executors.newSingleThreadExecutor().submit(() -> ProblemToolbar.plot(null));
-
}
private void changeProblem(SearchTask task, Problem newProblem) {
- var data = task.getExperimentalCurve();
- var calc = task.getCurrentCalculation();
+ var data = (ExperimentalData) task.getInput();
+ var calc = (Calculation) task.getResponse();
var oldProblem = calc.getProblem(); // stores previous information
var np = newProblem.copy();
if (oldProblem != null) {
np.initProperties(oldProblem.getProperties().copy());
np.getPulse().initFrom(oldProblem.getPulse());
+ np.setBaseline(oldProblem.getBaseline());
+ np.updateProperties(np, data.getMetadata());
}
calc.setProblem(np, data); // copies information from old problem to new problem type
+ if (oldProblem == null) {
+ np.retrieveData(data);
+ }
+
task.checkProblems(true);
toolbar.highlightButtons(!np.isReady());
-
}
private static void selectDefaultScheme(JList list, Problem p) {
@@ -348,8 +396,8 @@ private static void selectDefaultScheme(JList list, Problem p)
private void changeScheme(SearchTask task, DifferenceScheme newScheme) {
// TODO
- var calc = task.getCurrentCalculation();
- var data = task.getExperimentalCurve();
+ var calc = (Calculation) task.getResponse();
+ var data = (ExperimentalData) task.getInput();
if (calc.getScheme() == null) {
calc.setScheme(newScheme.copy(), data);
diff --git a/src/main/java/pulse/ui/frames/SearchOptionsFrame.java b/src/main/java/pulse/ui/frames/SearchOptionsFrame.java
index 2d7edda..567c449 100644
--- a/src/main/java/pulse/ui/frames/SearchOptionsFrame.java
+++ b/src/main/java/pulse/ui/frames/SearchOptionsFrame.java
@@ -32,6 +32,7 @@
import pulse.search.direction.LMOptimiser;
import pulse.search.direction.PathOptimiser;
+import pulse.tasks.Calculation;
import pulse.tasks.TaskManager;
import pulse.ui.components.PropertyHolderTable;
import pulse.ui.components.controllers.SearchListRenderer;
@@ -132,15 +133,14 @@ public void update() {
//model for the flags list already created
if (rightTblModel instanceof SelectedKeysModel) {
- var searchKeys = ActiveFlags.activeParameters(activeTask);
+ var searchKeys = activeTask.activeParameters();
((ParameterTableModel)leftTable.getModel()).populateWithAllProperties();
((SelectedKeysModel) rightTblModel).update(searchKeys);
} //Create a new model for the flags list
else {
- if (activeTask != null
- && activeTask.getCurrentCalculation() != null
- && activeTask.getCurrentCalculation().getProblem() != null) {
- var searchKeys = ActiveFlags.activeParameters(activeTask);
+ var c = (Calculation)activeTask.getResponse();
+ if (c != null && c.getProblem() != null) {
+ var searchKeys = activeTask.activeParameters();
rightTable.setModel(new SelectedKeysModel(searchKeys, mandatorySelection));
/*
diff --git a/src/main/java/pulse/ui/frames/TaskControlFrame.java b/src/main/java/pulse/ui/frames/TaskControlFrame.java
index 3bcccea..f04f050 100644
--- a/src/main/java/pulse/ui/frames/TaskControlFrame.java
+++ b/src/main/java/pulse/ui/frames/TaskControlFrame.java
@@ -113,8 +113,12 @@ private void initListeners() {
@Override
public void onProblemStatementShowRequest() {
- problemStatementFrame.update();
- setProblemStatementFrameVisible(true);
+ if (TaskManager.getManagerInstance().getSelectedTask() != null) {
+ problemStatementFrame.update();
+ setProblemStatementFrameVisible(true);
+ } else {
+ System.out.println("Please select a task");
+ }
}
@Override
diff --git a/src/main/java/pulse/util/Group.java b/src/main/java/pulse/util/Group.java
index 07936b1..2b1f888 100644
--- a/src/main/java/pulse/util/Group.java
+++ b/src/main/java/pulse/util/Group.java
@@ -25,7 +25,9 @@ public List subgroups() {
var methods = this.getClass().getMethods();
for (var m : methods) {
- if (m.getParameterCount() > 0 || !Group.class.isAssignableFrom(m.getReturnType())
+
+ if (m.getParameterCount() > 0
+ || !Group.class.isAssignableFrom(m.getReturnType())
|| m.getReturnType().isAssignableFrom(getClass())) {
continue;
}
@@ -39,7 +41,7 @@ public List subgroups() {
e.printStackTrace();
}
- /* Ignore null, factor/instance methods returning same accessibles */
+ /* Ignore null, factory/instance methods returning same accessibles */
if (a == null || a.getDescriptor().equals(getDescriptor())) {
continue;
}
diff --git a/src/main/java/pulse/util/UpwardsNavigable.java b/src/main/java/pulse/util/UpwardsNavigable.java
index 70bc5e2..ab8e744 100644
--- a/src/main/java/pulse/util/UpwardsNavigable.java
+++ b/src/main/java/pulse/util/UpwardsNavigable.java
@@ -19,21 +19,21 @@
public abstract class UpwardsNavigable implements Descriptive {
private UpwardsNavigable parent;
- private List listeners = new ArrayList();
+ private final List listeners = new ArrayList<>();
- public void removeHierarchyListeners() {
+ public final void removeHierarchyListeners() {
this.listeners.clear();
}
- public void removeHierarchyListener(HierarchyListener l) {
+ public final void removeHierarchyListener(HierarchyListener l) {
this.listeners.remove(l);
}
- public void addHierarchyListener(HierarchyListener l) {
+ public final void addHierarchyListener(HierarchyListener l) {
this.listeners.add(l);
}
- public List getHierarchyListeners() {
+ public final List getHierarchyListeners() {
return listeners;
}
@@ -76,7 +76,6 @@ public UpwardsNavigable specificAncestor(Class extends UpwardsNavigable> aClas
if (aClass.equals(this.getClass())) {
return this;
}
- var parent = this.getParent();
UpwardsNavigable result = null;
if (parent != null) {
result = parent.getClass().equals(aClass) ? parent : parent.specificAncestor(aClass);
From 00ba73373c4069dc48dc15d6246927442cee9ae0 Mon Sep 17 00:00:00 2001
From: kotik-coder
Date: Fri, 9 Sep 2022 14:35:04 +0300
Subject: [PATCH 02/14] Pull update
---
pom.xml | 2 +-
.../pulse/math/filters/PolylineOptimiser.java | 2 +-
.../transforms/StandardTransformations.java | 3 -
src/main/resources/NumericProperty.xml | 46 +-
src/main/resources/Version.txt | 2 +-
src/main/resources/messages.properties | 4 +-
src/main/resources/test/fft.txt | 1024 +++++++++++++++++
7 files changed, 1069 insertions(+), 14 deletions(-)
create mode 100644 src/main/resources/test/fft.txt
diff --git a/pom.xml b/pom.xml
index ecbe713..e511886 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
kotik-coder
PULsE
- 1.95
+ 1.97
PULsE
Processing Unit for Laser flash Experiments
diff --git a/src/main/java/pulse/math/filters/PolylineOptimiser.java b/src/main/java/pulse/math/filters/PolylineOptimiser.java
index 0624698..dde0142 100644
--- a/src/main/java/pulse/math/filters/PolylineOptimiser.java
+++ b/src/main/java/pulse/math/filters/PolylineOptimiser.java
@@ -87,4 +87,4 @@ public double evaluate(double t) {
}
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/pulse/math/transforms/StandardTransformations.java b/src/main/java/pulse/math/transforms/StandardTransformations.java
index c5b9503..a8206fd 100644
--- a/src/main/java/pulse/math/transforms/StandardTransformations.java
+++ b/src/main/java/pulse/math/transforms/StandardTransformations.java
@@ -19,9 +19,6 @@ public class StandardTransformations {
@Override
public double transform(double a) {
- if(a < 0) {
- System.err.println(a);
- }
return log(a);
}
diff --git a/src/main/resources/NumericProperty.xml b/src/main/resources/NumericProperty.xml
index 3d4b61a..edf471e 100644
--- a/src/main/resources/NumericProperty.xml
+++ b/src/main/resources/NumericProperty.xml
@@ -21,21 +21,31 @@
dimensionfactor="1" discreet="false" keyword="MODEL_WEIGHT"
maximum="1" minimum="0" primitive-type="double" value="0">
+
+
+
+
+ maximum="5" minimum="0" primitive-type="double" value="0.1" default-search-variable="false">
+
+
-
+
+ Diathermic Sample with Grey Walls (1D)
LinearizedProblem2D.Descriptor=Classical 2D Problem Statement- Based on 1D formulation, except:
- Allows heat losses from side surface
- Allows radial heat flow
UniformlyCoatedSample.Descriptor=Core-Shell 2D Problem Statement- Based on the classical 2D problem, except:
- Explicitly accounts for a coating that covers front, rear, and side surfaces
Allows for axial, radial, and circumferential heat fluxes
NonlinearProblem.Descriptor=Nonlinear Heat Sink (1D) Problem Statement- Precise calculation of heat losses (front and rear only)
- Cp and ρ data required
+TwoTemperatureModel.Descriptor=Two-Temperature Penetration Model (1D) Problem Statement- Different temperatures for solid and gas phase
- Energy exchange between phases
- Extended light penetration
- Cp and ρ data required
Problem.6=Laser Pulse
Problem.7=Heating Curve
DATReader.0=dat
@@ -289,4 +290,5 @@ MixedScheme2.4=Increased Accuracy Semi-implicit Scheme- Order of approximation O(h4 + &tau2)
- Unconditionally stable
- Steps are computationally more expensive but their number is fewer compared to other schemes
- Heat equation and BC are linear while RTE has a nonlinear emission term processed with a fixed iteration algorithm
TextWrap.0=
TextWrap.1=
-TextWrap.2=
\ No newline at end of file
+TextWrap.2=
+msg.running=An instance of PULsE appears to be running. Please switch back to the running version or delete the pulse.lock file found in the PULsE directory.
\ No newline at end of file
diff --git a/src/main/resources/test/fft.txt b/src/main/resources/test/fft.txt
new file mode 100644
index 0000000..194936e
--- /dev/null
+++ b/src/main/resources/test/fft.txt
@@ -0,0 +1,1024 @@
+1.8623883939948125
+1.440191140077873
+0.0856911188761609
+0.3177405081698117
+0.10853351481231108
+0.11844768772657704
+0.14359180808670602
+0.09056412538979447
+0.10023722372433143
+0.05012708645229069
+0.06281734105869234
+0.049631166773682844
+0.05334748215923658
+0.07407767757133589
+0.03971008132098835
+0.04416964802114836
+0.040107973059110145
+0.033383489903923126
+0.053510587820655715
+0.029764726896007627
+0.028897396016806746
+0.028375440254179138
+0.02608494923958421
+0.02848092345249004
+0.03098610667355402
+0.019704730700161342
+0.02205971150558122
+0.021542133187751365
+0.021717439637497112
+0.020225860751051376
+0.019475979475189267
+0.014608596264644893
+0.01835870883217293
+0.017665011148277704
+0.01752138440835296
+0.015525900169506836
+0.015595410516248704
+0.015566570463898585
+0.015953238738805293
+0.01599587158897621
+0.013360695667264524
+0.015002089502846793
+0.014731537902388517
+0.013800515283259545
+0.014315157889845456
+0.013575152863046239
+0.012352341075970283
+0.012855780651818575
+0.012137860345243811
+0.012335928227005669
+0.011322310696797096
+0.011236261387870374
+0.011574641436270015
+0.011701043926932157
+0.011357150931082414
+0.009886326266142687
+0.009786382245722685
+0.010208387344388233
+0.009714230475277096
+0.009956827366738348
+0.009664725534625166
+0.009191624259773164
+0.009872561989745792
+0.009201888705471856
+0.008827948804843581
+0.008959893796151698
+0.00945443404186388
+0.008745592717618387
+0.009110905334280571
+0.008596123252820742
+0.008184929886419213
+0.008608854455027131
+0.008307320168098539
+0.008117648970713836
+0.008024758407971955
+0.007628751198035526
+0.007083062409124776
+0.007751030347403762
+0.007249154231345055
+0.007175520037985863
+0.00707064335177111
+0.00711871897750612
+0.007305437461793674
+0.007072070255306337
+0.006707680163861008
+0.006303859175803904
+0.007416579081448052
+0.0070619057661997445
+0.006854023369349145
+0.006455665945038045
+0.006835208781953551
+0.0065725374488924135
+0.006131013167403963
+0.006444591376811081
+0.0056394266037035545
+0.006066231052847979
+0.006303991327230198
+0.005949270797656248
+0.0063450056763406275
+0.006196167505123584
+0.005858153424762702
+0.0053913180909300855
+0.0058747255763572604
+0.006090643974924875
+0.005589115745925811
+0.005505074654993644
+0.005588245995291544
+0.005250392382850327
+0.005369156668180935
+0.005194106014717803
+0.005358717441455797
+0.005321043318596023
+0.005012422951166697
+0.005505553842319726
+0.0053432974110541155
+0.004971133806504812
+0.005037290685910062
+0.004765936894177503
+0.005141737892182391
+0.005410339758037131
+0.004885897265174704
+0.004922942306263837
+0.0045790685496497835
+0.00458229361635885
+0.004708660507341414
+0.0048042899663832475
+0.004625127808914531
+0.004743025594503575
+0.004598808630414814
+0.004626386499782302
+0.004459853592652658
+0.004377955368359365
+0.0046513163879235405
+0.0043256859045455115
+0.004512982427236372
+0.004588981897250833
+0.004295974465089781
+0.0043551312599052466
+0.004100096307988168
+0.004353555159813722
+0.00413193523732321
+0.004119654488401856
+0.0035986600134537334
+0.00430772639995229
+0.004058684144930945
+0.004194927813093337
+0.004135454329628857
+0.003707416777758124
+0.004024729209517794
+0.004139371147329603
+0.004167089013471642
+0.003761231388360764
+0.003952355678601933
+0.004066041106296513
+0.004136911700384993
+0.003932359264558167
+0.003542614608770456
+0.003746570018068218
+0.00395090631076722
+0.003537222144720005
+0.0035297026799832177
+0.003925348847332404
+0.0036757151959072244
+0.003602224343978626
+0.0036161028088550077
+0.0036307723158452575
+0.00368144084363016
+0.0036600294498210996
+0.00363782935999298
+0.003405756152194927
+0.003431252110629916
+0.0035649169954907745
+0.003236389910029101
+0.0034433473114116307
+0.0034932650584519062
+0.0035634560282200027
+0.0034296977806162633
+0.0034319461285292714
+0.003312308846263632
+0.003722618636988596
+0.0032536729682297472
+0.0031759378052392275
+0.00314708262406618
+0.003381194017340103
+0.0034226632338035484
+0.003201761963155763
+0.0034019628513818913
+0.0032004395904046603
+0.003102610835125887
+0.003323853973090416
+0.00301143619457104
+0.0033706851832347637
+0.002997554103076301
+0.0034025072727111427
+0.003206086938481629
+0.0031066962307518854
+0.002786437309626743
+0.0030835387904124883
+0.003031043385463557
+0.003011272769112621
+0.003026614277513354
+0.0031038064873766267
+0.002914867534237071
+0.0032106014711124264
+0.002960737750691456
+0.002848084333438608
+0.0029144693542782463
+0.002917497771325989
+0.0027129790526007544
+0.002612885902673647
+0.0029181831060856893
+0.0029055373553426543
+0.002714169194398066
+0.002863600775792233
+0.002684118883481437
+0.0028921148049106745
+0.0028302475704821105
+0.0028594112091045497
+0.0028091941754447122
+0.002761917483210222
+0.002831998224106552
+0.0029082049049603256
+0.0025433232627721726
+0.002744779635531415
+0.002610372762493025
+0.00269604297513204
+0.002522668560461302
+0.0027325824152729257
+0.0024340793422731313
+0.0026319425441122444
+0.002568112067959159
+0.0027683254158293864
+0.0024581501074080517
+0.00272139350102542
+0.0024097746095871524
+0.0026713014097986495
+0.002608528482915483
+0.002757952020574316
+0.002473940039239647
+0.0025698875343990245
+0.0024206272171112667
+0.002527643420140039
+0.002485348316653174
+0.002501106850185462
+0.0028036894150320207
+0.0023487069284162656
+0.002494732633732202
+0.002543346916671682
+0.002434448718146823
+0.002353903482083443
+0.0024849214295775495
+0.002280687444001982
+0.0021460731943987506
+0.0022744284159968734
+0.002355282996760084
+0.002374879375501902
+0.0025636565520782252
+0.0021429362225892585
+0.002512462546679564
+0.002457432015923903
+0.0022275839408261297
+0.002050220061718769
+0.0023897363016175868
+0.002280185276629757
+0.002551552138995319
+0.0020281057349859953
+0.0021776305132253397
+0.0021716442295787192
+0.0022024922812540998
+0.0022643433828360574
+0.0023171079460284592
+0.002209610418455076
+0.002091761906587569
+0.0024699303868929044
+0.0021924456147592924
+0.0025132238234213977
+0.0021413493664871534
+0.0023797515636802095
+0.002116464198887065
+0.0021010965208245326
+0.002200893207135162
+0.0022888366645033406
+0.0022506744392961795
+0.0020200323013424798
+0.0020269379217901146
+0.002235674958617841
+0.0021589634253941837
+0.002007694399579814
+0.002028468326489692
+0.001973178947286009
+0.0021722784832706923
+0.002152321588552352
+0.0020541661208640333
+0.0018443215090906614
+0.0023040970417671667
+0.0022070756163091905
+0.0021458535206313593
+0.0021234981725089773
+0.0020196842506682777
+0.002081325554159696
+0.0019622403312532185
+0.0018956765850871688
+0.002011758678159863
+0.002048584744472413
+0.001967968629034845
+0.0017890536700308419
+0.0018274200657948042
+0.0019495255858672576
+0.0019763604713690084
+0.002007665612620955
+0.002038019646262002
+0.0019323145911434045
+0.0018931617505309171
+0.0017176101935718177
+0.002035717753676598
+0.001997221376476268
+0.00208445761810857
+0.0018213990827714713
+0.0020335566706469687
+0.0019222800995692716
+0.0018730106550425844
+0.0018957021931545856
+0.0020131587529492274
+0.0019006911064656951
+0.0019006385154010802
+0.0018669836596750347
+0.0018387111891236968
+0.001860803645995648
+0.001875487905261806
+0.0019805330604071637
+0.0019333574999443324
+0.0017493923270269086
+0.0018635151864636905
+0.0018839497921766995
+0.001779170384859654
+0.0017369124667888725
+0.0018692706792106512
+0.0018555909898186722
+0.0019861219387481703
+0.0016768772425769986
+0.00173425585005027
+0.0017368104770272986
+0.0018444509218926088
+0.0018344780148905706
+0.0017421482008388048
+0.0019574501495635828
+0.0018485551997456673
+0.0016478397506516388
+0.0019006059767611814
+0.00178908230798387
+0.0017626449686498368
+0.001732149103600908
+0.0017420128347331559
+0.0016694600796223398
+0.0016892814923382899
+0.0017537019545246677
+0.0018336543315263922
+0.0018812436665203323
+0.0017781051942758364
+0.0016246718077691606
+0.0016673577866322385
+0.001759831952508731
+0.0017473637258567304
+0.00173104355552501
+0.001805140539073113
+0.0015973095237779042
+0.0015894420732170923
+0.001654768691098651
+0.0017328672602817553
+0.0018102375834557266
+0.0016478489084596247
+0.0016625501301660536
+0.001755668369649966
+0.0015363102784954816
+0.0017291672122388942
+0.0017614055969386695
+0.001711801977088871
+0.0016645828526783177
+0.0017291523364988042
+0.0017553659401122418
+0.0017300557169120786
+0.0016118911737583585
+0.0016013197537592275
+0.0017380041852213207
+0.0014933333031327699
+0.001559188637981803
+0.0017126653445467563
+0.0015807009808334307
+0.0016628973432414047
+0.0016047005870487945
+0.0017559387040599565
+0.0016243236914338785
+0.0015765644690180533
+0.0015828719203620945
+0.0015398177507824152
+0.0015032959585347633
+0.0016490341843532685
+0.001617396634735605
+0.0015957274117611951
+0.0015794738352842284
+0.0015388573781546031
+0.0016154513019219219
+0.0014816121634873749
+0.0015287905271643165
+0.0014617249768153456
+0.0015711554607759192
+0.0014682188208443925
+0.0015796458655902039
+0.001689735159818995
+0.001433704731383778
+0.0016166759882060668
+0.0014391892059119086
+0.0013712295490970739
+0.0016812167351267391
+0.0015319778370590715
+0.0014236368531158066
+0.0015087839252398833
+0.0016085941140473177
+0.0014820936165921505
+0.0014688802804647845
+0.0014354622391669247
+0.0015967583162015352
+0.0014216344753546506
+0.0015161040951119505
+0.0015096607386122969
+0.001384397608374938
+0.0015245746520588476
+0.0014081823605333326
+0.0016024041035034328
+0.001452871449554933
+0.0014308607906196105
+0.001522136599814874
+0.001481124047817481
+0.0015255580662159325
+0.001309843943187161
+0.0014586938481273024
+0.0014656459708439035
+0.0012726184983539426
+0.001367916494362877
+0.0013395100945080495
+0.0014389087123870105
+0.0015167920773429093
+0.0014722043865967177
+0.0014019882776771784
+0.0014049321693303425
+0.0013847814076527866
+0.0012478724504164254
+0.001459103728716397
+0.001406587374258575
+0.0014418827202656941
+0.0014096520586717536
+0.0014492409154258758
+0.001409394534879737
+0.0014705862502728947
+0.0012983605478659292
+0.001359781891861031
+0.0013736087171087959
+0.0015844689960084271
+0.001284557520511467
+0.0014926221038714146
+0.0013154469364888553
+0.0013159171219375757
+0.0013195726347157337
+0.0013224667986831112
+0.0013970767109930781
+0.0013792554501893374
+0.001302973911800565
+0.0014168082576272456
+0.0012576820832382774
+0.001542675666003404
+0.001307463747149029
+0.0012699109134222467
+0.0014539429326068782
+0.0013921268253928327
+0.0012829264103424237
+0.0014453813185194514
+0.0013361946194903225
+0.0012859127293610348
+0.001219864587298067
+0.0013729822159914303
+0.0013387240271219942
+0.001269166882994578
+0.0013816792929721383
+0.0013093666697172612
+0.0013326007495184746
+0.001334993151008571
+0.001235037425193347
+0.0011362030225542878
+0.0014377371705801458
+0.0013853954016113952
+0.0013471913518237851
+0.0012495283227950647
+0.001266562246997323
+0.0013227908159747438
+0.0012995488131381518
+0.0013904367286179792
+0.0012906469430955612
+0.0013315397480469341
+0.0012934821261761714
+0.0013250673575971874
+0.0013469150077112225
+0.0013202875781665269
+0.0012146174018993268
+0.00122881580627127
+0.0014129481339015366
+0.0011903810318464286
+0.0012449686959895507
+0.0012651176467834173
+0.0013046110131927327
+0.001237171432692225
+0.0011075767342333515
+0.0012758702965103852
+0.0011920086165592336
+0.0011866092015483018
+0.0012707921781073572
+0.001219579012657507
+0.0013616560614411427
+0.0012936725062240194
+0.00123301890710047
+0.0013025018941970037
+0.0011961146586798811
+0.0012808758077574244
+0.001190999826367067
+0.0012141207065111215
+0.0011843613569923832
+0.001335136462186405
+0.0011539681513207233
+0.0013632022792263935
+0.0013805744039978088
+0.0011881868755503888
+0.0011939077843169824
+0.0011270966583446721
+0.0012274172725854615
+0.0012672896373819246
+0.0012091250192438592
+0.001260421275046162
+0.0013151663232838697
+0.0012249004166542665
+0.00117899397310745
+0.0011734446482045359
+0.0012624596819513108
+0.0012764495812893665
+0.0010964856284655289
+0.001252761077726981
+0.0012529236282346054
+0.0012716297422796393
+0.0012861540922519037
+0.0011956481563782898
+0.0011121730631293352
+0.0012784895399416258
+0.0012202804971150033
+0.001045606751447345
+0.0013908900453571335
+0.001197171130379206
+0.0011705475688395964
+0.001269776840408273
+0.0011822952280807005
+0.0011066157789244133
+0.0012798660547691063
+0.0012809823962816405
+0.001109278093988003
+0.0011861159004747741
+0.0010835188502740056
+0.0011746191332898408
+0.001230977749834832
+0.0010795055496552108
+0.0012635419825219678
+0.0012756553936316552
+0.0011898806099122639
+0.0011608250848784943
+0.0012017305666559433
+0.001133310479022337
+0.0012358558242260653
+0.0011754317432781062
+0.0011033932179006088
+0.0011222424420222205
+0.0010375205291658766
+0.0012348160575316306
+0.0011826927315491012
+0.0010671410415516137
+0.0011711615448849848
+0.0011226251500075733
+0.00109441076055885
+0.001094864463168803
+0.0012022274437243083
+0.0011448479964942628
+0.001177852369182545
+0.0011002194983556388
+0.0011536796847610848
+0.0012020752603471268
+0.0010927386293982887
+0.00119823947194137
+0.0010685209532565016
+0.0011808365130782394
+0.0011372096566268058
+0.0011557260888021865
+0.0011304444819921215
+0.0011073395461831943
+0.0011146527005709973
+0.0011737068014750476
+0.001196673453050192
+0.001099569016246178
+0.0010796933440538885
+0.001043599943288889
+0.001153815061186113
+0.00131400849101086
+0.0011597212267390755
+0.0012451816466449049
+0.0010969945781010115
+0.0011004892551955102
+0.0011490190194486621
+0.0012283203493037387
+0.0010586820817033659
+0.0011891430899622388
+0.0011420664067813631
+0.0010229478025710005
+0.0010691985495450338
+0.0012006413404640646
+0.0011247227156228196
+0.0011907207706990607
+0.0010624252987184526
+0.0010228569653310151
+0.0011311460363274618
+0.0010831867629922491
+0.001078372575538281
+0.0011211665776477088
+0.0011605348662726803
+0.0010468906446104121
+0.001111427826815859
+0.0010188359106680675
+0.0011832758640857235
+0.0010596513093145692
+0.0011528677436051875
+0.0011282187354133004
+0.0010452271074060323
+0.0011074716717346302
+0.0011205642580078064
+9.867064467871667E-4
+0.001075272432523398
+9.872992855691574E-4
+0.0011157348160055031
+0.0011666183330647387
+0.001134882543661718
+0.0010855425213214857
+9.486135179973545E-4
+0.001022739916990013
+0.0011230768811140068
+0.0011034279475247624
+0.0011256491710883978
+0.0010678857770924672
+0.0010462878905578591
+0.001126936721613097
+0.0010518572445067302
+0.00100850428956523
+0.0011262068223730414
+0.0011005048073512705
+0.0011543348908842977
+0.0010939783368006336
+0.001022253007938055
+9.327735142685685E-4
+0.0011040492611731388
+0.001031427321278705
+0.0011174208044228532
+0.0010711547316751779
+0.0010263748860923343
+9.271388117916817E-4
+0.0010119339016748938
+0.0010729189004375487
+0.001017358352006335
+0.0012325543901770487
+0.0010559322713433975
+0.0010388280188947873
+0.0010112348874334633
+0.0011041523292409918
+0.001139488720022
+9.478706332814315E-4
+0.0010618470148916553
+0.0010535115515057064
+0.0011410732587352308
+0.0010390307941775675
+0.0011029457801466742
+0.00113809700552862
+0.0010230097035513453
+9.54459369975072E-4
+9.575993594545408E-4
+0.0010089179546782145
+0.0010742472276899845
+0.0010508183691489978
+0.001015706339611075
+9.63931367881156E-4
+9.892104999012375E-4
+0.0011395912499243275
+0.001027489144123793
+9.938574333827525E-4
+0.0010141638067099764
+0.0010850567240691322
+0.0010567209240592832
+0.0010546186206946042
+0.0010591449258845588
+0.0010788103431173524
+0.001001327795102536
+0.0010537475604692989
+9.776562827771178E-4
+0.0010301238724556479
+9.999903298850048E-4
+9.996640973755774E-4
+9.982351690180635E-4
+0.0010282243521071899
+9.793735100862085E-4
+9.937214763986947E-4
+0.0010560997662210044
+0.001064940358969091
+9.321880074986722E-4
+0.0010448277305721279
+9.336692191825015E-4
+0.001083214198713888
+0.0010289052566263427
+0.0010878579899422471
+9.628443269300946E-4
+9.148432953590753E-4
+0.0010009806857296107
+0.001064634768220053
+0.0010917456341344672
+0.001039660018309393
+9.640620972111818E-4
+9.473501095787988E-4
+8.898399478407448E-4
+0.0010752641810434242
+0.0010225882851613213
+0.001031186267761093
+0.001032388300708419
+9.692852639524189E-4
+0.0010636290585673226
+0.0011157012652095268
+9.445338312394765E-4
+9.796550027818063E-4
+9.380874632594835E-4
+9.171090871220963E-4
+0.0010338819871365346
+9.817352980271506E-4
+0.001035548610723382
+0.0010366089040039462
+0.0010023017609384433
+0.0010350418131665217
+0.0010078566274789762
+8.68331298898284E-4
+8.974661539826759E-4
+9.705357497685943E-4
+0.0010949970765370904
+9.495183412072032E-4
+9.737454775958202E-4
+0.0010217995814455307
+9.522448537898191E-4
+9.779127147104816E-4
+9.86232475982084E-4
+0.0010298898005799344
+0.0010131585301009062
+0.0010574032640673276
+9.48474613345645E-4
+0.0010620791774603989
+9.276998623420052E-4
+9.204849451858387E-4
+0.0010399404511545424
+9.264433947557337E-4
+9.089041102056008E-4
+8.985993184669925E-4
+0.0010315295220899943
+0.0010147607153646264
+9.377201100029269E-4
+9.537576069215683E-4
+0.0010009682437537631
+9.99695015129562E-4
+9.242726798056872E-4
+9.24635450522338E-4
+9.956002157419526E-4
+0.0010611750592811704
+0.0010763265510399733
+9.299215963015973E-4
+9.559145806317533E-4
+8.895396926441966E-4
+0.0010214904500228136
+0.0010665758733511713
+9.38328912522674E-4
+9.979567946888498E-4
+9.265333791378834E-4
+9.839671786840895E-4
+0.001028895479833451
+8.506542503867044E-4
+0.0010133621193351137
+8.787126554211259E-4
+9.963469146455363E-4
+9.615126345157179E-4
+9.85958165485008E-4
+9.00999168671934E-4
+9.22395160595154E-4
+9.847387915653623E-4
+9.550681987435555E-4
+0.0010157534718449773
+9.033087045773685E-4
+0.0010196936306393514
+9.886304333696812E-4
+9.621123908614798E-4
+9.961358429027196E-4
+9.185365383486628E-4
+9.802937997516852E-4
+0.0010325104413239838
+8.856756388963145E-4
+9.561355684135135E-4
+9.657359083146397E-4
+9.274753354606738E-4
+9.817087748994818E-4
+9.290601376764568E-4
+9.549805031394914E-4
+0.0010053984111506784
+0.0010171563035885468
+8.490199507419586E-4
+9.56482243200863E-4
+9.605373194334563E-4
+0.0010119157832749685
+8.622504120430778E-4
+9.827176707024432E-4
+9.373533932955863E-4
+9.675303640829435E-4
+0.0010249931272057681
+9.61126280284176E-4
+9.184629421665977E-4
+0.0010050193148524005
+9.787415813740507E-4
+8.972025579781401E-4
+9.687533583789295E-4
+8.925667325497291E-4
+9.642009967372524E-4
+9.053263729012275E-4
+9.921545067133972E-4
+8.908052742353586E-4
+9.467385459143673E-4
+8.734896034648221E-4
+0.001006776295415798
+9.648248427972446E-4
+0.0010178447964271453
+0.0010334043744897557
+9.623872532366822E-4
+8.08721329670184E-4
+8.981291571899335E-4
+8.965830799635602E-4
+9.411649803398181E-4
+9.233563139416925E-4
+9.427443681121117E-4
+9.942239823302458E-4
+9.088242408932741E-4
+9.540261346786916E-4
+9.741512437633195E-4
+9.305784543443058E-4
+8.936810810671528E-4
+8.922716098607077E-4
+9.078055011613465E-4
+9.380441154268395E-4
+9.293086318591539E-4
+9.975803217654006E-4
+8.729079377154703E-4
+8.944054849967194E-4
+9.603926066129352E-4
+9.359497708437436E-4
+8.584287049822975E-4
+9.084124785513469E-4
+9.690922729424672E-4
+9.577562696746035E-4
+8.787112588322701E-4
+9.25262999202752E-4
+9.069952161436504E-4
+8.553040119121029E-4
+9.441837660562317E-4
+8.881766062200255E-4
+9.182443930143199E-4
+9.210270704674465E-4
+0.0010207690003883872
+9.212511483642543E-4
+9.697071438700654E-4
+8.728908036006088E-4
+0.0010346924699559093
+9.98847382922486E-4
+9.243479071810528E-4
+8.86103374277685E-4
+8.924994979962734E-4
+8.810799504326165E-4
+0.0010062064982125846
+9.448553865605595E-4
+9.382799635233933E-4
+9.304974738814165E-4
+0.0010457539120059794
+8.357527786592987E-4
+9.217727903643321E-4
+9.179572581649916E-4
+9.168779812731295E-4
+9.622433504513817E-4
+9.32675306480942E-4
+8.553908706400959E-4
+9.83197977629328E-4
+8.380823090224836E-4
+9.098683129447309E-4
+9.521735462902145E-4
+9.234869018250256E-4
+9.101871270324486E-4
+9.571374853617023E-4
+9.014654684161298E-4
+9.454236030554885E-4
+8.743210842609578E-4
+0.001009335913540478
+8.942776328813976E-4
+9.46445773117879E-4
+9.261167832501032E-4
+9.36900494161455E-4
+0.0010312031257503273
+9.900728853623566E-4
+8.952595563375166E-4
+9.834533909209228E-4
+8.663718595624797E-4
+9.043261594713736E-4
+9.279968431679345E-4
+8.750985392750564E-4
+9.371156720928401E-4
+8.549939108391614E-4
+9.106702956319355E-4
+9.733885260125103E-4
+9.251988897112464E-4
+9.163237448419129E-4
+9.763413853652612E-4
+8.17850953219026E-4
+9.578846196673777E-4
+8.365217856229663E-4
+0.0010026936481388117
+7.928175701311635E-4
+8.893189554431385E-4
+9.017435287623222E-4
+8.783729172775835E-4
+8.669714891290667E-4
+8.950098150254109E-4
+9.102292374057512E-4
+8.678038819327828E-4
+9.072342094860982E-4
+9.204681033012889E-4
+9.140102265789373E-4
+9.679079074939713E-4
+8.97266035411225E-4
+9.253785287178447E-4
+8.87548440924595E-4
+8.982166442089941E-4
+9.331063397107384E-4
+9.793688190172947E-4
+8.571873137309112E-4
+7.653171049075817E-4
+9.437126053661114E-4
+9.130674200589031E-4
+9.921485769821788E-4
+9.309642233887024E-4
+9.060627123548954E-4
+8.980914435685737E-4
+9.652877389717347E-4
+9.047117932972571E-4
+9.667537814851369E-4
+9.535766035259877E-4
+8.941375274267972E-4
+8.984040549051778E-4
+8.652377377593744E-4
+9.20640529777493E-4
+9.180878222942158E-4
+9.559498677603602E-4
+9.036754182526869E-4
+8.948543811167884E-4
+8.577419937245519E-4
+9.328693608319587E-4
+9.448588934203852E-4
+8.874946478023135E-4
+9.201634267392057E-4
+8.218524536406166E-4
+9.554481063991601E-4
+8.727141872122932E-4
+0.0010440163697008847
+8.73836572999781E-4
+8.474705098276823E-4
+9.242788766551806E-4
+9.6628533033844E-4
+9.552653779506281E-4
+8.541963891119773E-4
+9.447177794880269E-4
+8.826859272186537E-4
+8.329850473356033E-4
+8.450126312152971E-4
+8.878943253854854E-4
+9.061636989099398E-4
+9.572319794719509E-4
+9.622037024296709E-4
+9.500723242444433E-4
+9.32405414821388E-4
+8.565420408414186E-4
+8.399901318746076E-4
+9.695118362994088E-4
+8.550086248119928E-4
+8.940615541457234E-4
+0.0010099358754753034
+9.203713767686853E-4
+8.886241205073025E-4
+9.380363126489836E-4
+8.853380504739757E-4
+9.403908197696909E-4
+8.631159768530599E-4
+9.595645004578227E-4
+9.477911078217122E-4
+8.587532061341414E-4
+9.110737725752171E-4
+8.817375500176881E-4
+8.506326823980858E-4
+0.0010001005385404018
+9.101279499969762E-4
+8.321551714226473E-4
+9.509451733575742E-4
+8.358075345119111E-4
+9.362701841463229E-4
+8.750119106584959E-4
+8.856057393331677E-4
+9.750659213866944E-4
+9.699331289208207E-4
+8.291897553302293E-4
+9.72959515072471E-4
\ No newline at end of file
From 4cb45c7b3553843301d0f849e1bc583ef3b5cda1 Mon Sep 17 00:00:00 2001
From: kotik-coder
Date: Fri, 9 Sep 2022 16:11:46 +0300
Subject: [PATCH 03/14] Updated splash screen
---
src/main/resources/images/splash.png | Bin 67897 -> 67108 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/src/main/resources/images/splash.png b/src/main/resources/images/splash.png
index d8ce89ad9ca02f2e8a043e095b8ab888cbce8813..c9583b6ef18dc2c1130fd57b2d9804f368219730 100644
GIT binary patch
literal 67108
zcmV)?K!U%CP)~Y|NnT!(FO$5yRJ9~Y;3jksP_v{o88M%iN{Ez+Tp%nh^Ck^Z
zoTRXn!>G8rGrUzUfjFIOyA+v4?^eu{69PlW&4;}}lmL?WcNb`G9g<0XRVn6IZf$Q1
zT~sL?@3KV+drm_LC@zp{KUMS!m`GJZpr6U?P9mgV1`B(v_bDP0-3hph69Rq-`bv~kX){EZOsS|C*yCPD)1
zF9E8UQqG0J+6gVckGS
z!@A~k-kpz4S=rrmM$>Z0Ky*6)J0`A6_S=1T<;nQFcKI2NtD9pwnB5zVBY(!j@tuY9
z$Jb+lM4kA9g_TXjo2RWd_lNe8-=LdwzwD7YnF_@REh7r2LSuByXfN!NpZ@;XGO%F!
z0y%Rn!~KPD_W$e8O<1_$6uy`^1Ywp6kG{_i#{I>tFV5uh+Y95ebuvfb%~$t9EKv_v
z>0_;+@(>Va%%MV%`;vx>GJ!4q?B$gemplb>a&s#X$!vyXuq0OW(@Pag*0$3!u9*`m
zA!5QQrwCkMRAv>7*8Z`i&w!wfbS3flzUG##Zh7?f=xDxi5DPb6lD|qvV3&Nd086YP
z)K!~d)+1Hz;jeA_6LnkOXMdkJslQyS86v|!+e^Iap@d_1(oV@NBF>nAO02L%EjH_b
z7GV|w$M`KSp8vWPNR2P5!f4ee!Y6wMH~q~@h_d=g4ow?_%y{T8sB3kC{;z4!c6!Mz
zR_$9SV4(2KRGn21Cq|!eqj7X_tn%z@V@;M)BNnYqZR#$!X2Vwvd3Dt_%xmcwg9gK_
zO_&f?&e6l8{hf*P91zt957JD6RzA?~YZTxekB19X7qaCYyk{)llKgc_%0Pi!D4W
zSPy!uoz8CYpuDmi9$vW|bKmS~C-Y{RO9jEqPoFM8pJxWk_TOhM#Oosl$##E#+zLd}
z`wPPS1u(j_=PG+7&V2nYL`>NORnclPP4vf9a1KUU91Z~-t(r23AcSl+r{(?G%?l&5
zxidQ}499m{3+&ir+347lnRyf4fny*uKJ&U+Xly*$Q_v=2?$}lszvdPuwu`sNSGHkG
z^s$iR$Ma@%wc7nXJQRrY7w?UM5Td``8E8tKal!V75NwQMRwEVE36|Q+t=;r
z#_TglK)afX9lB#)2Ul13UX3@N?jfCB9K$)QE*guNC1dXs-M`6iDuyES4hU>L0BI
zlFct=Pz}WXaGVMx+bvhA_Yhc0KMo{^VX?&^&37TLsV$2(((VC*{!!KN0N898Ag=1v$S+nN7t
zYweL8g80X+Ku*j!jPgSXNHWP?t0L}qmceXui`
zQwLj9B}7@$#|nd)nG-A^+x%%z$fL0p2J^Jh&YNT@fYuHn>d-f2^LKC#n$@j9TscBUtY_-%9Q-%YWxr{iy+atN;kR5#b&Mef6&P2!R3E7T5Y=7^)
zgbwvfyHkj9*!JTxH0fuN4PPBI%at{?$7mo#!*6m@$e>lk=QR-c_
z5VPkHkRH55C5;?s=bsbH`_$$$6O|B;^jm4zuM*L5TtAGNz5>(7^suvZY+hb`cOlB&
zb07Av{)Y<0U6+A58R6ZB;DyC!kbGbh=8}>)Y~o^)LH+Ig94)SKG0FSvqy?BUZm=U+
zKz5G>!Z@7&`xwf$u*ebv^;S}<*OrImgHcB=Y(5rHB0Uj10`2JUSQw7(%>Ka}7MXy1
z-3!B!--rDx5;gn5Yhf@y*SJ^tp1sJ^TcO+*Pe((AOV7k~GFfZqaPn{A9P0kyrCKrG$F$<>jObagLuKW2}(n$41B
z(@vi=PGR_qI|7b4y7{{9n$q@K46#fz7`|@>@u7`w^fm{fM18Pr2-3}C&@Jp}bLNF&
zN5Z?sYk^c-Vi|t61q~ma{dH@oFtR?Yi0~(Ajzk@4BXN5QMXJdK!)R@W@jcczo0rX<
zKP?D&ERd*+tDP26d)oh@p@PW#v^K)JeFm|5cb|B&!eskMY$oBrXGp3u+V;wy4hVQG
zkkYG%+ey6b`%tmkLHj*)%SS_f_jYJHOt6RXWQiDa3Yk+Y$zDZwO!HeHXa4?G-tS@K
zC5REU>Z7-1NvFe#57t#=-FDm4M(^!un>)ApyLS1dG+IU!UDf98@%bbzC(=__(={xN
z$rw86S2>K$&oMqRp(f^xx!WU8o1f6Dt+l?4bTUa96vHr42yayX!OaAnUv&%Fd6!>^}AD
zO7HFc>DQEnbt@3Z{T|+!8-9Nmnyzm^RgAViU!~C*xX#7O87g5v3-f}ys0ch
zj$xzeyRwCM1m4l^NYCuE9GXM+KCFg@J?yI=f-sE9qZTwz#
z%S^hAh=fv3{;n^cz`H~`YH3Gf1F?$qusP6bk8%V+k5(BY$(xKmqQ!aBc#tQAv%jRc6b$+8jaPaTw3
z$*SvjL)zTRz}`Qhd5M}Qt5Nlw2x*O_Kob8Rhbw(&*}N1zUB5yb04%U02+aL?T1J{;
zwy>RUUBT!|_XssZZDTAnE3QcBWwAQ_HC@_cmj#Pxuj8LdmQ33U+4gkg?U*j8ia7D}
z_2N_@2^+tH*|rc`V2fHj8+FGgA^r3}&z|IJ_f+kOugz$vp<4xZdTawr5_M4ssU`8kFeIA$;g+5&ip+mY5rHg9}ao7L~r
zsX*ktA$q@IECfF2vKCC13q%!O6sD9L$XfQPLxE6mTUdj_xb7e_rvka&_IV`y`kp2G
zCL^5=;N+bR3$4*ow2ws6+UZgru7cR_PS9$2THR|c5F?!w6fDDvP-D-t;(Y
zj+gzk0n-+5lJ|d9d}t6Rk-YKL+{h_0-=Mt{MP=)jML(d~zybKs%0Fi*^&ZNpK-6rN
zNS1}zbo!LXP`d9wq-_Q+lH4ODIa+zyytBTU3f;OtY_AB5vt-ilkPC|qOqR0g1Xj!b
zJu#J@?^2<>_KszJ?wAjM#`G5+#3)*STgDm}+yB7|!)6|?ALpdA$nIjcP-cZOk~DQC
zEAMSQ19>_X2n%RyPCPMDx;KP{^+ao0^P5lpp5hGDjn&6l*6!|O)~9W;G%E~dT-V>W
zmR&7>+V$;@c6}WjWUH-~Tb?r=y3?+dxqWvlkZaG+L-BWq%6yaC(uSS2$Ft+G?i1G})+2A)?SWb*)5`ZZt-GCkh21oN5$4cFlDRZ~B+xjLqhZ_CY#VZz++fC5
z%N*%!c1fQ?TcBfYuWrvVD=uStk5X>#fjYPqNY-8VLdvwTksBtaEQW>44mS5dBk@F^
z+U;>q&N*_+IJ_B=HCtf#r+e^a=M0Sa{uF^b*p1f|D#&9bUu?jy`*tDPJTl0MZWwKO
zt13!(oeJExH<8JU=SMffu#Z;K;TdMMhyXT6*R{rVT9!jdXy;+?q7!RHFKz|GLS2~i
zFUk&TBQr>9R1XOUjzMDk4uiBm2afiNEDXj6^jiuar4s|Co~Gx<5b3f?m?R#&eD!u*4=4Z$&Xz9qpC4bOI;
z1;TfXd=Wd4I^)zaMyg#Z(nGy`&J2UBW5g
zSyF6lj2n(X-XIY43R3jYhbVIJkV405A&9IH@Ss&9W1oUGj?BTy56saoP
zbNWZ~#6imu@2f_`cw~hen+mJ$gIX=%P@mIoe%yg0;0u9(DoEAu6RpQnJ}pEofVHtCyVU0)0_;`3&r*|AZ>B-n#74%EVxxyRInx
z$A-`$IR17O2O9AmK<|5dM&1IDaVrV`?74te&Fdh+cEw)aMrr4+xPnyuI?*1;(W31<
z1*(S5%VHh>-#>ZGi3v8U%1L
z)xM$2MISru;u_ei<5>p1I#>q-Xl`f4+I=ue7GCPo^)c(IdiMJ-nX9LHCfoXMwzyKh
z)6C(V1W)vVr8IlHW&L{^qGptH!)D{vrIqtSOq;vyIe}Kx3fgkE*Bm@0TD7}Cz9_bA
z#$}u}dB(z(F~des#mKjebZ?U&d$X0jlFM-euHopqa*A(}N4(u>eY+^CAXVp7CjHtS
z-0-JYLo8OscMM*9HBYRA;cd$*Tt^b!@>c=+MZR%_M!2+&UIE#~O7|e*#e>M0QpYV^
z)!9@@o;c;^o)d>2ZR*;C^=MZg`u*$i<5|ESM3Q}V2tF+b0+AKP-)^vJRapf>A84a=XcnC4Y
zvpG;VM@^c8x0C%dCe?r{JQ`td?8^=ls7(`zumN+Rn?KwsB+E_3AG+YofK^WJIeGE+
zkxrofb9rivm+b7Dv}}Z@y7-m?t`|1i0=wQfYjd|f*@qrcyOr(L?fE+8lVLDo&LPYi
zZb?J(&NcFO2~Qhy+!%Os5aZ<`9>&{NxfrPp@2xZ@(>lsI@b0Bc@yYH?Cwga!z~B5<
zkeFRG58*NzMfxr@t)EmJo2oB$pT2vNT30&Bp;!fIUtTMRRaNf{!>*NH`50+7-S{e9
z>-zplCz=d$i+F7V?e!?*~OWQw$vnNht7;QeauGEnUT+`+2&R?%F(k395a@z?=-so6d?87yqmb~X@
z%<_vtxhRcE3s=Lo9*HhdGbK!75-9!8neLO6!w${&;ow`^J`w=USe%|QW2l?0BAF%KY^=+)(
zn7I=Zk#hMQp8wo)*?5y6EI!90UYz2m>lvF2P^J%lF{Cn>v|*-vyZh}!@Q(ca*;#(e
zx9cWfBg|;!{8LY39_=iYjX48DCoIE*Pgyp@SsX2YhmZe>EYuhU+4!s=#aF(WeG-X7
z#9~4@hd1Tc@X34VW3M9zFwne(VfT8)fzw7)CHc&ul1$o$^w*j|e`q`O&1-@YE7|qGN7Kd3PE%0G(Wz#Fi>=mnt?dS4m=XSMm%b
zY*>vJ6t{aLlxZv2eu1YJQrZ3~3hVs3mSiq~ze
z3Y|&F4M)Hi0zNB97Oj}ooZI6oe87H^&iy-8%EYMG(`CcSbo+ChB}kDfkj@`-3ZD9G
zGia+dMEILaoZMNwu0~1s&NU2wzq1hVSwXJ%o`TX-?{`DQbYurqHSTtE_vfJh`Ac~E
zQ2m8-^f!Jz0h&?MWhdzjb-7qK+{Nhk?}GGJZ$!MkRQ55mO5~w}q~1NiC1knSrVfImJfh`w|U>bp~y
z$R%MJZwx@pPsd$ceZT6K&qmgF(}*Z{-5S%i>+-S^)6refXHZFc;io^i7vY)d5F(e+=M$S8o3bG6Rp^=|CZwhl%v@mZu8BK4!nhF|3vN
z&Ed^qw4SraoZh60alj;CE1kJ#uk@s3*QGcLL*-z3@L53^K~mQ-h+A%HvDrH_RQZwl
z!HYBz_ksNG^$)GyP48D9hO8{FB!PN}odzT0y=S1`@VnojnJ@N+s?CEiWwI1Io6H6s
zoE<{s&GsSLk|RV_wOTcDRSxFn?Sp&vCF=+fBcf_Hb7)O^vLBNYgXCxH
zhb_<9|J=l+4n>G8Qg*lfaZHoV?i!X!DQ28MD8W*J=?p}hnKz-A%~~j)&iV0>rb=@5O#4skk7mUU;?+Q~U26$CTs5pUBWt+eHs
zwbWae|B5ANfg33T=8o+q&jEnu0&J}~JI~X0KpsmHJGGDw+Fb{usLi<^W+r%f1`sK$&v8Mw848BUTgW?gPM
z4JK#3XDa27=@zq}Zv?SOEm=>|hMQoJ5=d9PLHRPua~f{>a?pjwcP@v?8&fgsmF`Y@
z6Ps@>2&1Tiu!NnXkE%kKYWAyIY>74evjMjnR73pk?9n92NYW-qM`POJ3C5Fsi04*i
zr!yElbHjt3hi&`Vr|-eiq%sCo|G~mM_NeB%-GZJY{)ySMJ*rW~}?hS?^&h
zELd01eDjcnE9og;zCK8vKxFe2^WL+>@0KqIeWqfoHi)`;Sq^W>t3_|JbPatbHcvbi
zR}dEaS^BujJbFI_I*QcMuomTJ^=eS5M8q9BLJgJLe#oyQT|wG45s^5(YEMBX!R?f1
zc0ReyjA;~Zvm&Z&O+?X~Q{|v{Tfg5%=qNpyo9$F+Rymk?+v#2ol0w$XW#ePhJ!E3~
zSHJoZ`nnC|Bo)wrhYb$?yp0eDN(FJm!&pAiURjuX_|}amIr?$hipn}(
z!7&;dj=D1WBV=~EKR66I7mk1z1cF{cT;s`V+6rg39(8r5F?a)R?B9(l+y6u4fxQsY
zQtdPnDb$(OYT;PRdr+)Cjj7WyLELZz3IYMA3ZiHYPS8_HOB-U_($9tQHG2Q~gyrYr
z#a}rB`GtUd{Xu?3#^d1#6gC883DRW5{NO1Fg$)6oUXFkl1lVOpPF*Z7bljOEaK|EG
zuOOb58RQizSt-|1>dG=iU-}D?>9jP3Hta~&(;);=Lu;lr$c(6rv@-YMLP^^A6kjT@
zlEV3N1Uw>O)5q-<#3NO(9BE%jiM^8$f9hMy9p4Uo`xeH-8ccJM1
z_hnx}R3Wu&cU)>RofaLj1?${!1o9q%Jgp$w)Dx)sPX{_!!J^{iM$wVXCPbh68P({=
z4x&EQW+k%X>*PH`Jcc_Ofjp@otmRK!*OL}2%EBP%02`^omH+#Gh%{k%uEjiLlx`pN
zI5JN8Y}9+Y}Dn;QWG=H&X?WvxO~Cqq3#Fi0D>@HsvLo!A`r9+l5lJm
zitU}8qlzKYVk-7y#!US%_6x+Y?Z7pDu8x$dkK)Q*lL86KX*mKu5eP~Jss397+8~wW
zGa{QO>lUfXwSd@eDjjBBj-0JE!$#onl+rH2{O=nuoms1BZ%OR&ZxDZO36797;f5m+
z3mR2^r+@I^&vo}`wYZV1YaQ8j#$Znb(6rf(X-kaoi(E4I467Dd8w&u8V(cK9E}n*E*Qr%E9dt%j`6E73J;vmsKKE4N1V=uQY{*FnGH5s$1)
ztdjgv1&1D>Rl(eF1ag2tz!jwAj+aRxPw^NP>+x%c?|~2=@6lh~e>IGsRfK-!6VQ}x
z3RSNkJ<=nAO
zQM572&s>Bmz6wk?PQY+>D;@k)3#yTayz*1*p^iY<)2E>Ow35e4qP@Bk+LRN}$5v6y
zk`r9=WK?H-=cMzDGZAj;ecU^6&4r?cOFD
zmd*NKBEnxjZFkG5MTn~aO%+-odF*dD77=IvadXRwgKa6ax3JUcM8i1iK%I^DOFD(n
zb!UCn-gS6-$$6QLZM%VuK1Y{sx+KW)K6e){`>VfOZW-Z5I@fmqT_KShV@|({;qU(?
zv-lq!V_MX6N5m|?z(G+3
zDgNJhTL0nBl}!L@1}$;-@Z+LtG!*zNyMi!shJ*fnk|eL5@)O#>x4PF{nEzLaq!i=o
zY|5|dhjU$WKRCd+)@e~6)gvt>eeLp9Y&dX9j%*B_i5rZLBO`V?!(*L7Cw
z+7t7-x<~pXRV;(1gu6!$TohH1_=DegR(>B_mV+oM2-Pe#W!vcT0h_3r=-;nGmE=Uu
z_&S8rjNAm%r!5>@EY`3K+uYo8>QJjmUEE*HR(y2v3^B4vfZyo!X-B`D#^F1h2~SN}
zB;N?d=o&V;3(xeZ>oG`|Ru;X_qo)r?<4Ny$9bUN{Q@5mhYz!CiLQ@c2CY$s3N0lWFFAexkuv^v)@
znU*+Iw7O6%+c4k=Z2^RM8gaVnE-jc&B7D*knrAoJNOSZQVoTF1-*A}pI=ApK$Ce?r
zS}!;EU^*NI>3#RmX_M4*+i+iqgHM{i$w#>)+
zG@x~~V^U1=%S@^q%*>e(Smj`0WZAEZXI3Xe`%Pg;K0<#zSCHY;x1#G41D(R;=EZLX
zsq|wPkCTF$;Xf;jmrZH2zL<*yk``M0b1-~G;A44Y(g1;a7Cs~>yM
zqT>7C=({|5$!@GM4twDu@2F`=A~DrxU#_eLUzjHX_4cQ=w`42<^R%vN;9(
z6pAEz)SXOvOA8k;Lze(cK3M=uk+^u!Ypi>l;7$|-7xv*#ePa-cg^TF>%wY5l0?%v~
zmICsnP|tq49)^FuFFOd?{>zY1>YmO{Zh^kc7*7}IO!yTOSDwT8Zsq0ROXe;?7~KS_
zV|^$OX66AM9(B5M&I3_^PChG$kadgpkh^nKm#OXU=)*;*+!|S9D|5*)yJ@2@6Im$zy{f|O^{nApB1F|
znhA7umODV2{-3(1(1(lW{l(AZ`vdb~tpgDa&j%LYuOTq+o2}kFE?IRxUj1d${N;!sM)3zdc54EO!
z1_jK=H2~|#Ol+Uv>g@JDb$m~fX3J&w%ao;&)|;f<2!r6j5PN7$4>wLMt$jx2u3P8E
zlpK6k5a_bphIi$yu^yCePs|Q^tFp5cS3yzg;X_c-`bS2zzs#?G@_Q
zPe8Y3Hqu_Gg6Q`S&2yPqeEik8P1UG}Y*eXZ5^#3YAqb6>fa#_s>6(2{)!*p=1X
zaqdHs-t-%>cpc1nrh%Q;kVkr;L)BQB<){y~%1?FqyIiBN)4O?)gU9Zdkp@c0_-TG*
z8VD9WaYyD2`Mp`B#W|3_i$7j~RX3#UwCFBk=;SqcZ~PFHP+2(1_rsI5eVl8mEDcRp
zhavYs;`T-Bvx1n}JO!(o4n~Z~nbIso#91y_xAIDVyPX49-&Vuba|ojyg*0v}6KZ5;d`kJBTi
zvm?82eCUK_nE&kx%y;k-)KQrAL~RF`oLN74?;pZj`Ip|Sl!zHqR?!vfiEa_Pj-b6v
z6L~h{HUD8{P$yczYjkt2qwz>@ydaZMPcP`kX9a=LJw7SAjJu;k7Y(&X2A9b}g+Za4
z{UpLhS}Fw#Bhq>~vJUs~R9Ult^f9YgY{hu3*{w@)|_{v}x7cZ~s
z@_w=K64I};&k7=$Ttyk_L8YquW$KMUC|wuQnf>0peYzX={6q7x*+y*e08Cq#+a1!L
zs*30@SS4{cOyBX87k5hT!Vz#rz-I*k^=jOVOJCm2-Y0-QSM#<%
zbJdc&EnoK{%=9m{gLc{)dy2$U2Xhs#olzcJ%r_5V_(wbKu_#e)?Zg3Cj;Bbds&K~n
zX&P~wO8Z-AKnZMr$sDxA+Z~EH#U|-fAZTOp;`jylU}Cmn&6c*aCGLgU_^co*vp@?K
z<=($Nk7iS*-5#igb%AnY98)4?rqe9HXKq;+&N@jsDJ8{ivM>izIi4d6va1+ZLte_A
zx^oRiE;t3l(cP5x3|hY36~o>q32e|=Mr;hXFzlV*X%tVuJX$Eo<_Hqvw5ZYLemq(`
zN}l%!qjAr-#|^>ppMJ)ovl3ELvSix7Xo9jz`IFf6+W~xcC>^i8IRvGzAH=g?A4UBx
z_hM+nBJee{B&8m63R@xV0)!$lNTRhfOHY~6yAm64HOuYml%GzZapqq9c~gU%NqWp3
z-y7c_y^OVgT$bl^f(&2K+4-y>CT$#~jAW-s}DxX<*jw~PF%(Rqy=(rGSK8lMOYtgAs3lU7JVO=bQQEN=TcH|08s1ceEH5-7qzh*hPu@}>ceNa`q%gx=FL+1NW`|=Lh&-m}JZj+df
zO!P}=xja=6DfN~|Nt0H$y(4+Z*liLdJ3-DBo4LEUO#)~Et!zG}%E64Ka!43C?+9jE
z-9DMN0M9zCcFpE2WzPq@h*p~a!&d5&vDxc?cBPldY&r8%;}48Sc*V$s`m^|A5;aS{`U)7KF|t%Yh=@nBgw>O!oMdcK@7v(
z8ng |