code: def on_train_batch_end(
      self,
      trainer: Trainer,
      pl_module: LightningModule,
      outputs: List,
      batch: SampleList,
      batch_idx: int,
      dataloader_idx: int,
  ):
      # prepare the next batch
      self.lightning_trainer.data_module.train_loader.change_dataloader()
  
      # aggregate train combined_report
      self.train_combined_report = self._update_and_create_report(
          SampleList(batch),
          batch_idx,
          outputs,
          pl_module,
          self.train_combined_report,
      )
  
      # Continue if an update has not finished
      if (batch_idx + 1) % self.trainer_config.accumulate_grad_batches:
          return
  
      # log
      if (
          self._get_num_updates_for_logging(trainer)
          % self.trainer_config.log_every_n_steps
          == 0
      ):
          self._train_log(trainer, pl_module)
  
imports: import logging
  from typing import Any, Dict, List
  import torch
  from mmf.common.meter import Meter
  from mmf.common.registry import registry
  from mmf.common.report import Report
  from mmf.common.sample import SampleList
  from mmf.utils.logger import calculate_time_left, summarize_report
  from mmf.utils.timer import Timer
  from pytorch_lightning import LightningModule, Trainer
  from pytorch_lightning.callbacks.base import Callback
label_desc: Use image node_id 3 for calling the LightningLoopCallback obj's underlying member method code with example usage: obj.on_train_batch_end(trainer, pl_module, outputs, batch, batch_idx, dataloader_idx) without return types