Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:19:57

0001 import numpy as np
0002 import matplotlib.pyplot as plt
0003 import glob
0004 
0005 def Normalize(f, x) :
0006     dx = x[1:] - x[:-1]
0007     integral = np.sum(f[:-1] * dx)
0008     f_norm = f / integral
0009     return f_norm
0010 
0011 # When running in MT and outputting to cvs, each thread outputs to a different file.
0012 # Therefore I need to cycle through each thread and append them all together.
0013 
0014 energy = np.empty([0,1])
0015 length = np.empty([0,1])
0016 
0017 ntuple_name = "radioprotection_nt_102"
0018 output_name = ntuple_name + "_t" + "*" + ".csv"
0019 output_list = glob.glob(output_name)
0020 
0021 for this_file in output_list :  
0022     energy_thread, length_thread = np.loadtxt(this_file, delimiter=',', unpack=True, usecols=(0,1))
0023     
0024     energy = np.append(energy, energy_thread)
0025     length = np.append(length, length_thread)
0026 
0027 # Experimentally, the mean path length is calculated geometrically as a mean chord length.
0028 # Here for convenience it's taken by averaging the effective path lengths.
0029 mean_path_length = np.average(length)
0030 
0031 # A conversion factor can be used to convert the target material to water or tissue equivalent.
0032 # Its choice depends on the material and can be calculated in different ways.
0033 # It is suggested that the user replace the following value with his own.
0034 conversion_factor = 1.
0035 
0036 # If the previous value is not overriden by the user, this script will attempt to read geometry.mac
0037 # and provide a factor accordingly
0038 if conversion_factor == 1. :
0039     detector = np.array(["Diamond", "MicroDiamond", "Silicon", "SiliconBridge"])
0040     factor = np.array([0.32, 0.32, 0.57, 0.57]) # conversion factor based on material stopping power
0041     
0042     with open("geometry.mac") as search:
0043         for line in search:
0044             line = line.rstrip()  # remove new line
0045             
0046             for this in detector :
0047                 match = "/geometrySetup/selectDetector " + this
0048                 
0049                 if match == line:
0050                     conversion_factor = factor[ detector == this ][0]
0051                 else:
0052                     conversion_factor = factor[ detector == "Diamond" ][0]  # default detector type (no macro used)
0053 
0054 
0055 y = energy * conversion_factor / mean_path_length
0056 
0057 
0058 # The spectrum is now binned logarithmically, to avoid oscillations at higher energies
0059 # (due to fewer counts) that wouldn't much meaning.
0060 
0061 minimum = np.amin(y)
0062 maximum = np.amax(y)
0063 
0064 exp_start = np.floor(np.log10(minimum))
0065 exp_end = np.ceil(np.log10(maximum))
0066 
0067 n_decades = int(exp_end - exp_start)
0068 
0069 # Number of logarithmic bins per decade:
0070 # Higher values give better resolution, but lead to oscillations
0071 # (especially at high energy) if your statistic has too few counts.
0072 bins_per_dec = 60
0073 
0074 n_bins = n_decades * bins_per_dec
0075 
0076 y_bins = np.zeros(n_bins)
0077 
0078 y_bins[0] = 10**exp_start
0079 
0080 for i in range(1, n_bins) :
0081     y_bins[i] = y_bins[i-1] * 10**( 1 / bins_per_dec )
0082 
0083 
0084 # Create the histogram
0085 
0086 # For now f is a number of counts...
0087 f = np.histogram( y, bins=y_bins ) [0]
0088 
0089 tot_counts = np.sum(f)
0090 
0091 # ... so now I turn f into a density
0092 bin_width = y_bins[1:] - y_bins[:-1]
0093 f = f / bin_width
0094 
0095 f = np.append(f, 0.)    # give f and y_bins arrays the same size
0096 
0097 # Normalize the spectra to unit area under the curve
0098 f = Normalize(f, y_bins)
0099 d = Normalize(y_bins*f, y_bins)
0100 
0101 
0102 # Save to file
0103 
0104 output_file = "analysed_spectra.csv"
0105 header = "y[keV/um], f(y)[um/keV], d(y)[um/keV]"
0106 
0107 np.savetxt( output_file, np.c_[ y_bins, f, d ], header=header, delimiter=',' )
0108 
0109 
0110 # Plot
0111 
0112 fig, ax1 = plt.subplots()
0113 
0114 color = 'tab:blue'
0115 
0116 ax1.semilogx( y_bins, y_bins * f, linewidth=0.5, color=color  )
0117 
0118 ax1.set_xlabel(r'$y \,\, [keV / \mu m]$')
0119 ax1.set_ylabel(r'$y \cdot f(y) $', color=color)
0120 ax1.tick_params(axis='y', labelcolor=color)
0121 
0122 ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis
0123 
0124 color = 'tab:red'
0125 
0126 ax2.semilogx( y_bins, y_bins * d, linewidth=0.5, color=color )
0127 
0128 ax2.set_ylabel(r'$y \cdot d(y) $', color=color)
0129 ax2.tick_params(axis='y', labelcolor=color)
0130 
0131 title = str(tot_counts) + " counts, " + str(bins_per_dec) + " bins per decade, " + str(conversion_factor) + " conversion factor"
0132 fig.suptitle(title)
0133 
0134 fig.tight_layout()
0135 
0136 plt.subplots_adjust(top=0.92)
0137 plt.show()