In the below code, please debug the error that, the log file is not created and no data were stored in the log file, I also need to clarify that i am using another log file in the subprogram snippet which is running during call function present in the below code(train part of the main code) where the log information were properly stored in that execution command in the subprogram snippet, but with in the main program train loop it doesnot working why? whether we need to use only one log file to store information either one of the code(either in sub program or at main program)
And Also i am having the following errors,
with in the directory 'OPAMP_GNNRL_log_file', the csv files 'rewards_log.csv' and 'losses_log.csv' were properly created and the required data were stored after the each episode loop finish, 
if we use 'with open('training_output/rewards.csv', 'w', newline='') as rewards_file, open('training_output/losses.csv', 'w', newline='') as losses_file, open(‘training_output/metrics.csv’, ‘w’, newline=‘’) as metrics_file:', instead of 
rewards_file = open('training_output/rewards.csv', 'w', newline='')
losses_file = open('training_output/losses.csv', 'w', newline='')
metrics_file = open('training_output/metrics.csv', 'w', newline='')
with proper indent correction, then the first episode data only were stored in the 'rewards_log.csv' and 'losses_log.csv' csv files remaining episodes data were not stored so i changed the opening file with out using 'with'.
one more error, with in the directory 'training_output', the csv files 'rewards.csv', 'losses.csv', and 'metrics.csv' were created but no data were stored as expected after finish each episodes. please debug the above said errors and update the program,

 

import pandas as pd
import logging
import os
import csv

