code: def cooling(matrix, points, temperature, params):
      dt = temperature / float(params.iterations + 1)
      displacement = np.zeros((params.dim, len(points)))
      for iteration in range(params.iterations):
          displacement *= 0
          for i in range(matrix.shape[0]):
              # difference between this row's node position and all others
              delta = (points[i] - points).T
  
              # distance between points
              distance = np.sqrt((delta**2).sum(axis=0))
  
              # enforce minimum distance of 0.01
              distance = np.where(distance < 0.01, 0.01, distance)
  
              # the adjacency matrix row
              ai = matrix[i].toarray()
  
              # displacement "force"
              dist = params.k * params.k / distance**2
  
              if params.nohubs:
                  dist = dist / float(ai.sum(axis=1) + 1)
              if params.linlog:
                  dist = np.log(dist + 1)
              displacement[:, i] += (
                  delta * (dist - ai * distance / params.k)
              ).sum(axis=1)
  
          # update points
          length = np.sqrt((displacement**2).sum(axis=0))
          length = np.where(length < 0.01, 0.01, length)
          points += (displacement * temperature / length).T
  
          # cool temperature
          temperature -= dt
  
file_path: datashader/datashader/layout.py
imports: from __future__ import annotations
  import numpy
  import param
  import scipy.sparse
label_desc: Use image node_id 4 for calling a global function with example usage: cooling(matrix, points, temperature, params) without return types