/** Groups packets into Burst Collections */
  private void groupIntoBursts() {
    // Validate that there are packets
    List<PacketInfo> packets = this.analysis.getPackets();
    if (packets.size() <= 0) {
      this.burstCollection = Collections.emptyList();
      return;
    }
    ArrayList<Burst> result = new ArrayList<Burst>();
    double burstThresh = profile.getBurstTh();
    double longBurstThresh = profile.getLongBurstTh();
    List<PacketInfo> burstPackets = new ArrayList<PacketInfo>();
    // Step 1: Build bursts using burst time threshold
    PacketInfo lastPacket = null;
    for (PacketInfo packet : packets) {
      if (lastPacket == null
          || (packet.getTimeStamp() - lastPacket.getTimeStamp() > burstThresh
              && !mss.contains(lastPacket.getPayloadLen()))) {
        if (burstPackets.size() > 0) {
          result.add(new Burst(burstPackets));
          burstPackets.clear();
        }
      }
      burstPackets.add(packet);
      lastPacket = packet;
    }
    result.add(new Burst(burstPackets));

    // Step 2: Remove promotion delays and merge bursts if possible
    Map<PacketInfo, Double> timestampList = normalizeCore(packets);
    List<Burst> newBurstColl = new ArrayList<Burst>(result.size());
    int n = result.size();
    Burst newBurst = result.get(0);
    for (int i = 0; i < n - 1; i++) {
      Burst bnext = result.get(i + 1);
      double time1 = timestampList.get(newBurst.getEndPacket());
      double time2 = timestampList.get(bnext.getBeginPacket());
      if ((time2 - time1) < burstThresh) {
        newBurst.merge(bnext);
      } else {
        newBurstColl.add(newBurst);
        newBurst = bnext;
      }
    }
    newBurstColl.add(newBurst);
    this.burstCollection = newBurstColl;

    // Step 3: compute burstID for each packet
    n = burstCollection.size();
    for (Burst b : burstCollection) {
      for (PacketInfo p : b.getPackets()) {
        p.setBurst(b);
      }
    }

    // Step 4: determine short/long IBTs
    n = burstCollection.size();
    for (int i = 0; i < n; i++) {
      Burst b = burstCollection.get(i);
      assert (b.getEndTime() >= b.getBeginTime());
      if (i < n - 1) {
        double ibt = burstCollection.get(i + 1).getBeginTime() - b.getEndTime();
        assert (ibt >= burstThresh);
        b.setbLong((ibt > longBurstThresh));
      } else {
        b.setbLong(true);
      }
    }
  }