# Basic configuration for logging
logging.basicConfig(filename='D:\\OPAMP CIRCUITS\\RL_GNN\\agent_training.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class PPOAgent:
    def __init__(self, gnn_model, state_dim, action_space, lr_actor, lr_critic, gamma, gae_lambda, epsilon, policy_clip, epochs, entropy_coef):
        self.gamma = gamma
        self.gae_lambda = gae_lambda
        self.epsilon = epsilon
        self.policy_clip = policy_clip
        self.epochs = epochs
        self.entropy_coef = entropy_coef  # Dynamic entropy coefficient
        
        self.actor = Actor(gnn_model)
        self.critic = Critic()
        self.optimizer_actor = optim.Adam(self.actor.parameters(), lr=lr_actor)
        self.optimizer_critic = optim.Adam(self.critic.parameters(), lr=lr_critic)
        self.action_space = action_space  # Assume continuous
        
        self.log_dir = 'OPAMP_GNNRL_log_file'
        os.makedirs(self.log_dir, exist_ok=True)

def train(env, agent, num_episodes, max_timesteps, batch_size):
    
    # CSV setup: Ensure the output directory exists.
    os.makedirs('training_output', exist_ok=True)
    
    # Opening CSV files for writing.
    #with open('training_output/rewards.csv', 'w', newline='') as rewards_file, open('training_output/losses.csv', 'w', newline='') as losses_file, open('training_output/metrics.csv', 'w', newline='') as metrics_file:    
    rewards_file = open('training_output/rewards.csv', 'w', newline='')
    losses_file = open('training_output/losses.csv', 'w', newline='')
    metrics_file = open('training_output/metrics.csv', 'w', newline='')
    # Creating CSV writers.
    rewards_writer = csv.writer(rewards_file)
    losses_writer = csv.writer(losses_file)
    metrics_writer = csv.writer(metrics_file)
    
    # Writing headers.
    rewards_writer.writerow(['Episode', 'Immediate Reward', 'Cumulative Reward'])
    losses_writer.writerow(['Episode', 'Actor Loss', 'Critic Loss'])
    headers = ['Episode', 'Actor Loss', 'Critic Loss', 'Area', 'PowerDissipation', 'SlewRate', 
                'Gain', 'Bandwidth3dB', 'UnityGainFreq', 'PhaseMargin', 'Mean Episode Reward', 'Deployment Accuracy']
    metrics_writer.writerow(headers)
        
        
    rewards_log = []
    losses_log = []
    episode_lengths = []
        
    for episode in range(num_episodes):        
        node_features_tensor, edge_feature_tensor, edge_index, performance_metrics = env.reset()
        state = (node_features_tensor, edge_feature_tensor, edge_index)
    
        episode_rewards = []
        states = []
        actions = []
        log_probs = []
        values = []
        masks = []
        perf_metrics_log = []
    
        for t in range(max_timesteps):
            # Selecting action based on the current state
            action, log_prob, perf_metrics = agent.select_action(state, performance_metrics)
            next_node_features_tensor, next_edge_feature_tensor, next_edge_index, reward, done, previous_metrics = env.step(action, perf_metrics)
            next_state = (next_node_features_tensor, next_edge_feature_tensor, next_edge_index)
    
            episode_rewards.append(reward)
            states.append(state)
            actions.append(action)
            log_probs.append(log_prob.item())
            values.append(agent.critic(state[0]).item())  # Ensure Critic can handle state format
            masks.append(1.0 - float(done))
            perf_metrics_log.append(perf_metrics)
                
            performance_metrics = previous_metrics
            state = next_state
    
            if done:
                break
    
        next_value = agent.critic(state[0]).item() if not done else 0        
        returns = agent.compute_gae(next_value, episode_rewards, masks, values)
    
        # Correcting format for updating the policy
        advantages = (torch.tensor(returns) - torch.tensor(values)).detach().numpy()
        returns = torch.tensor(returns).detach().numpy()
        # Update the policy with collected data
        average_loss_actor, average_loss_critic = agent.update_policy(states, actions, log_probs, returns, advantages)                        
            
        episode_length = len(episode_rewards)
        total_reward = sum(episode_rewards)
            
        # Compute mean episode reward and deployment accuracy (example placeholders)
        mean_episode_reward = total_reward / episode_length
        deployment_accuracy = calculate_accuracy(perf_metrics_log) 
            
        # Log episode information            
        print(f'Episode {episode + 1}/{num_episodes}, Total Reward: {total_reward}')
             
        # Logging
        logging.info(f"Episode {episode + 1} - Reward: {total_reward}, Length: {episode_length}, Actor Loss: {average_loss_actor}, Critic Loss: {average_loss_critic}")
        logging.info(f"Episode {episode + 1} - Mean Episode Reward: {mean_episode_reward}, Deployment Accuracy: {deployment_accuracy}")
   
        # Writing to CSV files
        rewards_writer.writerow([episode + 1, total_reward, total_reward])  # Assuming total_reward represents the cumulative reward
        losses_writer.writerow([episode + 1, average_loss_actor, average_loss_critic])             
            
        # Writing performance metrics to CSV, alongside mean episode reward and deployment accuracy
        metrics_row = [episode + 1, average_loss_actor, average_loss_critic] + [performance_metrics[metric] for metric in ['Area', 'PowerDissipation', 'SlewRate', 'Gain', 'Bandwidth3dB', 'UnityGainFreq', 'PhaseMargin']] + [mean_episode_reward, deployment_accuracy]
        metrics_writer.writerow(metrics_row)
            
        # Append to logs for pandas DataFrame
        rewards_log.append({'episode': episode + 1, 'total_reward': total_reward})
        losses_log.append({'episode': episode + 1, 'actor_loss': average_loss_actor, 'critic_loss': average_loss_critic})
            
        episode_lengths.append(episode_length)
             
        # Save model checkpoints and pandas data frame logging every n episodes
        agent.save_checkpoint(episode) 
        if episode % 5 == 0 or episode == num_episodes - 1:
            # Calls to ‘pd.DataFrame.to_csv’ replaced with conditional checkpoint inside loop
            pd.DataFrame(rewards_log).to_csv(os.path.join(agent.log_dir, 'rewards_log.csv'), index=False)
            pd.DataFrame(losses_log).to_csv(os.path.join(agent.log_dir, 'losses_log.csv'), index=False)     
                
    # Final save for logs
    pd.DataFrame(rewards_log).to_csv(os.path.join(agent.log_dir, 'final_rewards_log.csv'), index=False)
    pd.DataFrame(losses_log).to_csv(os.path.join(agent.log_dir, 'final_losses_log.csv'), index=False)
    
    # Consider also saving final model checkpoints
    agent.save_checkpoint('final')
        
    # Close CSV files after the training loop.
    rewards_file.close()
    losses_file.close()
    
    logging.info("Training Completed.")