diff options
Diffstat (limited to 'src/zdab-cat.c')
-rw-r--r-- | src/zdab-cat.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/src/zdab-cat.c b/src/zdab-cat.c new file mode 100644 index 0000000..294e014 --- /dev/null +++ b/src/zdab-cat.c @@ -0,0 +1,330 @@ +/* Copyright (c) 2019, Anthony Latorre <tlatorre at uchicago> + * + * 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 <https://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include "zebra.h" +#include "event.h" +#include "zdab_utils.h" +#include "pmt.h" +#include "db.h" +#include "dqxx.h" +#include <inttypes.h> /* for PRIu32 macro */ +#include <string.h> /* for memcpy() */ +#include <errno.h> /* for errno */ +#include "release.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," -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; + MCTKBank bmctk; + MCVXBank bmcvx; + event ev = {0}; + char *filename = NULL; + char *output = NULL; + FILE *fout = NULL; + size_t nhit; + int last_run; + char dqxx_file[256]; + + for (i = 1; i < argc; i++) { + 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; + } + + 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) { + printf("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, " - gtid: %i\n", ev.gtid); + fprintf(fout, " nhit: %zu\n", nhit); + } + + /* 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) 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; +} |