/*- * Copyright 2015 Diamond Light Source Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package uk.ac.diamond.scisoft.analysis.peakfinding; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; import org.eclipse.dawnsci.analysis.api.peakfinding.IPeakFinder; import org.eclipse.dawnsci.analysis.api.peakfinding.IPeakFinderParameter; import org.eclipse.january.dataset.IDataset; import uk.ac.diamond.scisoft.analysis.utils.ClassUtils; public class PeakFindingServiceImpl implements IPeakFindingService { private final Map<String, PeakFinderInfo> PEAKFINDERS = new HashMap<String, PeakFinderInfo>(); public PeakFindingServiceImpl() { //Intentionally left blank (OSGi). } /** * Checks whether the PEAKFINDERS is populated and if not tries to fill it. */ private void checkForPeakFinders() { if (!PEAKFINDERS.isEmpty()) return; addPeakFindersByExtension(); } private void checkForPFID(String pfID) { if (PEAKFINDERS.containsKey(pfID)) return; throw new IllegalArgumentException(pfID+" is not registered with the peak finding service"); } @Override public void addPeakFindersByClass(ClassLoader cl, String pakage) throws ClassNotFoundException,IllegalAccessException,InstantiationException { final List<Class<?>> clazzes = ClassUtils.getClassesForPackage(cl, pakage); for (Class<?> clazz : clazzes) { if (Modifier.isAbstract(clazz.getModifiers())) continue; if (IPeakFinder.class.isAssignableFrom(clazz)) { IPeakFinder pf = (IPeakFinder) clazz.newInstance(); registerPeakFinder(null, pf.getName(), null, pf); } } } @Override public void addPeakFindersByExtension() { IConfigurationElement[] elems = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.dawnsci.analysis.api.peakfinder"); for (IConfigurationElement el: elems) { if (el.getName().equals("peakFinder")) { final String pfID = el.getAttribute("id"); final String pfNm = el.getAttribute("name"); final String pfDesc = el.getAttribute("description"); IPeakFinder pf = null; try { pf = (IPeakFinder)el.createExecutableExtension("class"); } catch (Exception ex) { ex.printStackTrace(); continue; } registerPeakFinder(pfID, pfNm, pfDesc, pf); } } } private void registerPeakFinder(String pfID, String pfNm, String pfDesc, IPeakFinder pf) { //In case we're not working from extension points. if (pfID == null) { pfID = pf.getClass().getName(); } PEAKFINDERS.put(pfID, new PeakFinderInfo(pfNm, pfDesc, pf)); } @Override public String getPeakFinderName(String pfID) { checkForPeakFinders(); checkForPFID(pfID); return PEAKFINDERS.get(pfID).getName(); } @Override public Collection<String> getRegisteredPeakFinders() { checkForPeakFinders(); return PEAKFINDERS.keySet(); } @Override public Map<String, IPeakFinderParameter> getPeakFinderParameters(String pfID) { checkForPeakFinders(); checkForPFID(pfID); IPeakFinder selectedPeakFinder = PEAKFINDERS.get(pfID).getPeakFinder(); return selectedPeakFinder.getParameters(); } @Override public String getPeakFinderDescription(String pfID) { checkForPeakFinders(); checkForPFID(pfID); return PEAKFINDERS.get(pfID).getDescription(); } @Override public void findPeaks(IPeakFindingData peakFindingData) throws Exception { Set<String> activePeakFinders; Map<String, Map<String, IPeakFinderParameter>> peakFinderParameters = new TreeMap<String, Map<String, IPeakFinderParameter>>(); Map<String, Map<Integer, Double>> allFoundPeaks = new TreeMap<String, Map<Integer, Double>>(); IDataset[] searchData; Integer nPeaks = peakFindingData.getNPeaks(); //Get the data to find peaks in if (peakFindingData.hasData()){ searchData = peakFindingData.getData(); } else { throw new Exception("No data set to find peaks in."); } //Get the peak finders to use and their parameters if (peakFindingData.hasActivePeakFinders()) { activePeakFinders = (Set<String>)peakFindingData.getActivePeakFinders(); for (String pfID : activePeakFinders) { checkForPFID(pfID); peakFinderParameters.put(pfID, peakFindingData.getPFParametersByPeakFinder(pfID)); } } else { throw new IllegalArgumentException("No peak finders set active"); } Iterator<String> activePeakFindersIter = activePeakFinders.iterator(); while (activePeakFindersIter.hasNext()) { //Get each active IPeakFinder in turn... String currID = activePeakFindersIter.next(); IPeakFinder currPF = PEAKFINDERS.get(currID).getPeakFinder(); //... set new parameters on PeakFinder ... Map<String, IPeakFinderParameter> currPFParams = peakFinderParameters.get(currID); for (Map.Entry<String, IPeakFinderParameter> pfParam : currPFParams.entrySet()) { //Will only set parameters which are in the map (may be others unset) currPF.setParameter(pfParam.getKey(), pfParam.getValue()); } //... call the findPeaks method, record the result & reset the peak finder parameters allFoundPeaks.put(currID, currPF.findPeaks(searchData[0], searchData[1], nPeaks)); currPF.resetParameters(); } //TODO Add some process here which averages the results of the findPeaks calls //Finally set the found peaks on the IPeakFindingData DTO peakFindingData.setPeaks(allFoundPeaks); } private class PeakFinderInfo { private String name; private String description; private IPeakFinder peakFinder; public PeakFinderInfo(String nm, String desc, IPeakFinder pf) { this.name = nm; this.description = desc; this.peakFinder = pf; } public String getName() { return name; } public String getDescription() { return description; } public IPeakFinder getPeakFinder() { return peakFinder; } } }