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