/* * Copyright (C) 2013 Serdar * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.fub.maps.project.detector.model; import de.fub.maps.project.api.process.ProcessState; import de.fub.maps.project.detector.DetectorMode; import de.fub.maps.project.detector.model.converter.DataConverter; import de.fub.maps.project.detector.model.gpx.TrackSegment; import de.fub.maps.project.detector.model.inference.InferenceMode; import de.fub.maps.project.detector.model.inference.InferenceModelInputDataSet; import de.fub.maps.project.detector.model.inference.InferenceModelResultDataSet; import de.fub.maps.project.detector.model.pipeline.postprocessors.tasks.Task; import de.fub.maps.project.detector.model.pipeline.preprocessors.FilterProcess; import de.fub.maps.project.detector.model.xmls.DataSet; import de.fub.maps.project.detector.model.xmls.Profile; import de.fub.maps.project.detector.model.xmls.TransportMode; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; /** * The controller class of a Detector. This class provides the logic for the * process execution of a Detector. * * @author Serdar */ @NbBundle.Messages({ "CLT_Trainings_Process_Running=Training", "CLT_Inference_Process_Running=Clustering" }) class DetectorRunSupport { private final Detector detector; private Profile currentProfile; private final ArrayList<DataConverter> converterList; private static final Logger LOG = Logger.getLogger(DetectorRunSupport.class.getName()); public DetectorRunSupport(Detector detector) { assert detector != null; this.detector = detector; this.currentProfile = detector.getCurrentActiveProfile(); this.converterList = new ArrayList<DataConverter>(Lookup.getDefault().lookupResult(DataConverter.class).allInstances()); } /** * Starts the the classification process. */ void start() { this.currentProfile = detector.getCurrentActiveProfile(); final ProgressHandle handle = ProgressHandleFactory.createHandle(Bundle.CLT_Running_Process(detector.getDetectorDescriptor().getName(), "")); try { detector.getInferenceModel().getResult().clear(); handle.start(); detector.setDetectorState(ProcessState.RUNNING); switch (detector.getInferenceModel().getInferenceMode()) { case TRAININGS_MODE: handle.setDisplayName(Bundle.CLT_Running_Process(detector.getDetectorDescriptor().getName(), Bundle.CLT_Trainings_Process_Running())); startTraining(); break; case INFERENCE_MODE: handle.setDisplayName(Bundle.CLT_Running_Process(detector.getDetectorDescriptor().getName(), Bundle.CLT_Inference_Process_Running())); startInference(); break; case ALL_MODE: handle.setDisplayName(Bundle.CLT_Running_Process(detector.getDetectorDescriptor().getName(), Bundle.CLT_Trainings_Process_Running())); startTraining(); handle.setDisplayName(Bundle.CLT_Running_Process(detector.getDetectorDescriptor().getName(), Bundle.CLT_Inference_Process_Running())); startInference(); break; default: break; } detector.setDetectorState(ProcessState.INACTIVE); } catch (Exception ex) { LOG.log(Level.SEVERE, ex.getMessage(), ex); detector.setDetectorState(ProcessState.ERROR); } finally { // clean up detector.getInferenceModel().getResult().clear(); detector.getInferenceModel().getInput().clearAllInferenceData(); detector.getInferenceModel().getInput().clearAllTrainingsData(); detector.getInferenceSet().clear(); detector.getTrainingsSet().clear(); handle.finish(); } } /** * Starts the trainigns process. */ private void startTraining() { Map<String, List<TrackSegment>> trainingsMap = getTrainingsSet(); if (this.currentProfile.getPreprocess().isActive() && (this.currentProfile.getPreprocess().getMode() == DetectorMode.TRAINING || this.currentProfile.getPreprocess().getMode() == DetectorMode.BOTH)) { final ProgressHandle filterHandle = ProgressHandleFactory.createHandle("Applying Preprocessors..."); Set<Entry<String, List<TrackSegment>>> entrySet = trainingsMap.entrySet(); filterHandle.start(entrySet.size()); int index = 0; try { for (Entry<String, List<TrackSegment>> entry : entrySet) { List<TrackSegment> tracks = entry.getValue(); // TODO could lead to an infinity loop or to a concurrent modification exception! trainingsMap.put(entry.getKey(), applyPreProcessors(tracks)); filterHandle.progress(index++); } } finally { filterHandle.finish(); } } // convert GPSTracks to fileObjects InferenceModelInputDataSet inferenceModelInputDataSet = new InferenceModelInputDataSet(); for (Entry<String, List<TrackSegment>> entry : trainingsMap.entrySet()) { inferenceModelInputDataSet.putTrainingsData(entry.getKey(), entry.getValue()); } detector.getInferenceModel().setInput(inferenceModelInputDataSet); // start training & crossvalidation detector.getInferenceModel().setInferenceMode(InferenceMode.TRAININGS_MODE); detector.getInferenceModel().run(); } /** * Starts the inference process. */ private void startInference() { List<TrackSegment> inferenceSet = getInferenceSet(); // apply pre precossers if (this.currentProfile.getPreprocess().isActive() && (this.currentProfile.getPreprocess().getMode() == DetectorMode.INFERENCE || this.currentProfile.getPreprocess().getMode() == DetectorMode.BOTH)) { inferenceSet = applyPreProcessors(inferenceSet); } InferenceModelInputDataSet inferenceModelInputDataSet = detector.getInferenceModel().getInput(); if (inferenceModelInputDataSet == null) { inferenceModelInputDataSet = new InferenceModelInputDataSet(); } inferenceModelInputDataSet.getInferenceSet().clear(); inferenceModelInputDataSet.getInferenceSet().addAll(inferenceSet); detector.getInferenceModel().setInput(inferenceModelInputDataSet); // set state of inference model to inference detector.getInferenceModel().setInferenceMode(InferenceMode.INFERENCE_MODE); detector.getInferenceModel().run(); // apply post processors if (this.currentProfile.getPostprocess().isActive() && (this.currentProfile.getPostprocess().getMode() == DetectorMode.INFERENCE || this.currentProfile.getPostprocess().getMode() == DetectorMode.BOTH)) { InferenceModelResultDataSet resultDataset = detector.getInferenceModel().getResult(); if (resultDataset != null) { for (Task task : detector.getPostProcessorPipeline().getProcesses()) { // maybe here is a concurrent execution possible task.setInput(resultDataset); task.run(); } } } } /** * Applies all pre processors on the provided dataset. * * @param dataset a List of Tracksegments, null not allowed. * @return a list of Tracksegments. */ private List<TrackSegment> applyPreProcessors(List<TrackSegment> dataset) { List<TrackSegment> gpsTracks = new ArrayList<TrackSegment>(); List<TrackSegment> tracks = dataset; for (FilterProcess filterProcess : detector.getPreProcessorPipeline().getProcesses()) { if (filterProcess.getScope() == InferenceMode.ALL_MODE || filterProcess.getScope() == detector.getInferenceModel().getInferenceMode()) { filterProcess.setInput(tracks); filterProcess.run(); tracks = filterProcess.getResult(); } else { LOG.log(Level.INFO, "Scope of filter {0} does not match to current inference mode {1}. Skiping filter!", new Object[]{filterProcess.getName(), detector.getInferenceModel().getInferenceMode().toString()}); } } gpsTracks.addAll(tracks); return gpsTracks; } /** * Returns the trainingset, which is provided via the DetectorDescriptor. * * @return a map with the Data for each class. */ public Map<String, List<TrackSegment>> getTrainingsSet() { HashMap<String, List<TrackSegment>> trainingsSet = new HashMap<String, List<TrackSegment>>(); for (TransportMode transportMode : detector.getDetectorDescriptor().getDatasets().getTrainingSet().getTransportModeList()) { if (!trainingsSet.containsKey(transportMode.getName())) { trainingsSet.put(transportMode.getName(), new ArrayList<TrackSegment>()); } for (DataSet dataSet : transportMode.getDataset()) { if (dataSet.getUrl() != null) { File file = new File(dataSet.getUrl()); File normalizedFile = FileUtil.normalizeFile(file); FileObject datasetFileObject = FileUtil.toFileObject(normalizedFile); if (datasetFileObject != null && datasetFileObject.isValid()) { try { List<TrackSegment> gpsTrackList = convertFileObject(datasetFileObject); trainingsSet.get(transportMode.getName()).addAll(gpsTrackList); } catch (DataConverter.DataConverterException ex) { Exceptions.printStackTrace(ex); } } } } } return trainingsSet; } /** * * @return */ public List<TrackSegment> getInferenceSet() { List<TrackSegment> inferenceSet = new ArrayList<TrackSegment>(); for (DataSet dataset : detector.getDetectorDescriptor().getDatasets().getInferenceSet().getDatasetList()) { File file = new File(dataset.getUrl()); File normalizeFile = FileUtil.normalizeFile(file); FileObject datasetFileObject = FileUtil.toFileObject(normalizeFile); if (datasetFileObject != null && datasetFileObject.isValid()) { try { List<TrackSegment> dataList = convertFileObject(datasetFileObject); inferenceSet.addAll(dataList); } catch (DataConverter.DataConverterException ex) { Exceptions.printStackTrace(ex); } } } return inferenceSet; } /** * * @param fileObject * @return * @throws * de.fub.mapsforge.project.detector.model.converter.DataConverter.DataConverterException */ private List<TrackSegment> convertFileObject(FileObject fileObject) throws DataConverter.DataConverterException { List<TrackSegment> gpsTrackList = new ArrayList<TrackSegment>(); for (DataConverter converter : converterList) { if (converter.isFileTypeSupported(fileObject)) { gpsTrackList = converter.convert(fileObject); break; } } return gpsTrackList; } }