/* Copyright (c) 2019, Anthony Latorre * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include #include "zebra.h" #include "event.h" #include "zdab_utils.h" #include "pmt.h" #include "db.h" #include "dqxx.h" #include /* for PRIu32 macro */ #include /* for memcpy() */ #include /* for errno */ #include "release.h" #include "dc.h" #define EV_RECORD 0x45562020 // 'EV ' #define MCTK_RECORD 0x4d43544b // 'MCTK' #define MCVX_RECORD 0x4d435658 // 'MCVX' char *GitSHA1(void); char *GitDirty(void); void usage(void) { fprintf(stderr,"Usage: ./zdab-cat [options] FILENAME\n"); fprintf(stderr," -o output file (default: stdout)\n"); fprintf(stderr," --skip-second-event only fit the first event after a MAST bank\n"); fprintf(stderr," -h display this help message\n"); exit(1); } int main(int argc, char **argv) { int i; zebraFile *f; zebraBank bmast, bmc, bmcgn, mctk, b; int rv; EVBank bev; FTPVBank bftpv; FTXKBank bftxk; RSPBank bftxr; MCTKBank bmctk; MCVXBank bmcvx; event ev = {0}; char *filename = NULL; char *output = NULL; FILE *fout = stdout; int skip_second_event = 0; size_t nhit; int last_run; char dqxx_file[256]; for (i = 1; i < argc; i++) { if (strlen(argv[i]) >= 2 && !strncmp(argv[i], "--", 2)) { if (!strcmp(argv[i]+2,"skip-second-event")) { skip_second_event = 1; continue; } } else if (argv[i][0] == '-') { switch (argv[i][1]) { case 'o': output = argv[++i]; break; case 'h': usage(); default: fprintf(stderr, "unrecognized option '%s'\n", argv[i]); exit(1); } } else { filename = argv[i]; } } if (!filename) usage(); f = zebra_open(filename); if (!f) { fprintf(stderr, "%s\n", zebra_err); return 1; } if (output) { fout = fopen(output, "w"); if (!fout) { fprintf(stderr, "failed to open '%s': %s\n", output, strerror(errno)); return 1; } } if (fout) { fprintf(fout, "git_sha1: %s\n", GitSHA1()); fprintf(fout, "git_dirty: %s\n", GitDirty()); fprintf(fout, "data:\n"); } if (load_pmt_info()) { zebra_close(f); if (output) fclose(fout); return 1; } for (i = 0; i < MAX_PMTS; i++) { ev.pmt_hits[i].hit = 0; ev.pmt_hits[i].flags = 0; } ev.run = -1; dict *db = db_init(); last_run = 10000; if (load_file(db, "DQXX_0000010000.dat", 0)) { fprintf(stderr, "failed to load DQXX_0000010000.dat: %s\n", db_err); goto err; } if (dqxx_init(db, &ev)) { fprintf(stderr, "failed to initialize DQXX bank: %s\n", dqxx_err); goto err; } while (1) { rv = zebra_read_next_logical_record(f); if (rv == -1) { fprintf(stderr, "error getting logical record: %s\n", zebra_err); goto err; } else if (rv == 1) { /* EOF */ break; } rv = zebra_get_bank(f, &bmast, f->first_bank); if (rv) { fprintf(stderr, "error getting MAST bank: %s\n", zebra_err); goto err; } if (fout) fprintf(fout, " -\n"); if (bmast.links[KMAST_MC-1] == 0) goto skip_mc; rv = zebra_get_bank(f,&bmc,bmast.links[KMAST_MC-1]); if (rv) { fprintf(stderr, "error getting MC bank: %s\n", zebra_err); goto err; } if (bmast.links[KMC_MCGN-1] == 0) { fprintf(stderr, "MCGN link is zero!\n"); goto err; } rv = zebra_get_bank(f,&bmcgn,bmc.links[KMC_MCGN-1]); if (rv) { fprintf(stderr, "error getting MCGN bank: %s\n", zebra_err); goto err; } if (fout) fprintf(fout, " mcgn:\n"); while (1) { if (bmcgn.links[KMCGN_MCTK-1] == 0) { fprintf(stderr, "MCTK link is zero!\n"); goto err; } rv = zebra_get_bank(f,&mctk,bmcgn.links[KMCGN_MCTK-1]); if (rv) { fprintf(stderr, "error getting MCTK bank: %s\n", zebra_err); goto err; } if (mctk.orig == mctk.up - KMCVX_MCTK) { /* This is the first MCTK bank. */ unpack_mctk(mctk.data, &bmctk); } else { /* For some reason SNOMAN sometimes links to the second MCTK * from the MCGN bank. */ rv = zebra_get_bank(f,&b,mctk.orig); if (b.idh != MCTK_RECORD) { fprintf(stderr, "error following origin link from MCTK bank!\n"); goto err; } if (rv) { fprintf(stderr, "error getting MCTK bank: %s\n", zebra_err); goto err; } unpack_mctk(b.data, &bmctk); } if (mctk.up == 0) { fprintf(stderr, "MCVX link is zero!\n"); goto err; } rv = zebra_get_bank(f,&b,mctk.up); if (rv) { fprintf(stderr, "error getting MCVX bank: %s\n", zebra_err); goto err; } unpack_mcvx(b.data, &bmcvx); if (fout) { fprintf(fout, " -\n"); fprintf(fout, " id: %" PRIu32 "\n", bmctk.idp); fprintf(fout, " energy: %.2f\n", bmctk.ene); fprintf(fout, " posx: %.2f\n", bmcvx.x); fprintf(fout, " posy: %.2f\n", bmcvx.y); fprintf(fout, " posz: %.2f\n", bmcvx.z); fprintf(fout, " dirx: %.4f\n", bmctk.drx); fprintf(fout, " diry: %.4f\n", bmctk.dry); fprintf(fout, " dirz: %.4f\n", bmctk.drz); } if (bmcgn.next) { rv = zebra_get_bank(f,&bmcgn,bmcgn.next); if (rv) { fprintf(stderr, "error getting MCGN bank: %s\n", zebra_err); goto err; } } else { break; } } skip_mc: if (bmast.links[KMAST_EV-1] == 0) { /* First logical record in SNOCR files doesn't have an EV bank. */ continue; } rv = zebra_get_bank(f,&b,bmast.links[KMAST_EV-1]); if (rv) { fprintf(stderr, "error getting EV bank: %s\n", zebra_err); goto err; } /* Skip to the last event so we can traverse them in reverse order. The * reason for this is that for some reason SNOMAN puts the events in * reverse order within each logical record. */ while (b.next) { rv = zebra_get_bank(f,&b,b.next); if (rv) { fprintf(stderr, "error getting EV bank: %s\n", zebra_err); goto err; } } if (fout) fprintf(fout, " ev:\n"); while (1) { unpack_ev(b.data, &bev); ev.run = bev.run; ev.gtid = bev.gtr_id; if (ev.run != last_run) { fprintf(stderr, "loading DQXX file for run %010i\n", ev.run); sprintf(dqxx_file, "DQXX_%010i.dat", ev.run); if (load_file(db, dqxx_file, 1)) { fprintf(stderr, "failed to load %s: %s\n", dqxx_file, db_err); goto err; } if (dqxx_init(db, &ev)) { fprintf(stderr, "failed to initialize DQXX bank: %s\n", dqxx_err); goto err; } last_run = ev.run; } rv = get_event(f,&ev,&b); nhit = get_nhit(&ev); if (fout) { fprintf(fout, " - run: %i\n", ev.run); fprintf(fout, " gtr: %.0f\n", ev.trigger_time); fprintf(fout, " nhit: %zu\n", nhit); fprintf(fout, " gtid: %i\n", ev.gtid); fprintf(fout, " trg_type: 0x%08x\n", ev.trigger_type); fprintf(fout, " dc: 0x%08x\n", get_dc_word(&ev, f, &bmast, &b)); } if (fout) { if (get_ftpv(f,&b,&bftpv)) { fprintf(stderr, "%s\n", zdab_err); } else { fprintf(fout, " ftp:\n"); fprintf(fout, " x: %.2f\n", bftpv.x); fprintf(fout, " y: %.2f\n", bftpv.y); fprintf(fout, " z: %.2f\n", bftpv.z); } } if (fout) { if (get_ftxk(f,&b,&bftxk)) { fprintf(stderr, "%s\n", zdab_err); } else { fprintf(fout, " ftk:\n"); fprintf(fout, " energy: %.2f\n", bftxk.energy); } } if (fout) { if (get_rsp(f,&b,&bftxr)) { fprintf(stderr, "%s\n", zdab_err); } else { fprintf(fout, " rsp:\n"); fprintf(fout, " energy: %.2f\n", bftxr.ene); } } /* Note the origin link for the first EV bank points back to the * structural link location in the MAST bank. These links are super * confusing! */ if ((b.orig == f->first_bank - KMAST_EV) || skip_second_event) break; rv = zebra_get_bank(f,&b,b.orig); if (rv) { fprintf(stderr, "error getting EV bank: %s\n", zebra_err); goto err; } } } db_free(db); if (fout) fclose(fout); zebra_close(f); return 0; err: db_free(db); if (fout) fclose(fout); zebra_close(f); return 1; }