From 2a069b322c96dd50e0a244e1e29a37a2e2c5a7ad Mon Sep 17 00:00:00 2001 From: "Antonello, Dr. Massimiliano" <massimiliano.antonello@uni-hamburg.de> Date: Fri, 21 Jun 2024 14:38:02 +0200 Subject: [PATCH] Patch for new versions of numpy 2.0.0 (with Python 3.12). Now added Main_example.py with the ability to plot transients interactively. --- AdditionalPDFs.py | 5 +- LightSimtastic.py | 27 ++++------ Main_example.py | 130 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 19 deletions(-) create mode 100644 Main_example.py diff --git a/AdditionalPDFs.py b/AdditionalPDFs.py index 2934d4c..1c3885b 100644 --- a/AdditionalPDFs.py +++ b/AdditionalPDFs.py @@ -1,11 +1,10 @@ import numpy as np -from scipy.stats import rv_discrete, rv_continuous, uniform +from scipy.stats import rv_discrete, uniform import scipy.special as sc -import matplotlib.pyplot as plt from scipy.stats._distn_infrastructure import ( - rv_discrete, _ncx2_pdf, _ncx2_cdf, get_distribution_names) + rv_discrete, get_distribution_names) class gpd_gen(rv_discrete): diff --git a/LightSimtastic.py b/LightSimtastic.py index c09d042..a4c72ca 100644 --- a/LightSimtastic.py +++ b/LightSimtastic.py @@ -1,29 +1,24 @@ import time -import os -import glob import numpy as np import pandas as pd -import matplotlib -import matplotlib.pyplot as plt import scipy import scipy.stats as stats import scipy.signal as signal from tqdm.auto import tqdm -from itertools import repeat, chain, product, zip_longest +from itertools import chain, product, zip_longest from operator import add from types import SimpleNamespace from AdditionalPDFs import borel -import json -import re import codecs -import random -from copy import deepcopy np.set_printoptions(suppress=True) # evil but works: just suppress the numpy nested ragged array warning import warnings -warnings.filterwarnings("ignore", category=np.VisibleDeprecationWarning) +if hasattr(np, 'VisibleDeprecationWarning'): + warnings.filterwarnings("ignore", category=np.VisibleDeprecationWarning) +else: + warnings.filterwarnings("ignore", category=DeprecationWarning) class SiPMSimulation: @@ -447,7 +442,7 @@ class SiPMSimulation: Ap_d = [] Ap_t = [] - + for list_apg_d, list_apg_t in zip(apg_d, apg_t): _Apd_list = [] _Apt_list = [] @@ -486,9 +481,9 @@ class SiPMSimulation: Ap_d.append(_Apd_list) Ap_t.append(_Apt_list) - - Ap_d = np.array(Ap_d) - Ap_t = np.array(Ap_t) + + Ap_d = np.array(Ap_d, dtype="object") + Ap_t = np.array(Ap_t, dtype="object") @@ -505,8 +500,8 @@ class SiPMSimulation: for list_pg_t, list_pXT_t, list_dXT_t, list_Ap_t, in zip(pg_t, pXT_t, dXT_t, Ap_t) ] - ns.ag_d = ag_d - ns.ag_t = ag_t + ns.ag_d = np.asarray(ag_d, dtype="object") + ns.ag_t = np.asarray(ag_t, dtype="object") pbar.update(1) pbar.set_description("{0}".format(self.pb_ag_text[6])) diff --git a/Main_example.py b/Main_example.py new file mode 100644 index 0000000..d6b940c --- /dev/null +++ b/Main_example.py @@ -0,0 +1,130 @@ +from LightSimtastic import SiPMSimulation +import matplotlib.pyplot as plt +import numpy as np + +################################# +# THE SIMULATION TOOL TAKES A DICTIONARY AS AN INPUT, WITH EACH OF THE VARIABLES AS KEYS. +# FOR EACH ELEMENT YOU ADD TO THE LISTS, ANOTHER SIMULATION WILL BE PERFORMED. +# THIS ALLOWS SCANS THROUGH PARAMETERS. +################################# + +variables={ +"Name_Sim":[0], #THIS CAN BE ANYTHING YOU LIKE +"mu":[7], # MEAN NUMBER OF GEIGER DISCHARGES +"ppXT":[0.0], # PROBABILITY OF PROMPT CROSS-TALK +"pdXT":[0.2], #PROBABILITY OF DELAYED CROSS-TALK +"taudXT":[25], #TIME CONSTANT FOR DELAYED CROSS-TALK (NS) +"rdXT":[0.5], #FRACTION OF DELAYED CROSS-TALK FROM ADJACENT CELLS +"pAp":[0.15], #PROBABILITY OF AFTERPULSE +"tauAp":[7.5], #TIME CONSTANT OF AFTERPULSE +"taur":[20], # SIPM RECOVERY TIME CONSTANT +"Sig0":[0.075], #WIDTH OF PEDESTAL [NORMALISED ADC] +"Sig1":[0.02], # INCREASE IN PEAK WIDTH PER ADDITIONAL DISCHARGE [NORMALISED ADC] +"DCR":[0.0], # DARK COUNT RATE [GHZ] +"Sigt":[0.02], # ELECTRONICS NOISE FOR CURRENT TRANSIENT (FOR TRANSIENT) +"GSig":[0.75], # WIDTH OF ELECTRONICS NOISE TRANSFER FUNCTION (FOR TRANSIENT) +"tslow":[20], # TIME CONSTANT FOR SLOW PART OF PULSE +"tfast":[1.5], # TIME CONSTANT FOR FAST PART OF PULSE +"rfast":[0.2], # PROPORTION OF SLOW/FAST +"start_tgate":[-5], # GATE START TIME [NS] +"len_tgate":[150], # LENGTH OF GATE +"t0":[100,], # STARTING POINT OF GATE +"tl0":[0], #GAUSSIAN MEAN OF PRIMARY GEIGER DICHARGE TIME DISTRIBUTION +"tl1":[0.1], #GAUSSIAN WIDTH OF PRIMARY GEIGER DICHARGE TIME DISTRIBUTION +"tl2":[0], #FREE PARAMETER +"Gen_mu":["Poisson"], # NUMBER PRIMARY GEIGER DISCHARGE PDF +"Gen_tmu":["Gauss"], # TIME OF PRIMARY GEIGER DISCHARGE PDF +"Gen_gain":["Gauss"], # GAIN PDF (FOR TRANSIENT) +"Gen_npXT":["Binomial"], #NUMBER PROMPT X-TALK DISCHARGE DISTRIBUTION +"Gen_ndXT":["Binomial"], #NUMBER PROMPT X-TALK DISCHARGE DISTRIBUTION +"Gen_tdXT":["Exp"], #TIME DELAYED X-TALK DISTRIBUTION +"Gen_nAP":["Binom"], #NUMBER AFTER DISTRIBUTION +"Gen_tAP":["Exp"], #AFTERPULSE TIME DISTRIBUTION +"Gen_noise":["Gauss"] #ELECTRONIC NOISE DISTRIBUTION (FOR TRANSIENT) +} + +################################# +# CREATE A SIPM SIMULATION CLASS OBJECT +################################# + +s = SiPMSimulation() + +################################# +# ADD VARIABLES +################################# + +s.AddVariables(variables) + +n_events = int(1e2) +iterplot=10 + +################################# +# SIMULATE +################################# + +#s.Simulate(n_events, transients=False) +s.Simulate(n_events, transients=True, n_transients=n_events) + +################################# +# EXTRACT SIMULATION DATAFRAME +################################# + +df = s.pars + +################################# +# TRANSIENT +################################# +I = df.iloc[0]["Transients"]['I'] +t = df.iloc[0]["Transients"]['t'] + +if iterplot>0: + # Iterative plot + wave_sum = np.sum(I, axis=0) + wave_avg = wave_sum / len(I) + x_min = t.min(); x_max = t.max() + y_min = -0.2; y_max = np.max(I)+1 + + fig, ax = plt.subplots(figsize=(15.5,10.5)) + plt.rc('font', size=20) + plt.ion() + plt.show() + + for index in range(iterplot): + ax.clear() + ax.plot(t, I[index], color='blue', label='Transient '+str(index)) + ax.plot(t, wave_avg, color='red', label='Average transient') + + ax.grid(True, which='both', linestyle=':', linewidth=0.5, color='lightgrey') + ax.set_xlim([x_min, x_max]) + ax.set_ylim([y_min, y_max]) + ax.set_xlabel('Time [ns]',loc='right') + ax.set_ylabel('Intensity [a.u.]',loc='top') + ax.set_title('Transients') + ax.legend() + plt.draw() + plt.pause(0.01) + input(" ") + plt.ioff() + plt.close() + +################################# +# EXTRACT CHARGE SPECTRUM +################################# + +Qs = df.iloc[0]["ChargeSpectrum"] + +################################# +# PLOT +################################# + +plt.figure(figsize=(15.5,10.5)) +H, edges = np.histogram(Qs, bins=1000) +edges = edges[:-1]+(edges[1]-edges[0]) +plt.plot(edges, H) +plt.title("Simulated Charge Spectrum") +plt.yscale("log") +plt.xticks(fontsize=25) +plt.yticks(fontsize=25) +plt.xlabel("# GD", fontsize=25), +plt.savefig("./Example.png") + -- GitLab