docs: def _estimate_progress(self):
          """
          estimates the current progress that is then used in _receive_signal
  
          :return: current progress in percent
          """
          estimate = True
          # ==== get the current subscript and the time it takes to execute it =====
          current_subscript = self._current_subscript_stage['current_subscript']
  
          # ==== get the number of subscripts =====
          num_subscripts = len(self.scripts)
  
          # ==== get number of iterations and loop index ======================
          if self.iterator_type == 'loop':
              num_iterations = self.settings['num_loops']
          elif self.iterator_type == 'sweep':
              sweep_range = self.settings['sweep_range']
              if self.settings['stepping_mode'] == 'value_step':
                  num_iterations = int((sweep_range['max_value'] - sweep_range['min_value']) / sweep_range['N/value_step']) + 1
                  # len(np.linspace(sweep_range['min_value'], sweep_range['max_value'],
                  #                                        (sweep_range['max_value'] - sweep_range['min_value']) /
                  #                                        sweep_range['N/value_step'] + 1, endpoint=True).tolist())
              elif self.settings['stepping_mode'] == 'N':
                  num_iterations = sweep_range['N/value_step']
              else:
                  raise KeyError('unknown key' + self.settings['stepping_mode'])
  
          else:
              print('unknown iterator type in Iterator receive signal - can\'t estimate ramining time')
              estimate = False
  
  
          if estimate:
              # get number of loops (completed + 1)
              loop_index = self.loop_index
  
  
              if num_subscripts > 1:
                  # estimate the progress based on the duration the individual subscripts
  
                  loop_execution_time = 0.  # time for a single loop execution in s
                  sub_progress_time = 0.  # progress of current loop iteration in s
  
                  # ==== get typical duration of current subscript ======================
                  if current_subscript is not None:
                      current_subscript_exec_duration = self._current_subscript_stage['subscript_exec_duration'][
                          current_subscript.name].total_seconds()
                  else:
                      current_subscript_exec_duration = 0.0
  
  
                  current_subscript_elapsed_time = (datetime.datetime.now() - current_subscript.start_time).total_seconds()
                  # estimate the duration of the current subscript if the script hasn't been executed once fully and subscript_exec_duration is 0
                  if current_subscript_exec_duration == 0.0:
                      remaining_time = current_subscript.remaining_time.total_seconds()
                      current_subscript_exec_duration = remaining_time + current_subscript_elapsed_time
  
                  # ==== get typical duration of one loop iteration ======================
                  remaining_scripts = 0  # script that remain to be executed for the first time
                  for subscript_name, duration in self._current_subscript_stage['subscript_exec_duration'].items():
                      if duration.total_seconds() == 0.0:
                          remaining_scripts += 1
                      loop_execution_time += duration.total_seconds()
                      # add the times of the subscripts that have been executed in the current loop
                      # ignore the current subscript, because that will be taken care of later
                      if self._current_subscript_stage['subscript_exec_count'][subscript_name] == loop_index \
                              and subscript_name is not current_subscript.name:
                          # this subscript has already been executed in this iteration
                          sub_progress_time += duration.total_seconds()
  
                  # add the proportional duration of the current subscript given by the subscript progress
                  sub_progress_time += current_subscript_elapsed_time
  
                  # if there are scripts that have not been executed yet
                  # assume that all the scripts that have not been executed yet take as long as the average of the other scripts
                  if remaining_scripts == num_subscripts:
                      # none of the subscript has been finished. assume that all the scripts take as long as the first
                      loop_execution_time = num_subscripts * current_subscript_exec_duration
                  elif remaining_scripts > 1:
                      loop_execution_time = 1. * num_subscripts / (num_subscripts - remaining_scripts)
                  elif remaining_scripts == 1:
                      # there is only one script left which is the current script
                      loop_execution_time += current_subscript_exec_duration
  
                  if loop_execution_time > 0:
                      progress_subscript = 100. * sub_progress_time / loop_execution_time
                  else:
                      progress_subscript = 1. * progress_subscript / num_subscripts
  
              # print(' === script iterator progress estimation loop_index = {:d}/{:d}, progress_subscript = {:f}'.format(loop_index, number_of_iterations, progress_subscript))
              progress = 100. * (loop_index - 1. + 0.01 * progress_subscript) / num_iterations
  
          else:
              # if can't estimate the remaining time set to half
              progress = 50
          return progress