code: def test_query_images_api_custom_densities_sparse(self):
      client = self.client
  
      query = self.isolated_query_patch()
      response = client.get(
          "/api/runs/search/images/",
          params={
              "q": query,
              "record_density": 10,
              "index_density": 4,
              "report_progress": False,
          },
      )
      self.assertEqual(200, response.status_code)
  
      decoded_response = decode_tree(
          decode_encoded_tree_stream(
              response.iter_bytes(chunk_size=512 * 1024)
          )
      )
      self.assertEqual(1, len(decoded_response))
      run_data = decoded_response[self.run_hash]
      trace_data = run_data["traces"][0]
      self.assertEqual(11, len(trace_data["values"]))
      self.assertEqual(11, len(trace_data["iters"]))
      self.assertEqual(4, len(trace_data["values"][0]))
      self.assertEqual(4, len(trace_data["values"][9]))
      image_indices = [img["index"] for img in trace_data["values"][0]]
      self.assertListEqual([0, 4, 8, 12], image_indices)
      image_names = [img["caption"] for img in trace_data["values"][9]]
      self.assertListEqual(
          ["Image 90 0", "Image 90 4", "Image 90 8", "Image 90 12"],
          image_names,
      )
  
imports: from parameterized import parameterized
  import random
  from tests.base import ApiTestBase
  from tests.utils import decode_encoded_tree_stream, generate_image_set
  from aim.storage.treeutils import decode_tree
  from aim.storage.context import Context
  from aim.sdk.run import Run
label_desc: Use image node_id 3 for calling the TestRunImagesSearchApi obj's underlying member method code with example usage: obj.test_query_images_api_custom_densities_sparse() without return types