diff --git a/src/main/java/gov/usgs/earthquake/nshmp/calc/HazardInput.java b/src/main/java/gov/usgs/earthquake/nshmp/calc/HazardInput.java index a7d029c6563983f7cb58fbaca8601e6c6d300805..817eb0edc6b1de54140cd3f32b26ae99e7b04f8b 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/calc/HazardInput.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/calc/HazardInput.java @@ -19,22 +19,23 @@ public final class HazardInput extends GmmInput { double rate, double Mw, double rJB, double rRup, double rX, double dip, double width, double zTor, double zHyp, double rake, - double vs30, boolean vsInf, double z1p0, double z2p5) { + double vs30, boolean vsInf, double z1p0, double z2p5, double zSed) { super(GmmInput.builder() - .dip(dip) .mag(Mw) - .rake(rake) .rJB(rJB) .rRup(rRup) .rX(rX) + .dip(dip) + .width(width) + .zTor(zTor) + .zHyp(zHyp) + .rake(rake) .vs30(vs30) .vsInf(vsInf) - .width(width) .z1p0(z1p0) .z2p5(z2p5) - .zHyp(zHyp) - .zTor(zTor)); + .zSed(zSed)); this.rate = rate; } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/calc/Site.java b/src/main/java/gov/usgs/earthquake/nshmp/calc/Site.java index 8a90c3a02c56acef816033576804e603e481fe00..11dbb64f67799e89c99d53397e5ca8d1e5b2be1d 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/calc/Site.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/calc/Site.java @@ -80,8 +80,8 @@ public class Site { */ public static final double ZSED_DEFAULT = Double.NaN; - /** Supported {@link #zSed()} values: {@code [0..20] km}. */ - public static final Range<Double> ZSED_RANGE = Range.closed(0.0, 20.0); + /** Supported {@link #zSed()} values: {@code [0..25] km}. */ + public static final Range<Double> ZSED_RANGE = Range.closed(0.0, 25.0); private final String name; private final Location location; diff --git a/src/main/java/gov/usgs/earthquake/nshmp/calc/Transforms.java b/src/main/java/gov/usgs/earthquake/nshmp/calc/Transforms.java index 27aecac80e599f4326bc67e274f6ae298c0ac375..b0b69821f10e65d513d4de866388ec6d645c2698 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/calc/Transforms.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/calc/Transforms.java @@ -102,7 +102,8 @@ final class Transforms { site.vs30(), site.vsInferred(), site.z1p0(), - site.z2p5()); + site.z2p5(), + site.zSed()); hazardInputs.add(input); // System.out.println(input); } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/gmm/GroundMotions.java b/src/main/java/gov/usgs/earthquake/nshmp/gmm/GroundMotions.java index c7534107f71b85b2728c7f1a2de9ed48b99bc1e9..d6194a84e0dd7da4866927ea0b53e6a814a6a18d 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/gmm/GroundMotions.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/gmm/GroundMotions.java @@ -165,6 +165,11 @@ public class GroundMotions { return 1; } + @Override + public String toString() { + return LogicTree.toString(this); + } + @Override public Branch<GroundMotion> get(int index) { return new Branch<GroundMotion>() { @@ -183,6 +188,11 @@ public class GroundMotions { public double weight() { return 1.0; } + + @Override + public String toString() { + return Branch.toString(this); + } }; } } @@ -218,6 +228,16 @@ public class GroundMotions { throw new UnsupportedOperationException(); } + @Override + public int size() { + return μs.length; + } + + @Override + public String toString() { + return LogicTree.toString(this); + } + @Override public Branch<GroundMotion> get(int index) { return new Branch<GroundMotion>() { @@ -235,12 +255,12 @@ public class GroundMotions { public double weight() { return wts[index]; } - }; - } - @Override - public int size() { - return μs.length; + @Override + public String toString() { + return Branch.toString(this); + } + }; } } @@ -288,6 +308,11 @@ public class GroundMotions { return μs.length * σs.length; } + @Override + public String toString() { + return LogicTree.toString(this); + } + @Override public Branch<GroundMotion> get(int index) { return new Branch<GroundMotion>() { @@ -314,6 +339,11 @@ public class GroundMotions { public double weight() { return μWts[μIndex] * σWts[σIndex]; } + + @Override + public String toString() { + return Branch.toString(this); + } }; } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/gmm/NgaEast.java b/src/main/java/gov/usgs/earthquake/nshmp/gmm/NgaEast.java index 4fd40b2b6fa78d4b2fc6017e68019b8625effd43..9c0ef56c916f7469343faa74ad12f1344900ec7e 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/gmm/NgaEast.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/gmm/NgaEast.java @@ -389,12 +389,28 @@ public abstract class NgaEast implements GroundMotionModel { public static void main(String[] args) { GmmInput in1 = GmmInput.builder().withDefaults().build(); - GmmInput in2 = GmmInput.builder().withDefaults().zSed(10).build(); - GroundMotionModel gmm = Gmm.NGA_EAST_2023.instance(Imt.SA1P0); - GroundMotion gm1 = GroundMotions.combine(gmm.calc(in1)); - GroundMotion gm2 = GroundMotions.combine(gmm.calc(in2)); - System.out.println(gm1); - System.out.println(gm2); + // GmmInput in2 = GmmInput.builder().withDefaults().zSed(10).build(); + + Imt imt = Imt.PGA; + + GroundMotionModel gmm18 = Gmm.NGA_EAST_SEEDS_2018.instance(imt); + GroundMotionModel gmm23 = Gmm.NGA_EAST_SEEDS_2023.instance(imt); + + LogicTree<GroundMotion> gmm18lt = gmm18.calc(in1); + LogicTree<GroundMotion> gmm23lt = gmm23.calc(in1); + System.out.println(gmm18lt); + System.out.println(gmm23lt); + + GroundMotion gm18 = GroundMotions.combine(gmm18lt); + GroundMotion gm23 = GroundMotions.combine(gmm23lt); + + System.out.println(gm18); + System.out.println(gm23); + + // GroundMotion gm1 = GroundMotions.combine(gmm.calc(in1)); + // GroundMotion gm2 = GroundMotions.combine(gmm.calc(in2)); + // System.out.println(gm1); + // System.out.println(gm2); } /* @@ -591,8 +607,8 @@ public abstract class NgaEast implements GroundMotionModel { double μPga; if (seed == Gmm.NGA_EAST_SEED_SP16) { - μ = sp16.calcMeanRock(in.Mw, in.rRup); - μPga = sp16pga.calcMeanRock(in.Mw, in.rRup); + μ = sp16.calcMeanRock(in.Mw, in.rJB); + μPga = exp(sp16pga.calcMeanRock(in.Mw, in.rJB)); } else if (imt == Imt.PGV && noPgvSeeds.contains(seed)) { // note rock input; TODO this doesn't really work as the PGV // is conditioned on vs30 so site should already be applied @@ -1026,7 +1042,7 @@ public abstract class NgaEast implements GroundMotionModel { double fNonlin = 0.0; if (vs30 < c.vc) { - double f2 = c.f4 * (exp(c.f5 * (min(vs30, vRefNl) - 360.0)) - + double f2 = calcF4() * (exp(c.f5 * (min(vs30, vRefNl) - 360.0)) - exp(c.f5 * (vRefNl - 360.0))); fNonlin = f2 * rkRefTerm; } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/model/HazardModel.java b/src/main/java/gov/usgs/earthquake/nshmp/model/HazardModel.java index c89c991bcc2d4d6706499add1a9f55be8f802099..edbb8516dcccd8779cbf38ee5b0e5b77377256e7 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/model/HazardModel.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/model/HazardModel.java @@ -12,6 +12,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.EnumMap; import java.util.EnumSet; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -61,6 +62,7 @@ public final class HazardModel implements Iterable<SourceTree> { private final String name; private final CalcConfig config; private final Map<NehrpSiteClass, Double> siteClassMap; + private final Map<String, Double> bounds; private final Multimap<SourceType, RuptureSet<? extends Source>> ruptureSetMap; private final Set<TectonicSetting> settings; @@ -74,6 +76,9 @@ public final class HazardModel implements Iterable<SourceTree> { this.name = builder.info.name; this.config = builder.config; this.siteClassMap = Maps.immutableEnumMap(builder.info.siteClassMap); + this.bounds = builder.info.bounds != null + ? new HashMap<>(builder.info.bounds) + : new HashMap<>();; // TODO make immutable this.ruptureSetMap = builder.ruptureSetMap; this.settings = Sets.immutableEnumSet(builder.settings); this.mapRegionMap = Maps.immutableEnumMap(builder.mapRegionMap); @@ -177,6 +182,13 @@ public final class HazardModel implements Iterable<SourceTree> { return siteClassMap; } + /** + * The latitude and longitude range over which this model is applicable. + */ + public Map<String, Double> bounds() { + return bounds; + } + /** * The site data used with this model. */ @@ -316,10 +328,15 @@ public final class HazardModel implements Iterable<SourceTree> { final String name; @SerializedName("site-class-vs30") final Map<NehrpSiteClass, Double> siteClassMap; + final Map<String, Double> bounds; - Info(String name, Map<NehrpSiteClass, Double> siteClassMap) { + Info( + String name, + Map<NehrpSiteClass, Double> siteClassMap, + Map<String, Double> bounds) { this.name = name; this.siteClassMap = siteClassMap; + this.bounds = bounds; } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/model/ModelLoader.java b/src/main/java/gov/usgs/earthquake/nshmp/model/ModelLoader.java index 2af32b8354966ce1ae66c10405589fd5d92c727d..e7998390a98347a19dc382e3e96cd73b16405729 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/model/ModelLoader.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/model/ModelLoader.java @@ -622,7 +622,8 @@ abstract class ModelLoader { : "-" + String.valueOf((int) Math.round(1.0 / rate)) + "-yr"); String clusterLabel = clusterData.name + " : " + rateLabel; - Path branchPath = root.relativize(branch.value()).resolve(rateLabel); + Path clusterPath = branch.value().resolve(rateLabel); + Path branchPath = root.relativize(clusterPath); System.out.println(" branch: " + branchPath); ClusterSource clusterSource = new ClusterSource.Builder() @@ -642,7 +643,7 @@ abstract class ModelLoader { pathTreeBuilder.addBranch( clusterLabel, - Path.of(clusterLabel), + clusterPath, rateBranch.weight()); } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/model/SystemRuptureSet.java b/src/main/java/gov/usgs/earthquake/nshmp/model/SystemRuptureSet.java index 4bc773ef16c31e483704cb2765bc12d8e4f34dd3..ca825ed1c9f0e1fb31506561320312aa519ac3d2 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/model/SystemRuptureSet.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/model/SystemRuptureSet.java @@ -758,7 +758,8 @@ public class SystemRuptureSet extends AbstractRuptureSet<SystemRuptureSet.System site.vs30(), site.vsInferred(), site.z1p0(), - site.z2p5()); + site.z2p5(), + site.zSed()); } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/Branch.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/Branch.java index 67f586ea90332400d6fdbd134ee45a84da21c0a4..ccf0dbd9f96ce422fde53b7093a59b2aacc85def 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/Branch.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/Branch.java @@ -17,4 +17,14 @@ public interface Branch<T> { /** The branch weight. */ double weight(); + /** + * String representation of a logic tree branchfor use by concrete + * implementations. + * + * @param branch to render as a string + */ + static <T> String toString(Branch<T> branch) { + return branch.id() + " [" + branch.weight() + "] " + branch.value(); + } + } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/EnumBranch.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/EnumBranch.java index 18cdca10ed3102f684fc58b36cee62877a411491..fb240360c65b5004f8b5a23a9ac33cf673fd80fe 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/EnumBranch.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/EnumBranch.java @@ -37,6 +37,6 @@ class EnumBranch<E extends Enum<E>, T> implements Branch<T> { @Override public String toString() { - return RegularBranch.toString(id(), weight); + return Branch.toString(this); } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/EnumValueBranch.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/EnumValueBranch.java index 6515c2e4848069954ead477a92af21279a6ff09a..241e947dc67113b275526d16b79b18077221f7de 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/EnumValueBranch.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/EnumValueBranch.java @@ -35,6 +35,6 @@ class EnumValueBranch<E extends Enum<E>> implements Branch<E> { @Override public String toString() { - return RegularBranch.toString(id(), weight); + return Branch.toString(this); } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/GroupBranch.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/GroupBranch.java index 7c429648d8f62ef4dca8d09605acead6eb29b256..129e37bbc9ea241a92a75c02f2ddd079a677fc1f 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/GroupBranch.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/GroupBranch.java @@ -38,6 +38,6 @@ class GroupBranch<T> implements Branch<T> { @Override public String toString() { - return RegularBranch.toString(id, scale); + return Branch.toString(this); } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/LogicGroup.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/LogicGroup.java index 94ab66b19e9efb13fca8827e147c1e452affd8eb..5e24420dd6348e8b9718ce9090745816cdfc4d7b 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/LogicGroup.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/LogicGroup.java @@ -48,7 +48,7 @@ public final class LogicGroup<T> extends AbstractList<Branch<T>> implements Logi @Override public String toString() { - return RegularTree.toString(NAME, branches); + return LogicTree.toString(this); } @Override diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/LogicTree.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/LogicTree.java index 7c3b4886f6bd8302dc8425e12607b8f59cb4acc0..60b352d0198890b02381170634ce45d8290106a8 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/LogicTree.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/LogicTree.java @@ -49,6 +49,28 @@ public interface LogicTree<T> extends List<Branch<T>> { */ List<Branch<T>> sample(double[] probabilities); + /** + * String representation of a logic tree for use by concrete implementations. + * + * @param tree to render as a string + */ + public static <T> String toString(LogicTree<T> tree) { + StringBuilder sb = new StringBuilder(tree.name()); + for (int i = 0; i < tree.size(); i++) { + switch (i) { + case 0: + sb.append((tree.size() == 1) ? " ─ " : " ┬ "); + break; + default: + sb.append(" ".repeat(tree.name().length())); + sb.append((i == tree.size() - 1) ? " └ " : " ├ "); + } + sb.append(tree.get(i)); + sb.append((i == tree.size() - 1) ? "" : Text.NEWLINE); + } + return sb.toString(); + } + /** * A logic tree with a single branch. * diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/RegularBranch.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/RegularBranch.java index cd903fbf81c05b130976e8bba232a46b172ed9aa..57ace586fe07727785a862fb1e36a76d70350398 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/RegularBranch.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/RegularBranch.java @@ -40,7 +40,7 @@ class RegularBranch<T> implements Branch<T> { @Override public String toString() { - return toString(id, weight); + return Branch.toString(this); } static String checkId(String id) { @@ -48,7 +48,4 @@ class RegularBranch<T> implements Branch<T> { return id; } - static String toString(String id, double weight) { - return id + " [" + weight + "]"; - } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/RegularTree.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/RegularTree.java index 18233545bc2fb7bfa924669002d4fb54836cc32f..e77f060a8dd7bcc041cf83625c87c3043ef256ce 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/RegularTree.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/RegularTree.java @@ -5,8 +5,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import gov.usgs.earthquake.nshmp.Text; - /** * Basic logic tree implementation. * @@ -68,23 +66,6 @@ class RegularTree<T> extends AbstractList<Branch<T>> implements LogicTree<T> { @Override public String toString() { - return toString(name, branches); - } - - static <T> String toString(String name, List<Branch<T>> branches) { - StringBuilder sb = new StringBuilder(name); - for (int i = 0; i < branches.size(); i++) { - switch (i) { - case 0: - sb.append((branches.size() == 1) ? " ─ " : " ┬ "); - break; - default: - sb.append(" ".repeat(name.length())); - sb.append((i == branches.size() - 1) ? " └ " : " ├ "); - } - sb.append(branches.get(i)); - sb.append((i == branches.size() - 1) ? "" : Text.NEWLINE); - } - return sb.toString(); + return LogicTree.toString(this); } } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/tree/StringValueBranch.java b/src/main/java/gov/usgs/earthquake/nshmp/tree/StringValueBranch.java index 0b7baac604a5e5631a99ffd15238d87a962019b0..d6412c8de3942c4f04db850ee04dd0debf61edcb 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/tree/StringValueBranch.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/tree/StringValueBranch.java @@ -35,6 +35,6 @@ class StringValueBranch implements Branch<String> { @Override public String toString() { - return RegularBranch.toString(id, weight); + return Branch.toString(this); } } diff --git a/src/test/java/gov/usgs/earthquake/nshmp/tree/LogicTreeTests.java b/src/test/java/gov/usgs/earthquake/nshmp/tree/LogicTreeTests.java index 607875af17f18c61d96278f5f38ea9166a4d66c0..cfd4a34f2a828fe6e4db88cb7c5e8bbefac4379e 100644 --- a/src/test/java/gov/usgs/earthquake/nshmp/tree/LogicTreeTests.java +++ b/src/test/java/gov/usgs/earthquake/nshmp/tree/LogicTreeTests.java @@ -41,7 +41,7 @@ class LogicTreeTests { assertEquals(id[1], branch.id()); assertEquals(value[1], branch.value()); assertEquals(weight[1], branch.weight()); - assertEquals(branchString(id[1], weight[1]), branch.toString()); + assertEquals(branchString(id[1], weight[1], value[1]), branch.toString()); assertEquals(tree.get(0), tree.iterator().next()); // iterator /* StringValueTree */ @@ -57,7 +57,7 @@ class LogicTreeTests { assertEquals(id[2], branch.id()); assertEquals(id[2], branch.value()); assertEquals(0.1, branch.weight()); - assertEquals(branchString(id[2], weight[2]), branch.toString()); + assertEquals(branchString(id[2], weight[2], id[2]), branch.toString()); /* EnumTree */ LogicTree.EnumBuilder<EnumKey, String> enumTreeBuilder = @@ -72,7 +72,7 @@ class LogicTreeTests { assertEquals(EnumKey.ID_2.name(), branch.id()); assertEquals(value[2], branch.value()); assertEquals(0.1, branch.weight()); - assertEquals(branchString(EnumKey.ID_2.name(), weight[2]), branch.toString()); + assertEquals(branchString(EnumKey.ID_2.name(), weight[2], value[2]), branch.toString()); /* EnumValueTree */ LogicTree.EnumValueBuilder<EnumKey> enumValueTreeBuilder = @@ -87,7 +87,9 @@ class LogicTreeTests { assertEquals(EnumKey.ID_2.name(), enumBranch.id()); assertEquals(EnumKey.ID_2, enumBranch.value()); assertEquals(0.1, enumBranch.weight()); - assertEquals(branchString(EnumKey.ID_2.name(), weight[2]), enumBranch.toString()); + assertEquals( + branchString(EnumKey.ID_2.name(), weight[2], EnumKey.ID_2.name()), + enumBranch.toString()); /* LogicGroup */ LogicGroup.Builder<String> groupBuilder = LogicGroup.builder(); @@ -101,14 +103,14 @@ class LogicTreeTests { assertEquals(id[0], branch.id()); assertEquals(value[0], branch.value()); assertEquals(weight[0], branch.weight()); - assertEquals(branchString(id[0], weight[0]), branch.toString()); + assertEquals(branchString(id[0], weight[0], value[0]), branch.toString()); assertEquals(2, group.size()); assertEquals(group.get(0), group.iterator().next()); // iterator } - private static String branchString(String id, double weight) { - return id + " [" + weight + "]"; + private static String branchString(String id, double weight, String value) { + return id + " [" + weight + "] " + value; } final static String TEST_TREE = "test-tree"; @@ -126,17 +128,17 @@ class LogicTreeTests { .addBranch(id[2], value[2], weight[2]) .build(); String treeString = new StringBuilder() - .append(TEST_TREE).append(" ┬ ").append(branchString(id[0], weight[0])) + .append(TEST_TREE).append(" ┬ ").append(branchString(id[0], weight[0], value[0])) .append(Text.NEWLINE) - .append(" ├ ").append(branchString(id[1], weight[1])) + .append(" ├ ").append(branchString(id[1], weight[1], value[1])) .append(Text.NEWLINE) - .append(" └ ").append(branchString(id[2], weight[2])) + .append(" └ ").append(branchString(id[2], weight[2], value[2])) .toString(); assertEquals(treeString, tree.toString()); LogicTree<String> singletonTree = LogicTree.singleton(TEST_TREE, id[0], value[0]); String singletonTreeString = new StringBuilder() - .append(TEST_TREE).append(" ─ ").append(branchString(id[0], 1.0)) + .append(TEST_TREE).append(" ─ ").append(branchString(id[0], 1.0, value[0])) .toString(); assertEquals(singletonTreeString, singletonTree.toString()); @@ -146,9 +148,9 @@ class LogicTreeTests { .addBranch(id[1], value[1], 1.0) .build(); String groupString = new StringBuilder() - .append("logic-group").append(" ┬ ").append(branchString(id[0], 1.0)) + .append("logic-group").append(" ┬ ").append(branchString(id[0], 1.0, value[0])) .append(Text.NEWLINE) - .append(" └ ").append(branchString(id[1], 1.0)) + .append(" └ ").append(branchString(id[1], 1.0, value[1])) .toString(); assertEquals(groupString, group.toString()); }