package plugins.nherve.toolbox.image.feature.descriptor; import icy.system.profile.CPUMonitor; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.Future; import plugins.nherve.toolbox.Algorithm; import plugins.nherve.toolbox.concurrent.MultipleDataTask; import plugins.nherve.toolbox.concurrent.TaskException; import plugins.nherve.toolbox.concurrent.TaskManager; import plugins.nherve.toolbox.image.feature.Segmentable; import plugins.nherve.toolbox.image.feature.Signature; import plugins.nherve.toolbox.image.feature.IcySupportRegion; import plugins.nherve.toolbox.image.feature.descriptor.MultiThreadedSignatureExtractor.Listener; import plugins.nherve.toolbox.image.feature.region.IcyPixel; import plugins.nherve.toolbox.image.feature.signature.SignatureException; public class MultiThreadedExecutionContext extends Algorithm { private final TaskManager tm; private final List<Listener> listeners; /** The image. */ private Segmentable image; /** The done. */ private int done; /** The done pct. */ private int donePct; /** The step pct. */ private int stepPct; /** The ld. */ private LocalDescriptor<Segmentable, ? extends Signature, IcyPixel> ld; /** The regions. */ private IcySupportRegion[] regions; /** The result. */ private Signature[] result; /** The errors. */ private Map<Integer, SignatureException> errors; /** The cpu. */ private CPUMonitor cpu; /** The nbr. */ private int nbr; /** The do all pixels. */ private boolean doAllPixels; private boolean interrupted; /** * The Class SignatureExtractionWorker. * * @author Nicolas HERVE - nicolas.herve@pasteur.fr */ public class SignatureExtractionWorker extends MultipleDataTask<IcySupportRegion, Integer> { /** * Instantiates a new signature extraction worker. * * @param allData * the all data * @param idx1 * the idx1 * @param idx2 * the idx2 */ public SignatureExtractionWorker(List<IcySupportRegion> allData, int idx1, int idx2) { super(allData, idx1, idx2); } /* * (non-Javadoc) * * @see * plugins.nherve.toolbox.concurrent.MultipleDataTask#call(java. * lang.Object, int) */ @Override public void call(IcySupportRegion data, int idx) throws Exception { try { Signature sig = null; sig = ld.extractLocalSignature(getImage(), data); setResult(idx, sig); } catch (SignatureException e) { logError("On region " + data + " : " + e.getMessage()); addError(idx, e); } } /* * (non-Javadoc) * * @see * plugins.nherve.toolbox.concurrent.MultipleDataTask#outputCall() */ @Override public Integer outputCall() throws Exception { return 0; } @Override public void processContextualData() { } } /** * The Class PixelLineSignatureExtractionWorker. * * @author Nicolas HERVE - nicolas.herve@pasteur.fr */ public class PixelLineSignatureExtractionWorker implements Callable<Integer> { /** The line. */ private int line; /** The width. */ private int width; /** * Instantiates a new pixel line signature extraction worker. * * @param line * the line * @param width * the width */ public PixelLineSignatureExtractionWorker(int line, int width) { super(); this.line = line; this.width = width; } /* * (non-Javadoc) * * @see java.util.concurrent.Callable#call() */ @Override public Integer call() { int idx = width * line; Signature sig = null; for (int x = 0; x < width; x++) { try { sig = ld.extractLocalSignature(getImage(), new IcyPixel(x, line)); setResult(idx, sig); } catch (SignatureException e) { logError("On pixel " + x + "x" + line + " : " + e.getMessage()); addError(idx, e); } idx++; } return 0; } } /** * Instantiates a new execution context. * * @param image * the image * @param regions * the regions * @param descriptor * the descriptor */ public MultiThreadedExecutionContext(Segmentable image, IcySupportRegion[] regions, LocalDescriptor<Segmentable, ? extends Signature, IcyPixel> descriptor, TaskManager tm, List<Listener> listeners) { super(); this.tm =tm; this.listeners = listeners; this.image = image; this.regions = regions; this.ld = descriptor; cpu = new CPUMonitor(); doAllPixels = (regions == null); nbr = 0; } /** * Instantiates a new execution context. * * @param image * the image * @param descriptor * the descriptor */ public MultiThreadedExecutionContext(Segmentable image, LocalDescriptor<Segmentable, ? extends Signature, IcyPixel> descriptor, TaskManager tm, List<Listener> listeners) { this(image, null, descriptor, tm, listeners); } /** * Sets the result. * * @param idx * the idx * @param sig * the sig */ public synchronized void setResult(int idx, Signature sig) { result[idx] = sig; done++; if (isLogEnabled() || !listeners.isEmpty()) { while (done >= donePct) { for (Listener l : listeners) { l.notifyProgress(done, result.length); } if (isLogEnabled()) { cpu.stop(); log(" ~ " + done * 100.0 / nbr + " % ~ " + cpu.getElapsedTimeMilli() / 1000.0 + " s"); cpu.start(); } donePct += stepPct; } } } /** * Start. */ public void start() { if (isLogEnabled()) { cpu.start(); } interrupted = false; if (doAllPixels) { nbr = image.getHeight() * image.getWidth(); } else { nbr = regions.length; } result = new Signature[nbr]; errors = new HashMap<Integer, SignatureException>(); done = 0; stepPct = nbr / 100; if (stepPct == 0) { stepPct = 1; } donePct = stepPct; if (doAllPixels) { List<Future<Integer>> poolResults = new ArrayList<Future<Integer>>(); for (int y = 0; y < image.getHeight(); y++) { poolResults.add(tm.submit(new PixelLineSignatureExtractionWorker(y, image.getWidth()))); } try { tm.waitResults(poolResults, "Signatures extraction", 0); } catch (TaskException e) { e.printStackTrace(); } catch (InterruptedException e) { interrupted = true; log("MultiThreadedSignatureExtractor interrupted 1"); } } else { try { tm.submitMultiForAll(Arrays.asList(regions), SignatureExtractionWorker.class, this, "Signatures extraction", 0); } catch (TaskException e) { e.printStackTrace(); } catch (InterruptedException e) { interrupted = true; log("MultiThreadedSignatureExtractor interrupted 2"); } } if (isLogEnabled()) { cpu.stop(); } } /** * Gets the result. * * @return the result */ public Signature[] getResult() { return result; } /** * Gets the descriptor. * * @return the descriptor */ public LocalDescriptor<Segmentable, ? extends Signature, IcyPixel> getDescriptor() { return ld; } /** * Gets the image. * * @return the image */ public Segmentable getImage() { return image; } /** * Adds the error. * * @param idx * the idx * @param e * the e */ public void addError(int idx, SignatureException e) { errors.put(idx, e); } /** * Checks for errors. * * @return true, if successful */ public boolean hasErrors() { return errors.size() > 0; } /** * Gets the errors. * * @return the errors */ public Map<Integer, SignatureException> getErrors() { return errors; } public boolean isInterrupted() { return interrupted; } public void setInterrupted(boolean interrupted) { this.interrupted = interrupted; } }