6 #include "WireCellIface/IDepo.h" 7 #include "WireCellGen/GaussianDiffusion.h" 8 #include "WireCellUtil/NamedFactory.h" 9 #include "WireCellUtil/Units.h" 26 cfg[
"anodes_tn"] = Json::arrayValue;
27 cfg[
"anode"] =
"AnodePlane";
28 cfg[
"rng"] =
"Random";
29 cfg[
"artlabel"] =
"simpleSC";
42 cfg[
"use_energy"] =
false;
43 cfg[
"use_extra_sigma"] =
false;
50 auto anodes_tn = cfg[
"anodes_tn"];
51 for (
auto anode_tn: anodes_tn) {
52 auto anode = Factory::find_tn<IAnodePlane>(anode_tn.asString());
53 m_anodes.push_back(anode);
62 for (
auto& anode: m_anodes){
63 for (
auto&
channel: anode->channels()){
70 if (m_anodes.empty()) {
71 const std::string anode_tn = cfg[
"anode"].asString();
72 if (anode_tn.empty()) {
73 THROW(ValueError() << errmsg{
"SimChannelSink requires an anode plane"});
75 auto anode = Factory::find_tn<IAnodePlane>(anode_tn);
76 m_anodes.push_back(anode);
81 THROW(ValueError() << errmsg{
"SimChannelSink requires a noise source"});
83 m_rng = Factory::find_tn<IRandom>(rng_tn);
85 m_artlabel = cfg[
"artlabel"].asString();
86 m_artlabel =
get(cfg,
"artlabel",m_artlabel);
87 m_start_time =
get(cfg,
"start_time",-1.6*
units::ms);
88 m_readout_time =
get(cfg,
"readout_time",4.8*
units::ms);
90 m_nsigma =
get(cfg,
"nsigma",3.0);
92 m_u_to_rp =
get(cfg,
"uboone_u_to_rp",94*
units::mm);
93 m_v_to_rp =
get(cfg,
"uboone_v_to_rp",97*
units::mm);
94 m_y_to_rp =
get(cfg,
"uboone_y_to_rp",100*
units::mm);
96 if (cfg.isMember(
"u_to_rp")) m_u_to_rp =
get(cfg,
"u_to_rp",90.58*
units::mm);
97 if (cfg.isMember(
"v_to_rp")) m_v_to_rp =
get(cfg,
"v_to_rp",95.29*
units::mm);
98 if (cfg.isMember(
"y_to_rp")) m_y_to_rp =
get(cfg,
"y_to_rp",100.0*
units::mm);
100 m_u_time_offset =
get(cfg,
"u_time_offset",0.0*
units::us);
101 m_v_time_offset =
get(cfg,
"v_time_offset",0.0*
units::us);
102 m_y_time_offset =
get(cfg,
"y_time_offset",0.0*
units::us);
103 m_g4_ref_time =
get(cfg,
"g4_ref_time",-4050*
units::us);
104 m_use_energy =
get(cfg,
"use_energy",
false);
105 m_use_extra_sigma =
get(cfg,
"use_extra_sigma",
false);
111 collector.
produces< std::vector<sim::SimChannel> >(m_artlabel);
114 void SimChannelSink::save_as_simchannel(
const WireCell::IDepo::pointer& depo){
122 double response_plane = 10.0 *
units::cm;
123 double response_time_offset = response_plane / m_drift_speed;
124 int response_nticks = (
int)(response_time_offset / m_tick);
125 Binning tbins(m_readout_time/m_tick + response_nticks, m_start_time - response_time_offset, m_start_time+m_readout_time);
133 for (
auto anode: m_anodes) {
134 for(
auto face : anode->faces()){
135 auto boundbox = face->sensitive();
136 if(!boundbox.inside(depo->pos()))
continue;
140 for (
auto plane : face->planes()) {
142 int iplane = plane->planeid().index();
143 if (iplane<0)
continue;
144 const Pimpos* pimpos = plane->pimpos();
145 auto& wires = plane->wires();
147 const double center_time = depo->time();
148 const double center_pitch = pimpos->distance(depo->pos());
150 double sigma_L = depo->extent_long();
151 if (m_use_extra_sigma) {
153 double time_slice_width = nrebin * m_drift_speed * m_tick;
154 double add_sigma_L = 1.428249 * time_slice_width / nrebin / (m_tick/
units::us);
155 sigma_L = sqrt(
pow(depo->extent_long(),2) +
pow(add_sigma_L,2) );
157 Gen::GausDesc time_desc(center_time, sigma_L / m_drift_speed);
160 double nmin_sigma = time_desc.distance(tbins.min());
161 double nmax_sigma = time_desc.distance(tbins.max());
163 double eff_nsigma = depo->extent_long() / m_drift_speed>0?m_nsigma:0;
164 if (nmin_sigma > eff_nsigma || nmax_sigma < -eff_nsigma) {
170 auto wbins = pimpos->region_binning();
172 double sigma_T = depo->extent_tran();
173 if (m_use_extra_sigma) {
174 double add_sigma_T = wbins.binsize();
175 if (iplane==0) add_sigma_T *= (0.402993*0.3);
176 else if (iplane==1) add_sigma_T *= (0.402993*0.5);
177 else if (iplane==2) add_sigma_T *= (0.188060*0.2);
178 sigma_T = sqrt(
pow(depo->extent_tran(),2) +
pow(add_sigma_T,2) );
180 Gen::GausDesc pitch_desc(center_pitch, sigma_T);
183 double nmin_sigma = pitch_desc.distance(wbins.min());
184 double nmax_sigma = pitch_desc.distance(wbins.max());
186 double eff_nsigma = depo->extent_tran()>0?m_nsigma:0;
187 if (nmin_sigma > eff_nsigma || nmax_sigma < -eff_nsigma) {
192 auto gd = std::make_shared<Gen::GaussianDiffusion>(depo, time_desc, pitch_desc);
193 gd->set_sampling(tbins, wbins, m_nsigma, 0, 1);
199 id = depo->prior()->id();
200 if(m_use_energy){ energy = depo->prior()->energy(); }
204 if(m_use_energy){ energy = depo->energy(); }
207 const auto patch = gd->patch();
208 const int poffset_bin = gd->poffset_bin();
209 const int toffset_bin = gd->toffset_bin();
210 const int np =
patch.rows();
211 const int nt =
patch.cols();
214 int max_imp = wbins.nbins();
216 for (
int pbin = 0; pbin != np; pbin++){
217 int abs_pbin = pbin + poffset_bin;
218 if (abs_pbin < min_imp || abs_pbin >= max_imp)
continue;
220 auto iwire = wires[abs_pbin];
221 int channel = iwire->channel();
226 auto channelData = m_mapSC.find(channel);
229 : channelData->second;
231 for (
int tbin = 0; tbin!= nt; tbin++){
232 int abs_tbin = tbin + toffset_bin;
233 double charge =
patch(pbin, tbin);
234 double tdc = tbins.center(abs_tbin);
238 tdc = tdc + (m_u_to_rp/m_drift_speed) + m_u_time_offset;
242 tdc = tdc + (m_v_to_rp/m_drift_speed) + m_v_time_offset;
246 tdc = tdc + (m_y_to_rp/m_drift_speed) + m_y_time_offset;
250 WireCell::IDepo::pointer orig = depo_chain(depo).back();
255 unsigned int temp_time = (
unsigned int) ( (tdc - m_g4_ref_time) / m_tick );
256 charge =
abs(charge);
270 std::unique_ptr<std::vector<sim::SimChannel> > out(
new std::vector<sim::SimChannel>);
272 for(
auto&
m : m_mapSC){
273 out->emplace_back(
m.second);
278 for (
auto& elem: m_mapSC){
284 bool SimChannelSink::operator()(
const WireCell::IDepo::pointer& indepo,
285 WireCell::IDepo::pointer& outdepo)
290 save_as_simchannel(m_depo);
static constexpr double cm
static constexpr double us
Energy deposited on a readout channel by simulated tracks.
WIRECELL_FACTORY(wclsSimChannelSink, wcls::SimChannelSink, wcls::IArtEventVisitor, WireCell::IDepoFilter) using namespace wcls
static constexpr double ms
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
void AddIonizationElectrons(TrackID_t trackID, TDC_t tdc, double numberElectrons, double const *xyz, double energy)
Add ionization electrons and energy to this channel.
for(std::string line;std::getline(inFile, line);)
static constexpr double mm
Event finding and building.