code: def dicom_web_download_series(
      study_id,
      series_id,
      save_dir,
      client: DICOMwebClient,
      frame_fetch=False,
  ):
      start = time.time()
  
      # Limitation for DICOMWeb Client as it needs StudyInstanceUID to fetch series
      if not study_id:
          meta = Dataset.from_json(
              [
                  series
                  for series in client.search_for_series(
                      search_filters={"SeriesInstanceUID": series_id}
                  )
                  if series["0020000E"]["Value"] == [series_id]
              ][0]
          )
          study_id = str(meta["StudyInstanceUID"].value)
  
      os.makedirs(save_dir, exist_ok=True)
      if not frame_fetch:
          instances = client.retrieve_series(study_id, series_id)
          for instance in instances:
              instance_id = str(instance["SOPInstanceUID"].value)
              file_name = os.path.join(save_dir, f"{instance_id}.dcm")
              instance.save_as(file_name)
      else:
          # TODO:: This logic (combining meta+pixeldata) needs improvement
          def save_from_frame(m):
              d = Dataset.from_json(m)
              instance_id = str(d["SOPInstanceUID"].value)
  
              # Hack to merge Info + RawData
              d.is_little_endian = True
              d.is_implicit_VR = True
              d.PixelData = client.retrieve_instance_frames(
                  study_instance_uid=study_id,
                  series_instance_uid=series_id,
                  sop_instance_uid=instance_id,
                  frame_numbers=[1],
              )[0]
  
              file_name = os.path.join(save_dir, f"{instance_id}.dcm")
              logger.info(f"++ Saved {os.path.basename(file_name)}")
              d.save_as(file_name)
  
          meta_list = client.retrieve_series_metadata(
              study_id, series_id
          )
          logger.info(f"++ Saving DCM into: {save_dir}")
          with ThreadPoolExecutor(
              max_workers=2, thread_name_prefix="DICOMFetch"
          ) as executor:
              executor.map(save_from_frame, meta_list)
  
      logger.info(f"Time to download: {time.time() - start} (sec)")
  
file_path: MONAILabel/monailabel/datastore/utils/dicom.py
imports: import logging
  import os
  import time
  from concurrent.futures import ThreadPoolExecutor
  from dicomweb_client import DICOMwebClient
  from pydicom.dataset import Dataset
  from pydicom.filereader import dcmread
  from monailabel.utils.others.generic import md5_digest, run_command
label_desc: Use image node_id 4 for calling a global function with example usage: dicom_web_download_series(study_id, series_id, save_dir, client, frame_fetch) without return types