| 1 | package tmcsim.utilities; |
|---|
| 2 | |
|---|
| 3 | import java.io.File; |
|---|
| 4 | import java.io.FileNotFoundException; |
|---|
| 5 | import java.io.IOException; |
|---|
| 6 | import java.io.PrintWriter; |
|---|
| 7 | import java.util.ArrayList; |
|---|
| 8 | import java.util.HashMap; |
|---|
| 9 | import java.util.HashSet; |
|---|
| 10 | import java.util.List; |
|---|
| 11 | import java.util.Map; |
|---|
| 12 | import java.util.Scanner; |
|---|
| 13 | import java.util.Set; |
|---|
| 14 | import java.util.logging.Level; |
|---|
| 15 | import java.util.logging.Logger; |
|---|
| 16 | |
|---|
| 17 | /** |
|---|
| 18 | * This utility program is used to create the highway map file used as part |
|---|
| 19 | * of the configuration files needed by the simulator. |
|---|
| 20 | * It merges info from three input files to create highway map file. |
|---|
| 21 | * Input: 1. VDS file is the district VDS metadata file downloaded from the PeMS |
|---|
| 22 | * Data Clearinghouse. It gives identifying info about each VDS. |
|---|
| 23 | * 2. Loop detector (lane) file that we found on the ATMS server. |
|---|
| 24 | * It lists all the lanes associated with each VDS. |
|---|
| 25 | * 3. LDS file that has the fep line number for each LDS. |
|---|
| 26 | * Output: 1. The highway map file that lists VDS info and the lanes it governs. |
|---|
| 27 | * 2. A slightly reformatted loop file. (Not sure what this is for.) |
|---|
| 28 | * @author jdalbey, jtorres |
|---|
| 29 | */ |
|---|
| 30 | public class BuildHighwayFile |
|---|
| 31 | { |
|---|
| 32 | final public static String filepath = "config/vds_data/old_vds_data/"; |
|---|
| 33 | final public static String vdsFileName = "d12_vds_meta.txt"; |
|---|
| 34 | final public static String loopFileName = "cleaned_chu_atms_loop_data.txt"; |
|---|
| 35 | final public static String ldsFileName = "cleaned_chu_atms_lds_data.txt"; |
|---|
| 36 | final public static String reformattedLoopFile = "loop.txt"; |
|---|
| 37 | final public static String highwayFile = "highway_stations.txt"; |
|---|
| 38 | /** A dictionary of ldsIDs to VDSids */ |
|---|
| 39 | Map<String,StationAddr> ldsDict; |
|---|
| 40 | /** A dictionary of FEP line numbers to a list of VDSids */ |
|---|
| 41 | Map<String,List<String>> feplines; |
|---|
| 42 | /** A dictionary to lookup VDS data given vdsID */ |
|---|
| 43 | Map<String,VehicleDetectionStation> vdsDict; |
|---|
| 44 | /** A list of ignored VDS id's - FOR DEBUGGING*/ |
|---|
| 45 | List<String> ignored = new ArrayList<String>(); |
|---|
| 46 | /** Reported missing */ |
|---|
| 47 | Set<String> missingVDS = new HashSet<String>(); |
|---|
| 48 | Set<String> missingLDS = new HashSet<String>(); |
|---|
| 49 | |
|---|
| 50 | public void createHighwayFile() |
|---|
| 51 | { |
|---|
| 52 | try |
|---|
| 53 | { |
|---|
| 54 | PrintWriter hwyWriter = new PrintWriter(new File(filepath+highwayFile)); |
|---|
| 55 | hwyWriter.print(feplines.size()+"\n"); |
|---|
| 56 | for (String fep_line: feplines.keySet()) // for each fep line |
|---|
| 57 | { |
|---|
| 58 | hwyWriter.print(fep_line+" 0 "); |
|---|
| 59 | List<String> vdsList = feplines.get(fep_line); |
|---|
| 60 | hwyWriter.print(vdsList.size()+"\n"); |
|---|
| 61 | // output the vds info |
|---|
| 62 | for (String vds: vdsList) |
|---|
| 63 | { |
|---|
| 64 | VehicleDetectionStation vdsItem = vdsDict.get(vds); |
|---|
| 65 | if (vdsItem == null) |
|---|
| 66 | { |
|---|
| 67 | System.out.println(vds + " not found in vdsDict"); |
|---|
| 68 | } |
|---|
| 69 | else |
|---|
| 70 | { |
|---|
| 71 | // Output the VDS identifying info |
|---|
| 72 | hwyWriter.print(vdsItem.id + " "); |
|---|
| 73 | hwyWriter.print(vdsItem.toString() + " "); |
|---|
| 74 | hwyWriter.print(vdsItem.getLaneList().size() + " "); |
|---|
| 75 | hwyWriter.print(vdsItem.street+"\n"); |
|---|
| 76 | List<String> laneList = vdsItem.getLaneList(); |
|---|
| 77 | // output all the lanes |
|---|
| 78 | for (String lane: laneList) |
|---|
| 79 | { |
|---|
| 80 | hwyWriter.print(lane); |
|---|
| 81 | hwyWriter.print("\n"); |
|---|
| 82 | } |
|---|
| 83 | } |
|---|
| 84 | } |
|---|
| 85 | } |
|---|
| 86 | hwyWriter.close(); |
|---|
| 87 | }catch (FileNotFoundException ex) |
|---|
| 88 | { |
|---|
| 89 | Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex); |
|---|
| 90 | } catch (Exception ex) |
|---|
| 91 | { |
|---|
| 92 | ex.printStackTrace(); |
|---|
| 93 | Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex); |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | /** Read the loop file to create a dictionary to lookup all the lanes |
|---|
| 99 | * for a given VDS. As a byproduct we will write the reformatted Loop file. |
|---|
| 100 | * (Not sure if this is needed. Ask jtorres.) |
|---|
| 101 | */ |
|---|
| 102 | public void createLanelookup() |
|---|
| 103 | { |
|---|
| 104 | feplines = new HashMap<String,List<String>> (); |
|---|
| 105 | |
|---|
| 106 | try |
|---|
| 107 | { |
|---|
| 108 | Scanner loopScanner = new Scanner(new File(filepath+loopFileName)); |
|---|
| 109 | PrintWriter loopWriter = new PrintWriter(new File(filepath+reformattedLoopFile)); |
|---|
| 110 | |
|---|
| 111 | loopScanner.nextLine(); // Skip the column headers |
|---|
| 112 | |
|---|
| 113 | // Read all the lines in the loop file |
|---|
| 114 | while(loopScanner.hasNextLine()) |
|---|
| 115 | { |
|---|
| 116 | String line = loopScanner.nextLine(); |
|---|
| 117 | Scanner lineScanner = new Scanner(line); |
|---|
| 118 | |
|---|
| 119 | Integer fwy = lineScanner.nextInt(); |
|---|
| 120 | String dir = lineScanner.next(); |
|---|
| 121 | String postmile = lineScanner.next(); |
|---|
| 122 | String ldsID = lineScanner.next(); |
|---|
| 123 | String vdsID = lineScanner.next(); |
|---|
| 124 | String loopID = lineScanner.next(); |
|---|
| 125 | String shortLoc = lineScanner.next(); |
|---|
| 126 | Integer laneNum = lineScanner.nextInt(); |
|---|
| 127 | String loop_name = line.substring(73).trim(); // grab rest of line |
|---|
| 128 | loop_name = loop_name.replace(" ", "_"); |
|---|
| 129 | |
|---|
| 130 | loopWriter.print(fwy + "\t"); |
|---|
| 131 | loopWriter.print(dir+ "\t"); |
|---|
| 132 | loopWriter.print(postmile + "\t"); |
|---|
| 133 | loopWriter.print(ldsID + "\t"); |
|---|
| 134 | loopWriter.print(vdsID + "\t"); |
|---|
| 135 | loopWriter.print(loopID + "\t"); |
|---|
| 136 | loopWriter.print(shortLoc + "\t"); |
|---|
| 137 | loopWriter.print(laneNum + "\t"); |
|---|
| 138 | loopWriter.print(loop_name + "\t"); |
|---|
| 139 | loopWriter.print("?" + "\t"); |
|---|
| 140 | loopWriter.print("0" + "\t"); |
|---|
| 141 | loopWriter.print('\n'); |
|---|
| 142 | |
|---|
| 143 | lineScanner.close(); |
|---|
| 144 | |
|---|
| 145 | // Combine fields for one lane description |
|---|
| 146 | String laneDesc = loopID + " " + shortLoc + " " + loop_name; |
|---|
| 147 | // Add the lane to the lookup table |
|---|
| 148 | if (vdsDict.containsKey(vdsID)) |
|---|
| 149 | { |
|---|
| 150 | vdsDict.get(vdsID).addLane(laneDesc); |
|---|
| 151 | } |
|---|
| 152 | else |
|---|
| 153 | { |
|---|
| 154 | boolean desiredType = shortLoc.equals("ML") || shortLoc.equals("OS"); |
|---|
| 155 | if (desiredType && !missingVDS.contains(vdsID)) |
|---|
| 156 | { |
|---|
| 157 | System.out.println("createLaneLookup(): vdsID: "+vdsID+ |
|---|
| 158 | " of type "+shortLoc+" not found. "+ String.format("%3s %s %5s",fwy,dir,postmile)); |
|---|
| 159 | missingVDS.add(vdsID); |
|---|
| 160 | } |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | // Also Add this vdsID to the list associated with a fepline |
|---|
| 164 | // lookup which fepline to use for this VDS (using ldsid as |
|---|
| 165 | // intermediate key. |
|---|
| 166 | StationAddr sa = ldsDict.get(ldsID); |
|---|
| 167 | if (sa == null) |
|---|
| 168 | { |
|---|
| 169 | if (!missingLDS.contains(ldsID)) |
|---|
| 170 | { |
|---|
| 171 | System.out.println("missing ldsID in Station Addr lookup: "+ldsID); |
|---|
| 172 | missingLDS.add(ldsID); |
|---|
| 173 | } |
|---|
| 174 | } |
|---|
| 175 | else |
|---|
| 176 | { |
|---|
| 177 | String fep_line = sa.line_num; |
|---|
| 178 | // Fetch the info about this VDS |
|---|
| 179 | VehicleDetectionStation curr = vdsDict.get(vdsID); |
|---|
| 180 | // Some VDS were ignored because they weren't Mainline |
|---|
| 181 | if (curr != null) |
|---|
| 182 | { |
|---|
| 183 | // Assign the station address for this VDS |
|---|
| 184 | curr.setStaAddr(ldsDict.get(ldsID).station_address); |
|---|
| 185 | |
|---|
| 186 | if (fep_line == null) |
|---|
| 187 | { |
|---|
| 188 | System.out.println("No fepline for ldsID "+ldsID+ " :vdsid " |
|---|
| 189 | +vdsID+" "+fwy+dir+postmile); |
|---|
| 190 | } |
|---|
| 191 | else |
|---|
| 192 | { |
|---|
| 193 | // Add vdsID to list of feplines |
|---|
| 194 | if (feplines.containsKey(fep_line)) |
|---|
| 195 | { |
|---|
| 196 | List<String> vdsList = feplines.get(fep_line); |
|---|
| 197 | // only add it if it isn't already there |
|---|
| 198 | if (!vdsList.contains(vdsID)) |
|---|
| 199 | { |
|---|
| 200 | feplines.get(fep_line).add(vdsID); |
|---|
| 201 | } |
|---|
| 202 | } |
|---|
| 203 | else // Create a new one |
|---|
| 204 | { |
|---|
| 205 | List<String> arraylist1 = new ArrayList<String>(); |
|---|
| 206 | arraylist1.add(vdsID); |
|---|
| 207 | feplines.put(fep_line, arraylist1); |
|---|
| 208 | } |
|---|
| 209 | } |
|---|
| 210 | } |
|---|
| 211 | } |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | loopScanner.close(); |
|---|
| 215 | loopWriter.close(); |
|---|
| 216 | |
|---|
| 217 | } catch (FileNotFoundException ex) |
|---|
| 218 | { |
|---|
| 219 | Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex); |
|---|
| 220 | } |
|---|
| 221 | } |
|---|
| 222 | /** Create a dictionary of VehicleDetectionStations */ |
|---|
| 223 | public void createVDSdict() |
|---|
| 224 | { |
|---|
| 225 | vdsDict = new HashMap<String,VehicleDetectionStation>(); |
|---|
| 226 | try |
|---|
| 227 | { |
|---|
| 228 | Scanner vdsScanner = new Scanner(new File(filepath+vdsFileName)); |
|---|
| 229 | |
|---|
| 230 | System.out.println(vdsScanner.nextLine()); // echo col headers |
|---|
| 231 | |
|---|
| 232 | // Read the tab-delimited vds file |
|---|
| 233 | while(vdsScanner.hasNextLine()) |
|---|
| 234 | { |
|---|
| 235 | String line = vdsScanner.nextLine(); |
|---|
| 236 | Scanner lineScanner = new Scanner(line).useDelimiter("\t"); |
|---|
| 237 | VehicleDetectionStation vds = new VehicleDetectionStation(lineScanner); |
|---|
| 238 | // We only want stations that are mainline |
|---|
| 239 | if (vds.type.equals("ML")) |
|---|
| 240 | { |
|---|
| 241 | vdsDict.put(vds.id, vds); |
|---|
| 242 | } |
|---|
| 243 | else |
|---|
| 244 | { |
|---|
| 245 | ignored.add(vds.id); |
|---|
| 246 | } |
|---|
| 247 | lineScanner.close(); |
|---|
| 248 | } |
|---|
| 249 | vdsScanner.close(); |
|---|
| 250 | System.out.println("Ignored "+ignored.size() + " non-Mainline VDS's"); |
|---|
| 251 | |
|---|
| 252 | } catch (FileNotFoundException ex) |
|---|
| 253 | { |
|---|
| 254 | Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex); |
|---|
| 255 | } |
|---|
| 256 | } |
|---|
| 257 | /** Read the lds file to create a dictionary to lookup the FEP line number. |
|---|
| 258 | */ |
|---|
| 259 | public void createLDSdict() |
|---|
| 260 | { |
|---|
| 261 | ldsDict = new HashMap<String,StationAddr> (); |
|---|
| 262 | |
|---|
| 263 | try |
|---|
| 264 | { |
|---|
| 265 | Scanner ldsScanner = new Scanner(new File(filepath+ldsFileName)); |
|---|
| 266 | |
|---|
| 267 | ldsScanner.nextLine(); // Skip the column headers |
|---|
| 268 | |
|---|
| 269 | // Read all the lines in the loop file |
|---|
| 270 | while(ldsScanner.hasNextLine()) |
|---|
| 271 | { |
|---|
| 272 | String line = ldsScanner.nextLine(); |
|---|
| 273 | Scanner lineScanner = new Scanner(line); |
|---|
| 274 | |
|---|
| 275 | String ldsID = lineScanner.next(); |
|---|
| 276 | String line_num = lineScanner.next(); |
|---|
| 277 | String stn_address = lineScanner.next(); |
|---|
| 278 | // Save the fep linenum and station address for this LDS |
|---|
| 279 | StationAddr sa = new StationAddr(line_num,stn_address); |
|---|
| 280 | lineScanner.close(); |
|---|
| 281 | // Add the ldsID to the dict |
|---|
| 282 | ldsDict.put(ldsID, sa); |
|---|
| 283 | } |
|---|
| 284 | ldsScanner.close(); |
|---|
| 285 | } catch (FileNotFoundException ex) |
|---|
| 286 | { |
|---|
| 287 | Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex); |
|---|
| 288 | } |
|---|
| 289 | } |
|---|
| 290 | |
|---|
| 291 | /** |
|---|
| 292 | * @param args the command line arguments |
|---|
| 293 | */ |
|---|
| 294 | public static void main(String[] args) |
|---|
| 295 | { |
|---|
| 296 | BuildHighwayFile app = new BuildHighwayFile(); |
|---|
| 297 | app.createLDSdict(); |
|---|
| 298 | app.createVDSdict(); |
|---|
| 299 | app.createLanelookup(); |
|---|
| 300 | app.createHighwayFile(); |
|---|
| 301 | } |
|---|
| 302 | |
|---|
| 303 | /** A record for a fep line_num and Station Address pair */ |
|---|
| 304 | final class StationAddr |
|---|
| 305 | { |
|---|
| 306 | public final String line_num; |
|---|
| 307 | public final String station_address; |
|---|
| 308 | public StationAddr(String line, String addr) |
|---|
| 309 | { |
|---|
| 310 | this.line_num = line; |
|---|
| 311 | this.station_address = addr; |
|---|
| 312 | } |
|---|
| 313 | } |
|---|
| 314 | } |
|---|
| 315 | |
|---|