22 package org.matsim.run.gui;
24 import java.io.BufferedInputStream;
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.util.Locale;
29 import java.util.zip.GZIPInputStream;
31 import javax.swing.GroupLayout;
32 import javax.swing.GroupLayout.Alignment;
33 import javax.swing.JButton;
34 import javax.swing.JDialog;
35 import javax.swing.JFileChooser;
36 import javax.swing.JFrame;
37 import javax.swing.JLabel;
38 import javax.swing.JOptionPane;
39 import javax.swing.JSpinner;
40 import javax.swing.JTextField;
41 import javax.swing.LayoutStyle.ComponentPlacement;
42 import javax.swing.SpinnerNumberModel;
43 import javax.swing.SwingUtilities;
45 import org.apache.logging.log4j.LogManager;
46 import org.apache.logging.log4j.Logger;
56 import com.github.luben.zstd.ZstdInputStream;
61 final class PopulationSampler
extends JDialog {
63 private final static Logger log = LogManager.getLogger(PopulationSampler.class);
65 private static final long serialVersionUID = 1L;
67 private JTextField txtPath;
68 private JSpinner pctSpinner;
69 private JButton btnChoose;
70 private JButton btnCreateSample;
72 PopulationSampler(JFrame parent) {
74 setTitle(
"Create Population Sample");
76 this.btnChoose =
new JButton(
"Choose…");
78 JLabel lblinput =
new JLabel(
"Input Population:");
79 this.txtPath =
new JTextField(
"");
80 JLabel lblpercentage =
new JLabel(
"Sample Size:");
81 this.pctSpinner =
new JSpinner(
new SpinnerNumberModel(10, 1, 100, 1));
82 JLabel lblPercentage =
new JLabel(
"%");
83 btnCreateSample =
new JButton(
"Create Sample…");
85 GroupLayout groupLayout =
new GroupLayout(getContentPane());
86 groupLayout.setHorizontalGroup(groupLayout.createParallelGroup(Alignment.LEADING)
87 .addGroup(groupLayout.createSequentialGroup()
89 .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
90 .addGroup(groupLayout.createSequentialGroup()
91 .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
92 .addComponent(lblinput)
93 .addComponent(lblpercentage))
94 .addPreferredGap(ComponentPlacement.RELATED)
95 .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
96 .addGroup(groupLayout.createSequentialGroup()
97 .addComponent(pctSpinner, GroupLayout.PREFERRED_SIZE,
98 GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
99 .addPreferredGap(ComponentPlacement.RELATED)
100 .addComponent(lblPercentage, GroupLayout.DEFAULT_SIZE,
101 GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE)
102 .addGap(0, 20, Short.MAX_VALUE))
103 .addGroup(groupLayout.createSequentialGroup()
104 .addComponent(txtPath, GroupLayout.DEFAULT_SIZE, 170,
106 .addPreferredGap(ComponentPlacement.RELATED)
107 .addComponent(btnChoose))))
108 .addComponent(btnCreateSample, Alignment.TRAILING))
109 .addContainerGap()));
110 groupLayout.setVerticalGroup(groupLayout.createParallelGroup(Alignment.LEADING)
111 .addGroup(groupLayout.createSequentialGroup()
113 .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
114 .addComponent(btnChoose)
115 .addComponent(lblinput)
116 .addComponent(txtPath))
117 .addPreferredGap(ComponentPlacement.RELATED)
118 .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
119 .addComponent(lblpercentage)
120 .addComponent(lblPercentage)
121 .addComponent(pctSpinner))
122 .addPreferredGap(ComponentPlacement.UNRELATED)
123 .addComponent(btnCreateSample)
124 .addContainerGap()));
125 getContentPane().setLayout(groupLayout);
130 private void setupComponents() {
131 this.btnChoose.addActionListener(e -> {
132 JFileChooser chooser =
new JFileChooser();
133 int result = chooser.showOpenDialog(null);
134 if (result == JFileChooser.APPROVE_OPTION) {
135 File f = chooser.getSelectedFile();
136 String filename = f.getAbsolutePath();
137 PopulationSampler.this.txtPath.setText(filename);
141 this.btnCreateSample.addActionListener(e -> {
143 PopulationSampler.this.setVisible(
false);
147 private void createSample() {
148 final String srcFilename = PopulationSampler.this.txtPath.getText();
149 File srcFile =
new File(srcFilename);
150 if (!srcFile.exists()) {
151 JOptionPane.showMessageDialog(null,
"The specified file could not be found: " + srcFilename,
152 "File not found!", JOptionPane.ERROR_MESSAGE);
156 final String namePart = srcFilename.substring(0, srcFilename.toLowerCase(Locale.ROOT).lastIndexOf(
".xml"));
157 final int percentage = (Integer)PopulationSampler.this.pctSpinner.getValue();
158 final double samplesize = percentage / 100.0;
160 JFileChooser chooser =
new SaveFileSaver();
161 chooser.setCurrentDirectory(srcFile.getParentFile());
162 chooser.setSelectedFile(
new File(srcFile.getParentFile(), namePart +
"." + percentage +
"pct.xml.gz"));
163 int saveResult = chooser.showSaveDialog(PopulationSampler.this);
164 if (saveResult == JFileChooser.APPROVE_OPTION) {
165 File destFile = chooser.getSelectedFile();
166 doCreateSample(srcFile, null, samplesize, destFile);
170 private void doCreateSample(File inputPopulationFile, File networkFile,
double samplesize,
171 File outputPopulationFile) {
172 AsyncFileInputProgressDialog gui =
new AsyncFileInputProgressDialog();
175 MutableScenario sc = ScenarioUtils.createMutableScenario(ConfigUtils.createConfig());
177 if (networkFile != null) {
178 SwingUtilities.invokeLater(() -> gui.setTitle(
"Loading Network…"));
179 try (FileInputStream fis =
new FileInputStream(networkFile);
180 BufferedInputStream is = getBufferedInputStream(networkFile.getName(), fis)) {
181 new MatsimNetworkReader(sc.getNetwork()).parse(is);
183 log.error(e.getMessage(), e);
184 SwingUtilities.invokeLater(gui::dispose);
185 SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null,
186 "Error while reading the network file: " + e.getMessage(),
187 "Cannot create population sample", JOptionPane.ERROR_MESSAGE));
192 SwingUtilities.invokeLater(() -> gui.setTitle(
"Creating Population Sample…"));
193 StreamingPopulationReader reader =
new StreamingPopulationReader(sc);
194 StreamingPopulationWriter writer = null;
196 try (FileInputStream fis =
new FileInputStream(inputPopulationFile);
197 BufferedInputStream is = getBufferedInputStream(inputPopulationFile.getName(), fis)) {
198 writer =
new StreamingPopulationWriter(
new IdentityTransformation(), samplesize);
199 writer.startStreaming(outputPopulationFile.getAbsolutePath());
200 reader.addAlgorithm(writer);
202 SwingUtilities.invokeLater(gui::dispose);
203 writer.closeStreaming();
205 log.error(e.getMessage(), e);
206 SwingUtilities.invokeLater(gui::dispose);
208 if (writer != null) {
209 writer.closeStreaming();
210 outputPopulationFile.delete();
215 SwingUtilities.invokeLater(() -> {
216 JOptionPane.showMessageDialog(null,
217 "<html>It looks like the population file cannot be parsed without a network file.<br />Please select a matching network file in the next dialog.</html>",
218 "Problems creating population sample", JOptionPane.WARNING_MESSAGE);
219 JFileChooser netChooser =
new JFileChooser();
220 netChooser.setCurrentDirectory(inputPopulationFile.getParentFile());
221 int result = netChooser.showOpenDialog(
this);
222 if (result == JFileChooser.APPROVE_OPTION) {
223 doCreateSample(inputPopulationFile, netChooser.getSelectedFile(), samplesize,
224 outputPopulationFile);
228 SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null,
229 "The population sample cannot be created, as not all necessary data is available.",
230 "Cannot create population sample", JOptionPane.ERROR_MESSAGE));
233 },
"sampler").start();
236 private static BufferedInputStream getBufferedInputStream(String filename, FileInputStream fis)
throws IOException {
237 String lcFilename = filename.toLowerCase(Locale.ROOT);
238 if (lcFilename.endsWith(
".gz")) {
239 return new BufferedInputStream(
new UnicodeInputStream(
new GZIPInputStream(fis)));
241 if (lcFilename.endsWith(
".zst")) {
242 return new BufferedInputStream(
new UnicodeInputStream(
new ZstdInputStream(fis)));
244 return new BufferedInputStream(
new UnicodeInputStream(fis));