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