diff --git a/bin/hipo-multi-merge b/bin/hipo-multi-merge new file mode 100755 index 000000000..5dcbacea8 --- /dev/null +++ b/bin/hipo-multi-merge @@ -0,0 +1,107 @@ +#!/usr/bin/env ruby + +require 'optparse' +require 'ostruct' +require 'fileutils' + +def print_log(name, val) + puts name.rjust(30) + " = #{val}" +end + +# user options +@args = OpenStruct.new +@args.inputs = nil +@args.output_dir = nil +@args.prefix = nil +@args.num_merge = nil +@args.use_batch = false +@args.dry_run = false +OptionParser.new do |o| + o.banner = ''' + This tool merges a set of input HIPO files to a set of output HIPO files, + where you may control the number of input files per output file; for example, + use this tool if you have 1000 small HIPO files but would rather have 10 + large HIPO files. + ''' + o.separator "USAGE: #{$0} [OPTIONS]..." + o.separator '' + o.separator 'REQUIRED OPTIONS:' + o.on('-i', '--input INPUTS', 'input directory or file glob;', 'surround file glob in quotes') { |a| @args.inputs = a } + o.on('-o', '--output OUTPUT_DIR', 'output directory') { |a| @args.output_dir = a } + o.on('-p', '--prefix OUTPUT_PREFIX', 'output filename prefix; names will be:', ' [OUTPUT_DIR]/[OUTPUT_PREFIX]_#####.hipo') { |a| @args.prefix = a } + o.on('-n', '--num NUM_FILES', 'number of files per output merged file') { |a| @args.num_merge = a.to_i } + o.separator '' + o.separator 'OPTIONAL OPTIONS:' + o.on('-b', '--batch', 'submit jobs to Slurm', '(default is sequential jobs)') { |a| @args.use_batch = true } + o.on('-d', '--dry-run', 'just print what would be done') { |a| @args.dry_run = true } + o.on_tail('-h', '--help', 'show this message') do + puts o + exit + end +end.parse! ARGV.empty? ? ['--help'] : ARGV + +# check required options +if [@args.inputs, @args.output_dir, @args.prefix, @args.num_merge].include? nil + raise 'missing required option(s;) re-run with "--help" for guidance.' +end +raise 'option "--num" must be greater than zero' unless @args.num_merge > 0 + +# glob inputs +input_glob = File.expand_path @args.inputs +input_glob = File.join input_glob, "*.hipo" if File.directory? input_glob +print_log 'input glob', input_glob +print_log 'output dir', @args.output_dir +print_log 'output prefix', @args.prefix +print_log 'num files per output', @args.num_merge + +# chunks +input_files = Dir.glob input_glob +raise "no input files found with glob '#{input_glob}'" if input_files.empty? +input_chunks = input_files.each_slice(@args.num_merge).to_a +print_log 'num input files', input_files.size +print_log 'num output files', input_chunks.size +raise 'option "--num" >= num input files, therefore there is nothing to do' if input_chunks.size == 1 + +# build commands +puts "="*82 +merge_cmds = input_chunks.each_with_index.map do |input_chunk, chunk_num| + out_name = File.join @args.output_dir, "#{@args.prefix}_#{chunk_num.to_s.rjust(5, '0')}.hipo" + raise "output file #{out_name} already exists; cannot overwrite! delete it or choose another path/name" if File.exist? out_name + [ 'hipo-utils', '-merge', '-o', out_name, *input_chunk ].join ' ' +end + +# sbatch commands +if @args.use_batch + sbatch_args = { + 'job-name' => "hipo_multi_merge___#{@args.prefix}", + 'account' => 'clas12', + 'partition' => 'production', + 'mem-per-cpu' => 500, + 'time' => '1:00:00', + 'ntasks' => 1, + 'cpus-per-task' => 1, + }.map{ |opt, val| "--#{opt}=#{val.to_s}" } + exe_cmds = merge_cmds.each_with_index.map do |merge_cmd, job_num| + log_name = "/farm_out/%u/%x_#{job_num.to_s.rjust(5, '0')}" + [ + 'sbatch', + *sbatch_args, + "--output=#{log_name}.out", + "--error=#{log_name}.err", + "--wrap='#{merge_cmd}'", + ].join ' ' + end +else + exe_cmds = merge_cmds +end + +# execute +if @args.dry_run + puts 'THIS IS JUST A DRY RUN. Here are the commands which would be executed:' + puts "="*82 + puts "mkdir -p #{@args.output_dir}" + exe_cmds.each do |cmd| puts cmd end +else + FileUtils.mkdir_p @args.output_dir + exe_cmds.each do |cmd| system cmd end +end diff --git a/common-tools/clas-geometry/src/main/java/org/jlab/geom/detector/alert/ATOF/AlertTOFFactory.java b/common-tools/clas-geometry/src/main/java/org/jlab/geom/detector/alert/ATOF/AlertTOFFactory.java index 4057a9b67..e96d4f991 100644 --- a/common-tools/clas-geometry/src/main/java/org/jlab/geom/detector/alert/ATOF/AlertTOFFactory.java +++ b/common-tools/clas-geometry/src/main/java/org/jlab/geom/detector/alert/ATOF/AlertTOFFactory.java @@ -7,33 +7,37 @@ //package clas12vis; package org.jlab.geom.detector.alert.ATOF; - import org.jlab.geom.base.ConstantProvider; import org.jlab.geom.base.DetectorTransformation; import org.jlab.geom.base.Factory; import org.jlab.geom.component.ScintillatorPaddle; -import org.jlab.geom.prim.Plane3D; import org.jlab.geom.prim.Point3D; import org.jlab.geom.prim.Transformation3D; -import java.util.ArrayList; -import java.util.List; /** - * @author viktoriya - * this is the latest ATOF geometry class to be used in reco. and in GEMC simulations! - * commit on July 02, 2020 + * @author viktoriya, pilleux + * Original geometry July 02, 2020 + * Updated December 2024 to match actual atof conventions + * ATOF geometry class to be used in reco. and in GEMC simulations! */ public class AlertTOFFactory implements Factory { - private final int nsectors = 15; - private final int nsuperl = 2; - private final int nlayers1 = 10; - private final int npaddles = 4; - + //Convention definitions: https://clasweb.jlab.org/wiki/index.php/File:Atof_def.png + //The atof has 15 phi sectors. + private final int nsectors = 15; + //Top superlayer (index 1) = wedges. + //Bottom one (0) = bar. + private final int nsuperl = 2; + //Layers = quarters of sectors. + private final int nlayers = 4; + //Components = slices in z. 10 for the wedges, 1 for the bar. + private final int ncomponents = 10; + + //Each pad = quarter of module private final double openAng_pad_deg = 6.0; - private final double openAng_pad_rad = Math.toRadians(openAng_pad_deg); - private final double openAng_sector_rad = npaddles * openAng_pad_rad; + //4 pads = 4 layers = 1 sector + private final double openAng_sector_deg = nlayers * openAng_pad_deg; @Override public AlertTOFDetector createDetectorCLAS(ConstantProvider cp) { @@ -72,23 +76,15 @@ public AlertTOFSuperlayer createSuperlayer(ConstantProvider cp, int sectorId, in if (!(0 <= sectorId && sectorId < nsectors)) throw new IllegalArgumentException("Error: invalid sector=" + sectorId); if (!(0 <= superlayerId && superlayerId < nsuperl)) throw new IllegalArgumentException("Error: invalid superlayer=" + superlayerId); AlertTOFSuperlayer superlayer = new AlertTOFSuperlayer(sectorId, superlayerId); - - if (superlayerId == 0) { - int nlayers0 = 1; - for (int layerId = 0; layerId < nlayers0; layerId++) - superlayer.addLayer(createLayer(cp, sectorId, superlayerId, layerId)); - } else { - for (int layerId = 0; layerId < nlayers1; layerId++) - superlayer.addLayer(createLayer(cp, sectorId, superlayerId, layerId)); - } + for (int layerId = 0; layerId < nlayers; layerId++) superlayer.addLayer(createLayer(cp, sectorId, superlayerId, layerId)); return superlayer; } - + @Override public AlertTOFLayer createLayer(ConstantProvider cp, int sectorId, int superlayerId, int layerId) { if (!(0 <= sectorId && sectorId < nsectors)) throw new IllegalArgumentException("Error: invalid sector=" + sectorId); if (!(0 <= superlayerId && superlayerId < nsuperl)) throw new IllegalArgumentException("Error: invalid superlayer=" + superlayerId); - if (!(0 <= layerId && layerId < nlayers1)) throw new IllegalArgumentException("Error: invalid layer=" + layerId); + if (!(0 <= layerId && layerId < nlayers)) throw new IllegalArgumentException("Error: invalid layer=" + layerId); double R0 = 77.0d; double R1 = 80.0d; @@ -109,54 +105,68 @@ public AlertTOFLayer createLayer(ConstantProvider cp, int sectorId, int superlay double gap_pad_z = 0.3d; // mm, gap between paddles in z AlertTOFLayer layer = new AlertTOFLayer(sectorId, superlayerId, layerId); - - List planes = new ArrayList<>(); - - double len_b = layerId * pad_z + layerId * gap_pad_z; // back paddle plan - double len_f = len_b + pad_z; // front paddle plan + + //Dimensions for the bar double Rl = R0; double dR = dR0; double widthTl = small_pad_b2; double widthBl = small_pad_b1; - + //Dimensions for the wedge if (superlayerId == 1) { Rl = R1; dR = dR1; widthTl = pad_b2; widthBl = pad_b1; } - - for (int padId = 0; padId < npaddles; padId++) { - Point3D p0 = new Point3D(-dR / 2, -widthBl / 2, len_f); - Point3D p1 = new Point3D(dR / 2, -widthTl / 2, len_f); - Point3D p2 = new Point3D(dR / 2, widthTl / 2, len_f); - Point3D p3 = new Point3D(-dR / 2, widthBl / 2, len_f); - - Point3D p4 = new Point3D(-dR / 2, -widthBl / 2, len_b); - Point3D p5 = new Point3D(dR / 2, -widthTl / 2, len_b); - Point3D p6 = new Point3D(dR / 2, widthTl / 2, len_b); - Point3D p7 = new Point3D(-dR / 2, widthBl / 2, len_b); - ScintillatorPaddle Paddle = new ScintillatorPaddle(sectorId * 4 + padId, p0, p1, p2, p3, p4, p5, p6, p7); - - double openAng_sector_deg = npaddles * openAng_pad_deg; - Paddle.rotateZ(Math.toRadians(padId * openAng_pad_deg + sectorId * openAng_sector_deg)); - - double xoffset; - double yoffset; - - xoffset = (Rl + dR / 2) * Math.cos(padId * openAng_pad_rad + sectorId * openAng_sector_rad); - yoffset = (Rl + dR / 2) * Math.sin(padId * openAng_pad_rad + sectorId * openAng_sector_rad); - - Paddle.translateXYZ(xoffset, yoffset, 0); - - // Add the paddles to the list - layer.addComponent(Paddle); + + //Layer = quarter of a sector + double current_angle_deg = layerId * openAng_pad_deg + sectorId * openAng_sector_deg; + //Aligning the y axis with the separation between modules 0 and 14 + current_angle_deg = current_angle_deg + 90 + 3; + + //Component = z slice. + //There are 10 for the wedge/top/sl=1 + int current_ncomponents = ncomponents; + //There is only one for the bar/bottom/sl=0 + if(superlayerId==0) current_ncomponents = 1; + + //Starting loop on components + for (int padId = 0; padId < current_ncomponents; padId++) { + + //Component index increases with increasing z + double len_b = padId * pad_z + padId * gap_pad_z; // back paddle plan + double len_f = len_b + pad_z; // front paddle plan + + Point3D p0 = new Point3D(-dR / 2, -widthBl / 2, len_f); + Point3D p1 = new Point3D(dR / 2, -widthTl / 2, len_f); + Point3D p2 = new Point3D(dR / 2, widthTl / 2, len_f); + Point3D p3 = new Point3D(-dR / 2, widthBl / 2, len_f); + + Point3D p4 = new Point3D(-dR / 2, -widthBl / 2, len_b); + Point3D p5 = new Point3D(dR / 2, -widthTl / 2, len_b); + Point3D p6 = new Point3D(dR / 2, widthTl / 2, len_b); + Point3D p7 = new Point3D(-dR / 2, widthBl / 2, len_b); + + //Component index is the z slice for the top/wedge/sl=1 + int component = padId; + //It is 10 for the bottom/bar/sl=0 + if(superlayerId==0) component = 10; + + ScintillatorPaddle Paddle = new ScintillatorPaddle(component, p0, p1, p2, p3, p4, p5, p6, p7); + + Paddle.rotateZ(Math.toRadians(current_angle_deg)); + + double xoffset; + double yoffset; + + xoffset = (Rl + dR / 2) * Math.cos(Math.toRadians(current_angle_deg)); + yoffset = (Rl + dR / 2) * Math.sin(Math.toRadians(current_angle_deg)); + + Paddle.translateXYZ(xoffset, yoffset, 0); + + // Add the paddles to the list + layer.addComponent(Paddle); } - - Plane3D plane = new Plane3D(0, Rl, 0, 0, 1, 0); - plane.rotateZ(sectorId * openAng_sector_rad - Math.toRadians(90)); - planes.add(plane); - return layer; } diff --git a/common-tools/cnuphys/parent/pom.xml b/common-tools/cnuphys/parent/pom.xml index cd9c88c77..9948e6fdb 100644 --- a/common-tools/cnuphys/parent/pom.xml +++ b/common-tools/cnuphys/parent/pom.xml @@ -38,7 +38,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.8.6.5 + 4.8.6.6 spotbugs-exclude.xml diff --git a/parent/pom.xml b/parent/pom.xml index 9aa80916b..99495aa72 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -62,7 +62,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.8.6.5 + 4.8.6.6 spotbugs-exclude.xml @@ -71,7 +71,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.11.1 + 3.11.2 coatjavadocs coatjavadocs diff --git a/reconstruction/htcc/src/main/java/org/jlab/rec/htcc/HTCCReconstruction.java b/reconstruction/htcc/src/main/java/org/jlab/rec/htcc/HTCCReconstruction.java index 4b503bc51..ca3d0bcf2 100644 --- a/reconstruction/htcc/src/main/java/org/jlab/rec/htcc/HTCCReconstruction.java +++ b/reconstruction/htcc/src/main/java/org/jlab/rec/htcc/HTCCReconstruction.java @@ -61,9 +61,9 @@ public void processEvent(DataEvent event) { // Place all of the hits into clusters List clusters = new ArrayList(); - HTCCCluster cluster; - while (!remainingHits.isEmpty() && (cluster = findCluster(remainingHits)) != null) { - clusters.add(cluster); + while (!remainingHits.isEmpty()) { + HTCCCluster cluster = findCluster(remainingHits); + if(cluster!=null) clusters.add(cluster); } // Push all of the clusters into the bank and print the results