From 659f32a1a8fc88ef419970241d699917969f6bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Quast?= <guenter.quast@online.de> Date: Fri, 7 Jun 2024 17:25:56 +0200 Subject: [PATCH] added components of mimoCoRB --- config/spectrum_config.yaml | 80 +++++++++++++ modules/#redPitaya_source.py# | 64 +++++++++++ modules/__pycache__/filters.cpython-310.pyc | Bin 0 -> 2728 bytes modules/__pycache__/filters.cpython-311.pyc | Bin 0 -> 5594 bytes .../plot_histograms.cpython-310.pyc | Bin 0 -> 976 bytes .../plot_histograms.cpython-311.pyc | Bin 0 -> 1418 bytes .../__pycache__/plot_waveform.cpython-310.pyc | Bin 0 -> 1175 bytes .../__pycache__/plot_waveform.cpython-311.pyc | Bin 0 -> 1616 bytes .../__pycache__/save_files.cpython-310.pyc | Bin 0 -> 982 bytes .../__pycache__/save_files.cpython-311.pyc | Bin 0 -> 1493 bytes .../spectrum_filter.cpython-310.pyc | Bin 0 -> 3736 bytes .../spectrum_filter.cpython-311.pyc | Bin 0 -> 5498 bytes modules/filters.py | 94 ++++++++++++++++ modules/plot_histograms.py | 27 +++++ modules/plot_waveform.py | 33 ++++++ modules/redPitaya_source.py | 54 +++++++++ modules/save_files.py | 26 +++++ modules/spectrum_filter.py | 106 ++++++++++++++++++ redP_mimoCoRB.py | 51 +++++++++ setup.yaml | 86 ++++++++++++++ 20 files changed, 621 insertions(+) create mode 100644 config/spectrum_config.yaml create mode 100644 modules/#redPitaya_source.py# create mode 100644 modules/__pycache__/filters.cpython-310.pyc create mode 100644 modules/__pycache__/filters.cpython-311.pyc create mode 100644 modules/__pycache__/plot_histograms.cpython-310.pyc create mode 100644 modules/__pycache__/plot_histograms.cpython-311.pyc create mode 100644 modules/__pycache__/plot_waveform.cpython-310.pyc create mode 100644 modules/__pycache__/plot_waveform.cpython-311.pyc create mode 100644 modules/__pycache__/save_files.cpython-310.pyc create mode 100644 modules/__pycache__/save_files.cpython-311.pyc create mode 100644 modules/__pycache__/spectrum_filter.cpython-310.pyc create mode 100644 modules/__pycache__/spectrum_filter.cpython-311.pyc create mode 100644 modules/filters.py create mode 100644 modules/plot_histograms.py create mode 100644 modules/plot_waveform.py create mode 100644 modules/redPitaya_source.py create mode 100644 modules/save_files.py create mode 100644 modules/spectrum_filter.py create mode 100644 redP_mimoCoRB.py create mode 100644 setup.yaml diff --git a/config/spectrum_config.yaml b/config/spectrum_config.yaml new file mode 100644 index 0000000..433f84e --- /dev/null +++ b/config/spectrum_config.yaml @@ -0,0 +1,80 @@ +# Dict with uid's as key and a nested dict with configuration variables +general: + runtime: 600 # desired runtime in seconds + runevents: &number_of_events 100000 + number_of_samples: &number_of_samples 2048 + analogue_offset: &analogue_offset 0 + sample_time_ns: &sample_time_ns 32 + + trigger_level: &trigger_level 50 + trigger_channel: &trigger_channel '1' + trigger_direction: &trigger_direction 'rising' + pre_trigger_samples: &pre_trigger_samples 103 # 5% + +find_peaks: + sample_time_ns: *sample_time_ns + analogue_offset: *analogue_offset + number_of_samples: *number_of_samples + pre_trigger_samples: *pre_trigger_samples + peak_minimal_prominence: 50 # has to be positive and higher than avg. noise peaks to not cause havoc! + trigger_channel: *trigger_channel + peak_minimal_distance: 10 # minimal distance between two peaks in number of samples + peak_minimal_width: 7 # in number of samples + trigger_channel: *trigger_channel + trigger_position_tolerance: 7 # in number of samples + +# dict for RedPitaya redPoscidaq +redP_to_rb: + ip_address: '192.168.0.103' + eventcount: *number_of_events + sample_time_ns: *sample_time_ns + number_of_samples: *number_of_samples + pre_trigger_samples: *pre_trigger_samples + trigger_channel: *trigger_channel + trigger_level: *trigger_level + trigger_mode: 'norm' + +# Dict for simul_source.py +simul_source: + sample_time_ns: *sample_time_ns + number_of_samples: *number_of_samples + pre_trigger_samples: *pre_trigger_samples + analogue_offset: *analogue_offset + eventcount: *number_of_events + sleeptime: 0.03 + random: true + +# Dict for push_simul +push_simul: + sample_time_ns: *sample_time_ns + number_of_samples: *number_of_samples + pre_trigger_samples: *pre_trigger_samples + analogue_offset: *analogue_offset + eventcount: *number_of_events + sleeptime: 0.03 + random: true + +save_to_txt: + filename: "spectrum" + +save_parquet: + filename: "spectrum" + +plot_waveform: + title: "Muon waveform" + min_sleeptime: 0.5 # time to wait between graphics updates + number_of_samples: *number_of_samples + sample_time_ns: *sample_time_ns + analogue_offset: *analogue_offset # analogue offset in V + pre_trigger_samples: *pre_trigger_samples + channel_range: 4096 # channel range in mV + trigger_channel: *trigger_channel # Channel name in the PicoScope. Valid values are 'A', 'B', 'C' or 'D' + trigger_level: *trigger_level # value in mV, take account of analogue_offset, which is added to input voltage ! + +plot_histograms: + title: "on-line histograms" + # define histograms + histograms: + # name min max nbins ymax name lin/log + chA_height: [50., 3000., 250, 5.9, "ph 1A", 0] + chB_height: [50., 3000., 250, 5.9, "ph 1B", 0] diff --git a/modules/#redPitaya_source.py# b/modules/#redPitaya_source.py# new file mode 100644 index 0000000..423ea6f --- /dev/null +++ b/modules/#redPitaya_source.py# @@ -0,0 +1,64 @@ +""" +**redPitaya_source**: mimoCoRB source compatible to redPoscdaq + +Input data is provided as numpy-arry of shape (number_of_channels, number_of_samples). +""" + +from mimocorb.buffer_control import rbImport +import numpy as np +import sys, time +from mutiprocessing import Event + +def simul_source(source_list=None, sink_list=None, observe_list=None, config_dict=None, **rb_info): + """ + Generate simulated data and pass data to buffer + + The class mimocorb.buffer_control/rbImport is used to interface to the + newBuffer and Writer classes of the package mimoCoRB.mimo_buffer + + This example may serve as a template for other data sources + + :param config_dict: configuration dictionary + + - events_required: number of events to be simulated or 0 for infinite + - sleeptime: (mean) time between events + - random: random time between events according to a Poission process + - number_of_samples, sample_time_ns, pretrigger_samples and analogue_offset + describe the waveform data to be generated (as for oscilloscope setup) + + Internal parameters of the simulated physics process (the decay of a muon) + are (presently) not exposed to user. + """ + + global databuffer + data_ready = Event() + data_ready.clear() + + run_rpControl(callback=rp_data) + + def rp_data(data): + while data_ready.is_set(): + time.sleep(0.01) + databuffer = data + data_ready.set() + + events_required = 1000 if "eventcount" not in config_dict else config_dict["eventcount"] + + def yield_data(): + """generate simulated data, called by instance of class mimoCoRB.rbImport""" + + event_count = 0 + while events_required == 0 or event_count < events_required: + data_ready.wait() + # deliver pulse data and no metadata + yield (databuffer, None) + data_ready.clear() + event_count += 1 + + datasource = rbImport(config_dict=config_dict, sink_list=sink_list, ufunc=yield_data, **rb_info) + # possibly check consistency of provided dtype with simulation ! + + # TODO: Change to logger! + # print("** simul_source ** started, config_dict: \n", config_dict) + # print("?> sample interval: {:02.1f}ns".format(osci.time_interval_ns.value)) + datasource() diff --git a/modules/__pycache__/filters.cpython-310.pyc b/modules/__pycache__/filters.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9aef4eb7f1388cf9ab8704995f557ad269652889 GIT binary patch literal 2728 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 literal 0 HcmV?d00001 diff --git a/modules/__pycache__/filters.cpython-311.pyc b/modules/__pycache__/filters.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb6d48f582732eccf3eeb668b632970fc3d21180 GIT binary patch literal 5594 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 literal 0 HcmV?d00001 diff --git a/modules/__pycache__/plot_histograms.cpython-310.pyc b/modules/__pycache__/plot_histograms.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf4bec83dff02352931ad37bd2a6f2832be03571 GIT binary patch literal 976 zcmZWo&2AGh5MJ+3vfU&tr$RaTgh-?|N2Ca$hBk<bc2hN}1i7r7*h$>(t`~bZQlfBb z&%6Sy#HH`SQ~1iMFTeo_iP<ESsvYgjc;@qtW<J}ZQt=FsZ$Ey~7nWiC%!B(<gkTp` zU4o%T&!C8!A?l%pH+v>{E3_iJXQL(N^c?0~6{vlUAhS*#TDU~LB6Df++?2a)jk?S{ z^R7w^os}utGOp26;{x^qvIe;d^{&=wiI%U;3u}?B<R~>e3$1R<K6$lT5{fh!bCrsb zB$2As8u%{46Cye3hwP=Q;-M4~?q|axlQ>g69^r^bVo#jB-MRZASmE9+3~Bf`NI!Xq zX{USM9E}EczGEc?@DAt)P=&#y#@v{rxjDCnHaF(>ck~r~apum2k#o~As^)C!VUTtl z@|a=DRT7dZ7Q_F|=RHIGXawk*=UuO6@fLL&34!S`kCQBI;DLyTe3VI&auGxELGFp1 zF8BJ<gchp>T~Z>G0~Un9o?Zh=&X>!w=qn~CE1<Nj7UX4gQT78K4}~t~yZ~D_hAcs~ z-~08kh*<q|MpRlK@w9%z=rK>pl+-1o$zrt~4U#dbM}lS{Q}qWYx06iu#)Di1N~@gd z&7y~79%(lSBEsV!n7N&S<Oz&BbC0L#Si}vik$1b9w}ZB4ue$FKIvBntK5Flu9=34P z-^YHti;r4Ozl-0sPjIITx#nTpZ{gO**4}CNpzT*}AEdgWi$OreAPBUjrb?Sa>8<?6 z420}Ix-k--jG?`Vr1=CP?`taq4*zu=lZZhfCy_i(wVjZ3tld6QEC;kr<Y=Oc6DAd$ slXk+hOr;B2@0s#q_}5GF-XMt7GcdN{S}rOh7kQRvxuxf56C(T1U&;a-a{vGU literal 0 HcmV?d00001 diff --git a/modules/__pycache__/plot_histograms.cpython-311.pyc b/modules/__pycache__/plot_histograms.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..888023e5d33dc72af599714231aa19140b3b82eb GIT binary patch literal 1418 zcmZWn&1)M+6rb50NvoADHJ1qY(xHZ?5+u6#14JmOmYNC@DcB0MYGGMvR?^!0mDybf zsVb=8gHNT0Kzgew#c^;B{u6rWA0P!m#a`P>ZUU1YeCo_fa%<(y%$u3_HS>P&y<A<D z0i$33_=kKV0`M2VEJ&IkF0&AT7l42|Adm<Ktix~@>H^zELo`tx!I>^nj|f1E>_-<t z2s&ln=WNZ0*{zbu5v<2Fi9`<sE~SL|#7RsO_QT(B*-3))WzyjO%0foq+TsXqzR_dy zn-U1Z7bNDtx^N=#ljP$3|DDJramxO69{!DMP8l-iY|UsMYi0QbBJ2UaGRfZ8ayIK2 zwx@J-*R$JHHQj7BkFRg|P^G%sFtktI3~o`|#0|gI(kS*_-D+b~H|-sJ_w#$#4$53F zzvX|Zyn?|8%eo*^J1Df<O*H=|-*^=`j+c4HUI6d93IOy$ANGa5*g`t!qu=0<@OxId ze&m!{p0hP0UR9Qn(Cf;WQPnbZOT$EW9YgJ6yY*j6JQH?*FEN&j&U2Y(D2H+Kj><5> zy5;y@9ye{PrMG>mdb(|~;7z`(v^%q{P>y^i8YEoXr%g>U7^Xp-0d+7tuGkG%qla@v zVirx|VS*TKD7w|MgBVAPVd!#1cqSNM6>}Zi)N)UK)%9|1-OKH2<gxClT{TBF;)JKW zX4C1YInyS-p}D!Gn%;A|L25}xc~9{kb90Ohz`G<!ef0BpXXT6j@81lQ-||_T9|jL5 zC^2~OL;0vY2*)LJ0fD3_rm9<t(v$X@RCgFeJ?U}R>)2KvUqSipZDw@^@AkH9UzYbU zn+5!+T72@bgbS4-u2gIIQK?X=;V-JYc(2A}g@@Hj375Vq?L4WKtCb9@Fv_HYn4%E7 zsVITycHKa*-C&LPUel(H_j-@=#tLLp^?1gH-UvjW;m*_LKekj;V}T+L)h#bTj_P#+ zsiC?WR|H6<?ZY5;s8N^IHi#JezU#dLG{w9rN9#(uKLhzQ`Z2rmMs@#YY$`$sr-A^{ z6mS*=Ffow%n1J{o922lLyg4V})^IVoM`|D+C6AwtKza<)Ly(?EC77Ioo9s3~E62Sz z;@VJLo1plhbe#Q(K7aOS`p%p5oip*ZbaCr-VwBz(r#D9O#t3bW(dH0sE=-%x4^B2- t=6}tfH7?di>s#aXtr6NDqwOKu4sC|=&IlF9s5o5AX$+tb*=r#R{{jfgepdhh literal 0 HcmV?d00001 diff --git a/modules/__pycache__/plot_waveform.cpython-310.pyc b/modules/__pycache__/plot_waveform.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4803edcf405c5ab825674ee3fc3f085ebe0cf1e GIT binary patch literal 1175 zcmZ8g&2Aev5GMCWTCXIhhrs<g@hT&>js=9Gh!U%4&{#4o1qgH@s3o<cy}R6!TpKc! zlXLDX)CPLVd-N%I?WK8v9tsrb?8*t;4wf^V9}d5r8LD0{MnJ#*{ulq#N9d1Qc}#6k zp2ITlfpN4z9CI(j3*1O=;eqrsKMxiG-uc2sD8joI5AHEo_Ib!#@A0B7BHq6A^mDPt zBjH`dcO8K*x*UIv?(vuC7GlA(2euxM@Ai3zckjJhzp?geFZX86>OZ-88y_B)nX-q6 zLsCmCi<DfmE3r~KH)N$%PL|bbB{Zo_?aO7ZUaIpK$2%)cRAIHsj;BkZjnG#@pD@cv z{1N^UO+H}PsngP3v<v5#qclx|+W9~&kRhy}U>O3;qAl9ut+(}8fkfNjH~b5J7jDB_ zR99t&`W`#Q2*m{G403;lOL%>A0~t`t8s!7_xCtJXOtYNGqO9zY0PvMeE6uD_1>rKO zCDWT-EFnitJ*bs76GM_}R<31YNTU<0$WjoqR@ViA(~Y;eqdu3*f|^W-(#jl;)*Pbk zwGaiVN&qR$=UBt?G81r1E@)w%kz~z^LS$64A{Ea_sfE=tO@*erNJCh`VX;i5m7r?1 zGQvJ&BZLc+XbH&dTKump44SDlQ6`aD23(bZU)ZW_4o|cPmG8G)$EZptf@acKw+9`+ z+-<vR*>rcOb#}$0b=6#3FR3h6%C*YOLZ3e%-GO9(zZk4lE(SkW%-BIH?ciMSGilj| z4Yc58vpdR@a?J+0;#DThpc$1<(|25MT<<@YeMoES**WOOSodJ#B1&@x^`<w`41T?Y z#@<9{8@pD;kT@KFJgA}IqnmH%Kfam~_(tS(dh+J=n2aVTWHOzT)A49BCqGQj$!rd` z(d+4COvZ1=FW<~xO(*?e0@Q!v+LUsYQ0jcMG0s!QJ+0qDqV)3k(THn!`N+jNv$Zjk zOXpWmxldpV292gJEVV4G3rc3!E?P1pYKIG$POn@W9+81zbYXT;8QWCz5$iVp{oSr+ e-@{8l<||+Uih>AtafD+(_M<Pp!3UrP|NINagkClP literal 0 HcmV?d00001 diff --git a/modules/__pycache__/plot_waveform.cpython-311.pyc b/modules/__pycache__/plot_waveform.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..13b544f98c384cbdc54a7eff10c19b584be60ad5 GIT binary patch literal 1616 zcmZ7$J!>OJbXHn@cxBlfgeXo@3~_N-*j8hoL4<(Mmhr(^GPW)pYL?ONNLqWpGBdKV zqJRP}T!j<|mo6p*-yOcfWqv@4l+q!H*)}P1oxmi8tGwB@%-L^e-kW*z-n`G*SJ|wF z0Dk`cKl7hBLVwB47}7V3tGt5HOJt%NG8HpsD>Wsgv04mh+>SeHO;w_^L@g0RG_jW) zUt+3fpnVQA0+7p^iDRXfqG>a^ACp{Wg3g4QqOrZu8_7G(NPHitvNt*Anaa#~iSF9y z0RJvWL7{~-=x4`D=EUjLc>N(YH8XPtew~ND$&)k4%sI>mZtj}AZ^4Z1B01-#I?uIy z-nTuG&lj<z!g8DVkQ~s4#~h9u%yV$P-DpsT+gzSGmgB8?JC7G5u5Ng)V4l5LsZ+)& zJD_Zx2!gfu(uMLHCCJEY^+-BMRQFe#O+&qLP!gGcnZc_fpqEJ8<{zOh>MGq>H{MV! z)Kz~~eo(%HnspOrAbAcm0$ERpB}TSDRl@+=VDUBxY)XH^K)`oP`hF9U777=A!ia+{ z*Kdm=hHx5Iv(1RGJQtgmAt_-;ku1gwVU~1Z37ZyilM%mV861auEIeGNn76z`7lU?q z8rqP0j^*myrqmaf1F8~(v^b>H#cdy)r2JNv6UVnHSaGQC@_B5ui0e{YXT)vNdF(SP znAL1jrbm(-6W4@EY_Hj-y4PrMDsFDW*reQG7I-FF^j=yBl-Og~<A!D1fIT1lr=snL z%4H^7X)YOLxYuR|)oqK5U;_GJKUz+D^|0pAE)ykBmstx^tgc&b!wZtWEui{b)>#$@ z<Lk$TmgmsIH*La2p=pW24mGzeL5@g)QPU4s3y$HpNWt;UwoQ2<Y@%^rF8W77_6~>1 z_aP@=1k^+SeuAcEe){axy7>IJZ~NJ=Vf@jIXm8_E)p{G>Zys;<!tV++P>|Mjhd_z+ zPI?!z<wGxY(%VO(<+(+Ct!VE*2B~Xhp|eume6ovStm3W8`m?7cyjotz<w_NAl~&7D zyiwV~yH((=KCP5Xxb(cV_N@A(Ql3-G0CUqpO4m)#(DfkBk9ZLCc<_;YREEduiyyod zCLc+lIYdaNZPkN#8<H)9l+L;YdP5HqKC@gAs6G*`AYCV%%7Z{9ta%Wm;5BmS-ymV{ zwYhkM*feM}`CqwCe;K9rEA|C!<)h<&0~*B@MH$6niaJ6PrIC{9Y4W>76TR@eMDzW- z;}SjSkH;v9l<A&!Jauw7K)E5x^-*q=%qrOtx{EMUCr>)>;xqmD%%wWfE1l$jWG@c? z%sqUUd-yv3HhuBnZDx>L8s?S;+R{K>9;(ZIb$Kjmyx2codR6?T__}^EJD7bmoP9J< fSBC0JUtI}h`r6t+T_39J{qY#3koqZD3$yS)yRg6Q literal 0 HcmV?d00001 diff --git a/modules/__pycache__/save_files.cpython-310.pyc b/modules/__pycache__/save_files.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2288e065bf1d008f36656f6533fcbd3773e07f4 GIT binary patch literal 982 zcmZ`%%}?7f6t~l)P16G1G=a9m<ZBNs$4O{nt461xL5paSre3l%c4;7qi|tml>ZD0* z+HHTq4j}EqVgHb?J8|ZQG-=N%f?arupWm0?$M1zNEqMs&clv4Yy@1dkqx?@LP~O0i zUw~26Lljdh!9AScR?mXFkQ7q8XQxij!HBL<n>t@{uLx3+mOv^om%7K6*kol|X4a8+ zUSasCO7T;4f!EL(#t1wf*p_JJe3@41(uH+a$gRu9ORY|R>b2RoT~5adBQl(@U=Sxv z62-|d%qSR*PPY9v8E`>ps6rBFM4c)EZZZnR$(SkQOGD*(gplqqmLy#y6fB7$8P7<R zgi?YCZ__yC5f}Xz{qbPHL=f>z37&XY00wH+EnOA;K=JOWGNpAb*Y*~Lj3u&7;4Ky5 zcHn$~bNw8cf}!SUUZD7=HMf7^ANaE~cg_$Dj5_GDU<y<uAB%_uNi3DFK>a~{7|=LU zm#B_~1z9eO!erKE8E40fxGL{UCIBGwN|+Vu60{a)1FkJO5iVGAcJtaF@|5`}<4`L9 zFjoFPqkFLmr=c$x9p%z`8jXgbzracQ_sG8(O`$)t2*m?{xe95o&BRZzhs6pA56&-4 zm@sI-6!706Q8w(ZF|iD)uI9;a7x&l%)C_xMd~Oh=VVniQ%<V)X9;pp7bN8ld$g>Ti zv3Io!Q8##f_OknayF=h>klpsy!A_GjT3e*m?vmYRqtzwv+WVx_1zTgM-D;BN$L8CE z?smIXw_8B<6<rDf%A+9A1v!=4;!>|Y@L%NnSd3$)ziTuLQwHyyk%%*;?NO+P+U<vu z8Hct*aX8VX2@^8rnRb$+F>LJ~id@R^a9=H!u!$kNGy~embzEG-p6wM~=NVqbRc!zL E2mXQtjsO4v literal 0 HcmV?d00001 diff --git a/modules/__pycache__/save_files.cpython-311.pyc b/modules/__pycache__/save_files.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8438319ec401b1a914fec694630618c82f38c344 GIT binary patch literal 1493 zcmb_b&2Jk;6rb50f9%>xTM$^`G*S+csaju>1_cC4Y9k^wb`-k^`Le8c*6}9ZU3YdI z8WSWV710yoP^lLV7D8#G6sgDl2|e1CC8Cw+g;Q^qa?6P~yD>BcZoHj&Z|2RL_kQoq z+eb4qIs*FD{j&MJiqIc&Go|$T;&c`x^bj#rM+`Hijq5m)N?ie|wpEwZiJPb=Fk&-| z+{5)G$OOogoo2~hMf%}PLAJ(Hwz3mNl)6Di@;AxGJK3p@;koG&9RiADm@)N0T-0C` zMM%T_nW+`i2D8)k>yqg#a|pPOBW&{I5VAjp8PmD1?3)poQbls+XM5jm_^jKuX<+Wz zM$>8A0Tn)NnH~eB+|%_!g*JUonJG-_cvRdK6pm@f<afHZkY}zbbe&RKYdHaRV~5;s zJK)UssMR)u0G4pqbzI-_dE<Jc+icq0uzXK&zpcNLc*}Vu%<_gI{Mub1Lx-26-DVs} zYAkY|nG{Kwvh=4P0DFkUUqwZb+yOdJ8U9H*Aiv-r@HYts9V8CH?iglF@XV-+j#L>o z6Zl<j*+$z5M3@0oO=sI+jwOyz9&=gGqa;s(2(`fRc4ND&-w13DWs|qKY_l*0fE};t zhf1&)NPJKfptDa3E#I{Zce-XE3fqn-Y}stn5$3*G;5O?-t81>+X_<w%d_m#w2f5za z2Y~W@gl|Cg`DJh{dn>pKtdD-z-Wh6JgR9Rz1OemuLM;1hCnVWl`?h$m*pI$bFh~D? z3As!Z$|T>0%fI5a%=snQhuH}IdBgCxLG_k2o5G(PYM&2wpM4Di#`Eo1{sTV0B7LO| z!!;exFnZ~##hs2=p}q9xzG(U03O&R6t9QZb3}5Rl*FIaXQW&drqf)$mt3+4JMOv=Z z=tgO^T%(^>wrI5my472ia*39{DBZkWTd$P!qzsh56s8P=`IcdXYOo)KiXViz|LEVS zL*o49+e8^kpq}a4a6i%EjweFWF-0p(H_X762O%-}_FkCUvw7h7UYKa_bfJ$l=|E;0 zmF_J4QQQz8^Lfz877tzmo2VG$iK1dML6YeRXZpJQPLS4*z7w=I{I@YlD_EPLi!6I_ z8=dNiWbgN0sB=Sg?u2Ol(*5^;<PX03Ew}I@xA0hfl74#SNoJH=9Oo8C`r?QzjmgrG zEKN<V2fKsCM=L+CJZ?OlAI;ww&)*o4<uO?vlI6%|sNWos;+PbN(=kaQ@*YHs^8XX% Cw0dj+ literal 0 HcmV?d00001 diff --git a/modules/__pycache__/spectrum_filter.cpython-310.pyc b/modules/__pycache__/spectrum_filter.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2654ba2c30ba1ff2f15a2e882c28db1786368ca7 GIT binary patch literal 3736 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 literal 0 HcmV?d00001 diff --git a/modules/__pycache__/spectrum_filter.cpython-311.pyc b/modules/__pycache__/spectrum_filter.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb8923dcc4ebbf21c4b01e74dd7460d7a7ed07df GIT binary patch literal 5498 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 F{10oL37r4{ literal 0 HcmV?d00001 diff --git a/modules/filters.py b/modules/filters.py new file mode 100644 index 0000000..7158cc6 --- /dev/null +++ b/modules/filters.py @@ -0,0 +1,94 @@ +from mimocorb import mimo_buffer as bm +from scipy import signal +import numpy as np +from numpy.lib import recfunctions as rfn +import sys +import os + + +def normed_pulse(ch_input, position, prominence, analogue_offset): + # > Compensate for analogue offset + ch_data = ch_input - analogue_offset + # > Find pulse area + # rel_height is not good because of the quantized nature of the picoscope data + # so we have to "hack" a little bit to always cut 10mV above the analogue offset + width_data = signal.peak_widths(ch_data, [int(position)], rel_height=(ch_data[int(position)] - 10) / prominence) + left_ips, right_ips = width_data[2], width_data[3] + # Crop pulse area and normalize + pulse_data = ch_data[int(np.floor(left_ips)) : int(np.ceil(right_ips))] + pulse_int = sum(pulse_data) + pulse_data *= 1 / pulse_int + return pulse_data, int(np.floor(left_ips)), pulse_int + + +def correlate_pulses(data_pulse, reference_pulse): + correlation = signal.correlate(data_pulse, reference_pulse, mode="same") + shift_array = signal.correlation_lags(data_pulse.size, reference_pulse.size, mode="same") + shift = shift_array[np.argmax(correlation)] + return shift + + +def tag_peaks(input_data, prominence, distance, width): + peaks = {} + peaks_prop = {} + for key in input_data.dtype.names: + peaks[key], peaks_prop[key] = signal.find_peaks( + input_data[key], prominence=prominence, distance=distance, width=width + ) + return peaks, peaks_prop + + +def correlate_peaks(peaks, tolerance): + m_dtype = [] + for key in peaks.keys(): + m_dtype.append((key, np.int32)) + next_peak = {} + for key, data in peaks.items(): + if len(data) > 0: + next_peak[key] = data[0] + correlation_list = [] + while len(next_peak) > 0: + minimum = min(next_peak.values()) + line = [] + for key, data in peaks.items(): + if key in next_peak: + if abs(next_peak[key] - minimum) < tolerance: + idx = data.tolist().index(next_peak[key]) + line.append(idx) + if len(data) > idx + 1: + next_peak[key] = data[idx + 1] + else: + del next_peak[key] + else: + line.append(-1) + else: + line.append(-1) + correlation_list.append(line) + array = np.zeros(len(correlation_list), dtype=m_dtype) + for idx, line in enumerate(correlation_list): + array[idx] = tuple(line) + return array + + +def match_signature(peak_matrix, signature): + if len(signature) > len(peak_matrix): + return False + # Boolean array with found peaks + input_peaks = rfn.structured_to_unstructured(peak_matrix) >= 0 + must_have_peak = np.array(signature, dtype=np.str0) == "+" + must_not_have_peak = np.array(signature, dtype=np.str0) == "-" + match = True + # Check the signature for each peak (1st peak with 1st signature, 2nd peak with 2nd signature, ...) + for idx in range(len(signature)): + # Is everywhere a peak, where the signature expects one -> Material_conditial(A, B): (not A) OR B + first = (~must_have_peak[idx]) | input_peaks[idx] + # Is everywhere no peak, where the signature expects no peak -> NAND(A, B): not (A and B) + second = ~(must_not_have_peak[idx] & input_peaks[idx]) + match = match & (np.all(first) & np.all(second)) + return match + + +if __name__ == "__main__": + print("Script: " + os.path.basename(sys.argv[0])) + print("Python: ", sys.version, "\n".ljust(22, "-")) + print("THIS IS A MODULE AND NOT MEANT FOR STANDALONE EXECUTION") diff --git a/modules/plot_histograms.py b/modules/plot_histograms.py new file mode 100644 index 0000000..fce2408 --- /dev/null +++ b/modules/plot_histograms.py @@ -0,0 +1,27 @@ +""" +**plot_histograms**: histogram variable(s) from buffer using mimoCoRB.histogram_buffer +""" +import sys +import os +from mimocorb.histogram_buffer import histogram_buffer +import matplotlib + +# select matplotlib frontend if needed +matplotlib.use("TkAgg") + + +def plot_histograms(source_list=None, sink_list=None, observe_list=None, config_dict=None, **rb_info): + """ + Online display of histogram(s) of variable(s) from mimiCoRB buffer + + :param input: configuration dictionary + + """ + histbuf = histogram_buffer(source_list, sink_list, observe_list, config_dict, **rb_info) + histbuf() + + +if __name__ == "__main__": + print("Script: " + os.path.basename(sys.argv[0])) + print("Python: ", sys.version, "\n".ljust(22, "-")) + print("THIS IS A MODULE AND NOT MEANT FOR STANDALONE EXECUTION") diff --git a/modules/plot_waveform.py b/modules/plot_waveform.py new file mode 100644 index 0000000..66d0c12 --- /dev/null +++ b/modules/plot_waveform.py @@ -0,0 +1,33 @@ +""" +**plot**: plotting waveforms from buffer using mimoCoRB.buffer_control.OberserverData +""" + +import sys +import os +from mimocorb.plot_buffer import plot_buffer +import matplotlib + +# select matplotlib frontend if needed +matplotlib.use("TkAgg") + + +def plot_waveform(source_list=None, sink_list=None, observe_list=None, config_dict=None, **rb_info): + """ + Plot waveform data from mimiCoRB buffer + + :param input: configuration dictionary + + - plot_title: graphics title to be shown on graph + - min_sleeptime: time between updates + - sample_time_ns, channel_range, pretrigger_samples and analogue_offset + describe the waveform data as for oscilloscope setup + """ + + pltbuf = plot_buffer(source_list, sink_list, observe_list, config_dict, **rb_info) + pltbuf() + + +if __name__ == "__main__": + print("Script: " + os.path.basename(sys.argv[0])) + print("Python: ", sys.version, "\n".ljust(22, "-")) + print("THIS IS A MODULE AND NOT MEANT FOR STANDALONE EXECUTION") diff --git a/modules/redPitaya_source.py b/modules/redPitaya_source.py new file mode 100644 index 0000000..adabc04 --- /dev/null +++ b/modules/redPitaya_source.py @@ -0,0 +1,54 @@ +""" +**simul_source**: a simple template for a mimoCoRB source to +enter simulated wave form data in a mimoCoRB buffer. + +Input data is provided as numpy-arry of shape (number_of_channels, number_of_samples). +""" + +from mimocorb.buffer_control import rbImport +import numpy as np +import sys, time +from pulseSimulator import pulseSimulator + +def simul_source(source_list=None, sink_list=None, observe_list=None, config_dict=None, **rb_info): + """ + Generate simulated data and pass data to buffer + + The class mimocorb.buffer_control/rbImport is used to interface to the + newBuffer and Writer classes of the package mimoCoRB.mimo_buffer + + This example may serve as a template for other data sources + + :param config_dict: configuration dictionary + + - events_required: number of events to be simulated or 0 for infinite + - sleeptime: (mean) time between events + - random: random time between events according to a Poission process + - number_of_samples, sample_time_ns, pretrigger_samples and analogue_offset + describe the waveform data to be generated (as for oscilloscope setup) + + Internal parameters of the simulated physics process (the decay of a muon) + are (presently) not exposed to user. + """ + + events_required = 1000 if "eventcount" not in config_dict else config_dict["eventcount"] + + def yield_data(): + """generate simulated data, called by instance of class mimoCoRB.rbImport""" + + event_count = 0 + while events_required == 0 or event_count < events_required: + pulse = dataSource(number_of_channels) + # deliver pulse data and no metadata + yield (pulse, None) + event_count += 1 + + dataSource = pulseSimulator(config_dict) + simulsource = rbImport(config_dict=config_dict, sink_list=sink_list, ufunc=yield_data, **rb_info) + number_of_channels = len(simulsource.sink.dtype) + # possibly check consistency of provided dtype with simulation ! + + # TODO: Change to logger! + # print("** simul_source ** started, config_dict: \n", config_dict) + # print("?> sample interval: {:02.1f}ns".format(osci.time_interval_ns.value)) + simulsource() diff --git a/modules/save_files.py b/modules/save_files.py new file mode 100644 index 0000000..0007447 --- /dev/null +++ b/modules/save_files.py @@ -0,0 +1,26 @@ +"""Module save_files to handle file I/O for data in txt and parquet format + + This module relies on classes in mimocorb.buffer_control +""" + +import sys +import os +from mimocorb.buffer_control import rb_toTxtfile, rb_toParquetfile + + +# def save_to_txt(source_dict): +def save_to_txt(source_list=None, sink_list=None, observe_list=None, config_dict=None, **rb_info): + sv = rb_toTxtfile(source_list=source_list, config_dict=config_dict, **rb_info) + sv() + # print("\n ** save_to_txt: end seen") + + +def save_parquet(source_list=None, sink_list=None, observe_list=None, config_dict=None, **rb_info): + sv = rb_toParquetfile(source_list=source_list, config_dict=config_dict, **rb_info) + sv() + + +if __name__ == "__main__": + print("Script: " + os.path.basename(sys.argv[0])) + print("Python: ", sys.version, "\n".ljust(22, "-")) + print("THIS IS A MODULE AND NOT MEANT FOR STANDALONE EXECUTION") diff --git a/modules/spectrum_filter.py b/modules/spectrum_filter.py new file mode 100644 index 0000000..fc80228 --- /dev/null +++ b/modules/spectrum_filter.py @@ -0,0 +1,106 @@ +"""Module **pulse_filter** + +This (rather complex) module filters waveform data to search for valid signal pulses. +The code first validates the trigger pulse, identifies coincidences of signals in +different layers (indiating the passage of a cosmic ray particle, a muon) and finally +searches for double-pulse signatures indicating that a muon was stopped in or near +a detection layer where the resulting decay-electron produced a delayed pulse. +The time difference between the initial and the delayed pulses is the individual +lifetime of the muon. + +The decay time and the properties of the signal pulses (height, integral and +postition in time) are written to a buffer; the raw wave forms are optionally +also written to another buffer. + +The callable functions *find_peaks()* and *calulate_decay_time()* depend on the +buffer manager *mimoCoRB* and provide the filter functionality described above. +These functions support multiple sinks to be configured for output. + +The relevant configuration parameters can be found in the section *find_peaks:* +and *calculate_decay_time:* in the configuration file. + +""" + +from mimocorb.buffer_control import rbTransfer +import numpy as np +import pandas as pd +import os, sys + +from filters import * + +def find_peaks(source_list=None, sink_list=None, observe_list=None, config_dict=None, **rb_info): + """filter client for mimoCoRB: Find valid signal pulses in waveform data + + Input: + + - wave form data from source buffer defined in source_list + + Returns: + + - None if filter not passed + - list of list(s) of pulse parameters, written to sinks defined in sink_list + + """ + + if config_dict is None: + raise ValueError("ERROR! Wrong configuration passed (in lifetime_modules: calculate_decay_time)!!") + + # Load configuration + sample_time_ns = config_dict["sample_time_ns"] + analogue_offset = config_dict["analogue_offset"]*1000 + peak_minimal_prominence = config_dict["peak_minimal_prominence"] + peak_minimal_distance = config_dict["peak_minimal_distance"] + peak_minimal_width = config_dict["peak_minimal_width"] + pre_trigger_samples = config_dict["pre_trigger_samples"] + trigger_channel = config_dict["trigger_channel"] + if trigger_channel not in ['A','B','C','D']: + trigger_channel = None + trigger_position_tolerance = config_dict["trigger_position_tolerance"] + + pulse_par_dtype = sink_list[-1]['dtype'] + + + def tag_pulses(input_data): + """find all valid pulses + + This function to be called by instance of class mimoCoRB.rbTransfer + + Args: input data as structured ndarray + + Returns: list of parameterized pulses + """ + + # Find all the peaks and store them in a dictionary + peaks, peaks_prop = tag_peaks(input_data, peak_minimal_prominence, peak_minimal_distance, peak_minimal_width) + + # identify trigger channel, validate trigger pulse and get time of trigger pulse + if trigger_channel is not None: + trigger_peaks = peaks['ch' + trigger_channel] + if len(trigger_peaks) == 0: + return None + reference_position = trigger_peaks[np.argmin(np.abs(trigger_peaks - pre_trigger_samples))] + else: # external or no trigger: set to nominal position + reference_position = pre_trigger_samples + + peak_data= np.zeros( (1,), dtype=pulse_par_dtype) + for key in peaks.keys(): + for position, height, left_ips, right_ips in zip( + peaks[key], peaks_prop[key]['prominences'], + peaks_prop[key]['left_ips'], peaks_prop[key]['right_ips']): + if np.abs(reference_position - position) < trigger_position_tolerance: + peak_data[0][key+'_position'] = position + peak_data[0][key+'_height'] = input_data[key][position] - analogue_offset #height + left = int(np.floor(left_ips)) + right = int(np.ceil(right_ips)) + peak_data[0][key+'_integral'] = \ + sum(input_data[key][left:right] - analogue_offset) * sample_time_ns * 1e-9/50/5 + return [peak_data] + + p_filter = rbTransfer(source_list=source_list, sink_list=sink_list, config_dict=config_dict, + ufunc=tag_pulses, **rb_info) + p_filter() + +if __name__ == "__main__": + print("Script: " + os.path.basename(sys.argv[0])) + print("Python: ", sys.version, "\n".ljust(22, '-')) + print("THIS IS A MODULE AND NOT MEANT FOR STANDALONE EXECUTION") diff --git a/redP_mimoCoRB.py b/redP_mimoCoRB.py new file mode 100644 index 0000000..6882767 --- /dev/null +++ b/redP_mimoCoRB.py @@ -0,0 +1,51 @@ +""" +**redP_mimoCoRB**: a simple template to use mimoCoRB with the RedPitaya and redPoscdaq.py + +Input data is provided as numpy-arry of shape (number_of_channels, number_of_samples). +""" + +import time +import sys + +import redPoscdaq as rp + + +def redP_to_rb(source_list=None, sink_list=None, observe_list=None, config_dict=None, **rb_info): + """ + Get data from RedPitaya and pass data to buffer + + The class mimocorb.buffer_control/rbImport is used to interface to the + newBuffer and Writer classes of the package mimoCoRB.mimo_buffer + + This example may serve as a template for other data sources + + :param config_dict: configuration dictionary + + - events_required: number of events to be simulated or 0 for infinite + - sleeptime: (mean) time between events + - random: random time between events according to a Poission process + - number_of_samples, sample_time_ns, pretrigger_samples and analogue_offset + describe the waveform data to be generated (as for oscilloscope setup) + + Internal parameters of the simulated physics process (the decay of a muon) + are (presently) not exposed to user. + """ + + # initialize mimocorb class inside redPoscidaq + datasource= rp.redP_mimocorb(config_dict=config_dict, sink_list=sink_list, **rb_info) + #print("data source initialized") + + # start oscilloscope + #print("starting osci") + rp.run_rpControl(callback=datasource.data_sink, conf_dict=config_dict) + + +#daq = run_mimoDAQ('redP_mimoCoRB.yaml') +#daq.setup() +#RB_1 = daq.ringbuffers['RB_1'] +#sink_dict = RB_1.new_writer() +#datasource= rp.redP_mimocorb(config_dict={}, sink_list=[sink_dict], RB_1='write') +#print("data source initialized") +#rp.run_rpControl(callback=datasource.data_sink) +#print("starting DAQ") +#daq.run() diff --git a/setup.yaml b/setup.yaml new file mode 100644 index 0000000..a079387 --- /dev/null +++ b/setup.yaml @@ -0,0 +1,86 @@ +# Configuration for recording two channels with mimoCoRB +# ----------------------------------------------------- +# +# configure two buffers: +# - RB_1 for raw waveforms +# - RB_2 for derived pulse parameters +# data from RB_2, the result buffer, are saved to a file in csv (text) format. +# +# - data from RB_1 are also passed to an obsever process driving a real-time display +# - data from RB_2 are passed to a Reader process driving a real-time histogram display +# +# Notes: +# +# 1. additional config files controlling the user functions are +# located in the subdirectory config/ +# 2. necessary application-specific user code is located +# in the subdirectory modules/ +# +# ---------------------------------------------------------------------------- +# + +RingBuffer: + # define ring buffers + - RB_1: + # raw input data buffer (from picoScope, file or simulation) + number_of_slots: 16 + channel_per_slot: 2048 + data_type: + 1: ['chA', "float32"] + 2: ['chB', "float32"] + - RB_2: + # buffer with correct signature double pulse parameters + number_of_slots: 16 + channel_per_slot: 1 + data_type: + data_type: + 1: ['chA_height', "float32"] + 2: ['chA_position', "int32"] + 3: ['chA_integral', "float32"] + 4: ['chB_height', "float32"] + 5: ['chB_position', "int32"] + 6: ['chB_integral', "float32"] + +Functions: + # define functions and ringbuffer assignment + + - Fkt_main: + config_file: "config/spectrum_config.yaml" + + - Fkt_1: + ## for simulation with rbPut + file_name: "redP_mimoCoRB" + fkt_name: "redP_to_rb" + num_process: 1 + RB_assign: + RB_1: "write" + + - Fkt_2: + file_name: "modules/spectrum_filter" + fkt_name: "find_peaks" + num_process: 2 + RB_assign: + RB_1: "read" + RB_2: "write" + + - Fkt_3: + file_name: "modules/save_files" + fkt_name: "save_to_txt" + num_process: 1 + RB_assign: + RB_2: "read" + +# --- the following functions are optioal + + - Fkt_4: + file_name: "modules/plot_waveform" + fkt_name: "plot_waveform" + num_process: 1 + RB_assign: + RB_1: "observe" + - Fkt_5: + file_name: "modules/plot_histograms" + fkt_name: "plot_histograms" + num_process: 1 + RB_assign: + RB_2: "read" # pulse parameters -- GitLab