Stereocenters.prototype.buildFromBonds = function()

in packages/ketcher-core/src/domain/serializers/smi/stereocenters.js [30:150]


Stereocenters.prototype.buildFromBonds = function (
  /* const int *atom_types, const int *atom_groups, const int *bond_orientations, */ ignoreErrors,
) {
  const atoms = this.molecule.atoms;
  const bonds = this.molecule.bonds;

  /*
		this is a set of atoms that are likely to belong to allene structures and
		therefore should not be considered as potential stereocenters in the code below,
		as allenes cannot be encoded in the SMILES notation
	*/

  const alleneMask = new Pile();
  atoms.forEach((atom, aid) => {
    const neiList = this.getNeighbors.call(this.context, aid);
    if (neiList.length !== 2) return false;
    const nei1 = neiList[0];
    const nei2 = neiList[1];
    // check atom labels
    if (
      [aid, nei1.aid, nei2.aid].findIndex(
        (aid) => ['C', 'Si'].indexOf(atoms.get(aid).label) < 0,
        this,
      ) >= 0
    ) {
      return false;
    }

    // check adjacent bond types
    if (
      [nei1.bid, nei2.bid].findIndex(
        (bid) => bonds.get(bid).type !== Bond.PATTERN.TYPE.DOUBLE,
        this,
      ) >= 0
    ) {
      return false;
    }

    // get the other neighbors of the two adjacent atoms except for the central atom
    const nei1nei = this.getNeighbors
      .call(this.context, nei1.aid)
      .filter((nei) => nei.aid !== aid);
    const nei2nei = this.getNeighbors
      .call(this.context, nei2.aid)
      .filter((nei) => nei.aid !== aid);
    if (
      nei1nei.length < 1 ||
      nei1nei.length > 2 ||
      nei2nei.length < 1 ||
      nei2nei.length > 2
    ) {
      return false;
    }

    if (
      nei1nei
        .concat(nei2nei)
        .findIndex(
          (nei) => bonds.get(nei.bid).type !== Bond.PATTERN.TYPE.SINGLE,
          this,
        ) >= 0
    ) {
      return false;
    }

    if (
      nei1nei
        .concat(nei2nei)
        .findIndex(
          (nei) => bonds.get(nei.bid).stereo === Bond.PATTERN.STEREO.EITHER,
          this,
        ) >= 0
    ) {
      return false;
    }
    alleneMask.add(nei1.aid).add(nei2.aid);
    return true;
  });

  if (alleneMask.size > 0) {
    // TODO: add error handler call
    // legacy message: This structure may contain allenes, which cannot be represented in the SMILES notation. Relevant stereo-information will be discarded.

    atoms.forEach((atom, aid) => {
      if (alleneMask.has(aid)) return;
      /*
      if (atom_types[atom_idx] == 0)
         continue;
         */
      const neiList = this.getNeighbors.call(this.context, aid);
      let stereocenter = false;

      neiList.find(function (nei) {
        const bond = this.molecule.bonds.get(nei.bid);

        if (bond.type === Bond.PATTERN.TYPE.SINGLE && bond.begin === aid) {
          if (
            bond.stereo === Bond.PATTERN.STEREO.UP ||
            bond.stereo === Bond.PATTERN.STEREO.DOWN
          ) {
            stereocenter = true;
            return true;
          }
        }
        return false;
      }, this);

      if (!stereocenter) return;

      if (ignoreErrors) {
        this.buildOneCenter(
          aid /* , atom_groups[atom_idx], atom_types[atom_idx], bond_orientations */,
        );
      } else {
        this.buildOneCenter(
          aid /* , atom_groups[atom_idx], atom_types[atom_idx], bond_orientations */,
        );
      }
    });
  }
};