如何在含峰值的随机数组中替换线性斜率为指数衰减并添加峰值后递减指数元素
Hey there! I get that you want to generate a random array with peaks, replace linear slopes with exponential ones, and add decreasing exponential elements right after each peak. Let's start by pointing out a couple of issues with your current code, then walk through a complete solution.
Issues in Your Original Code
- Comparing floating-point values with
i==select_count[j]is unreliable—randomly generated floats almost never match exactly, so your replacement logic won't work as intended. - Right now you're just swapping a few random values, which doesn't handle exponential slopes or post-peak decay at all.
Step-by-Step Solution
Let's build this properly, step by step:
1. Set Up Base Parameters & Peak Positions
First, we'll define our core parameters, generate a noise baseline, and pick unique peak positions (sorted by time):
import numpy as np import matplotlib.pyplot as plt # Core settings total_time_points = 1000 time_range = np.linspace(1, 100, total_time_points) # Generate noise baseline (your original count_list logic) noise_baseline = np.random.uniform(low=5.-np.sqrt(5.), high=5.+np.sqrt(5.), size=total_time_points) # Randomly pick 5-8 unique peak positions (indices) num_peaks = np.random.randint(5, 9) peak_indices = np.random.choice(total_time_points, size=num_peaks, replace=False) peak_indices.sort() # Make sure peaks are in time order
2. Replace Linear Slopes with Exponential Rise
For each peak, we'll create an exponential rise from the noise baseline up to the peak value, replacing the linear segment before the peak:
# Initialize spectrum with noise baseline spectrum = noise_baseline.copy() for peak_idx in peak_indices: # Define how long the exponential rise should be (max 20 points before peak) rise_segment_length = min(20, peak_idx) rise_start_idx = peak_idx - rise_segment_length # Generate a random peak value (your original photon_list logic) peak_value = np.random.uniform(low=40.-np.sqrt(40.), high=40.+np.sqrt(40.)) start_value = spectrum[rise_start_idx] # Value at the start of the rise # Create exponential rise curve: smooth transition from start to peak x_normalized = np.linspace(0, 1, rise_segment_length) exponential_rise = start_value * (peak_value / start_value) ** x_normalized # Replace the linear segment with our exponential rise spectrum[rise_start_idx:peak_idx] = exponential_rise ### 3. Add Post-Peak Exponential Decay # Define how long the decay should last (max 30 points after peak) decay_segment_length = min(30, total_time_points - peak_idx - 1) decay_end_idx = peak_idx + decay_segment_length # Create exponential decay: starts at peak, fades towards noise baseline decay_rate = 0.15 # Adjust this to make decay faster/slower x_decay = np.linspace(0, decay_segment_length, decay_segment_length) exponential_decay = peak_value * np.exp(-decay_rate * x_decay) # Make sure decay doesn't drop below the noise baseline exponential_decay = np.clip(exponential_decay, noise_baseline[peak_idx:decay_end_idx].min(), peak_value) # Apply the decay to the spectrum spectrum[peak_idx:decay_end_idx] = exponential_decay
4. Visualize the Result
Finally, plot the curve with a log x-axis to match your desired output:
plt.figure(figsize=(10, 3)) plt.plot(time_range, spectrum, lw=0.8, color='#ff7f0e') # Orange curve like your reference plt.ylabel("spec") plt.xscale('log') plt.show()
Key Notes
- No Floating-Point Matching: We use array indices to modify segments, which avoids the unreliable float equality checks from your original code.
- Smooth Exponential Transitions: The rise curve uses a normalized exponent to ensure a smooth transition from baseline to peak, and the decay uses a natural exponential fade that stays above the noise floor.
- Adjustable Parameters: Tweak
rise_segment_length,decay_segment_length, ordecay_rateto change the shape of your curve to match exactly what you need.
This will give you the colored curve effect you're looking for, with proper exponential slopes and post-peak decay!
内容的提问来源于stack exchange,提问作者OGUZ HAN ATAS

