docs: def calc2dcoords(mol):
      """ Calculate optimal 2D coordinates of chemical structure
      """
      topology.recognize(mol)
      g = set(i for i, _ in mol.atoms_iter())
      # 1: get nodes in scaffolds
      scaffolds = []
      belongs = {}
      for i, rkeys in enumerate(sorted(mol.scaffolds, key=len)):
          scf = []
          for rkey in rkeys:
              ring = mol.rings[rkey]
              for r in ring:
                  belongs[r] = i
              scf.append(ring)
              g -= set(ring)
          scaffolds.append(scf)
      # 2: traverse nodes and scaffolds
      # the node and scaffold graph should be a tree (no cycles)
      f = True
      # print(scaffolds)
      coords = {}
      while g:
          if f and scaffolds:  # largest scaffold is first
              stack = [scaffolds[-1][0][0]]
              f = False
          else:
              stack = [g.pop()]
          pred = {}
          branch = {}
          while stack:
              # print("stack: {}".format(stack))
              tail = stack.pop()
              # print("tail: {}".format(tail))
              if tail in belongs:  # scaffolds
                  scf = scaffold_coords(scaffolds[belongs[tail]])
                  # print(scf.keys())
                  # rotate and translate
                  if not coords:
                      coords = scf
                  else:
                      u = coords[pred[tail]]
                      v = scf[tail]
                      op = [u[0] + math.cos(u[2]), u[1] + math.sin(u[2])]
                      translate(scf, gm.vector(v[:2], op))
                      rotate(scf, op, gm.rad(u[2] + math.pi - v[2]))
                      coords.update(scf)
                  # stack nbrs of scaffold
                  for k in scf.keys():
                      pred[k] = None
                      for nbr in mol.neighbors(k):
                          if nbr not in scf.keys():
                              stack.append(nbr)
                              pred[nbr] = k
              else:  # append linker
                  if tail not in pred:  # isolated
                      coords[tail] = [0, 0, 0, 1]
                      continue
                  p = pred[tail]
                  x, y, ang, d = coords[p]
                  # TODO: ring configuration
                  coords[tail] = [x + math.cos(ang), y + math.sin(ang),
                                  ang + d * math.pi / 3, d * -1]
                  if p not in branch:
                      coords[p][2] = gm.rad(coords[p][2] + math.pi * 2 / 3 * d)
                      branch[p] = 1
                  elif branch[p] == 1:
                      coords[p][2] = gm.rad(coords[p][2] + math.pi * d)
                      branch[p] += 1
                  elif branch[p] == 2:
                      coords[p][2] = gm.rad(coords[p][2] + math.pi * 2 / 3 * d)
                      branch[p] += 1
                  for nbr in mol.neighbors(tail):
                      if nbr not in pred:
                          stack.append(nbr)
                          pred[nbr] = tail
          g -= set(pred)
      resolve_overlap(coords)
      for i, a in mol.atoms_iter():
          mol.atom(i).coords = coords[i][:2]