protected boolean appliesTo(List<IStoreItem> selection) {
    // ok, check we have two collections
    boolean allGroups = aTests.numberOfGroups(selection, 2);
    boolean allTracks = aTests.numberOfTracks(selection, 2);
    boolean someHaveFreq = aTests.someHave(selection, Frequency.UNIT.getDimension(), true) != null;
    boolean topLevelSpeed =
        aTests.someHave(selection, METRE.divide(SECOND).getDimension(), true) != null;

    return (aTests.exactNumber(selection, 3)
        && allGroups
        && allTracks
        && someHaveFreq
        && topLevelSpeed);
  }
    public void organiseData() {
      // ok, we need to collate the data
      data = new HashMap<String, ICollection>();

      final CollectionComplianceTests tests = new CollectionComplianceTests();

      // ok, transmitter data
      data.put(TX + "FREQ", tests.someHave(_tx, Frequency.UNIT.getDimension(), true));
      data.put(TX + "COURSE", tests.someHave(_tx, SI.RADIAN.getDimension(), true));
      data.put(TX + "SPEED", tests.someHave(_tx, METRE.divide(SECOND).getDimension(), true));
      data.put(TX + "LOC", tests.someHaveLocation(_tx));

      // and the receiver
      data.put(RX + "COURSE", tests.someHave(_rx, SI.RADIAN.getDimension(), true));
      data.put(RX + "SPEED", tests.someHave(_rx, METRE.divide(SECOND).getDimension(), true));
      data.put(RX + "LOC", tests.someHaveLocation(_rx));

      // and the sound speed
      data.put(
          "SOUND_SPEED", tests.someHave(getInputs(), METRE.divide(SECOND).getDimension(), false));
    }