001/* *********************************************************************** *
002 * project: org.matsim.*
003 *                                                                         *
004 * *********************************************************************** *
005 *                                                                         *
006 * copyright       : (C) 2016 by the members listed in the COPYING,        *
007 *                   LICENSE and WARRANTY file.                            *
008 * email           : info at matsim dot org                                *
009 *                                                                         *
010 * *********************************************************************** *
011 *                                                                         *
012 *   This program is free software; you can redistribute it and/or modify  *
013 *   it under the terms of the GNU General Public License as published by  *
014 *   the Free Software Foundation; either version 2 of the License, or     *
015 *   (at your option) any later version.                                   *
016 *   See also COPYING, LICENSE and WARRANTY file                           *
017 *                                                                         *
018 * *********************************************************************** */
019
020package org.matsim.contrib.util;
021
022import java.util.function.Function;
023
024import org.matsim.api.core.v01.Coord;
025import org.matsim.api.core.v01.Identifiable;
026import org.matsim.contrib.util.timeprofile.TimeProfiles;
027import org.matsim.core.controler.MatsimServices;
028import org.matsim.core.mobsim.framework.events.MobsimBeforeCleanupEvent;
029import org.matsim.core.mobsim.framework.events.MobsimBeforeSimStepEvent;
030import org.matsim.core.mobsim.framework.events.MobsimInitializedEvent;
031import org.matsim.core.mobsim.framework.listeners.MobsimBeforeCleanupListener;
032import org.matsim.core.mobsim.framework.listeners.MobsimBeforeSimStepListener;
033import org.matsim.core.mobsim.framework.listeners.MobsimInitializedListener;
034import org.matsim.core.utils.io.IOUtils;
035
036public class XYDataCollector<T extends Identifiable<T>>
037                implements MobsimInitializedListener, MobsimBeforeSimStepListener, MobsimBeforeCleanupListener {
038        public interface XYDataCalculator<T> {
039                String[] getHeader();
040
041                Coord getCoord(T object);
042
043                Object[] calculate(T object);
044        }
045
046        private final Iterable<T> monitoredObjects;
047        private final XYDataCalculator<T> calculator;
048        private final int interval;
049        private final String outputFile;
050        private final MatsimServices matsimServices;
051
052        private Function<Object[], String[]> valuesToStringsConverter = TimeProfiles::combineValuesIntoStrings;
053        private CompactCSVWriter writer;
054
055        public XYDataCollector(Iterable<T> monitoredObjects, XYDataCalculator<T> calculator, int interval,
056                        String outputFile, MatsimServices matsimServices) {
057                this.monitoredObjects = monitoredObjects;
058                this.calculator = calculator;
059                this.interval = interval;
060                this.outputFile = outputFile;
061                this.matsimServices = matsimServices;
062        }
063
064        @Override
065        public void notifyMobsimInitialized(@SuppressWarnings("rawtypes") MobsimInitializedEvent e) {
066                String file = matsimServices.getControlerIO().getIterationFilename(matsimServices.getIterationNumber(),
067                                outputFile);
068                writer = new CompactCSVWriter(IOUtils.getBufferedWriter(file + ".xy.gz"));
069                writer.writeNext("time", "id", "x", "y", calculator.getHeader());
070        }
071
072        @Override
073        public void notifyMobsimBeforeSimStep(@SuppressWarnings("rawtypes") MobsimBeforeSimStepEvent e) {
074                if (e.getSimulationTime() % interval == 0) {
075                        String time = (int)e.getSimulationTime() + "";
076                        for (T o : monitoredObjects) {
077                                Coord coord = calculator.getCoord(o);
078                                writer.writeNext(time, o.getId() + "", coord.getX() + "", coord.getY() + "",
079                                                valuesToStringsConverter.apply(calculator.calculate(o)));
080                        }
081                }
082        }
083
084        public void setValuesToStringsConverter(Function<Object[], String[]> valuesToStringsConverter) {
085                this.valuesToStringsConverter = valuesToStringsConverter;
086        }
087
088        @Override
089        public void notifyMobsimBeforeCleanup(@SuppressWarnings("rawtypes") MobsimBeforeCleanupEvent e) {
090                writer.close();
091        }
092}