code: def test_rotate_angle():
      """Rotate an image through an angle"""
      #
      # Draw a rectangle with intensity that varies monotonically according
      # to angle.
      #
      i, j = numpy.mgrid[-5:6, -9:10]
      angle = numpy.arctan2(
          i.astype(float) / 5.0, j.astype(float) / 9.0
      )
      img = (1 + numpy.cos(angle)) / 2
      assert round(abs(img[5, 0] - 0), 7) == 0
      assert round(abs(img[5, 18] - 1), 7) == 0
      assert round(abs(img[0, 9] - 0.5), 7) == 0
      assert round(abs(img[10, 9] - 0.5), 7) == 0
      #
      # The pixels with low values get masked out
      #
      mask = img > 0.5
      #
      # Rotate the rectangle from 10 to 350
      #
      for angle in range(10, 360, 10):
  
          def fn(module, angle=angle):
              assert isinstance(
                  module,
                  cellprofiler.modules.flipandrotate.FlipAndRotate,
              )
              module.flip_choice.value = (
                  cellprofiler.modules.flipandrotate.FLIP_NONE
              )
              module.rotate_choice.value = (
                  cellprofiler.modules.flipandrotate.ROTATE_ANGLE
              )
              module.wants_crop.value = False
              module.angle.value = angle
  
          output_image, measured_angle = run_module(img, mask, fn)
          assert round(abs(measured_angle - angle), 3) == 0
          rangle = float(angle) * numpy.pi / 180.0
          pixel_data = output_image.pixel_data
          #
          # Check that the output contains the four corners of the original
          #
          corners_in = numpy.array(
              [[-5, -9], [-5, 9], [5, -9], [5, 9]], float
          )
          corners_out_i = numpy.sum(
              corners_in
              * numpy.array([numpy.cos(rangle), -numpy.sin(rangle)]),
              1,
          )
          corners_out_j = numpy.sum(
              corners_in
              * numpy.array([numpy.sin(rangle), numpy.cos(rangle)]),
              1,
          )
          i_width = numpy.max(corners_out_i) - numpy.min(corners_out_i)
          j_width = numpy.max(corners_out_j) - numpy.min(corners_out_j)
          assert i_width < pixel_data.shape[0]
          assert i_width > pixel_data.shape[0] - 2
          assert j_width < pixel_data.shape[1]
          assert j_width > pixel_data.shape[1] - 2
          # The maximum rotates clockwise - i starts at center and increases
          # and j starts at max and decreases
          #
          i_max = min(
              pixel_data.shape[0] - 1,
              max(
                  0,
                  int(
                      -numpy.sin(rangle) * 8
                      + float(pixel_data.shape[0]) / 2
                  ),
              ),
          )
          j_max = min(
              pixel_data.shape[1] - 1,
              max(
                  0,
                  int(
                      numpy.cos(rangle) * 8
                      + float(pixel_data.shape[1] / 2)
                  ),
              ),
          )
          assert pixel_data[i_max, j_max] > 0.9
          assert output_image.mask[i_max, j_max]
          i_min = min(
              pixel_data.shape[0] - 1,
              max(
                  0,
                  int(
                      numpy.sin(rangle) * 8
                      + float(pixel_data.shape[0]) / 2
                  ),
              ),
          )
          j_min = min(
              pixel_data.shape[1] - 1,
              max(
                  0,
                  int(
                      -numpy.cos(rangle) * 8
                      + float(pixel_data.shape[1]) / 2
                  ),
              ),
          )
          assert pixel_data[i_min, j_min] < 0.1
          assert not output_image.mask[i_min, j_min]
          #
          # The corners of the image should be masked except for angle
          # in 90,180,270
          #
          if angle not in (90, 180, 270):
              for ci, cj in ((0, 0), (-1, 0), (-1, -1), (0, -1)):
                  assert not output_image.mask[ci, cj]
  
file_path: CellProfiler/tests/frontend/modules/test_flipandrotate.py
imports: import centrosome.cpmorphology
  import numpy
  import cellprofiler_core.image
  import cellprofiler_core.measurement
  from cellprofiler_core.constants.measurement import COLTYPE_FLOAT
  import cellprofiler.modules.flipandrotate
  import cellprofiler_core.object
  import cellprofiler_core.pipeline
  import cellprofiler_core.workspace
label_desc: Use image node_id 5 for calling a global function with example usage: test_rotate_angle() without return types