/**
   * Note: if you change this unit test, also change the cook book:
   * http://www.biojava.org/wiki/BioJava:CookBook3:SupportedProtMod
   */
  public void testGetBy() {
    ProteinModification mod;
    Set<ProteinModification> mods;

    mod = ProteinModificationRegistry.getById("0001");
    assertNotNull(mod);

    // a set of protein modifications by RESID ID
    mods = ProteinModificationRegistry.getByResidId("AA0151");
    assertNotNull(mods);

    // a set of protein modifications by PSI-MOD ID
    mods = ProteinModificationRegistry.getByPsimodId("MOD:00305");
    assertNotNull(mods);

    // a set of protein modifications by PDBCC ID
    mods = ProteinModificationRegistry.getByPdbccId("SEP");
    assertNotNull(mods);

    // a set of protein modifications by category
    mods = ProteinModificationRegistry.getByCategory(ModificationCategory.ATTACHMENT);
    assertNotNull(mods);

    // a set of protein modifications by occurrence type
    mods = ProteinModificationRegistry.getByOccurrenceType(ModificationOccurrenceType.NATURAL);
    assertNotNull(mods);

    // a set of protein modifications by a keyword
    mods = ProteinModificationRegistry.getByKeyword("phosphoprotein");
    assertNotNull(mods);

    // a set of protein modifications by involved components.
    mods = ProteinModificationRegistry.getByComponent(Component.of("FAD"));
    assertNotNull(mods);
  }
  /**
   * Test the initialization registry of common protein modifications. Note: if you change this unit
   * test, also change the cook book: http://www.biojava.org/wiki/BioJava:CookBook3:SupportedProtMod
   */
  public void testRegisterCommonModification() {
    Set<ProteinModification> mods = ProteinModificationRegistry.allModifications();
    assertTrue(mods != null && !mods.isEmpty());

    //		logger.info("There are totally "+mods.size()
    //				+" protein modifications registered.");
    //
    //		printModifications(mods);
  }
  /**
   * Note: if you change this unit test, also change the cook book:
   * http://www.biojava.org/wiki/BioJava:CookBook3:AddProtMod
   */
  public void testRegisterModification() {
    // define the involved components, in this case two cystines (CYS)
    List<Component> components = new ArrayList<Component>(2);
    components.add(Component.of("CYS"));
    components.add(Component.of("CYS"));

    // define the atom linkages between the components, in this case the SG atoms on both CYS groups
    ModificationLinkage linkage = new ModificationLinkage(components, 0, "SG", 1, "SG");

    // define the modification condition, i.e. what components are involved and what atoms are
    // linked between them
    ModificationCondition condition =
        new ModificationConditionImpl(components, Collections.singletonList(linkage));

    // build a modification
    ProteinModification mod =
        new ProteinModificationImpl.Builder(
                "0018_test",
                ModificationCategory.CROSS_LINK_2,
                ModificationOccurrenceType.NATURAL,
                condition)
            .setDescription(
                "A protein modification that effectively cross-links two L-cysteine residues to form L-cystine.")
            .setFormula("C 6 H 8 N 2 O 2 S 2")
            .setResidId("AA0025")
            .setResidName("L-cystine")
            .setPsimodId("MOD:00034")
            .setPsimodName("L-cystine (cross-link)")
            .setSystematicName("(R,R)-3,3'-disulfane-1,2-diylbis(2-aminopropanoic acid)")
            .addKeyword("disulfide bond")
            .addKeyword("redox-active center")
            .build();

    // register the modification
    ProteinModificationRegistry.register(mod);
    assertNotNull(ProteinModificationRegistry.getById("0018_test"));
  }
  /** Merge identified modified compounds if linked. */
  private void mergeModComps(List<ModifiedCompound> modComps) {
    TreeSet<Integer> remove = new TreeSet<Integer>();
    int n = modComps.size();
    for (int icurr = 1; icurr < n; icurr++) {
      ModifiedCompound curr = modComps.get(icurr);

      String id = curr.getModification().getId();
      if (ProteinModificationRegistry.getById(id).getCategory() != ModificationCategory.UNDEFINED)
        continue;

      // find linked compounds that before curr
      // List<Integer> merging = new ArrayList<Integer>();
      int ipre = 0;
      for (; ipre < icurr; ipre++) {
        if (remove.contains(ipre)) continue;
        ModifiedCompound pre = modComps.get(ipre);
        if (!Collections.disjoint(pre.getGroups(false), curr.getGroups(false))) {
          break;
        }
      }

      if (ipre < icurr) {
        ModifiedCompound mcKeep = modComps.get(ipre);

        // merge modifications of the same type
        if (mcKeep.getModification().getId().equals(id)) {
          // merging the current one to the previous one
          mcKeep.addAtomLinkages(curr.getAtomLinkages());
          remove.add(icurr);
        }
      }
    }

    Iterator<Integer> it = remove.descendingIterator();
    while (it.hasNext()) {
      modComps.remove(it.next().intValue());
    }
  }
 /**
  * Identify all registered modifications in chains.
  *
  * @param chains query {@link Chain}s.
  */
 public void identify(final List<Chain> chains) {
   identify(chains, ProteinModificationRegistry.allModifications());
 }
 /**
  * Identify all registered modifications in a structure.
  *
  * @param structure
  */
 public void identify(final Structure structure) {
   identify(structure, ProteinModificationRegistry.allModifications());
 }