This is my performance metrics
{'Area': 3.2104190437614856e-11, 'PowerDissipation': 0.0393065, 'SlewRate': 2.7893815216964812, 'Gain': -44.9189, 'Bandwidth3dB': 605665.0, 'UnityGainFreq': 0.0, 'PhaseMargin': 0.0}
I am using the below function 'calculate_reward' in my RL algorithm to achieve my optimized values, in my process, I need to achieve the '7' performance metrics 'area', 'power dissipation', 'DC gain', 'Slew rate', 'Bandwidth3dB', 'Unity gain bandwidth', and 'Phase margin' with in the target performance metrics 'PERFORMANCE_METRICS_TARGET_LOW', 'PERFORMANCE_METRICS_TARGET_HIGH'. In this computation process, the parameters 'area', 'power dissipation' are need to be achieve as much as possible minimum with in the target is better and the parameters 'DC gain', 'Slew rate', 'Bandwidth3dB', 'Unity gain bandwidth', 'Phase margin' are need to be achieve as much as possible maximum with in the target is better. 
But the present code in the function 'calculate_reward' will treat all the '7' performance metrics as equally to be get maximum with in the target. I need you to alter the code according to my required different minimum and maximum conditions to achieve with the function.



# Define the constants and target metrics for reward calculation
CircuitEnvironment.PERFORMANCE_METRICS_TARGET_LOW = np.array([3e-10, 0.1, 20, 70, 30e3, 30e6, 65])
CircuitEnvironment.PERFORMANCE_METRICS_TARGET_HIGH = np.array([1e-10, 0.25, 50, 100, 100e3, 100e6, 90])
CircuitEnvironment.LARGE_REWARD = 10
CircuitEnvironment.SMALL_REWARD = 1
CircuitEnvironment.PENALTY = 1
CircuitEnvironment.LARGE_PENALTY = 10

class CircuitEnvironment:
    def is_performance_metrics_in_target(self, metrics):
        return np.all(metrics >= self.PERFORMANCE_METRICS_TARGET_LOW) and np.all(metrics <= self.PERFORMANCE_METRICS_TARGET_HIGH)

    def calculate_reward(self, c_metrics, p_metrics, transistor_regions):
        # Assuming this is the correct order of metrics
        metrics_order = ['Area', 'PowerDissipation', 'SlewRate', 'Gain', 'Bandwidth3dB', 'UnityGainFreq', 'PhaseMargin']
        current_metrics = np.array([c_metrics[k] for k in metrics_order])
        previous_metrics = np.array([p_metrics[k] for k in metrics_order])
        reward = 0
        # Check if all transistors are in saturation
        all_in_saturation = all(region == 2 for region in transistor_regions.values())
        print("all_in_saturation", all_in_saturation)
        # Check if the performance metrics is within the target specification
        performance_metrics_in_target = self.is_performance_metrics_in_target(current_metrics)
        print("performance_metrics_in_target", performance_metrics_in_target)
        # Check if the performance metrics is better or worse than before
        performance_metrics_getting_better = np.all(current_metrics >= previous_metrics) or np.abs(self.PERFORMANCE_METRICS_TARGET_LOW - current_metrics) < np.abs(self.PERFORMANCE_METRICS_TARGET_LOW - previous_metrics)
        print("performance_metrics_getting_better", performance_metrics_getting_better)
        # First priority: ideally we want both conditions to be true
        if performance_metrics_in_target and all_in_saturation:
            reward += self.LARGE_REWARD
        # If the performance metrics is not within target, but getting better, give some reward
        elif not performance_metrics_in_target and performance_metrics_getting_better and all_in_saturation:
            reward += self.SMALL_REWARD
        # If the performance metrics is within target but not all transistors are in region 2,
        # give some reward for at least having the performance metrics in range
        elif performance_metrics_in_target and not all_in_saturation:
            reward += self.SMALL_REWARD * 0.5
        # If the performance metrics is not in target and not improving or transistors moving away from saturation
        if not performance_metrics_in_target and not performance_metrics_getting_better or not all_in_saturation:
            reward -= self.PENALTY
        # Additional penalty if any transistor is out of region 2 (not in saturation)   
        if not all_in_saturation:
            penalty_count = sum(1 for region in transistor_regions.values() if region != 2)
            reward -= self.LARGE_PENALTY * penalty_count

        return reward