001/* *********************************************************************** * 002 * project: org.matsim.* 003 * PlansWriter.java 004 * * 005 * *********************************************************************** * 006 * * 007 * copyright : (C) 2007, 2012 by the members listed in the COPYING, * 008 * LICENSE and WARRANTY file. * 009 * email : info at matsim dot org * 010 * * 011 * *********************************************************************** * 012 * * 013 * This program is free software; you can redistribute it and/or modify * 014 * it under the terms of the GNU General Public License as published by * 015 * the Free Software Foundation; either version 2 of the License, or * 016 * (at your option) any later version. * 017 * See also COPYING, LICENSE and WARRANTY file * 018 * * 019 * *********************************************************************** */ 020 021package org.matsim.core.population.io; 022 023import java.io.IOException; 024import java.io.OutputStream; 025import java.util.HashMap; 026import java.util.Map; 027 028import org.apache.log4j.Logger; 029import org.matsim.api.core.v01.network.Network; 030import org.matsim.api.core.v01.population.Person; 031import org.matsim.api.core.v01.population.Population; 032import org.matsim.core.api.internal.MatsimWriter; 033import org.matsim.core.gbl.MatsimRandom; 034import org.matsim.core.population.PopulationUtils; 035import org.matsim.core.utils.geometry.CoordinateTransformation; 036import org.matsim.core.utils.geometry.transformations.IdentityTransformation; 037import org.matsim.core.utils.io.AbstractMatsimWriter; 038import org.matsim.core.utils.io.UncheckedIOException; 039import org.matsim.core.utils.misc.Counter; 040import org.matsim.utils.objectattributes.AttributeConverter; 041 042public final class PopulationWriter extends AbstractMatsimWriter implements MatsimWriter { 043 044 private final double write_person_fraction; 045 046 private final CoordinateTransformation coordinateTransformation; 047 private PopulationWriterHandler handler = null; 048 private final Population population; 049 private final Network network; 050 private Counter counter = new Counter("[" + this.getClass().getSimpleName() + "] dumped person # "); 051 052 private final static Logger log = Logger.getLogger(PopulationWriter.class); 053 private Map<Class<?>,AttributeConverter<?>> converters = new HashMap<>(); 054 055 056 public PopulationWriter(final Population population) { 057 this(population, null, 1.0); 058 } 059 060 public PopulationWriter( 061 final CoordinateTransformation coordinateTransformation, 062 final Population population) { 063 this(coordinateTransformation , population, null, 1.0); 064 } 065 066 /** 067 * Creates a new PlansWriter to write out the specified plans to the file and with version 068 * as specified in the {@linkplain org.matsim.core.config.groups.PlansConfigGroup configuration}. 069 * If plans-streaming is on, the file will already be opened and the file-header be written. 070 * If plans-streaming is off, the file will not be created until {@link #write(java.lang.String)} is called. 071 * 072 * @param population the population to write to file 073 */ 074 public PopulationWriter(final Population population, final Network network) { 075 this(population, network, 1.0); 076 } 077 078 public PopulationWriter( 079 final CoordinateTransformation coordinateTransformation, 080 final Population population, 081 final Network network) { 082 this(coordinateTransformation , population, network, 1.0); 083 } 084 085 /** 086 * Creates a new PlansWriter to write out the specified plans to the specified file and with 087 * the specified version. 088 * If plans-streaming is on, the file will already be opened and the file-header be written. 089 * If plans-streaming is off, the file will not be created until {@link #write(java.lang.String)} is called. 090 * 091 * @param coordinateTransformation transformation from the internal CRS to the CRS in which the file should be written 092 * @param population the population to write to file 093 * @param fraction of persons to write to the plans file 094 */ 095 public PopulationWriter( 096 final CoordinateTransformation coordinateTransformation, 097 final Population population, 098 final Network network, 099 final double fraction) { 100 this.coordinateTransformation = coordinateTransformation; 101 this.population = population; 102 this.network = network; 103 this.write_person_fraction = fraction; 104 this.handler = new PopulationWriterHandlerImplV6( coordinateTransformation ); 105 } 106 107 /** 108 * Creates a new PlansWriter to write out the specified plans to the specified file and with 109 * the specified version. 110 * If plans-streaming is on, the file will already be opened and the file-header be written. 111 * If plans-streaming is off, the file will not be created until {@link #write(java.lang.String)} is called. 112 * 113 * @param population the population to write to file 114 * @param fraction of persons to write to the plans file 115 */ 116 public PopulationWriter( 117 final Population population, 118 final Network network, 119 final double fraction) { 120 this( new IdentityTransformation() , population , network , fraction ); 121 } 122 123 public void putAttributeConverters( final Map<Class<?>, AttributeConverter<?>> converters ) { 124 this.converters.putAll( converters ); 125 } 126 127 public void putAttributeConverter( Class<?> key, AttributeConverter<?> converter ) { 128 this.converters.put( key, converter ); 129 } 130 131 /** 132 * Writes all plans to the file. 133 */ 134 @Override 135 public final void write(final String filename) { 136 try { 137 this.handler.putAttributeConverters(converters); 138 this.openFile(filename); 139 this.handler.writeHeaderAndStartElement(this.writer); 140 this.handler.startPlans(this.population, this.writer); 141 this.handler.writeSeparator(this.writer); 142 this.writePersons(); 143 this.handler.endPlans(this.writer); 144 log.info("Population written to: " + filename); 145 } catch (IOException e) { 146 throw new UncheckedIOException(e); 147 } finally { 148 this.close(); 149 counter.printCounter(); 150 counter.reset(); 151 } 152 } 153 154 /** 155 * Writes all plans to the output stream and closes it. 156 * 157 */ 158 public final void write(OutputStream outputStream) { 159 try { 160 this.handler.putAttributeConverters(converters); 161 this.openOutputStream(outputStream); 162 this.handler.writeHeaderAndStartElement(this.writer); 163 this.handler.startPlans(this.population, this.writer); 164 this.handler.writeSeparator(this.writer); 165 this.writePersons(); 166 this.handler.endPlans(this.writer); 167 } catch (IOException e) { 168 throw new UncheckedIOException(e); 169 } finally { 170 this.close(); 171 counter.printCounter(); 172 counter.reset(); 173 } 174 } 175 176 177 private final void writePersons() { 178 for (Person p : PopulationUtils.getSortedPersons(this.population).values()) { 179 writePerson(p); 180 } 181 } 182 183 private final void writePerson(final Person person) { 184 try { 185 if ((this.write_person_fraction < 1.0) && (MatsimRandom.getRandom().nextDouble() >= this.write_person_fraction)) { 186 return; 187 } 188 this.handler.writePerson(person, this.writer); 189 counter.incCounter(); 190 } catch (IOException e) { 191 throw new UncheckedIOException(e); 192 } 193 } 194 195 public final void writeV0(final String filename) { 196 this.handler = new PopulationWriterHandlerImplV0( coordinateTransformation , this.network); 197 write(filename); 198 } 199 200 public final void writeV4(final String filename) { 201 this.handler = new PopulationWriterHandlerImplV4( coordinateTransformation , this.network ); 202 write(filename); 203 } 204 205 public final void writeV5(final String filename) { 206 this.handler = new PopulationWriterHandlerImplV5(coordinateTransformation); 207 write(filename); 208 } 209 210 public final void writeV6(final String filename) { 211 this.handler = new PopulationWriterHandlerImplV6(coordinateTransformation); 212 write(filename); 213 } 214 215 public final void writeV6(final OutputStream stream) { 216 this.handler = new PopulationWriterHandlerImplV6(coordinateTransformation); 217 write(stream); 218 } 219 220 public final void setWriterHandler(final PopulationWriterHandler handler) { 221 this.handler = handler; 222 } 223 224}