37 #include <sys/types.h> 38 #include <sys/socket.h> 40 #include <netinet/ip.h> 42 #include <sys/types.h> 89 "Server: WebEVD/1.0.0\r\n" 90 "Content-Type: "+content+
"\r\n";
92 if(gzip) str +=
"Content-Encoding: gzip\r\n";
96 write(sock, &str.front(), str.size());
102 "HTTP/1.0 404 Not Found\r\n" 103 "Server: WebEVD/1.0.0\r\n" 104 "Content-Type: text/plain\r\n" 108 write(sock, str, strlen(str));
114 "HTTP/1.0 501 Not Implemented\r\n" 115 "Server: WebEVD/1.0.0\r\n" 116 "Content-Type: text/plain\r\n" 118 "I don't know how to do that\r\n";
120 write(sock, str, strlen(str));
127 std::vector<char> buf(1024*1024);
129 const int nread =
read(sock, &buf.front(), buf.size());
130 if(nread == 0)
return ret;
131 ret.insert(ret.end(), buf.begin(), buf.begin()+nread);
134 if(ret.find(
"\r\n\r\n") != std::string::npos)
return ret;
148 int run = -1, subrun = -1,
evt = -1;
151 if(cmd ==
"/QUIT") code =
kQUIT;
152 if(cmd ==
"/NEXT") code =
kNEXT;
153 if(cmd ==
"/PREV") code =
kPREV;
154 if(cmd ==
"/NEXT_TRACES"){ code =
kNEXT; traces =
true;}
155 if(cmd ==
"/PREV_TRACES"){ code =
kPREV; traces =
true;}
157 if(cmd.find(
"/seek/") == 0 ||
158 cmd.find(
"/seek_traces/") == 0){
159 if(cmd.find(
"/seek_traces/") == 0) traces =
true;
163 strtok_r(cmd.data(),
"/", &ctx);
164 run = atoi(strtok_r(0,
"/", &ctx));
165 subrun = atoi(strtok_r(0,
"/", &ctx));
166 evt = atoi(strtok_r(0,
"/", &ctx));
172 const int delay = (code ==
kQUIT) ? 2000 : 0;
174 const std::string next = traces ?
"/traces.html" :
"/";
178 const std::string msg =
TString::Format(
"<!DOCTYPE html><html><head><meta charset=\"utf-8\"><script>setTimeout(function(){window.location.replace('%s');}, %d);</script></head><body><script>if(window.sessionStorage.theme != 'lighttheme'){document.body.style.backgroundColor='black';document.body.style.color='white';}</script><h1>%s</h1></body></html>", next.c_str(), delay, txt.c_str()).
Data();
180 write(sock, msg.c_str(), msg.size());
204 std::cout <<
"Unable to find webevd files under $MRB_SOURCE or $PRODUCTS" <<
std::endl;
226 const char* pName = strtok_r(&doc.front(),
"_", &ctx);
227 const char* pIdx = strtok_r(0,
"_", &ctx);
228 const char* pDim = strtok_r(0,
".", &ctx);
230 if(!pName || !pIdx || !pDim){
237 const int idx = atoi(pIdx);
238 const int dim = atoi(pDim);
241 if(name ==
"/dig") arena = &digs->
GetArena();
242 if(name ==
"/wire") arena = &wires->
GetArena();
251 FILE*
f = fdopen(sock,
"wb");
259 std::vector<unsigned char>&
dest,
264 strm.zalloc = Z_NULL;
266 strm.opaque = Z_NULL;
269 strm.avail_in = length;
273 deflateInit2(&strm, level, Z_DEFLATED, 15 | 16, 9, Z_DEFAULT_STRATEGY);
276 dest.resize(deflateBound(&strm, length));
278 strm.next_out = dest.data();
279 strm.avail_out = dest.size();
281 deflate(&strm, Z_FINISH);
283 dest.resize(dest.size() - strm.avail_out);
295 std::vector<unsigned char>
dest;
298 std::cout <<
"Writing " << length <<
" bytes (compressed to " << dest.size() <<
") for " << name <<
"\n" <<
std::endl;
300 write(sock, dest.data(), dest.size());
306 int fd_in =
open(loc.c_str(), O_RDONLY);
311 unsigned char* src = (
unsigned char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd_in, 0);
315 munmap(src, st.st_size);
323 return s.rfind(suffix)+suffix.size() == s.size();
329 json <<
"\"" << t.
label();
355 <<
", \"rms\": " << hit.
RMS()
362 return json << TVector3(vtx.
position().x(),
381 return json << TVector3(sp.
XYZ());
387 std::vector<TVector3> pts;
393 pts.emplace_back(pt.X(), pt.Y(), pt.Z());
396 return json <<
"{ \"positions\": " << pts <<
" }";
403 if(apdg == 12 || apdg == 14 || apdg == 16)
return json <<
"{ \"pdg\": " << apdg <<
", \"positions\": [] }";
404 std::vector<TVector3> pts;
406 pts.emplace_back(part.
Vx(j), part.
Vy(j), part.
Vz(j));
409 return json <<
"{ \"pdg\": " << apdg <<
", \"positions\": " << pts <<
" }";
415 json << std::map<std::string, double>{
416 {
"tcenter", flash.
Time()},
419 {
"ywidth", flash.
YWidth()},
421 {
"zwidth", flash.
ZWidth()},
431 const TVector3 r0(cryo.
MinX(), cryo.
MinY(), cryo.
MinZ());
432 const TVector3 r1(cryo.
MaxX(), cryo.
MaxY(), cryo.
MaxZ());
433 return json <<
"{ \"min\": " << r0 <<
", \"max\": " << r1 <<
" }";
439 return json <<
"{ \"name\": " << opdet.
ID() <<
", " 440 <<
"\"center\": " << TVector3(opdet.
GetCenter().X(),
443 <<
"\"length\": " << opdet.
Length() <<
", " 444 <<
"\"width\": " << opdet.
Width() <<
", " 445 <<
"\"height\": " << opdet.
Height() <<
" }";
452 os <<
"{\"blocks\": [\n";
453 for(
unsigned int ix = 0; ix < v.
blocks.size(); ++ix){
454 for(
unsigned int iy = 0; iy < v.
blocks[ix].size(); ++iy){
458 if(!first) os <<
",\n";
478 <<
"\"fname\": \"" << v.
arena.
name <<
"_" << dataidx <<
"\", " 480 <<
"\"u\": " << texdx <<
", " 481 <<
"\"v\": " << texdy <<
", " 492 template<
class TProd,
class TEvt>
void 497 const std::vector<art::InputTag> tags = evt.template getInputTags<std::vector<TProd>>();
500 json <<
" " <<
tag <<
": ";
502 typename TEvt::template HandleT<std::vector<TProd>> prods;
504 if(!evt.getByLabel(tag, prods))
continue;
508 if(tag != tags.back()){
518 template<
class TProd,
class TEvt>
void 523 typename TEvt::template HandleT<std::vector<TProd>> prods;
524 evt.getByLabel(in_label, prods);
537 typedef std::map<std::string, int> EIdMap;
538 json << EIdMap({{
"run", evt.run()}, {
"subrun", evt.subRun()}, {
"evt", evt.event()}});
554 json <<
" \"planes\": {\n";
557 const int view = planegeo.
View();
559 const double pitch = planegeo.
WirePitch();
566 const double depth = planegeo.
Depth();
567 const double width = planegeo.
Width();
568 const TVector3 depthdir = planegeo.
DepthDir();
569 const TVector3 widthdir = planegeo.
WidthDir();
572 const double tick_pitch = detprop.
ConvertTicksToX(1, plane) - tick_origin;
576 if(!first) json <<
",\n";
579 json <<
" " << plane <<
": {" 580 <<
"\"view\": " << view <<
", " 581 <<
"\"nwires\": " << nwires <<
", " 582 <<
"\"pitch\": " << pitch <<
", " 583 <<
"\"nticks\": " << maxTick <<
", " 584 <<
"\"tick_origin\": " << tick_origin <<
", " 585 <<
"\"tick_pitch\": " << tick_pitch <<
", " 586 <<
"\"center\": " << c <<
", " 587 <<
"\"across\": " << d <<
", " 588 <<
"\"wiredir\": " << wiredir <<
", " 589 <<
"\"depth\": " << depth <<
", " 590 <<
"\"width\": " << width <<
", " 591 <<
"\"depthdir\": " << depthdir <<
", " 592 <<
"\"widthdir\": " << widthdir <<
", " 593 <<
"\"normal\": " << n <<
"}";
607 json <<
" \"cryos\": [\n";
608 for(
unsigned int i = 0; i < geom->
Ncryostats(); ++i){
610 if(i != geom->
Ncryostats()-1) json <<
",\n";
else json <<
"\n";
614 json <<
" \"opdets\": [\n";
615 for(
unsigned int i = 0; i < geom->
NOpDets(); ++i){
617 if(i != geom->
NOpDets()-1) json <<
",\n";
else json <<
"\n";
624 template<
class T>
void 627 std::map<art::InputTag, std::map<geo::PlaneID, std::vector<recob::Hit>>> plane_hits;
629 for(
art::InputTag tag: evt.template getInputTags<std::vector<recob::Hit>>()){
630 typename T::template HandleT<std::vector<recob::Hit>> hits;
632 if(!evt.getByLabel(
tag, hits))
continue;
645 plane_hits[
tag][plane].emplace_back(
hit.Channel(),
hit.StartTick(),
hit.EndTick(),
hit.PeakTime(),
hit.SigmaPeakTime(),
hit.RMS(),
hit.PeakAmplitude(),
hit.SigmaPeakAmplitude(),
hit.SummedADC(),
hit.Integral(),
hit.SigmaIntegral(),
hit.Multiplicity(),
hit.LocalIndex(),
hit.GoodnessOfFit(),
hit.DegreesOfFreedom(),
hit.View(),
hit.SignalType(), wire);
654 template<
class T> std::map<int, std::vector<T>>
ToSnippets(
const std::vector<T>& adcs,
T pedestal = 0)
657 snip.reserve(adcs.size());
659 std::map<int, std::vector<T>> snips;
665 snips[t-snip.size()] = snip;
670 snip.push_back(
adc - pedestal);
677 if(!snip.empty()) snips[t-snip.size()] = snip;
681 snips[adcs.size()] = {};
692 std::map<art::InputTag, std::map<geo::PlaneID, std::map<int, std::map<int, std::vector<short>>>>> traces;
694 for(
art::InputTag tag: evt.template getInputTags<std::vector<raw::RawDigit>>()){
695 typename T::template HandleT<std::vector<raw::RawDigit>> digs;
697 if(!evt.getByLabel(
tag, digs))
continue;
706 traces[
tag][plane][wire.Wire] =
ToSnippets(adcs,
short(dig.GetPedestal()));
720 std::map<art::InputTag, std::map<geo::PlaneID, std::map<int, std::map<int, std::vector<float>>>>> traces;
722 for(
art::InputTag tag: evt.template getInputTags<std::vector<recob::Wire>>()){
723 typename T::template HandleT<std::vector<recob::Wire>> wires;
725 if(!evt.getByLabel(
tag, wires))
continue;
745 std::stringstream ss;
749 else if(doc ==
"/tracks.json") SerializeProduct<recob::Track>(*
evt, json);
750 else if(doc ==
"/spacepoints.json") SerializeProduct<recob::SpacePoint>(*
evt, json);
751 else if(doc ==
"/vtxs.json") SerializeProduct<recob::Vertex>(*
evt, json);
752 else if(doc ==
"/trajs.json") SerializeProductByLabel<simb::MCParticle>(*
evt,
"largeant", json);
753 else if(doc ==
"/mctruth.json") SerializeProduct<simb::MCTruth>(*
evt, json);
754 else if(doc ==
"/opflashes.json") SerializeProduct<recob::OpFlash>(*
evt, json);
755 else if(doc ==
"/hits.json")
SerializeHits(*evt, geom, json);
757 else if(doc ==
"/digs.json") digs->
Serialize(json);
758 else if(doc ==
"/wires.json") wires->
Serialize(json);
776 if(doc ==
"/") doc =
"/index.html";
790 if(
endswith(doc,
".js" )) mime =
"application/javascript";
791 if(
endswith(doc,
".css")) mime =
"text/css";
792 if(
endswith(doc,
".ico")) mime =
"image/vnd.microsoft.icon";
797 const std::set<std::string> whitelist = {
"/evd.css",
"/evd.js",
"/traces.js",
"/favicon.ico",
"/index.html",
"/traces.html"};
799 if(whitelist.count(doc)){
813 if(
fSock != 0)
return 0;
816 gethostname(host, 1024);
817 char*
user = getlogin();
819 std::cout <<
"\n------------------------------------------------------------\n" <<
std::endl;
828 fSock = socket(AF_INET, SOCK_STREAM, 0);
829 if(
fSock == -1)
return err(
"socket");
833 if(setsockopt(
fSock, SOL_SOCKET, SO_REUSEADDR,
834 &one,
sizeof(one)) != 0)
return err(
"setsockopt");
837 addr.sin_family = AF_INET;
839 addr.sin_addr.s_addr = INADDR_ANY;
841 if(bind(
fSock, (sockaddr*)&addr,
sizeof(addr)) != 0)
return err(
"bind");
843 if(listen(
fSock, 128) != 0)
return err(
"listen");
847 std::cout <<
"ssh -L " 848 << port <<
":localhost:" << port <<
" " 849 << user <<
"@" << host << std::endl <<
std::endl;
850 std::cout <<
"and then navigate to http://localhost:" << port <<
"/ in your favorite browser." << std::endl <<
std::endl;
860 : fEvt(&evt), fGeom(geom), fArena(
"dig")
879 std::lock_guard guard(fLock);
881 if(!fEvt || !fGeom)
return;
883 for(
art::InputTag tag: fEvt->template getInputTags<std::vector<raw::RawDigit>>()){
884 typename T::template HandleT<std::vector<raw::RawDigit>> digs;
886 if(!fEvt->getByLabel(
tag, digs))
continue;
889 for(
geo::WireID wire: fGeom->ChannelToWire(dig.Channel())){
893 const geo::WireID w0 = fGeom->GetBeginWireID(plane);
905 const int adc = adcs[
tick] ?
int(adcs[
tick])-dig.GetPedestal() : 0;
934 std::map<art::InputTag, std::map<geo::PlaneID, PNGView>>
fImgs;
941 : fEvt(&evt), fGeom(geom), fArena(
"wire")
960 std::lock_guard guard(fLock);
962 if(!fEvt || !fGeom)
return;
964 for(
art::InputTag tag: fEvt->template getInputTags<std::vector<recob::Wire>>()){
965 typename T::template HandleT<std::vector<recob::Wire>> wires;
967 if(!fEvt->getByLabel(
tag, wires))
continue;
970 for(
geo::WireID wire: fGeom->ChannelToWire(rbwire.Channel())){
974 const geo::WireID w0 = fGeom->GetBeginWireID(plane);
982 const auto adcs = rbwire.Signal();
984 if(adcs[
tick] <= 0)
continue;
1006 std::map<art::InputTag, std::map<geo::PlaneID, PNGView>>
fImgs;
1017 signal(SIGPIPE, SIG_IGN);
1024 std::list<std::thread>
threads;
1027 int sock = accept(
fSock, 0, 0);
1028 if(sock == -1)
return err(
"accept");
1035 char* verb = strtok_r(&req.front(),
" ", &ctx);
1038 char* freq = strtok_r(0,
" ", &ctx);
1041 if(sreq ==
"/NEXT" ||
1043 sreq ==
"/NEXT_TRACES" ||
1044 sreq ==
"/PREV_TRACES" ||
1046 sreq.find(
"/seek/") == 0 ||
1047 sreq.find(
"/seek_traces/") == 0){
1048 for(std::thread&
t: threads)
t.join();
1052 threads.emplace_back(_HandleGet<T>, sreq, sock, &evt, &digs, &wires, geom, &detprop);
virtual PNGArena & GetArena() override
JSONFormatter & operator<<(JSONFormatter &json, const art::InputTag &t)
unsigned int NumberTrajectoryPoints() const
void SerializeDigitTraces(const T &evt, const geo::GeometryCore *geom, JSONFormatter &json)
void write_ok200(int sock, const std::string content="text/html", bool gzip=false)
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
std::map< int, std::vector< T > > ToSnippets(const std::vector< T > &adcs, T pedestal=0)
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
Collection of charge vs time digitized from a single readout channel.
void SerializeProductByLabel(const TEvt &evt, const std::string &in_label, JSONFormatter &json)
std::map< art::InputTag, std::map< geo::PlaneID, PNGView > > fImgs
void msg(const char *fmt,...)
std::vector< std::unique_ptr< std::array< png_byte, kTotBytes > > > data
void SerializeProduct(const TEvt &evt, JSONFormatter &json)
virtual PNGArena & GetArena() override
geo::WireID WireID() const
float RMS() const
RMS of the hit shape, in tick units.
const recob::TrackTrajectory & Trajectory() const
Access to the stored recob::TrackTrajectory.
size_t LastValidPoint() const
Returns the index of the last valid point in the trajectory.
EResult err(const char *call)
simb::Origin_t Origin() const
double MinX() const
Returns the world x coordinate of the start of the box.
The data type to uniquely identify a Plane.
int open(const char *, int)
Opens a file descriptor.
LazyWires(const T &evt, const geo::GeometryCore *geom)
void SerializePlanes(const geo::GeometryCore *geom, const detinfo::DetectorPropertiesData &detprop, JSONFormatter &json)
std::vector< short > ADCvector_t
Type representing a (compressed) vector of ADC counts.
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
void write_compressed_file(const std::string &loc, int fd_out, int level)
std::string read_all(int sock)
bool endswith(const std::string &s, const std::string &suffix)
size_t write(int, const char *, size_t)
Writes count bytes from buf to the filedescriptor fd.
void GetCenter(double *xyz, double localz=0.0) const
double MaxX() const
Returns the world x coordinate of the end of the box.
WireID_t Wire
Index of the wire within its plane.
int errno
Contains the last error code.
Geometry information for a single cryostat.
Vector GetNormalDirection() const
Returns the direction normal to the plane.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
Vector GetIncreasingWireDirection() const
Returns the direction of increasing wires.
Definition of vertex object for LArSoft.
LazyDigits(const T &evt, const geo::GeometryCore *geom)
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
void gzip_buffer(unsigned char *src, int length, std::vector< unsigned char > &dest, int level)
short swap_byte_order(short x)
IteratorBox< plane_id_iterator,&GeometryCore::begin_plane_id,&GeometryCore::end_plane_id > IteratePlaneIDs() const
Enables ranged-for loops on all plane IDs of the detector.
View_t View() const
Which coordinate does this plane measure.
int close(int)
Closes the file descriptor fd.
virtual PNGArena & GetArena()=0
const geo::GeometryCore * fGeom
const geo::GeometryCore * fGeom
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
Result HandleCommand(std::string cmd, int sock)
void swap(Handle< T > &a, Handle< T > &b)
A trajectory in space reconstructed from hits.
T LocationAtPoint(unsigned int p) const
Position at point p. Use e.g. as:
std::string getenv(std::string const &name)
double Depth() const
Return the depth of the plane.
Point GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
double Width() const
Return the width of the plane.
bool HasValidPoint(size_t i) const
Returns whether the specified point has NoPoint flag unset.
double MinZ() const
Returns the world z coordinate of the start of the box.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
void write_compressed_buffer(unsigned char *src, int length, int sock, int level, const std::string &name)
const art::EventAuxiliary & eventAuxiliary() const
virtual void Serialize(JSONFormatter &json)=0
unsigned int NumberTimeSamples() const
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
void _HandleGetPNG(std::string doc, int sock, ILazy *digs, ILazy *wires)
CodeOutputInterface * code
static int max(int a, int b)
Description of geometry of one entire detector.
void _HandleGet(std::string doc, int sock, const T *evt, ILazy *digs, ILazy *wires, const geo::GeometryCore *geom, const detinfo::DetectorPropertiesData *detprop)
std::vector< std::vector< png_byte * > > blocks
void SerializeGeometry(const geo::GeometryCore *geom, const detinfo::DetectorPropertiesData &detprop, JSONFormatter &json)
unsigned int NOpDets() const
Number of OpDets in the whole detector.
Detector simulation of raw signals on wires.
double MaxY() const
Returns the world y coordinate of the end of the box.
double ConvertTicksToX(double ticks, int p, int t, int c) const
void SerializeEventID(const T &evt, JSONFormatter &json)
Vector DepthDir() const
Return the direction of plane depth.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
double Vx(const int i=0) const
float PeakTime() const
Time of the signal peak, in tick units.
Declaration of signal hit object.
virtual void Serialize(JSONFormatter &json) override
size_t FirstValidPoint() const
Returns the index of the first valid point in the trajectory.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
void _HandleGetJSON(std::string doc, int sock, const T *evt, const geo::GeometryCore *geom, const detinfo::DetectorPropertiesData *detprop, ILazy *digs, ILazy *wires)
virtual void Serialize(JSONFormatter &json) override
void write_unimp501(int sock)
double MaxZ() const
Returns the world z coordinate of the end of the box.
void write_notfound404(int sock)
Result serve(const T &evt, const geo::GeometryCore *geom, const detinfo::DetectorPropertiesData &detprop)
unsigned int Nwires() const
Number of wires in this plane.
std::string MCTruthShortText(const simb::MCTruth &truth)
Provides recob::Track data product.
std::string find_file(std::string const &filename) const
Vector WidthDir() const
Return the direction of plane width.
double Vz(const int i=0) const
Class holding the regions of interest of signal from a channel.
const Double32_t * XYZ() const
std::map< art::InputTag, std::map< geo::PlaneID, PNGView > > fImgs
Access the description of detector geometry.
Declaration of basic channel signal object.
geo::OpDetID const & ID() const
Returns the geometry ID of this optical detector.
int read(int, char *, size_t)
Read bytes from a file descriptor.
void SerializeWireTraces(const T &evt, const geo::GeometryCore *geom, JSONFormatter &json)
2D representation of charge deposited in the TDC/wire plane
Event generator information.
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
The data type to uniquely identify a optical detector.
void WritePNGBytes(FILE *fout, int imgIdx, int dim)
void SerializeHits(const T &evt, const geo::GeometryCore *geom, JSONFormatter &json)
double MinY() const
Returns the world y coordinate of the start of the box.
byte bytes
Alias for common language habits.
constexpr std::enable_if_t< are_cv_compatible< TO, FROM >::value, std::add_pointer_t< std::remove_pointer_t< TO > > > addr(FROM &from)
const Point_t & position() const
Return vertex 3D position.
double Vy(const int i=0) const
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
QTextStream & endl(QTextStream &s)
Vector GetWireDirection() const
Returns the direction of the wires.