private static TrigramStringValidator readModel(ResourceFile sourceFile) throws IOException {
		Map<Trigram, Integer> counts = new HashMap<>();
		long totalTrigrams = 0;
		String modelType = null;
		double[] thresholds = null;
		int symbolSize = 128; // default
		int lineNum = 0;
		boolean inFileHeaderSection = true;

		String currString = "";
		try (BufferedReader br = new BufferedReader(
			new InputStreamReader(sourceFile.getInputStream(), StandardCharsets.UTF_8))) {
			while ((currString = br.readLine()) != null) {
				lineNum++;
				if (currString.isBlank()) {
					continue;
				}
				if (inFileHeaderSection && currString.startsWith("#")) {
					String[] headerFields = parseHeaderLine(currString.substring(1).trim());
					if (headerFields != null) {
						switch (headerFields[0]) {
							case "Model Type":
								modelType = headerFields[1];
								break;
							case "Thresholds":
								thresholds = parseThresholds(headerFields[1]);
								break;
							case "Symbol Size":
								symbolSize = Integer.parseInt(headerFields[1]);
								break;
						}
					}
					continue;
				}

				inFileHeaderSection = false;

				String[] lineParts = currString.split("\\t");
				if (lineParts.length != 4) {
					throw new IOException("Invalid field count in ngram %s:%d: %s"
							.formatted(sourceFile.getName(), lineNum, currString));
				}

				Trigram trigram = Trigram.fromStringRep(lineParts[0], lineParts[1], lineParts[2]);
				int currCount = Integer.parseInt(lineParts[3]);

				int[] codePoints = trigram.codePoints();
				if (codePoints[1] == 0 || (codePoints[0] == 0 && codePoints[2] == 0)) {
					// if invalid combination of start-of-string, end-of-string markers
					continue;
				}

				counts.merge(trigram, currCount, (oldVal, newVal) -> oldVal + newVal);
				totalTrigrams += currCount;
			}

			// fixup missing trigram elements
			int trigramEntryCount = counts.size();

			// fully populated trigram mappings would be symbolsize^3, but due to quirk of old
			// code, we also have the special start-of-string and end-of-string doublets to count.
			int expectedEntryCount = // symbolSize^3 + (symbolSize^2)*2
				(symbolSize * symbolSize * symbolSize) + (symbolSize * symbolSize * 2);

			totalTrigrams += (expectedEntryCount - trigramEntryCount);

			Map<Trigram, Double> logProb = calculateLogProbs(counts, totalTrigrams);
			modelType = Objects.requireNonNullElse(modelType, "");
			Function<String, String> transformer = getStringTransformer(modelType);

			// normalize whitespace (in addition to whatever the transformer does)
			transformer = transformer
					.andThen(s -> s.trim().replaceAll(" {2,}", " ").replaceAll("\t{2,}", "\t"));

			return new TrigramStringValidator(logProb, totalTrigrams, transformer, thresholds,
				sourceFile);
		}
		catch (NumberFormatException nfe) {
			throw new IOException(
				"Error parsing string ngram %s:%d: %s".formatted(sourceFile.getName(), lineNum,
					currString));
		}
	}
Remove this flag when the trigram model thresholds have been recalculated
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/TrigramStringValidator.java