API Documentation

For worked examples, see Python library tutorial; for calibration-specific examples and compatibility, see Percentile calibration for all predictors.

The compatibility module mhcflurry.local_parallelism re-exports the canonical mhcflurry.parallelism API. Its identical members are documented under that package rather than indexed twice through the old import path.

Class I MHC ligand prediction package

class mhcflurry.Class1AffinityPredictor(allele_to_allele_specific_models=None, class1_pan_allele_models=None, allele_to_sequence=None, manifest_df=None, allele_to_percent_rank_transform=None, metadata_dataframes=None, provenance_string=None, optimization_info=None, models_dir=None)[source]

Bases: object

High-level interface for peptide/MHC I binding affinity prediction.

This class manages low-level Class1NeuralNetwork instances, each of which wraps a single PyTorch network. The purpose of Class1AffinityPredictor is to implement ensembles, handling of multiple alleles, and predictor loading and saving. It also keeps per-allele percentile calibration transforms: compact curves for new calibration, or historical histogram mappings.

Parameters:
allele_to_allele_specific_modelsdict of string -> list of Class1NeuralNetwork

Ensemble of single-allele models to use for each allele.

class1_pan_allele_modelslist of Class1NeuralNetwork

Ensemble of pan-allele models.

allele_to_sequencedict of string -> string

MHC allele name to fixed-length pseudosequence. Required only if class1_pan_allele_models is specified.

manifest_dfpandas.DataFrame, optional

Must have columns: model_name, allele, config_json, model. Only required if you want to update an existing serialization of a Class1AffinityPredictor. Otherwise this dataframe will be generated automatically based on the supplied models.

allele_to_percent_rank_transformdict of string -> transform, optional

HistogramPercentRankTransform or CompactPercentRankTransform for each allele. Loading preserves the stored calibration method.

metadata_dataframesdict of string -> pandas.DataFrame, optional

Optional additional dataframes to write to the models dir when save() is called. Useful for tracking provenance.

provenance_stringstring, optional

Optional info string to use in __str__.

optimization_infodict, optional

Dict describing any optimizations already performed on the model. The only currently supported optimization is to merge ensembles together into one PyTorch model.

models_dirstring, optional

Directory this predictor was loaded from. Used for diagnostics.

property manifest_df

A pandas.DataFrame describing the models included in this predictor.

Based on: - self.class1_pan_allele_models - self.allele_to_allele_specific_models

Returns:
pandas.DataFrame
clear_cache()[source]

Clear values cached based on the neural networks in this predictor.

Users should call this after mutating any of the following:
  • self.class1_pan_allele_models

  • self.allele_to_allele_specific_models

  • self.allele_to_sequence

Methods that mutate these instance variables will call this method on their own if needed.

property neural_networks

List of the neural networks in the ensemble.

Returns:
list of Class1NeuralNetwork
classmethod merge(predictors)[source]

Merge the ensembles of two or more Class1AffinityPredictor instances.

Note: the resulting merged predictor will NOT have calibrated percentile ranks. Call calibrate_percentile_ranks on it if these are needed.

Parameters:
predictorssequence of Class1AffinityPredictor
Returns:
Class1AffinityPredictor instance
merge_in_place(others)[source]

Add the models present in other predictors into the current predictor.

Parameters:
otherslist of Class1AffinityPredictor

Other predictors to merge into the current predictor.

Returns:
list of stringnames of newly added models
canonicalize_allele_name(raw_name, raise_on_error=True, default_value=None)[source]

Normalize an allele name and map it to the canonical pseudosequence key if possible.

Tries without IMGT aliases first so that alleles like HLA-C*01:01 (which aliases map to C*01:02) resolve to their own pseudosequence when one exists.

By default, raises on names that cannot be normalized. Pass raise_on_error=False to return default_value instead. The no-alias-first logic lives in AlleleKeyResolver; training ingestion shares it via canonicalize_allele_series.

Parameters:
raw_namestr
raise_on_errorbool

Whether to raise a descriptive ValueError for invalid, ambiguous, non-class-I, or unsupported-annotation names.

default_valueobject

Value returned for an invalid name when raise_on_error is false.

Returns:
str
property supported_alleles

Alleles for which predictions can be made.

Returns:
list of string
property supported_peptide_lengths

(minimum, maximum) lengths of peptides supported by all models, inclusive.

Returns:
(int, int) tuple
check_consistency()[source]

Verify that self.manifest_df is consistent with: - self.class1_pan_allele_models - self.allele_to_allele_specific_models

Currently only checks for agreement on the total number of models.

Throws AssertionError if inconsistent.

save(models_dir, model_names_to_write=None, write_metadata=True)[source]

Serialize the predictor to a directory on disk. If the directory does not exist it will be created.

The serialization format consists of a file called “manifest.csv” with the configurations of each Class1NeuralNetwork, along with per-network files giving the model weights. If there are pan-allele predictors in the ensemble, the pseudosequences are also stored in the directory. There is also a small file “info.txt” with basic metadata: when the models were trained, by whom, on what host.

Parameters:
models_dirstring

Path to directory. It will be created if it doesn’t exist.

model_names_to_writelist of string, optional

Only write the weights for the specified models. Useful for incremental updates during training. Passing an explicit empty list writes no model artifacts; this is used by calibration-only updates that replace percentile calibration (CSV or JSON) without touching the manifest, weights, model provenance, allele sequences, or optimization metadata. Explicit metadata_dataframes are still written when write_metadata is true.

write_metadataboolean, optional

Whether to write optional metadata

static load(models_dir=None, max_models=None, optimization_level=None)[source]

Deserialize a predictor from a directory on disk.

Parameters:
models_dirstring, optional

Path to a standalone affinity predictor. If omitted, use the affinity path override or the active release’s standalone bundle; if that default bundle is absent, load the affinity component of the default presentation predictor. Explicit paths take precedence.

max_modelsint, optional

Maximum number of Class1NeuralNetwork instances to load

optimization_levelint

If >0, model optimization will be attempted. Defaults to value of environment variable MHCFLURRY_OPTIMIZATION_LEVEL (1 when unset).

Returns:
Class1AffinityPredictor instance
optimize(warn=True)[source]

EXPERIMENTAL: Optimize the predictor for faster predictions.

Currently the only optimization implemented is to merge multiple pan- allele predictors at the PyTorch level.

The optimization is performed in-place, mutating the instance.

Returns:
bool

Whether optimization was performed

static model_name(allele, num)[source]

Generate a model name

Parameters:
allelestring
numint
Returns:
string
static weights_path(models_dir, model_name)[source]

Generate the path to the weights file for a model

Parameters:
models_dirstring
model_namestring
Returns:
string
static checkpoint_weights_path(models_dir, model_name, policy)[source]

Generate the path to a retained training-checkpoint weight file.

property master_allele_encoding

An AlleleEncoding containing the universe of alleles specified by self.allele_to_sequence.

Returns:
AlleleEncoding
fit_allele_specific_predictors(n_models, architecture_hyperparameters_list, allele, peptides, affinities, inequalities=None, train_rounds=None, models_dir_for_save=None, verbose=0, progress_preamble='', progress_print_interval=5.0, seed=None)[source]

Fit one or more allele specific predictors for a single allele using one or more neural network architectures.

The new predictors are saved in the Class1AffinityPredictor instance and will be used on subsequent calls to predict.

Parameters:
n_modelsint

Number of neural networks to fit

architecture_hyperparameters_listlist of dict

List of hyperparameter sets.

allelestring
peptidesEncodableSequences or list of string
affinitieslist of float

nM affinities

inequalitieslist of string, each element one of “>”, “<”, or “=”

See Class1NeuralNetwork.fit for details.

train_roundssequence of int

Each training point i will be used on training rounds r for which train_rounds[i] > r, r >= 0.

models_dir_for_savestring, optional

If specified, the Class1AffinityPredictor is (incrementally) written to the given models dir after each neural network is fit.

verboseint

Verbosity level for training output

progress_preamblestring

Optional string of information to include in each progress update

progress_print_intervalfloat

How often (in seconds) to print progress. Set to None to disable.

seedint, optional

Base seed for this allele’s fits. When given, each (model_num, architecture_num) pair gets a distinct sub-seed derived from it, so ensemble members are decorrelated but the whole call is reproducible. When None, each Class1NeuralNetwork.fit is left entropy-seeded as before.

Returns:
list of Class1NeuralNetwork
fit_class1_pan_allele_models(n_models, architecture_hyperparameters, alleles, peptides, affinities, inequalities, models_dir_for_save=None, verbose=1, progress_preamble='', progress_print_interval=5.0, seed=None)[source]

Fit one or more pan-allele predictors using a single neural network architecture.

The new predictors are saved in the Class1AffinityPredictor instance and will be used on subsequent calls to predict.

Parameters:
n_modelsint

Number of neural networks to fit

architecture_hyperparametersdict
alleleslist of string

Allele names (not sequences) corresponding to each peptide

peptidesEncodableSequences or list of string
affinitieslist of float

nM affinities

inequalitieslist of string, each element one of “>”, “<”, or “=”

See Class1NeuralNetwork.fit for details.

models_dir_for_savestring, optional

If specified, the Class1AffinityPredictor is (incrementally) written to the given models dir after each neural network is fit.

verboseint

Verbosity level for training output

progress_preamblestring

Optional string of information to include in each progress update

progress_print_intervalfloat

How often (in seconds) to print progress. Set to None to disable.

seedint, optional

Base seed for these fits. When given, each ensemble member gets a distinct sub-seed derived from it, so members are decorrelated but the whole call is reproducible. When None, each Class1NeuralNetwork.fit is left entropy-seeded as before.

Returns:
list of Class1NeuralNetwork
add_pan_allele_model(model, models_dir_for_save=None)[source]

Add a pan-allele model to the ensemble and optionally do an incremental save.

Parameters:
modelClass1NeuralNetwork
models_dir_for_savestring

Directory to save resulting ensemble to

percentile_ranks(affinities, allele=None, alleles=None, throw=True)[source]

Return percentile ranks for the given ic50 affinities and alleles.

The ‘allele’ and ‘alleles’ argument are as in the predict method. Specify one of these.

Parameters:
affinitiessequence of float

nM affinities

allelestring
allelessequence of string
throwboolean

If True, a ValueError will be raised in the case of unsupported alleles. If False, a warning will be logged and NaN will be returned for those percentile ranks.

Returns:
numpy.array of float
models_dir_for_diagnostics()[source]

Return explicit or inferred models dir for user-facing messages.

percent_rank_calibrated_allele(allele)[source]

Return the allele key whose percentile-rank transform applies.

Percent-rank calibration is allele-specific, but pan predictors can reuse calibration from another allele with the same pseudosequence. This helper centralizes that equivalence check for prediction and CLI status/filtering code.

predict(peptides, alleles=None, allele=None, throw=True, centrality_measure='mean', model_kwargs=None)[source]

Predict nM binding affinities.

If multiple predictors are available for an allele, the predictions are the geometric means of the individual model (nM) predictions.

One of ‘allele’ or ‘alleles’ must be specified. If ‘allele’ is specified all predictions will be for the given allele. If ‘alleles’ is specified it must be the same length as ‘peptides’ and give the allele corresponding to each peptide.

Parameters:
peptidesEncodableSequences or list of string
alleleslist of string
allelestring
throwboolean

If True, a ValueError will be raised in the case of unsupported alleles or peptide lengths. If False, a warning will be logged and the predictions for the unsupported alleles or peptides will be NaN.

centrality_measurestring or callable

Measure of central tendency to use to combine predictions in the ensemble. Options include: mean, median, robust_mean.

model_kwargsdict

Additional keyword arguments to pass to Class1NeuralNetwork.predict

Returns
——-
numpy.array of predictions
predict_numeric(peptides, allele, centrality_measure='mean', model_kwargs=None)[source]

Score numeric peptides for one allele without materializing strings.

Parameters:
peptidesNumericSequences

Unaligned integer residues and actual lengths, on CPU or device.

allelestr

One sequence-resolved allele for all rows. Unsupported alleles, lengths and noncanonical residues raise, as with predict(throw=True).

centrality_measurestr or callable

The same log-affinity ensemble aggregation used by predict.

model_kwargsdict, optional

Network prediction options, including batch size.

Returns:
numpy.ndarray

Float64 ensemble affinities in input order (nM).

predict_cartesian_pan_allele(peptides, alleles, throw=True, centrality_measure='mean', model_kwargs=None)[source]

Predict a peptide x allele matrix using the optimized pan-allele path.

Returns None when the predictor is not a single optimized merged pan-allele model. Callers can then fall back to predict. This path keeps peptide encodings unique, computes the peptide stage once per peptide batch, and combines it with allele embeddings on-device.

predict_to_dataframe(peptides, alleles=None, allele=None, throw=True, include_individual_model_predictions=False, include_percentile_ranks=True, include_confidence_intervals=True, centrality_measure='mean', model_kwargs=None)[source]

Predict nM binding affinities with optional ensemble-member detail.

The default output includes the 5th and 95th percentiles of member predictions, interpolated in log-affinity space. These describe ensemble spread, not calibrated confidence intervals for true affinity.

If multiple predictors are available for an allele, the predictions are the geometric means of the individual model predictions.

One of ‘allele’ or ‘alleles’ must be specified. If ‘allele’ is specified all predictions will be for the given allele. If ‘alleles’ is specified it must be the same length as ‘peptides’ and give the allele corresponding to each peptide.

Parameters:
peptidesEncodableSequences or list of string
alleleslist of string
allelestring
throwboolean

If True, a ValueError will be raised in the case of unsupported alleles or peptide lengths. If False, a warning will be logged and the predictions for the unsupported alleles or peptides will be NaN.

include_individual_model_predictionsboolean

If True, the predictions of each individual model are included as columns in the result DataFrame.

include_percentile_ranksboolean, default True

If True, a “prediction_percentile” column will be included giving the percentile ranks. If no percentile rank info is available, this will be ignored with a warning.

include_confidence_intervalsboolean, default True

Include prediction_low and prediction_high, the 5th and 95th ensemble-member percentiles described above.

centrality_measurestring or callable

Measure of central tendency to use to combine predictions in the ensemble. Options include: mean, median, robust_mean.

model_kwargsdict

Additional keyword arguments to pass to Class1NeuralNetwork.predict

Returns:
pandas.DataFrame of predictions
calibrate_percentile_ranks(peptides=None, num_peptides_per_length=100000, alleles=None, bins=None, motif_summary=False, summary_top_peptide_fractions=None, verbose=False, model_kwargs=None, *, method=None, max_knots=128)[source]

Compute the cumulative distribution of ic50 values for a set of alleles over a large universe of random peptides, to enable taking quantiles of this distribution later.

Parameters:
peptidessequence of string or EncodableSequences, optional

Peptides to use

num_peptides_per_lengthint, optional

If peptides argument is not specified, then num_peptides_per_length peptides are randomly sampled from a uniform distribution for each supported length

allelessequence of string, optional

Alleles to perform calibration for. If not specified all supported alleles will be calibrated.

binsobject

Anything that can be passed to numpy.histogram’s “bins” argument can be used here, i.e. either an integer or a sequence giving bin edges in IC50 space. Explicit bins select histogram calibration unless a conflicting method is supplied. With no bins or method, the default is compact; method=”histogram” with no bins uses the historical fixed log-spaced IC50 grid.

motif_summarybool

If True, the length distribution and per-position amino acid frequencies are also calculated for the top x fraction of tightest- binding peptides, where each value of x is given in the summary_top_peptide_fractions list.

summary_top_peptide_fractionslist of float

Only used if motif_summary is True

verboseboolean

Whether to print status updates to stdout

model_kwargsdict

Additional low-level Class1NeuralNetwork.predict() kwargs.

method{“compact”, “histogram”}, optional

Compact by default; explicit bins select the historical histogram.

max_knots{64, 128}, default 128

Upper bound, not the starting size. Compact starts with 64 and permits 128 only when background validation demonstrates an improvement beyond the tolerance.

Returns:
dict of string -> pandas.DataFrame
If motif_summary is True, this will have keys “frequency_matrices” and
“length_distributions”. Otherwise it will be empty.
clear_calibration_fast_cache()[source]
calibrate_percentile_ranks_fast(peptides, alleles, bins=None, motif_summary=False, summary_top_peptide_fractions=(0.001,), allele_batch_size='auto', peptide_batch_size='auto', num_workers_per_gpu=1, device=None, verbose=False, *, method=None, max_knots=128)[source]

GPU-hoisted calibration for many alleles sharing a peptide set.

Drop-in replacement for the bulk of calibrate_percentile_ranks when calibration is dominated by per-allele Python dispatch (the pan-allele full-universe calibration workload, which sweeps ~20k alleles across the same peptide set). Two structural changes:

  1. Precompute peptide-stage activations once per network. The network’s locally-connected + peptide-dense + early-batchnorm layers are identity across alleles; we forward the calibration peptides through that stage exactly once per network and cache the output tensor on device.

  2. Batch ``allele_batch_size`` alleles per forward. A single forward_from_peptide_stage call replaces allele_batch_size separate model.predict calls — amortizing all the small kernel-launch + Python-dispatch overhead that was dominating wall-clock time on the pan-allele full-universe calibration. Effective batch size per forward: allele_batch_size * peptide_batch_size. Automatic sizes account for the current device and resident working set.

Uses the same geometric-mean ensemble aggregation and percentile method as calibrate_percentile_ranks. The batched floating-point schedule can change raw predictions slightly and, in turn, adaptive knot locations. Saved curves are not guaranteed bit-identical. Neural inference remains batched on-device for both methods; histogram fitting is also batched on-device, whereas compact fitting operates on the final ensemble scores on CPU without repeating neural inference.

Caching note: this method memoizes the peptide-stage activations on the predictor instance across calls. That cache is keyed on network identity, not weight content, so do not mutate the predictor’s network weights in place between calls on the same instance without first calling clear_calibration_fast_cache().

Only the pan-allele networks contribute to this path. Use calibrate_percentile_ranks for allele-specific ensembles or ensembles mixing pan-allele and allele-specific networks. Presentation calibration has its own score-based API.

Parameters:
peptidessequence of string or EncodableSequences
allelessequence of string — already-normalized allele names

(canonicalization is the caller’s responsibility for speed).

binssequence of bin edges in IC50 space (histogram only; default for

that method is 999 log-spaced IC50 bins). Scalar integer numpy.histogram bin counts are rejected in this fast path because they imply data-dependent edges per allele, while the batched GPU histogram uses one explicit edge vector for the whole allele chunk.

motif_summarybool — populate frequency matrices + length

distributions, same format as calibrate_percentile_ranks.

summary_top_peptide_fractionsiterable of float — only used

when motif_summary=True.

allele_batch_sizeint or “auto”

Alleles per forward pass. The default auto sizes for device capacity.

peptide_batch_sizeint or “auto”

Peptides per device chunk; auto sized by default.

num_workers_per_gpuint, default 1

Co-resident worker count used for automatic memory budgeting.

devicestr or torch.device, optional

Uses MHCflurry’s configured device when omitted (auto selects CUDA, then MPS, then CPU).

verbosebool — per-batch timing to stdout.
method{“compact”, “histogram”}, optional

Compact by default; explicit bins select the historical histogram.

max_knots{64, 128}, default 128

Validation-selected compact upper bound, not a starting size; 64 is retained unless 128 improves beyond the tolerance.

Returns:
dict (same schema as calibrate_percentile_ranks). Also
populates self.allele_to_percent_rank_transform[allele] for
every allele in alleles.
model_select(score_function, alleles=None, min_models=1, max_models=10000)[source]

Perform model selection using a user-specified scoring function.

This works only with allele-specific models, not pan-allele models.

Model selection is done using a “step up” variable selection procedure, in which models are repeatedly added to an ensemble until the score stops improving.

Parameters:
score_functionClass1AffinityPredictor -> float function

Scoring function

alleleslist of string, optional

If not specified, model selection is performed for all alleles.

min_modelsint, optional

Min models to select per allele

max_modelsint, optional

Max models to select per allele

Returns:
Class1AffinityPredictorpredictor containing the selected models
class mhcflurry.Class1NeuralNetwork(**hyperparameters)[source]

Bases: object

Low level class I predictor consisting of a single neural network.

Both single allele and pan-allele prediction are supported.

Users will generally use Class1AffinityPredictor, which gives a higher-level interface and supports ensembles.

network_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters (and their default values) that affect the neural network architecture.

compile_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Loss and optimizer hyperparameters.

fit_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters for neural network training.

early_stopping_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters for early stopping.

miscelaneous_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Miscelaneous hyperaparameters. These parameters are not used by this class but may be interpreted by other code.

hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Combined set of all supported hyperparameters and their default values.

hyperparameter_renames = {'embedding_init_method': None, 'embedding_input_dim': None, 'embedding_output_dim': None, 'fit_dataloader_backing': None, 'kmer_size': None, 'left_edge': None, 'mode': None, 'monitor': None, 'peptide_amino_acid_encoding': None, 'peptide_amino_acid_encoding_gpu': 'peptide_amino_acid_encoding_torch', 'pseudosequence_use_embedding': None, 'right_edge': None, 'take_best_epoch': None, 'use_embedding': None, 'verbose': None}
classmethod apply_hyperparameter_renames(hyperparameters)[source]

Handle hyperparameter renames.

Parameters:
hyperparametersdict
Returns:
dictupdated hyperparameters
MODELS_CACHE = {}

Process-wide model cache, a map from: architecture JSON string to (PyTorch model, existing network weights)

classmethod clear_model_cache()[source]

Clear the model cache.

classmethod borrow_cached_network(network_json, network_weights)[source]

Return a PyTorch model with the specified architecture and weights. As an optimization, when possible this will reuse architectures from a process-wide cache.

Parameters:
network_jsonstring of JSON
network_weightslist of numpy.array
Returns:
Class1NeuralNetworkModel
static model_cache_key(network_json)[source]

Given a JSON description of a neural network, return a cache key.

Parameters:
network_jsonstring
Returns:
string
static keras_network_cache_key(network_json)[source]

Backward-compatible alias for model_cache_key.

network(borrow=False)[source]

Return the PyTorch model associated with this predictor.

Parameters:
borrowbool

Whether to return a cached model if possible

Returns:
Class1NeuralNetworkModel
update_network_description()[source]

Update self.network_json and self.network_weights properties based on this instances’s neural network.

get_config()[source]

serialize to a dict all attributes except model weights

Returns:
dict
classmethod from_config(config, weights=None, weights_loader=None, weight_paths=None)[source]

deserialize from a dict returned by get_config().

Supports both: - Native Class1NeuralNetwork configs with ‘hyperparameters’ key - Legacy Keras model JSON configs with ‘class_name’, ‘config’, etc.

Parameters:
configdict
weightslist of array, optional

Network weights to restore

weights_loadercallable, optional

Function to call (no arguments) to load weights when needed

weight_pathsstring or list of strings, optional

Filename(s) the weights were loaded from. This is diagnostic provenance only and is not serialized by get_config().

Returns:
Class1NeuralNetwork
load_weights()[source]

Load weights by evaluating self.network_weights_loader, if needed.

get_weights()[source]

Get the network weights

Returns:
list of numpy.array giving weights for each layer or None if there is no
network
get_weights_list()[source]

Get the network weights as a list of numpy arrays.

Returns:
list of numpy.array giving weights for each layer or None if there is no
network
set_weights_list(weights, auto_convert_keras=True)[source]

Set the network weights from a list of numpy arrays.

If a network exists, the weights are set directly on it. Otherwise, the weights are stored and will be applied when the network is created.

Parameters:
weightslist of numpy.array

Weights for each layer

auto_convert_kerasbool

If True, attempt to auto-detect and convert Keras weight formats to PyTorch format. Default True.

available_checkpoint_policies()[source]

Return retained checkpoint policies in stable order.

get_checkpoint_weights(policy)[source]

Return retained weights for policy, loading lazily if needed.

set_checkpoint_weights_loader(policy, loader, weight_path=None)[source]

Attach a lazy loader for a retained training checkpoint.

uses_peptide_torch_encoding()[source]

Whether fixed peptide vectors are looked up in torch forward.

peptides_to_network_input(peptides, device=None)[source]

Encode peptides to the fixed-length encoding expected by the neural network (which depends on the architecture).

Return (N, L) int8 amino-acid indices; the network looks up fixed vectors on device. NumericSequences inputs return a Torch tensor directly, while string inputs retain the existing NumPy path.

Parameters:
peptidesEncodableSequences, NumericSequences or list of string
devicetorch.device or str, optional

Device for NumericSequences alignment; string encoding stays on CPU.

Returns:
numpy.ndarray or torch.Tensor
property supported_peptide_lengths

(minimum, maximum) lengths of peptides supported, inclusive.

Returns:
(int, int) tuple
allele_encoding_to_network_input(allele_encoding)[source]

Encode alleles to the fixed-length encoding expected by the neural network (which depends on the architecture).

Parameters:
allele_encodingAlleleEncoding
Returns:
(numpy.array, numpy.array)
Indices and allele representations.
static data_dependent_weights_initialization(network, x_dict=None, method='lsuv', target='post_activation', verbose=1)[source]

Data dependent weights initialization.

Parameters:
networkClass1NeuralNetworkModel
x_dictdict of string -> numpy.ndarray

Training data

methodstring

Initialization method. Currently only “lsuv” is supported.

target{“post_activation”, “pre_activation”}

Affine-layer output whose variance LSUV normalizes.

verboseint

Status updates printed to stdout if verbose > 0

get_device()[source]

Get the PyTorch device to use.

fit_streaming_batches(generator, validation_peptide_encoding, validation_affinities, validation_allele_encoding=None, validation_inequalities=None, validation_output_indices=None, steps_per_epoch=10, epochs=1000, min_epochs=0, patience=10, min_delta=0.0, verbose=1, progress_callback=None, progress_preamble='', progress_print_interval=5.0, generator_factory=None, generator_batches_are_encoded=False, seed=None, save_all_checkpoints=False)[source]

Pretrain from a stream of already batched examples.

This is the streaming pretraining path used by pan-allele training. It intentionally has a narrower contract than fit():

  • training examples arrive as complete batches from generator;

  • validation data is supplied explicitly rather than split from the training rows;

  • random negatives, sample weights, and the affinity fit() row layout are not part of this API.

The method still shares the same low-level optimizer step, loss object, regularization, and batched validation helpers as fit().

generator may yield either pre-encoded (x_dict, y) tuples (the path the shipped pan-allele pretrain pipeline uses) or legacy raw (allele_encoding, peptides, affinities) tuples. The legacy form is still tested for back-compat but is not exercised by any production pipeline. generator_factory enables DataLoader worker prefetch: each worker calls it with worker_id and num_workers to read a disjoint shard.

seed (int, optional) seeds numpy’s and torch’s global RNGs up front, so weight initialization and any shuffling in this pretrain pass derive from it; None leaves the worker’s entropy seeding in place. Mirrors fit()’s seed so one value can drive both phases of a pan-allele fit.

save_all_checkpoints retains both the terminal and minimum-validation weights. It does not change which state is primary; that remains controlled by the restore_best_weights hyperparameter.

fit_generator(generator, validation_peptide_encoding, validation_affinities, validation_allele_encoding=None, validation_inequalities=None, validation_output_indices=None, steps_per_epoch=10, epochs=1000, min_epochs=0, patience=10, min_delta=0.0, verbose=1, progress_callback=None, progress_preamble='', progress_print_interval=5.0, generator_factory=None, generator_batches_are_encoded=False, save_all_checkpoints=False)[source]

Backward-compatible alias for fit_streaming_batches().

The name is historical from the old Keras API. New internal code should call fit_streaming_batches because this path is specifically the pan-allele pretraining stream, not a general replacement for fit().

fit(peptides, affinities, allele_encoding=None, inequalities=None, output_indices=None, sample_weights=None, shuffle_permutation=None, verbose=1, progress_callback=None, progress_preamble='', progress_print_interval=5.0, seed=None, save_all_checkpoints=False)[source]

Fit the neural network.

Parameters:
peptidesEncodableSequences or list of string
affinitieslist of float

nM affinities. Must have the same length as peptides.

allele_encodingAlleleEncoding

If not specified, the model will be a single-allele predictor.

inequalitieslist of string, each element one of “>”, “<”, or “=”.
output_indiceslist of int

For multi-output models only.

sample_weightslist of float
shuffle_permutationlist of int
verboseint
progress_callbackfunction
progress_preamblestring
progress_print_intervalfloat
seedint, optional

Master seed for this fit. When given, it seeds numpy’s and torch’s global RNGs at the start of the call, so every stochastic step downstream flows from this one value: data-dependent weight initialization, the initial example shuffle, the per-epoch training-batch shuffle, and random-negative sampling. When None (the default) the RNGs are left unchanged. The caller or worker initializer is responsible for setting independent RNG states.

A seed does not guarantee identical weights across hardware, dependency versions or numerical settings. Automatic minibatch reduction can also change a trajectory; release workflows reject that reduction. Preserve the effective batch, source, dependencies, device and precision settings alongside the seed. See PyTorch’s reproducibility notes for backend-specific determinism controls.

save_all_checkpointsbool

Retain both terminal and minimum-validation weights from this fit. This does not change the primary state selected by the restore_best_weights hyperparameter.

predict(peptides, allele_encoding=None, batch_size='auto', output_index=0, num_workers_per_gpu=None)[source]

Predict affinities.

Parameters:
peptidesEncodableSequences or list of string
allele_encodingAlleleEncoding, optional
batch_sizeint or "auto"

"auto" (the default) sizes batches to the available GPU memory at call time — see compute_prediction_batch_size. Pass an explicit int to pin the size.

output_indexint or None
num_workers_per_gpuint, optional

When multiple training/calibration workers are co-resident on the same CUDA device, pass the worker count so the auto- sizer partitions the VRAM budget. Ignored for explicit int batch_size. When not passed, falls back to env_workers_per_gpu(1) (the MHCFLURRY_MAX_WORKERS_PER_GPU env var the worker pool sets), mirroring fit().

Returns:
numpy.array of nM affinity predictions
classmethod merge(models, merge_method='average')[source]

Merge multiple models at the neural network level.

Parameters:
modelslist of Class1NeuralNetwork
merge_methodstring, one of “average”, “sum”, or “concatenate”
Returns:
Class1NeuralNetwork
make_network(peptide_encoding, allele_amino_acid_encoding, allele_dense_layer_sizes, peptide_dense_layer_sizes, peptide_allele_merge_method, peptide_allele_merge_activation, layer_sizes, dense_layer_l1_regularization, dense_layer_l2_regularization, activation, init, output_activation, dropout_probability, batch_normalization, locally_connected_layers, topology, num_outputs=1, allele_representations=None, peptide_amino_acid_encoding_torch=True, peptide_amino_acid_encoding_gpu=None, normalization='none')[source]

Helper function to make a PyTorch network for class 1 affinity prediction.

clear_allele_representations()[source]

Set allele representations to an empty array.

set_allele_representations(allele_representations, force_surgery=False)[source]

Set the allele representations in use by this model.

Parameters:
allele_representationsnumpy.ndarray of shape (a, l, m)
force_surgerybool
class mhcflurry.Class1ProcessingPredictor(models, manifest_df=None, metadata_dataframes=None, provenance_string=None, percent_rank_transform=None)[source]

Bases: object

User-facing interface to antigen processing prediction.

Delegates to an ensemble of Class1ProcessingNeuralNetwork instances.

Instantiate a new Class1ProcessingPredictor

Users will generally call load() to restore a saved predictor rather than using this constructor.

Parameters:
modelslist of Class1ProcessingNeuralNetwork

Neural networks in the ensemble.

manifest_dfpandas.DataFrame

Manifest dataframe. If not specified a new one will be created when needed.

metadata_dataframesdict of string -> pandas.DataFrame

Arbitrary metadata associated with this predictor

provenance_stringstring, optional

Optional info string to use in __str__.

percent_rank_transformtransform, optional

HistogramPercentRankTransform or CompactPercentRankTransform fitted to this ensemble’s background score distribution. Historical processing predictors may have no calibration.

calibrate_percentile_ranks(scores, bins=None, *, method=None, max_knots=128, groups=None)[source]

Calibrate from explicit background processing scores.

Parameters:
scoressequence of float

Independent background scores from the same ensemble and flank policy used at prediction time. Evaluation labels are not used.

binsint or sequence, optional

Explicit bins select historical histogram calibration.

method{“compact”, “histogram”}, optional

Compact unless explicit bins select histogram. Compact plus bins is rejected. Histogram with no bins uses score quantiles.

max_knots{64, 128}, default 128

Upper bound, not a starting size; retain 64 unless 128 improves background validation beyond the tolerance. Ignored for histogram.

groupssequence, optional

Reference peptide identities, kept together during validation.

percentile_ranks(processing_scores, throw=True)[source]

Return lower-is-stronger percentiles without changing raw scores.

Parameters:
processing_scoressequence of float

Raw processing scores, not peptide sequences.

throwbool, default True

Raise when calibration is absent. False warns and returns NaNs.

Returns:
numpy.ndarray

Upper-tail percentiles from 0 to 100. This separate method does not add a percentile column to raw prediction dataframes.

property sequence_lengths

Supported maximum sequence lengths.

Passing a peptide greater than the maximum supported length results in an error.

Passing an N- or C-flank sequence greater than the maximum supported length results in some part of it being ignored.

Returns:
dict of string -> int
Keys are “peptide”, “n_flank”, “c_flank”. Values give the maximum
supported sequence length.
add_models(models)[source]

Add models to the ensemble (in-place).

Parameters:
modelslist of Class1ProcessingNeuralNetwork
Returns:
list of string
Names of the new models.
property manifest_df

A pandas.DataFrame describing the models included in this predictor.

Returns:
pandas.DataFrame
static model_name(num)[source]

Generate a model name

Returns:
string
static weights_path(models_dir, model_name)[source]

Generate the path to the weights file for a model

Parameters:
models_dirstring
model_namestring
Returns:
string
predict(peptides, n_flanks=None, c_flanks=None, throw=True, batch_size='auto')[source]

Predict antigen processing.

Parameters:
peptideslist of string

Peptide sequences

n_flankslist of string

Upstream sequence before each peptide

c_flankslist of string

Downstream sequence after each peptide

throwboolean

If True, a ValueError will be raised in the case of unsupported peptides. If False, a warning will be logged and the predictions for those peptides will be NaN.

batch_sizeint or “auto”

Prediction batch size, automatically sized by default.

Returns:
numpy.array
Processing scores. Range is 0-1, higher indicates more favorable
processing.
predict_to_dataframe(peptides, n_flanks=None, c_flanks=None, throw=True, batch_size='auto')[source]

Predict antigen processing.

See predict method for parameter descriptions.

Returns:
pandas.DataFrame
Processing predictions are in the “score” column. Also includes
peptides and flanking sequences.
predict_to_dataframe_encoded(sequences, throw=True, batch_size='auto')[source]

Predict antigen processing.

See predict method for more information.

Parameters:
sequencesFlankingEncoding
batch_sizeint or “auto”
throwboolean
Returns:
pandas.DataFrame
predict_encoded_tensor(sequences, throw=True, batch_size='auto')[source]

Predict antigen processing and return a torch tensor.

Ensemble members consume the tensor cache on sequences when available, so encoded inputs only need to move to each target device once per encoding/device combination.

check_consistency()[source]

Verify that self.manifest_df is consistent with instance variables.

Currently only checks for agreement on the total number of models.

Throws AssertionError if inconsistent.

save(models_dir, model_names_to_write=None, write_metadata=True, write_percent_ranks=True)[source]

Serialize the predictor to a directory on disk. If the directory does not exist it will be created.

The serialization format consists of a file called “manifest.csv” with the configurations of each Class1ProcessingNeuralNetwork, along with per-network files giving the model weights.

Parameters:
models_dirstring

Path to directory. It will be created if it doesn’t exist.

model_names_to_writelist of string, optional

Only write the weights for the specified models. Useful for incremental updates during training: previously saved members of this predictor remain in the manifest. In a fresh directory, save only the requested members, in the requested order. Such a subset has no percentile calibration; calibrate the exported predictor separately. Passing an explicit empty list writes no model artifacts; this is used by calibration-only updates that replace percentile calibration without touching the manifest, weights, or retained checkpoints.

write_metadataboolean, optional

Whether to write optional metadata

write_percent_ranksboolean, optional

Whether to write the percentile calibration

classmethod load(models_dir=None, max_models=None)[source]

Deserialize a predictor from a directory on disk.

Parameters:
models_dirstring

Path to directory. If unspecified the default downloaded models are used.

max_modelsint, optional

Maximum number of models to load

Returns:
Class1ProcessingPredictor instance
class mhcflurry.Class1ProcessingNeuralNetwork(**hyperparameters)[source]

Bases: object

A neural network for antigen processing prediction

network_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters (and their default values) that affect the neural network architecture.

fit_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters for neural network training.

early_stopping_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters for early stopping.

compile_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Loss and optimizer hyperparameters.

auxiliary_input_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Allele feature hyperparameters.

hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>
property sequence_lengths

Supported maximum sequence lengths

Returns:
dict of string -> int
Keys are “peptide”, “n_flank”, “c_flank”. Values give the maximum
supported sequence length.
get_device()[source]

Get the PyTorch device to use.

network()[source]

Return the PyTorch model associated with this network.

update_network_description()[source]

Update self.network_json and self.network_weights properties based on this instances’s neural network.

fit(sequences, targets, sample_weights=None, shuffle_permutation=None, verbose=1, progress_callback=None, progress_preamble='', progress_print_interval=5.0, seed=None, validation_mask=None, sample_ids=None)[source]

Fit the neural network.

Parameters:
sequencesFlankingEncoding

Peptides and upstream/downstream flanking sequences

targetslist of float

1 indicates hit, 0 indicates decoy

sample_weightslist of float

If not specified all samples have equal weight.

validation_maskarray of bool, optional

Explicit per-row validation membership, overriding validation_split. Used by matched processing training to keep complete samples together.

sample_idsarray of str, optional

Required for monitor_validation_ranking or checkpoint_metric= ‘val_macro_ap’. Samples must not cross the explicit training and stopping-validation mask. AP selects the earliest best-ranking epoch; early-stopping patience remains based on validation loss.

shuffle_permutationlist of int

Permutation of row indices, with the same length as targets. If None, then a random permutation will be generated.

verboseint

Verbosity level

progress_callbackfunction

No-argument function to call after each epoch.

progress_preamblestring

Optional string of information to include in each progress update

progress_print_intervalfloat

How often (in seconds) to print progress update. Set to None to disable.

seedint, optional

Master seed for this fit. When given, it seeds numpy’s and torch’s global RNGs at the start of the call, so every stochastic step downstream flows from this one value: weight initialization, the initial example shuffle, and the per-epoch training-batch shuffle. When None (the default) the RNGs are left unchanged. The caller or worker initializer is responsible for setting independent RNG states. Mirrors mhcflurry.class1_neural_network.Class1NeuralNetwork.fit()’s seed so one value can drive both trainers.

predict(peptides, n_flanks=None, c_flanks=None, batch_size='auto')[source]

Predict antigen processing.

Parameters:
peptideslist of string

Peptide sequences

n_flankslist of string

Upstream sequence before each peptide

c_flankslist of string

Downstream sequence after each peptide

batch_sizeint or “auto”

Prediction batch size, automatically sized by default.

Returns:
numpy.array
Processing scores. Range is 0-1, higher indicates more favorable
processing.
predict_encoded(sequences, throw=True, batch_size='auto')[source]

Predict antigen processing.

Parameters:
sequencesFlankingEncoding

Peptides and flanking sequences

throwboolean

Whether to throw exception on unsupported peptides

batch_sizeint or "auto"

Prediction batch size. "auto" (the default) auto-sizes per the current device — see mhcflurry.pytorch_sizing.compute_prediction_batch_size.

Returns:
numpy.array
predict_encoded_tensor(sequences, throw=True, batch_size='auto', device=None)[source]

Predict antigen processing and return a torch tensor.

This tensor-native path keeps encoded inputs resident on the target device when FlankingEncoding can provide a compatible tensor cache. predict_encoded delegates here and converts the final result to numpy for the public API.

network_input_tensors(sequences, device, throw=True)[source]

Encode peptides to the target-device tensors expected by the network.

network_input(sequences, throw=True)[source]

Encode peptides to the fixed-length encoding expected by the neural network (which depends on the architecture).

Parameters:
sequencesFlankingEncoding

Peptides and flanking sequences

throwboolean

Whether to throw exception on unsupported peptides

Returns:
dict
make_network(amino_acid_encoding, amino_acid_encoding_torch, peptide_max_length, n_flank_length, c_flank_length, flanking_averages, convolutional_filters, convolutional_kernel_size, convolutional_padding_mode, convolutional_activation, convolutional_kernel_l1_l2, dropout_rate, post_convolutional_dense_layer_sizes, init, normalization, cleavage_boundary_flank_length, cleavage_boundary_peptide_length, cleavage_boundary_hidden_size, cleavage_boundary_context_dropout)[source]

Helper function to make a PyTorch network given hyperparameters.

get_weights()[source]

Get the network weights

Returns:
list of numpy.array giving weights for each layer or None if there is no
network
get_config()[source]

serialize to a dict all attributes except model weights

Returns:
dict
classmethod from_config(config, weights=None)[source]

deserialize from a dict returned by get_config().

Parameters:
configdict
weightslist of array, optional

Network weights to restore

Returns:
Class1ProcessingNeuralNetwork
class mhcflurry.Class1PresentationPredictor(affinity_predictor=None, processing_predictor_with_flanks=None, processing_predictor_without_flanks=None, weights_dataframe=None, metadata_dataframes=None, percent_rank_transform=None, provenance_string=None)[source]

Bases: object

A logistic regression model over predicted binding affinity (BA) and antigen processing (AP) score.

Instances of this class delegate to Class1AffinityPredictor and Class1ProcessingPredictor instances to generate BA and AP predictions. These predictions are combined using a logistic regression model to give a “presentation score” prediction.

Most users will call the load static method to get an instance of this class, then call the predict method to generate predictions.

model_inputs = ['affinity_score', 'processing_score']
property supported_alleles

List of alleles supported by the underlying Class1AffinityPredictor

property supported_peptide_lengths

(min, max) of supported peptide lengths, inclusive.

property supports_affinity_prediction

Is there an affinity predictor associated with this instance?

property supports_processing_prediction

Is there a processing predictor associated with this instance?

property supports_presentation_prediction

Can this instance predict presentation?

predict_sequences_columns(alleles, use_flanks=True, include_affinity_percentile=True)[source]

Column names that predict_sequences(..., result="all") will emit.

Used so the empty-input fast-path in mhcflurry-predict-scan can seed a DataFrame with the same schema the populated path produces. Mirrors the column set assembled in predict() plus the sequence_name / pos columns inserted in predict_sequences.

predict_columns(affinity_only=False, use_flanking=True, include_affinity_percentile=False)[source]

Column names that predict() / predict_affinity() emit when called with non-empty inputs.

Used by mhcflurry-predict to give empty inputs the same output schema as populated ones. Mirrors the columns assembled by predict_affinity and the additional columns layered on by predict.

predict_affinity(peptides, alleles, sample_names=None, include_affinity_percentile=True, verbose=1, throw=True, model_kwargs=None)[source]

Predict binding affinities across samples, each with an MHC allele set.

Two modes are supported: each peptide can be evaluated for binding to any of the alleles in any sample (this is what happens when sample_names is None), or the i’th peptide can be evaluated for binding the alleles of the sample given by the i’th entry in sample_names.

For example, if we don’t specify sample_names, then predictions are taken for all combinations of samples and peptides, for a result size of num peptides * num samples:

>>> predictor = Class1PresentationPredictor.load()
>>> predictions = predictor.predict_affinity(
...    peptides=["SIINFEKL", "PEPTIDE"],
...    alleles={
...        "sample1": ["A0201", "A0301", "B0702"],
...        "sample2": ["A0101", "C0202"],
...    },
...    verbose=0)
>>> list(zip(predictions.sample_name, predictions.peptide))
[('sample1', 'SIINFEKL'), ('sample1', 'PEPTIDE'), ('sample2', 'SIINFEKL'), ('sample2', 'PEPTIDE')]
>>> bool((predictions.affinity > 0).all())
True

In contrast, here we specify sample_names, so peptide is evaluated for binding the alleles in the corresponding sample, for a result size equal to the number of peptides:

>>> predictions = predictor.predict_affinity(
...    peptides=["SIINFEKL", "PEPTIDE"],
...    alleles={
...        "sample1": ["A0201", "A0301", "B0702"],
...        "sample2": ["A0101", "C0202"],
...    },
...    sample_names=["sample2", "sample1"],
...    verbose=0)
>>> list(zip(predictions.sample_name, predictions.peptide))
[('sample2', 'SIINFEKL'), ('sample1', 'PEPTIDE')]
>>> bool((predictions.affinity > 0).all())
True
Parameters:
peptideslist of string

Peptide sequences

allelesdict of string -> list of string

Keys are sample names, values are the MHC alleles for that sample

sample_nameslist of string [same length as peptides]

Sample names corresponding to each peptide. If None, then predictions are generated for all sample MHC allele sets across all peptides.

include_affinity_percentilebool

Whether to include affinity percentile ranks

verboseint

Set to 0 for quiet.

throwbool

Whether to throw exception (vs. just log a warning) on invalid peptides, etc.

model_kwargsdict, optional

Keyword arguments forwarded to Class1AffinityPredictor.predict.

Returns:
pandas.DataFramepredictions
predict_processing(peptides, n_flanks=None, c_flanks=None, throw=True, verbose=1, batch_size='auto')[source]

Predict antigen processing scores for individual peptides, optionally including flanking sequences for better cleavage prediction.

Parameters:
peptideslist of string
n_flankslist of string [same length as peptides]
c_flankslist of string [same length as peptides]
throwboolean

Whether to raise exception on unsupported peptides

verboseint
batch_sizeint or “auto”
Returns:
numpy.arrayAntigen processing scores for each peptide
fit(targets, peptides, sample_names, alleles, n_flanks=None, c_flanks=None, verbose=1)[source]

Fit the presentation score logistic regression model.

Parameters:
targetslist of int/float

1 indicates hit, 0 indicates decoy

peptideslist of string [same length as targets]
sample_nameslist of string [same length as targets]
allelesdict of string -> list of string

Keys are sample names, values are the alleles for that sample

n_flankslist of string [same length as targets]
c_flankslist of string [same length as targets]
verboseint
fit_from_scores(targets, affinities, processing_scores_by_model, verbose=1)[source]

Fit presentation logistic-regression weights from precomputed scores.

Parameters:
targetslist of int/float

1 indicates hit, 0 indicates decoy.

affinitieslist of float

Best binding affinity predictions aligned to targets.

processing_scores_by_modeldict

Mapping from model name ("with_flanks" or "without_flanks") to processing predictions aligned to targets.

verboseint
get_model(name=None)[source]

Load or instantiate a new logistic regression model. Private helper method.

Parameters:
namestring

If None (the default), an un-fit LR model is returned. Otherwise the weights are loaded for the specified model.

Returns:
sklearn.linear_model.LogisticRegression
predict(peptides, alleles, sample_names=None, n_flanks=None, c_flanks=None, include_affinity_percentile=False, verbose=1, throw=True, affinity_model_kwargs=None, processing_batch_size='auto')[source]

Predict presentation scores across a set of peptides.

Presentation scores combine predictions for MHC I binding affinity and antigen processing.

This method returns a pandas.DataFrame giving presentation scores plus the binding affinity and processing predictions and other intermediate results.

Example:

>>> predictor = Class1PresentationPredictor.load()
>>> predictions = predictor.predict(
...    peptides=["SIINFEKL", "PEPTIDE"],
...    n_flanks=["NNN", "SNS"],
...    c_flanks=["CCC", "CNC"],
...    alleles={
...        "sample1": ["A0201", "A0301", "B0702"],
...        "sample2": ["A0101", "C0202"],
...    },
...    verbose=0)
>>> list(zip(predictions.sample_name, predictions.peptide))
[('sample1', 'SIINFEKL'), ('sample1', 'PEPTIDE'), ('sample2', 'SIINFEKL'), ('sample2', 'PEPTIDE')]
>>> bool(predictions.presentation_score.between(0, 1).all())
True

You can also specify sample_names, in which case peptide is evaluated for binding the alleles in the corresponding sample only. See predict_affinity for examples.

Parameters:
peptideslist of string

Peptide sequences

alleleslist of string or dict of string -> list of string

If you are predicting for a single sample, pass a list of strings indicating the sample MHC allele set (at most six alleles in this list form). If you are predicting across multiple samples, pass a dict where the keys are (arbitrary) sample names and the values are the alleles to predict for that sample. Set to an empty list or dict to perform processing prediction only.

sample_nameslist of string [same length as peptides]

If you are passing a dict for ‘alleles’, you can use this argument to specify which peptides go with which samples. If it is None, then predictions will be performed for each peptide across all samples.

n_flankslist of string [same length as peptides]

Upstream sequences before the peptide. Sequences of any length can be given and a suffix of the size supported by the model will be used.

c_flankslist of string [same length as peptides]

Downstream sequences after the peptide. Sequences of any length can be given and a prefix of the size supported by the model will be used.

include_affinity_percentilebool

Whether to include affinity percentile ranks

verboseint

Set to 0 for quiet.

throwbool

Whether to throw exception (vs. just log a warning) on invalid peptides, etc.

affinity_model_kwargsdict, optional

Keyword arguments forwarded to Class1AffinityPredictor.predict.

processing_batch_sizeint or “auto”

Batch size for antigen processing neural network prediction.

Returns:
pandas.DataFrame
Presentation scores and intermediate results.
resolve_comparison_quantity(alleles, comparison_quantity=None)[source]

Resolve the column used to rank scan predictions.

This is the single source of truth for the comparison_quantity defaulting and validation used by predict_sequences(). It is also called by the predict-scan CLI’s parallel path so that chunked execution ranks on exactly the same column the serial path would pick (which depends on the predictor’s capabilities, not on which columns happen to be present in a given result).

Parameters:
alleles

The alleles argument as passed to predict_sequences() (string, list, or dict). Only its length / emptiness is used here.

comparison_quantitystring or None

If None, a default is chosen: presentation_score when alleles are given and presentation is supported, else affinity when alleles are given, else processing_score.

Returns:
string

The resolved (and validated) comparison quantity.

static sort_predictions(result_df, comparison_quantity)[source]

Globally sort scan predictions by comparison_quantity.

Score columns (those ending in "score") sort descending (stronger binders first); affinity / affinity_percentile sort ascending (lower is stronger). peptide is the secondary key. Rows tied on both keys retain their input order. The scan CLI preserves serial input order when combining parallel chunks before this sort.

Returns a new DataFrame; the index is not reset.

predict_sequences(sequences, alleles, result='best', comparison_quantity=None, filter_value=None, peptide_lengths=(8, 9, 10, 11), use_flanks=True, include_affinity_percentile=True, verbose=1, throw=True, affinity_model_kwargs=None, processing_batch_size='auto')[source]

Predict presentation across protein sequences.

Example:

>>> predictor = Class1PresentationPredictor.load()
>>> predictions = predictor.predict_sequences(
...    sequences={
...        'protein1': "MDSKGSSQKGSRLLLLLVVSNLL",
...        'protein2': "SSLPTPEDKEQAQQTHH",
...    },
...    alleles={
...        "sample1": ["A0201", "A0301", "B0702"],
...        "sample2": ["A0101", "C0202"],
...    },
...    result="filtered",
...    comparison_quantity="affinity",
...    filter_value=500,
...    verbose=0)
>>> bool((predictions.affinity <= 500).all())
True
>>> {"sequence_name", "pos", "peptide", "affinity"}.issubset(predictions.columns)
True
Parameters:
sequencesstr, list of string, or string -> string dict

Protein sequences. If a dict is given, the keys are arbitrary ( e.g. protein names), and the values are the amino acid sequences.

alleleslist of string, list of list of string, or dict of string -> list of string

MHC I alleles. Can be: (1) a string (a single allele), (2) a list of strings (a single MHC allele set), (3) a list of list of strings (multiple MHC allele sets, where the number of sets must equal the number of sequences), or (4) a dict giving multiple MHC allele sets, which will each be run over the sequences.

resultstring, default “best”

Specify ‘best’ to return the strongest peptide for each sequence and sample, ‘all’ to return predictions for all peptides, or ‘filtered’ to return predictions where the comparison_quantity is stronger or equal to filter_value (<= for affinity/percentile, >= for scores).

comparison_quantitystring, optional

One of “presentation_score”, “processing_score”, “affinity”, or “affinity_percentile”. Prediction to use to rank (if result is “best”) or filter (if result is “filtered”) results. With MHC alleles, defaults to presentation when supported, else affinity; without MHC alleles, defaults to processing.

filter_valuefloat

Threshold value to use, only relevant when result is “filtered”. Affinity and affinity-percentile values at or below the threshold are retained; presentation and processing scores at or above it are retained. Required when result is “filtered”.

peptide_lengthssequence of int, default (8, 9, 10, 11)

Peptide lengths to scan.

use_flanksbool, default True

Whether to include flanking sequences when running the AP predictor (for better cleavage prediction).

include_affinity_percentilebool

Whether to include affinity percentile ranks in output.

verboseint

Set to 0 for quiet mode.

throwboolean

Whether to throw exceptions (vs. log warnings) on invalid inputs.

affinity_model_kwargsdict, optional

Keyword arguments forwarded to Class1AffinityPredictor.predict.

processing_batch_sizeint or “auto”

Batch size for antigen processing neural network prediction.

Returns:
pandas.DataFrame

Includes sequence_name, zero-based pos, peptide and sample_name. Available predictor components determine affinity, best_allele, processing_score and presentation_score columns. Flank columns and percentile columns depend on inputs, options and calibration.

save(models_dir, write_affinity_predictor=True, write_processing_predictor=True, write_weights=True, write_percent_ranks=True, write_info=True, write_metadata=True)[source]

Save the predictor to a directory on disk. If the directory does not exist it will be created.

The wrapped Class1AffinityPredictor and Class1ProcessingPredictor instances are included in the saved data.

Parameters:
models_dirstring

Path to directory. It will be created if it doesn’t exist.

write_affinity_predictorbool, default True

Save the embedded affinity ensemble.

write_processing_predictorbool, default True

Save the available embedded processing ensembles.

write_weightsbool, default True

Save fitted logistic-regression coefficients; requires a fitted model.

write_percent_ranksbool, default True

Replace the presentation calibration with its current state.

write_infobool, default True

Write save-time package, host and release-provenance metadata.

write_metadatabool, default True

Write dataframes in metadata_dataframes.

classmethod load(models_dir=None, max_models=None)[source]

Deserialize a predictor from a directory on disk.

This will also load the wrapped Class1AffinityPredictor and Class1ProcessingPredictor instances.

Parameters:
models_dirstring

Path to directory. If unspecified the default downloaded models are used.

max_modelsint, optional

Maximum number of affinity and processing (counted separately) models to load

Returns:
Class1PresentationPredictor instance
percentile_ranks(presentation_scores, throw=True)[source]

Return percentile ranks for the given presentation scores.

Parameters:
presentation_scoressequence of float

Raw presentation scores, not peptide sequences.

throwbool, default True

Raise when calibration is absent. False warns and returns NaNs.

Returns:
numpy.array of float

Upper-tail percentiles from 0 to 100; lower means stronger.

calibrate_percentile_ranks(scores, bins=None, *, method=None, max_knots=128, groups=None)[source]

Compute the cumulative distribution of scores, to enable taking quantiles of this distribution later.

Parameters:
scoressequence of float

Presentation prediction scores

binsobject

Anything that can be passed to numpy.histogram’s “bins” argument can be used here, i.e. either an integer or a sequence giving bin edges. Explicit bins select the historical histogram method.

method{“compact”, “histogram”}, optional

Defaults to compact unless bins are specified. Loading a saved predictor never recalibrates it.

max_knots{64, 128}, default 128

Upper bound, not a starting size. Compact starts with 64; 128 requires a background-validation improvement beyond the tolerance. Ignored for histogram calibration.

groupssequence, optional

Background peptide identities to keep together during validation.

class mhcflurry.HistogramPercentRankTransform[source]

Bases: object

Historical histogram-based CDF lookup, with preserved bin semantics.

The old PercentRankTransform name remains an alias. New predictor calibration defaults to CompactPercentRankTransform; use this class for saved-table compatibility or explicitly selected histogram calibration. Distinct raw scores can share one step value. Use survival=True for upper-tail percentiles, as required by processing/presentation predictors.

fit(values, bins)[source]

Fit the transform using the given values (e.g. ic50s).

Parameters:
valuespredictions (e.g. ic50 values)
binsbins for the cumulative distribution function

Anything that can be passed to numpy.histogram’s “bins” argument can be used here.

Returns:
HistogramPercentRankTransform

This fitted instance. Fit a fresh instance for each distribution.

classmethod fit_batch_torch(values_2d, bin_edges_1d)[source]

Batched GPU fit across multiple distributions.

Equivalent to calling fit(values_2d[i], bins=bin_edges_1d) for each row i, but vectorized across the row dim — eliminates the per-allele Python loop in calibrate’s hot path. Rows with no values inside the bin range are invalid and raise instead of fabricating an empty CDF.

Parameters:
values_2dtorch.Tensor of shape (n_distributions, n_values).

Stays on whatever device it’s on; histogram bucketing happens there.

bin_edges_1dtorch.Tensor of shape (n_edges,), monotonically

increasing. Same device as values_2d.

Returns:
list of HistogramPercentRankTransform

One transform per input distribution.

Numerically equivalent to the per-row numpy.histogram path
(matching to ≤1e-12, not bit-for-bit – division/cumsum ordering on
CUDA drifts in the last ULPs, far below bin resolution): same bin
assignment (right-open intervals, last bin inclusive), same CDF
normalization (% out of in-range count), and an identical cdf
array layout (length n_bins+3, sentinels at [0]=[1]=0, [-1]=100,
cumsum in [2:-1]).
transform(values, survival=False)[source]

Return percent ranks (range [0, 100]) for the given values.

Parameters:
valuessequence of float

Raw scores. Input NaNs become output NaNs.

survivalbool, default False

False returns the historical CDF lookup. True returns 100 minus that lookup, retaining the historical upper-tail behavior.

Returns:
numpy.ndarray

Percentiles using the saved histogram, without interpolation.

to_dict()[source]

Serialize without the NaN sentinels used in the historical CSV index.

classmethod from_dict(values)[source]

Restore a versioned histogram transform.

to_series()[source]

Serialize the fit to a pandas.Series.

The index on the series gives the bin edges and the values give the CDF.

Returns:
pandas.Series
static from_series(series)[source]

Deserialize a histogram transform from a pandas.Series, as returned by to_series().

Parameters:
seriespandas.Series
Returns:
HistogramPercentRankTransform
class mhcflurry.CompactPercentRankTransform(score_transform='logit')[source]

Bases: object

Small, versioned monotonic approximation to background percentiles.

The knots store transformed raw scores and logit midrank survival probabilities. Linear interpolation in those coordinates followed by a sigmoid gives upper-tail percentiles; the complementary sigmoid gives CDF percentiles. Duplicate reference scores are weighted by their mass. No evaluation labels are required or accepted.

Parameters:
score_transform{“logit”, “log”}

Use logit for probability-valued processing/presentation scores and log for positive quantities such as affinity IC50. This selects the input coordinate, not the output direction: pass survival=True to transform processing/presentation scores into lower-is-stronger ranks.

Notes

Low-level fit uses a fixed budget (64 by default). Predictor calibration uses the shared validation selector to decide whether 128 is warranted. Tail extrapolation models, rather than establishes, rare frequencies.

FORMAT = 'compact-log-survival-linear-v1'
fit(scores, num_knots=64)[source]

Fit a curve with a fixed knot budget; return this instance.

Parameters:
scoresone-dimensional sequence of float

Finite, nonconstant background scores. Log coordinates require positive values; logit coordinates require values in [0, 1].

num_knotsint, default 64

Maximum knot count, including endpoints. This low-level method does not choose between budgets or use validation data.

Returns:
CompactPercentRankTransform

This fitted instance. Fewer knots may suffice for small or linear reference curves. Any previous automatic-selection metadata is cleared.

log_percentiles(scores, survival=False)[source]

Return natural logs of percentiles on the 0–100 scale.

Parameters:
scoresfloat or array-like

Scores in the fitted coordinate’s domain; NaNs propagate.

survivalbool, default False

False returns log CDF-percentile; True returns log upper-tail percentile directly. This is not the log of a 0–1 probability.

Returns:
numpy.ndarray or numpy scalar

Log-percentiles, retaining tiny-tail information before ordinary percentile exponentiation underflows. Extrapolation is not an empirical guarantee of extreme-tail accuracy.

transform(scores, survival=False)[source]

Return CDF or upper-tail percentiles in [0, 100].

Parameters:
scoresfloat or array-like

Raw scores in the fitted coordinate’s domain. NaNs propagate; infinities and out-of-domain values raise ValueError.

survivalbool, default False

Use False for affinity IC50 (lower raw values get lower ranks). Use True for processing/presentation probabilities (higher raw values get lower ranks). The upper tail is evaluated directly, without subtracting a rounded CDF percentile from 100.

Returns:
numpy.ndarray or numpy scalar

Percentiles. Float64 rounding and underflow can still create ties in extreme tails; use log_percentiles for tiny-tail analysis.

to_dict()[source]

Return a JSON-serializable, explicitly versioned representation.

classmethod from_dict(values)[source]

Load a curve, rejecting unsupported versions and invalid knots.

Subpackages

Submodules

mhcflurry.allele_capabilities module

Model-bound execution and training evidence, without validation inference.

mhcflurry.allele_capabilities.model_fingerprint(models_dir)[source]

Hash every file and its relative name; reject symlinks inside the bundle.

mhcflurry.allele_capabilities.generator_metadata(source_file)[source]

Record code and dependency identities used to generate a report.

mhcflurry.allele_capabilities.training_evidence(models_dir, alleles, lengths)[source]

Count observations in bundled tables, preserving unknown host species.

Counts include every row (including decoys) and are not a complete inventory of pretraining, training, development or selection. MHC species never substitutes for the species of the peptide source or experimental host. Missing tables/columns produce null counts, not zero evidence.

mhcflurry.allele_capabilities.capability_rows(predictor, alleles, lengths)[source]

Describe no-flank modality support per requested allele and length.

Support is determined from the loaded model configuration. This function does not run predictions or establish empirical accuracy. Processing is allele-independent and remains available for an unsupported allele when its length is supported. Presentation requires that exact resolved allele.

mhcflurry.allele_capabilities.capability_report(models_dir, alleles, lengths=range(8, 16))[source]

Load an exact presentation bundle and report capability plus evidence.

Parameters:
models_dirstr or pathlib.Path

Frozen presentation bundle directory. All files are hashed; symlinks inside the bundle are rejected.

allelesiterable of str

Requested allele names. Order and aliases are retained in the report.

lengthsiterable of int

Positive peptide lengths to inspect, including unsupported lengths.

Returns:
dict

JSON-serializable evidence. Null validation/calibration provenance means unknown; presence of a transform or training row does not establish it.

mhcflurry.allele_capabilities.run_argv(argv, prog='mhcflurry eval allele-capabilities')[source]

Write a model-bound allele capability report as JSON.

mhcflurry.allele_encoding module

class mhcflurry.allele_encoding.AlleleEncoding(alleles=None, allele_to_sequence=None, borrow_from=None)[source]

Bases: object

A place to cache encodings for a sequence of alleles.

We frequently work with alleles by integer indices, for example as inputs to neural networks. This class is used to map allele names to integer indices in a consistent way by keeping track of the universe of alleles under use, i.e. a distinction is made between the universe of supported alleles (what’s in allele_to_sequence) and the actual set of alleles used for some task (what’s in alleles).

Parameters:
alleleslist of string

Allele names. If any allele is None instead of string, it will be mapped to the special index value -1.

allele_to_sequencedict of str -> str

Allele name to amino acid sequence

borrow_fromAlleleEncoding, optional

If specified, do not specify allele_to_sequence. The sequences from the provided instance are used. This guarantees that the mappings from allele to index and from allele to sequence are the same between the instances.

compact()[source]

Return a new AlleleEncoding in which the universe of supported alleles is only the alleles actually used.

Returns:
AlleleEncoding
allele_representations(encoding_name)[source]

Encode the universe of supported allele sequences to a matrix.

Parameters:
encoding_namestring

How to represent amino acids. Valid names include “BLOSUM62”, “one-hot”, “PMBEC”, “contact”, “physchem”, “atchley”, and +-joined composites. Add :minmax to a component to scale non-X values to [-1, 1]. See amino_acid.available_vector_encodings().

Returns:
numpy.array of shape

(num alleles in universe, sequence length, vector size)

where vector size is usually 21 (20 amino acids + X character)
fixed_length_vector_encoded_sequences(encoding_name)[source]

Encode allele sequences (not the universe of alleles) to a matrix.

Parameters:
encoding_namestring

How to represent amino acids. Valid names include “BLOSUM62”, “one-hot”, “PMBEC”, “contact”, “physchem”, “atchley”, and +-joined composites. Add :minmax to a component to scale non-X values to [-1, 1]. See amino_acid.available_vector_encodings().

Returns:
numpy.array with shape:

(num alleles, sequence length, vector size)

where vector size is usually 21 (20 amino acids + X character)

mhcflurry.amino_acid module

Functions for encoding fixed length sequences of amino acids into various vector representations, such as one-hot and BLOSUM62.

mhcflurry.amino_acid.peptide_to_indices(peptide, dtype='int8')[source]

Convert a peptide string to a 1-D integer index array.

Uppercases the input and uses AMINO_ACID_INDEX for the letter-to-index map so the result matches what index_encoding() produces for one row.

Parameters:
peptidestr
dtypenumpy dtype, default "int8"

Index payloads fit comfortably in int8 (alphabet size 21 << 127).

Returns:
numpy.ndarray of shape (len(peptide),)
mhcflurry.amino_acid.indices_to_peptide(indices)[source]

Convert a 1-D integer index array (or sequence) back to its peptide string.

Inverse of peptide_to_indices() for canonical alphabet members. Indices at or above the alphabet size raise IndexError; negative indices wrap (Python list indexing semantics); no per-element bounds check is added because this is a tight per-position loop on a hot re-materialization path.

Parameters:
indicesiterable of int
Returns:
str
mhcflurry.amino_acid.get_vector_encoding_df(name)[source]

Return the amino-acid vector encoding table for name.

name may be a base encoding such as "BLOSUM62", "PMBEC", "contact", "physchem", or "atchley". The aliases "simons1999-contact" and the AAindex id "SIMK990103" both refer to "contact". A component may use the ":minmax" suffix to scale its non-X values to [-1, 1] while keeping X neutral. +-joined composites such as "BLOSUM62+physchem" concatenate the component columns in order and keep the same amino-acid row order.

mhcflurry.amino_acid.available_vector_encodings()[source]

Return list of registered amino acid vector encodings.

get_vector_encoding_df also accepts +-joined composites of these names and the :minmax suffix, for example "BLOSUM62+PMBEC:minmax".

Several encodings are registered under more than one name (aliases: e.g. "PMBEC"/"pmbec", "contact"/"simons1999-contact"/ "SIMK990103"). Each underlying encoding is listed once – by its first-registered (canonical) name – so the advertised list has no duplicates; every alias still resolves via get_vector_encoding_df.

Returns:
list of string
mhcflurry.amino_acid.vector_encoding_length(name)[source]

Return the length of the given vector encoding.

Parameters:
namestring
Returns:
int
mhcflurry.amino_acid.vector_encoding_index_table(name)[source]

Return a float32 lookup table aligned to canonical amino-acid indices.

Rows are ordered so table[AMINO_ACID_INDEX[letter]] is the vector encoding for letter. Torch embedding layers and numpy materialization paths should both use this helper to keep amino-acid index semantics centralized.

mhcflurry.amino_acid.index_encoding(sequences, letter_to_index_dict)[source]

Encode a sequence of same-length strings to a matrix of integers of the same shape. The map from characters to integers is given by letter_to_index_dict.

Given a sequence of n strings all of length k, return an n * k array where the (i, j)th element is letter_to_index_dict[sequence[i][j]].

Parameters:
sequenceslist of length n of strings of length k
letter_to_index_dictdictstring -> int
Returns:
numpy.array of integers with shape (n, k)
mhcflurry.amino_acid.fixed_vectors_encoding(index_encoded_sequences, letter_to_vector_df)[source]

Given a n x k matrix of integers such as that returned by index_encoding() and a dataframe mapping each index to an arbitrary vector, return a n * k * m array where the (i, j)’th element is letter_to_vector_df.iloc[sequence[i][j]].

The dataframe index and columns names are ignored here; the indexing is done entirely by integer position in the dataframe.

Parameters:
index_encoded_sequencesn x k array of integers
letter_to_vector_dfpandas.DataFrame of shape (alphabet size, m)
Returns:
numpy.array with shape (n, k, m), using the vector table’s dtype

mhcflurry.calibrate_percentile_ranks_command module

Compatibility wrapper for mhcflurry.cli.calibrate_percentile_ranks_command.

mhcflurry.calibrate_percentile_ranks_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.class1_affinity_predictor module

class mhcflurry.class1_affinity_predictor.Class1AffinityPredictor(allele_to_allele_specific_models=None, class1_pan_allele_models=None, allele_to_sequence=None, manifest_df=None, allele_to_percent_rank_transform=None, metadata_dataframes=None, provenance_string=None, optimization_info=None, models_dir=None)[source]

Bases: object

High-level interface for peptide/MHC I binding affinity prediction.

This class manages low-level Class1NeuralNetwork instances, each of which wraps a single PyTorch network. The purpose of Class1AffinityPredictor is to implement ensembles, handling of multiple alleles, and predictor loading and saving. It also keeps per-allele percentile calibration transforms: compact curves for new calibration, or historical histogram mappings.

Parameters:
allele_to_allele_specific_modelsdict of string -> list of Class1NeuralNetwork

Ensemble of single-allele models to use for each allele.

class1_pan_allele_modelslist of Class1NeuralNetwork

Ensemble of pan-allele models.

allele_to_sequencedict of string -> string

MHC allele name to fixed-length pseudosequence. Required only if class1_pan_allele_models is specified.

manifest_dfpandas.DataFrame, optional

Must have columns: model_name, allele, config_json, model. Only required if you want to update an existing serialization of a Class1AffinityPredictor. Otherwise this dataframe will be generated automatically based on the supplied models.

allele_to_percent_rank_transformdict of string -> transform, optional

HistogramPercentRankTransform or CompactPercentRankTransform for each allele. Loading preserves the stored calibration method.

metadata_dataframesdict of string -> pandas.DataFrame, optional

Optional additional dataframes to write to the models dir when save() is called. Useful for tracking provenance.

provenance_stringstring, optional

Optional info string to use in __str__.

optimization_infodict, optional

Dict describing any optimizations already performed on the model. The only currently supported optimization is to merge ensembles together into one PyTorch model.

models_dirstring, optional

Directory this predictor was loaded from. Used for diagnostics.

property manifest_df

A pandas.DataFrame describing the models included in this predictor.

Based on: - self.class1_pan_allele_models - self.allele_to_allele_specific_models

Returns:
pandas.DataFrame
clear_cache()[source]

Clear values cached based on the neural networks in this predictor.

Users should call this after mutating any of the following:
  • self.class1_pan_allele_models

  • self.allele_to_allele_specific_models

  • self.allele_to_sequence

Methods that mutate these instance variables will call this method on their own if needed.

property neural_networks

List of the neural networks in the ensemble.

Returns:
list of Class1NeuralNetwork
classmethod merge(predictors)[source]

Merge the ensembles of two or more Class1AffinityPredictor instances.

Note: the resulting merged predictor will NOT have calibrated percentile ranks. Call calibrate_percentile_ranks on it if these are needed.

Parameters:
predictorssequence of Class1AffinityPredictor
Returns:
Class1AffinityPredictor instance
merge_in_place(others)[source]

Add the models present in other predictors into the current predictor.

Parameters:
otherslist of Class1AffinityPredictor

Other predictors to merge into the current predictor.

Returns:
list of stringnames of newly added models
canonicalize_allele_name(raw_name, raise_on_error=True, default_value=None)[source]

Normalize an allele name and map it to the canonical pseudosequence key if possible.

Tries without IMGT aliases first so that alleles like HLA-C*01:01 (which aliases map to C*01:02) resolve to their own pseudosequence when one exists.

By default, raises on names that cannot be normalized. Pass raise_on_error=False to return default_value instead. The no-alias-first logic lives in AlleleKeyResolver; training ingestion shares it via canonicalize_allele_series.

Parameters:
raw_namestr
raise_on_errorbool

Whether to raise a descriptive ValueError for invalid, ambiguous, non-class-I, or unsupported-annotation names.

default_valueobject

Value returned for an invalid name when raise_on_error is false.

Returns:
str
property supported_alleles

Alleles for which predictions can be made.

Returns:
list of string
property supported_peptide_lengths

(minimum, maximum) lengths of peptides supported by all models, inclusive.

Returns:
(int, int) tuple
check_consistency()[source]

Verify that self.manifest_df is consistent with: - self.class1_pan_allele_models - self.allele_to_allele_specific_models

Currently only checks for agreement on the total number of models.

Throws AssertionError if inconsistent.

save(models_dir, model_names_to_write=None, write_metadata=True)[source]

Serialize the predictor to a directory on disk. If the directory does not exist it will be created.

The serialization format consists of a file called “manifest.csv” with the configurations of each Class1NeuralNetwork, along with per-network files giving the model weights. If there are pan-allele predictors in the ensemble, the pseudosequences are also stored in the directory. There is also a small file “info.txt” with basic metadata: when the models were trained, by whom, on what host.

Parameters:
models_dirstring

Path to directory. It will be created if it doesn’t exist.

model_names_to_writelist of string, optional

Only write the weights for the specified models. Useful for incremental updates during training. Passing an explicit empty list writes no model artifacts; this is used by calibration-only updates that replace percentile calibration (CSV or JSON) without touching the manifest, weights, model provenance, allele sequences, or optimization metadata. Explicit metadata_dataframes are still written when write_metadata is true.

write_metadataboolean, optional

Whether to write optional metadata

static load(models_dir=None, max_models=None, optimization_level=None)[source]

Deserialize a predictor from a directory on disk.

Parameters:
models_dirstring, optional

Path to a standalone affinity predictor. If omitted, use the affinity path override or the active release’s standalone bundle; if that default bundle is absent, load the affinity component of the default presentation predictor. Explicit paths take precedence.

max_modelsint, optional

Maximum number of Class1NeuralNetwork instances to load

optimization_levelint

If >0, model optimization will be attempted. Defaults to value of environment variable MHCFLURRY_OPTIMIZATION_LEVEL (1 when unset).

Returns:
Class1AffinityPredictor instance
optimize(warn=True)[source]

EXPERIMENTAL: Optimize the predictor for faster predictions.

Currently the only optimization implemented is to merge multiple pan- allele predictors at the PyTorch level.

The optimization is performed in-place, mutating the instance.

Returns:
bool

Whether optimization was performed

static model_name(allele, num)[source]

Generate a model name

Parameters:
allelestring
numint
Returns:
string
static weights_path(models_dir, model_name)[source]

Generate the path to the weights file for a model

Parameters:
models_dirstring
model_namestring
Returns:
string
static checkpoint_weights_path(models_dir, model_name, policy)[source]

Generate the path to a retained training-checkpoint weight file.

property master_allele_encoding

An AlleleEncoding containing the universe of alleles specified by self.allele_to_sequence.

Returns:
AlleleEncoding
fit_allele_specific_predictors(n_models, architecture_hyperparameters_list, allele, peptides, affinities, inequalities=None, train_rounds=None, models_dir_for_save=None, verbose=0, progress_preamble='', progress_print_interval=5.0, seed=None)[source]

Fit one or more allele specific predictors for a single allele using one or more neural network architectures.

The new predictors are saved in the Class1AffinityPredictor instance and will be used on subsequent calls to predict.

Parameters:
n_modelsint

Number of neural networks to fit

architecture_hyperparameters_listlist of dict

List of hyperparameter sets.

allelestring
peptidesEncodableSequences or list of string
affinitieslist of float

nM affinities

inequalitieslist of string, each element one of “>”, “<”, or “=”

See Class1NeuralNetwork.fit for details.

train_roundssequence of int

Each training point i will be used on training rounds r for which train_rounds[i] > r, r >= 0.

models_dir_for_savestring, optional

If specified, the Class1AffinityPredictor is (incrementally) written to the given models dir after each neural network is fit.

verboseint

Verbosity level for training output

progress_preamblestring

Optional string of information to include in each progress update

progress_print_intervalfloat

How often (in seconds) to print progress. Set to None to disable.

seedint, optional

Base seed for this allele’s fits. When given, each (model_num, architecture_num) pair gets a distinct sub-seed derived from it, so ensemble members are decorrelated but the whole call is reproducible. When None, each Class1NeuralNetwork.fit is left entropy-seeded as before.

Returns:
list of Class1NeuralNetwork
fit_class1_pan_allele_models(n_models, architecture_hyperparameters, alleles, peptides, affinities, inequalities, models_dir_for_save=None, verbose=1, progress_preamble='', progress_print_interval=5.0, seed=None)[source]

Fit one or more pan-allele predictors using a single neural network architecture.

The new predictors are saved in the Class1AffinityPredictor instance and will be used on subsequent calls to predict.

Parameters:
n_modelsint

Number of neural networks to fit

architecture_hyperparametersdict
alleleslist of string

Allele names (not sequences) corresponding to each peptide

peptidesEncodableSequences or list of string
affinitieslist of float

nM affinities

inequalitieslist of string, each element one of “>”, “<”, or “=”

See Class1NeuralNetwork.fit for details.

models_dir_for_savestring, optional

If specified, the Class1AffinityPredictor is (incrementally) written to the given models dir after each neural network is fit.

verboseint

Verbosity level for training output

progress_preamblestring

Optional string of information to include in each progress update

progress_print_intervalfloat

How often (in seconds) to print progress. Set to None to disable.

seedint, optional

Base seed for these fits. When given, each ensemble member gets a distinct sub-seed derived from it, so members are decorrelated but the whole call is reproducible. When None, each Class1NeuralNetwork.fit is left entropy-seeded as before.

Returns:
list of Class1NeuralNetwork
add_pan_allele_model(model, models_dir_for_save=None)[source]

Add a pan-allele model to the ensemble and optionally do an incremental save.

Parameters:
modelClass1NeuralNetwork
models_dir_for_savestring

Directory to save resulting ensemble to

percentile_ranks(affinities, allele=None, alleles=None, throw=True)[source]

Return percentile ranks for the given ic50 affinities and alleles.

The ‘allele’ and ‘alleles’ argument are as in the predict method. Specify one of these.

Parameters:
affinitiessequence of float

nM affinities

allelestring
allelessequence of string
throwboolean

If True, a ValueError will be raised in the case of unsupported alleles. If False, a warning will be logged and NaN will be returned for those percentile ranks.

Returns:
numpy.array of float
models_dir_for_diagnostics()[source]

Return explicit or inferred models dir for user-facing messages.

percent_rank_calibrated_allele(allele)[source]

Return the allele key whose percentile-rank transform applies.

Percent-rank calibration is allele-specific, but pan predictors can reuse calibration from another allele with the same pseudosequence. This helper centralizes that equivalence check for prediction and CLI status/filtering code.

predict(peptides, alleles=None, allele=None, throw=True, centrality_measure='mean', model_kwargs=None)[source]

Predict nM binding affinities.

If multiple predictors are available for an allele, the predictions are the geometric means of the individual model (nM) predictions.

One of ‘allele’ or ‘alleles’ must be specified. If ‘allele’ is specified all predictions will be for the given allele. If ‘alleles’ is specified it must be the same length as ‘peptides’ and give the allele corresponding to each peptide.

Parameters:
peptidesEncodableSequences or list of string
alleleslist of string
allelestring
throwboolean

If True, a ValueError will be raised in the case of unsupported alleles or peptide lengths. If False, a warning will be logged and the predictions for the unsupported alleles or peptides will be NaN.

centrality_measurestring or callable

Measure of central tendency to use to combine predictions in the ensemble. Options include: mean, median, robust_mean.

model_kwargsdict

Additional keyword arguments to pass to Class1NeuralNetwork.predict

Returns
——-
numpy.array of predictions
predict_numeric(peptides, allele, centrality_measure='mean', model_kwargs=None)[source]

Score numeric peptides for one allele without materializing strings.

Parameters:
peptidesNumericSequences

Unaligned integer residues and actual lengths, on CPU or device.

allelestr

One sequence-resolved allele for all rows. Unsupported alleles, lengths and noncanonical residues raise, as with predict(throw=True).

centrality_measurestr or callable

The same log-affinity ensemble aggregation used by predict.

model_kwargsdict, optional

Network prediction options, including batch size.

Returns:
numpy.ndarray

Float64 ensemble affinities in input order (nM).

predict_cartesian_pan_allele(peptides, alleles, throw=True, centrality_measure='mean', model_kwargs=None)[source]

Predict a peptide x allele matrix using the optimized pan-allele path.

Returns None when the predictor is not a single optimized merged pan-allele model. Callers can then fall back to predict. This path keeps peptide encodings unique, computes the peptide stage once per peptide batch, and combines it with allele embeddings on-device.

predict_to_dataframe(peptides, alleles=None, allele=None, throw=True, include_individual_model_predictions=False, include_percentile_ranks=True, include_confidence_intervals=True, centrality_measure='mean', model_kwargs=None)[source]

Predict nM binding affinities with optional ensemble-member detail.

The default output includes the 5th and 95th percentiles of member predictions, interpolated in log-affinity space. These describe ensemble spread, not calibrated confidence intervals for true affinity.

If multiple predictors are available for an allele, the predictions are the geometric means of the individual model predictions.

One of ‘allele’ or ‘alleles’ must be specified. If ‘allele’ is specified all predictions will be for the given allele. If ‘alleles’ is specified it must be the same length as ‘peptides’ and give the allele corresponding to each peptide.

Parameters:
peptidesEncodableSequences or list of string
alleleslist of string
allelestring
throwboolean

If True, a ValueError will be raised in the case of unsupported alleles or peptide lengths. If False, a warning will be logged and the predictions for the unsupported alleles or peptides will be NaN.

include_individual_model_predictionsboolean

If True, the predictions of each individual model are included as columns in the result DataFrame.

include_percentile_ranksboolean, default True

If True, a “prediction_percentile” column will be included giving the percentile ranks. If no percentile rank info is available, this will be ignored with a warning.

include_confidence_intervalsboolean, default True

Include prediction_low and prediction_high, the 5th and 95th ensemble-member percentiles described above.

centrality_measurestring or callable

Measure of central tendency to use to combine predictions in the ensemble. Options include: mean, median, robust_mean.

model_kwargsdict

Additional keyword arguments to pass to Class1NeuralNetwork.predict

Returns:
pandas.DataFrame of predictions
calibrate_percentile_ranks(peptides=None, num_peptides_per_length=100000, alleles=None, bins=None, motif_summary=False, summary_top_peptide_fractions=None, verbose=False, model_kwargs=None, *, method=None, max_knots=128)[source]

Compute the cumulative distribution of ic50 values for a set of alleles over a large universe of random peptides, to enable taking quantiles of this distribution later.

Parameters:
peptidessequence of string or EncodableSequences, optional

Peptides to use

num_peptides_per_lengthint, optional

If peptides argument is not specified, then num_peptides_per_length peptides are randomly sampled from a uniform distribution for each supported length

allelessequence of string, optional

Alleles to perform calibration for. If not specified all supported alleles will be calibrated.

binsobject

Anything that can be passed to numpy.histogram’s “bins” argument can be used here, i.e. either an integer or a sequence giving bin edges in IC50 space. Explicit bins select histogram calibration unless a conflicting method is supplied. With no bins or method, the default is compact; method=”histogram” with no bins uses the historical fixed log-spaced IC50 grid.

motif_summarybool

If True, the length distribution and per-position amino acid frequencies are also calculated for the top x fraction of tightest- binding peptides, where each value of x is given in the summary_top_peptide_fractions list.

summary_top_peptide_fractionslist of float

Only used if motif_summary is True

verboseboolean

Whether to print status updates to stdout

model_kwargsdict

Additional low-level Class1NeuralNetwork.predict() kwargs.

method{“compact”, “histogram”}, optional

Compact by default; explicit bins select the historical histogram.

max_knots{64, 128}, default 128

Upper bound, not the starting size. Compact starts with 64 and permits 128 only when background validation demonstrates an improvement beyond the tolerance.

Returns:
dict of string -> pandas.DataFrame
If motif_summary is True, this will have keys “frequency_matrices” and
“length_distributions”. Otherwise it will be empty.
clear_calibration_fast_cache()[source]
calibrate_percentile_ranks_fast(peptides, alleles, bins=None, motif_summary=False, summary_top_peptide_fractions=(0.001,), allele_batch_size='auto', peptide_batch_size='auto', num_workers_per_gpu=1, device=None, verbose=False, *, method=None, max_knots=128)[source]

GPU-hoisted calibration for many alleles sharing a peptide set.

Drop-in replacement for the bulk of calibrate_percentile_ranks when calibration is dominated by per-allele Python dispatch (the pan-allele full-universe calibration workload, which sweeps ~20k alleles across the same peptide set). Two structural changes:

  1. Precompute peptide-stage activations once per network. The network’s locally-connected + peptide-dense + early-batchnorm layers are identity across alleles; we forward the calibration peptides through that stage exactly once per network and cache the output tensor on device.

  2. Batch ``allele_batch_size`` alleles per forward. A single forward_from_peptide_stage call replaces allele_batch_size separate model.predict calls — amortizing all the small kernel-launch + Python-dispatch overhead that was dominating wall-clock time on the pan-allele full-universe calibration. Effective batch size per forward: allele_batch_size * peptide_batch_size. Automatic sizes account for the current device and resident working set.

Uses the same geometric-mean ensemble aggregation and percentile method as calibrate_percentile_ranks. The batched floating-point schedule can change raw predictions slightly and, in turn, adaptive knot locations. Saved curves are not guaranteed bit-identical. Neural inference remains batched on-device for both methods; histogram fitting is also batched on-device, whereas compact fitting operates on the final ensemble scores on CPU without repeating neural inference.

Caching note: this method memoizes the peptide-stage activations on the predictor instance across calls. That cache is keyed on network identity, not weight content, so do not mutate the predictor’s network weights in place between calls on the same instance without first calling clear_calibration_fast_cache().

Only the pan-allele networks contribute to this path. Use calibrate_percentile_ranks for allele-specific ensembles or ensembles mixing pan-allele and allele-specific networks. Presentation calibration has its own score-based API.

Parameters:
peptidessequence of string or EncodableSequences
allelessequence of string — already-normalized allele names

(canonicalization is the caller’s responsibility for speed).

binssequence of bin edges in IC50 space (histogram only; default for

that method is 999 log-spaced IC50 bins). Scalar integer numpy.histogram bin counts are rejected in this fast path because they imply data-dependent edges per allele, while the batched GPU histogram uses one explicit edge vector for the whole allele chunk.

motif_summarybool — populate frequency matrices + length

distributions, same format as calibrate_percentile_ranks.

summary_top_peptide_fractionsiterable of float — only used

when motif_summary=True.

allele_batch_sizeint or “auto”

Alleles per forward pass. The default auto sizes for device capacity.

peptide_batch_sizeint or “auto”

Peptides per device chunk; auto sized by default.

num_workers_per_gpuint, default 1

Co-resident worker count used for automatic memory budgeting.

devicestr or torch.device, optional

Uses MHCflurry’s configured device when omitted (auto selects CUDA, then MPS, then CPU).

verbosebool — per-batch timing to stdout.
method{“compact”, “histogram”}, optional

Compact by default; explicit bins select the historical histogram.

max_knots{64, 128}, default 128

Validation-selected compact upper bound, not a starting size; 64 is retained unless 128 improves beyond the tolerance.

Returns:
dict (same schema as calibrate_percentile_ranks). Also
populates self.allele_to_percent_rank_transform[allele] for
every allele in alleles.
model_select(score_function, alleles=None, min_models=1, max_models=10000)[source]

Perform model selection using a user-specified scoring function.

This works only with allele-specific models, not pan-allele models.

Model selection is done using a “step up” variable selection procedure, in which models are repeatedly added to an ensemble until the score stops improving.

Parameters:
score_functionClass1AffinityPredictor -> float function

Scoring function

alleleslist of string, optional

If not specified, model selection is performed for all alleles.

min_modelsint, optional

Min models to select per allele

max_modelsint, optional

Max models to select per allele

Returns:
Class1AffinityPredictorpredictor containing the selected models

mhcflurry.class1_affinity_training_data module

Device-resident row space for class-I affinity model training.

This module is intentionally affinity-specific. It knows about the layout created by Class1NeuralNetwork.fit(): random-negative examples, when enabled, are prepended to the real affinity measurements and refreshed once per epoch. Other model families should use their own training-data container instead of inheriting these random-negative semantics.

class mhcflurry.class1_affinity_training_data.AffinityDeviceTrainingData(x_peptide: Tensor, x_allele: Tensor | None = None, y_encoded: Tensor | None = None, sample_weights: Tensor | None = None, random_negative_x_peptide: Tensor | None = None, random_negative_x_allele: Tensor | None = None, combined_peptide: Tensor | None = None, combined_allele: Tensor | None = None)[source]

Bases: object

Device tensors for one affinity-model fit() call.

The affinity fit loop indexes one logical row space:

[random negative rows | real training rows].

This container owns the torch tensors for that row space. When random negatives are present, combined_peptide and combined_allele hold the full row space; random_negative_x_* and x_* are views into those combined buffers. Refilling random-negative peptide rows updates the next epoch’s batches without reallocating or recopying the real-data block.

Peptide tensors may be either:

  • (N, L) integer amino-acid indices, consumed by the network’s torch embedding path; or

  • (N, L, V) fixed vector encodings, widened to float32 on device when loaded from compact integer caches.

x_peptide: Tensor
x_allele: Tensor | None = None
y_encoded: Tensor | None = None
sample_weights: Tensor | None = None
random_negative_x_peptide: Tensor | None = None
random_negative_x_allele: Tensor | None = None
combined_peptide: Tensor | None = None
combined_allele: Tensor | None = None
property device

The torch device holding this row space.

property row_count

Total rows in the logical [random negatives | real] space.

property random_negative_count

Number of mutable random-negative rows at the front of the space.

classmethod from_arrays(*, x_peptide, x_allele, y_encoded, sample_weights, random_negative_x_peptide_template, random_negative_x_allele, device)[source]

Materialize a device-resident affinity training row space.

Parameters mirror the arrays produced by Class1NeuralNetwork.fit. random_negative_x_peptide_template provides only shape and dtype for the mutable random-negative slice; epoch contents are filled via refill_random_negative_peptides().

The returned object is the only data source used by the inner fit loop: callers ask for batches by row index with batch_for_indices().

refill_random_negative_peptides(encoded_peptides)[source]

Overwrite the mutable random-negative peptide slice in place.

Does nothing when the fit has no random negatives. encoded_peptides may be a numpy array, CPU tensor, or tensor already on the target device; dtype is coerced to the existing random-negative slice.

batch_for_indices(batch_indices)[source]

Return (inputs, y_batch, weights_batch) for device indices.

Hot-path API used by the inner training and validation loops. batch_indices must be a torch integer tensor already on self.device; keeping indices on device lets the fit loop form batches with index_select and no per-batch host-to-device copies. For one-shot use cases that start from a host-side index array, see batch_dict_for_indices().

batch_dict_for_indices(indices, device=None)[source]

Return a flat {"peptide", "allele", "y", "weight"} dict.

Convenience wrapper used once per fit, by LSUV/data-dependent weight init. Unlike batch_for_indices(), this accepts host-side indices (numpy array, list, or any tensor) and moves them to the device for you, since the init path is called outside the hot loop and isn’t sensitive to the per-call host-to-device copy.

mhcflurry.class1_encoding module

Peptide encoding helpers for class I neural networks.

mhcflurry.class1_encoding.peptide_sequences_to_network_input(peptides, peptide_encoding, peptide_amino_acid_encoding_torch=True, device=None)[source]

Encode string or numeric peptides to categorical network inputs.

Numeric inputs align directly into a Torch tensor on device; strings retain the established NumPy representation and encoding cache. Peptides are always returned as compact (N, L) int8 amino-acid indices; the fixed-vector lookup then happens through the network’s frozen torch embedding table. (peptide_amino_acid_encoding_torch is accepted for config compatibility but the legacy dense-vector path is gone.)

mhcflurry.class1_neural_network module

Class1NeuralNetwork - PyTorch implementation for MHC class I binding prediction.

class mhcflurry.class1_neural_network.Class1NeuralNetworkModel(peptide_encoding_shape, allele_representations=None, locally_connected_layers=None, peptide_dense_layer_sizes=None, allele_dense_layer_sizes=None, layer_sizes=None, peptide_allele_merge_method='multiply', peptide_allele_merge_activation='', activation='tanh', output_activation='sigmoid', dropout_probability=0.0, batch_normalization=False, dense_layer_l1_regularization=0.001, dense_layer_l2_regularization=0.0, topology='feedforward', num_outputs=1, init='glorot_uniform', peptide_input_is_indices=False, peptide_input_vector_encoding_name=None, normalization='none')[source]

Bases: Module

PyTorch module for Class1 neural network.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

activation_output_for_layer(layer, output)[source]

Apply the activation belonging to a trainable affine layer.

This exposes the same layer-output boundary that Keras reports for a Dense layer. Data-dependent initialization uses it to measure post-activation variance even though PyTorch represents the linear transform and activation as separate operations.

forward_peptide_stage(peptide)[source]

Run only the peptide-side of the network.

Ends at the point where the allele information enters — just before the merge step. Used by the calibration fast path to compute the peptide-dependent activations once and reuse them across thousands of alleles.

Parameters:
peptidetorch.Tensor

(N, L, V) fp32 fixed-vector encoded, or (N, L) int indices when peptide_input_is_indices is True.

Returns:
torch.Tensor of shape (N, peptide_representation_dim) — the
input the forward_from_peptide_stage fast path expects.
forward_from_peptide_stage(peptide_stage, allele_idx)[source]

Run the allele-merge + main dense path from cached peptide reps.

peptide_stage must be the output of forward_peptide_stage. allele_idx has shape matching peptide_stage’s batch dim — typical calibration usage tiles one allele across many peptides or the cross-product of (peptide_chunk, allele_chunk).

This path skips all peptide-side ops, which for pan-allele calibration lets a single precomputed activation be reused across tens of thousands of allele forwards.

forward_cartesian_from_peptide_stage(peptide_stage, allele_idx)[source]

Forward every peptide-stage row against every allele index.

Returns predictions in allele-major order with shape (num_alleles, num_peptides, num_outputs). When the model’s merge + first linear layer can be factored, this avoids materializing the larger num_alleles * num_peptides * peptide_stage_dim repeated peptide-stage tensor used by forward_from_peptide_stage.

Skip-connections (topology == "with-skip-connections") are also factorized: layer 1’s input cat[merged_input, layer0_out] is computed without materializing the (a*p, peptide_width + allele_width) merged_input expansion — instead layer 1’s weight is split column-wise into peptide / allele / prev pieces and the contributions are summed in their factored shapes ((p, h1) + (a, h1) + (a, p, h1)). Layers ≥ 2’s input cat[prev[-2], prev[-1]] is similarly factorized via column-wise weight splits, avoiding the explicit concat.

forward(inputs)[source]

Forward pass.

Parameters:
inputsdict

Dictionary with ‘peptide’ and optionally ‘allele’ keys

Returns:
torch.Tensor

Predictions of shape (batch, num_outputs)

get_weights_list()[source]

Get weights as a list of numpy arrays (for compatibility with NPZ format).

Returns:
list of numpy.ndarray
set_weights_list(weights, auto_convert_keras=True)[source]

Set weights from a list of numpy arrays.

Supports automatic detection and conversion of Keras-format weights to PyTorch format for backward compatibility with pre-trained models.

Parameters:
weightslist of numpy.ndarray
auto_convert_kerasbool

If True, automatically detect and convert Keras-format weights

to_json()[source]

Serialize model configuration to JSON string.

Returns:
str

JSON representation of model configuration

class mhcflurry.class1_neural_network.Class1NeuralNetwork(**hyperparameters)[source]

Bases: object

Low level class I predictor consisting of a single neural network.

Both single allele and pan-allele prediction are supported.

Users will generally use Class1AffinityPredictor, which gives a higher-level interface and supports ensembles.

network_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters (and their default values) that affect the neural network architecture.

compile_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Loss and optimizer hyperparameters.

fit_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters for neural network training.

early_stopping_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters for early stopping.

miscelaneous_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Miscelaneous hyperaparameters. These parameters are not used by this class but may be interpreted by other code.

hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Combined set of all supported hyperparameters and their default values.

hyperparameter_renames = {'embedding_init_method': None, 'embedding_input_dim': None, 'embedding_output_dim': None, 'fit_dataloader_backing': None, 'kmer_size': None, 'left_edge': None, 'mode': None, 'monitor': None, 'peptide_amino_acid_encoding': None, 'peptide_amino_acid_encoding_gpu': 'peptide_amino_acid_encoding_torch', 'pseudosequence_use_embedding': None, 'right_edge': None, 'take_best_epoch': None, 'use_embedding': None, 'verbose': None}
classmethod apply_hyperparameter_renames(hyperparameters)[source]

Handle hyperparameter renames.

Parameters:
hyperparametersdict
Returns:
dictupdated hyperparameters
MODELS_CACHE = {}

Process-wide model cache, a map from: architecture JSON string to (PyTorch model, existing network weights)

classmethod clear_model_cache()[source]

Clear the model cache.

classmethod borrow_cached_network(network_json, network_weights)[source]

Return a PyTorch model with the specified architecture and weights. As an optimization, when possible this will reuse architectures from a process-wide cache.

Parameters:
network_jsonstring of JSON
network_weightslist of numpy.array
Returns:
Class1NeuralNetworkModel
static model_cache_key(network_json)[source]

Given a JSON description of a neural network, return a cache key.

Parameters:
network_jsonstring
Returns:
string
static keras_network_cache_key(network_json)[source]

Backward-compatible alias for model_cache_key.

network(borrow=False)[source]

Return the PyTorch model associated with this predictor.

Parameters:
borrowbool

Whether to return a cached model if possible

Returns:
Class1NeuralNetworkModel
update_network_description()[source]

Update self.network_json and self.network_weights properties based on this instances’s neural network.

get_config()[source]

serialize to a dict all attributes except model weights

Returns:
dict
classmethod from_config(config, weights=None, weights_loader=None, weight_paths=None)[source]

deserialize from a dict returned by get_config().

Supports both: - Native Class1NeuralNetwork configs with ‘hyperparameters’ key - Legacy Keras model JSON configs with ‘class_name’, ‘config’, etc.

Parameters:
configdict
weightslist of array, optional

Network weights to restore

weights_loadercallable, optional

Function to call (no arguments) to load weights when needed

weight_pathsstring or list of strings, optional

Filename(s) the weights were loaded from. This is diagnostic provenance only and is not serialized by get_config().

Returns:
Class1NeuralNetwork
load_weights()[source]

Load weights by evaluating self.network_weights_loader, if needed.

get_weights()[source]

Get the network weights

Returns:
list of numpy.array giving weights for each layer or None if there is no
network
get_weights_list()[source]

Get the network weights as a list of numpy arrays.

Returns:
list of numpy.array giving weights for each layer or None if there is no
network
set_weights_list(weights, auto_convert_keras=True)[source]

Set the network weights from a list of numpy arrays.

If a network exists, the weights are set directly on it. Otherwise, the weights are stored and will be applied when the network is created.

Parameters:
weightslist of numpy.array

Weights for each layer

auto_convert_kerasbool

If True, attempt to auto-detect and convert Keras weight formats to PyTorch format. Default True.

available_checkpoint_policies()[source]

Return retained checkpoint policies in stable order.

get_checkpoint_weights(policy)[source]

Return retained weights for policy, loading lazily if needed.

set_checkpoint_weights_loader(policy, loader, weight_path=None)[source]

Attach a lazy loader for a retained training checkpoint.

uses_peptide_torch_encoding()[source]

Whether fixed peptide vectors are looked up in torch forward.

peptides_to_network_input(peptides, device=None)[source]

Encode peptides to the fixed-length encoding expected by the neural network (which depends on the architecture).

Return (N, L) int8 amino-acid indices; the network looks up fixed vectors on device. NumericSequences inputs return a Torch tensor directly, while string inputs retain the existing NumPy path.

Parameters:
peptidesEncodableSequences, NumericSequences or list of string
devicetorch.device or str, optional

Device for NumericSequences alignment; string encoding stays on CPU.

Returns:
numpy.ndarray or torch.Tensor
property supported_peptide_lengths

(minimum, maximum) lengths of peptides supported, inclusive.

Returns:
(int, int) tuple
allele_encoding_to_network_input(allele_encoding)[source]

Encode alleles to the fixed-length encoding expected by the neural network (which depends on the architecture).

Parameters:
allele_encodingAlleleEncoding
Returns:
(numpy.array, numpy.array)
Indices and allele representations.
static data_dependent_weights_initialization(network, x_dict=None, method='lsuv', target='post_activation', verbose=1)[source]

Data dependent weights initialization.

Parameters:
networkClass1NeuralNetworkModel
x_dictdict of string -> numpy.ndarray

Training data

methodstring

Initialization method. Currently only “lsuv” is supported.

target{“post_activation”, “pre_activation”}

Affine-layer output whose variance LSUV normalizes.

verboseint

Status updates printed to stdout if verbose > 0

get_device()[source]

Get the PyTorch device to use.

fit_streaming_batches(generator, validation_peptide_encoding, validation_affinities, validation_allele_encoding=None, validation_inequalities=None, validation_output_indices=None, steps_per_epoch=10, epochs=1000, min_epochs=0, patience=10, min_delta=0.0, verbose=1, progress_callback=None, progress_preamble='', progress_print_interval=5.0, generator_factory=None, generator_batches_are_encoded=False, seed=None, save_all_checkpoints=False)[source]

Pretrain from a stream of already batched examples.

This is the streaming pretraining path used by pan-allele training. It intentionally has a narrower contract than fit():

  • training examples arrive as complete batches from generator;

  • validation data is supplied explicitly rather than split from the training rows;

  • random negatives, sample weights, and the affinity fit() row layout are not part of this API.

The method still shares the same low-level optimizer step, loss object, regularization, and batched validation helpers as fit().

generator may yield either pre-encoded (x_dict, y) tuples (the path the shipped pan-allele pretrain pipeline uses) or legacy raw (allele_encoding, peptides, affinities) tuples. The legacy form is still tested for back-compat but is not exercised by any production pipeline. generator_factory enables DataLoader worker prefetch: each worker calls it with worker_id and num_workers to read a disjoint shard.

seed (int, optional) seeds numpy’s and torch’s global RNGs up front, so weight initialization and any shuffling in this pretrain pass derive from it; None leaves the worker’s entropy seeding in place. Mirrors fit()’s seed so one value can drive both phases of a pan-allele fit.

save_all_checkpoints retains both the terminal and minimum-validation weights. It does not change which state is primary; that remains controlled by the restore_best_weights hyperparameter.

fit_generator(generator, validation_peptide_encoding, validation_affinities, validation_allele_encoding=None, validation_inequalities=None, validation_output_indices=None, steps_per_epoch=10, epochs=1000, min_epochs=0, patience=10, min_delta=0.0, verbose=1, progress_callback=None, progress_preamble='', progress_print_interval=5.0, generator_factory=None, generator_batches_are_encoded=False, save_all_checkpoints=False)[source]

Backward-compatible alias for fit_streaming_batches().

The name is historical from the old Keras API. New internal code should call fit_streaming_batches because this path is specifically the pan-allele pretraining stream, not a general replacement for fit().

fit(peptides, affinities, allele_encoding=None, inequalities=None, output_indices=None, sample_weights=None, shuffle_permutation=None, verbose=1, progress_callback=None, progress_preamble='', progress_print_interval=5.0, seed=None, save_all_checkpoints=False)[source]

Fit the neural network.

Parameters:
peptidesEncodableSequences or list of string
affinitieslist of float

nM affinities. Must have the same length as peptides.

allele_encodingAlleleEncoding

If not specified, the model will be a single-allele predictor.

inequalitieslist of string, each element one of “>”, “<”, or “=”.
output_indiceslist of int

For multi-output models only.

sample_weightslist of float
shuffle_permutationlist of int
verboseint
progress_callbackfunction
progress_preamblestring
progress_print_intervalfloat
seedint, optional

Master seed for this fit. When given, it seeds numpy’s and torch’s global RNGs at the start of the call, so every stochastic step downstream flows from this one value: data-dependent weight initialization, the initial example shuffle, the per-epoch training-batch shuffle, and random-negative sampling. When None (the default) the RNGs are left unchanged. The caller or worker initializer is responsible for setting independent RNG states.

A seed does not guarantee identical weights across hardware, dependency versions or numerical settings. Automatic minibatch reduction can also change a trajectory; release workflows reject that reduction. Preserve the effective batch, source, dependencies, device and precision settings alongside the seed. See PyTorch’s reproducibility notes for backend-specific determinism controls.

save_all_checkpointsbool

Retain both terminal and minimum-validation weights from this fit. This does not change the primary state selected by the restore_best_weights hyperparameter.

predict(peptides, allele_encoding=None, batch_size='auto', output_index=0, num_workers_per_gpu=None)[source]

Predict affinities.

Parameters:
peptidesEncodableSequences or list of string
allele_encodingAlleleEncoding, optional
batch_sizeint or "auto"

"auto" (the default) sizes batches to the available GPU memory at call time — see compute_prediction_batch_size. Pass an explicit int to pin the size.

output_indexint or None
num_workers_per_gpuint, optional

When multiple training/calibration workers are co-resident on the same CUDA device, pass the worker count so the auto- sizer partitions the VRAM budget. Ignored for explicit int batch_size. When not passed, falls back to env_workers_per_gpu(1) (the MHCFLURRY_MAX_WORKERS_PER_GPU env var the worker pool sets), mirroring fit().

Returns:
numpy.array of nM affinity predictions
classmethod merge(models, merge_method='average')[source]

Merge multiple models at the neural network level.

Parameters:
modelslist of Class1NeuralNetwork
merge_methodstring, one of “average”, “sum”, or “concatenate”
Returns:
Class1NeuralNetwork
make_network(peptide_encoding, allele_amino_acid_encoding, allele_dense_layer_sizes, peptide_dense_layer_sizes, peptide_allele_merge_method, peptide_allele_merge_activation, layer_sizes, dense_layer_l1_regularization, dense_layer_l2_regularization, activation, init, output_activation, dropout_probability, batch_normalization, locally_connected_layers, topology, num_outputs=1, allele_representations=None, peptide_amino_acid_encoding_torch=True, peptide_amino_acid_encoding_gpu=None, normalization='none')[source]

Helper function to make a PyTorch network for class 1 affinity prediction.

clear_allele_representations()[source]

Set allele representations to an empty array.

set_allele_representations(allele_representations, force_surgery=False)[source]

Set the allele representations in use by this model.

Parameters:
allele_representationsnumpy.ndarray of shape (a, l, m)
force_surgerybool
class mhcflurry.class1_neural_network.MergedClass1NeuralNetwork(networks, merge_method='average')[source]

Bases: Module

A merged ensemble of Class1NeuralNetworkModel instances.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

forward(inputs)[source]

Define the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

forward_peptide_stage(peptide)[source]

Run each sub-network’s peptide-side stage and concatenate.

Returned tensor has shape (batch, sum_i(peptide_dim_i)); forward_from_peptide_stage and forward_cartesian_from_peptide_stage split it back along the feature axis using the recorded per-subnet dims and merge the per-subnet outputs via self.merge_method.

forward_from_peptide_stage(peptide_stage, allele_idx)[source]
forward_cartesian_from_peptide_stage(peptide_stage, allele_idx)[source]
get_weights_list()[source]

Get all weights as a flat list.

set_weights_list(weights, auto_convert_keras=False)[source]

Set weights from a flat list.

mhcflurry.class1_neural_network.cartesian_network_output(model, peptide_stage, allele_idx, exact_forward=False)[source]

Run a pan-allele network over the (allele × peptide) cartesian product.

model is any network exposing forward_cartesian_from_peptide_stage and forward_from_peptide_stage (a Class1NeuralNetworkModel or a MergedClass1NeuralNetwork). The fast path delegates to the network’s factored forward_cartesian_from_peptide_stage; exact_forward instead materializes the full (num_alleles * num_peptides) batch and runs the plain forward_from_peptide_stage — the unfactored reference used to check the compact path’s numerics.

Returns a (num_alleles, num_peptides, num_outputs) tensor.

mhcflurry.class1_neural_network.cartesian_output_log_ic50_sum(network_output, model, log50000, accum_dtype)[source]

Convert cartesian network outputs to summed log(IC50).

Normal models may expose multiple output channels; prediction defaults to channel 0, so fast calibration must do the same. Optimized pan-model ensembles are different: MergedClass1NeuralNetwork with merge_method='concatenate' returns one channel per merged submodel. Those channels are ensemble members and must all contribute to the geometric mean.

Returns:
(torch.Tensor, int)

(a_size, chunk_n) summed log(IC50) contribution and the number of ensemble members represented by the sum.

mhcflurry.class1_presentation_predictor module

mhcflurry.class1_presentation_predictor.presentation_percent_rank_bins(scores, num_bins=10000)[source]

Return quantile bins with extra resolution in the upper score tail.

Parameters:
scoressequence of float

Calibration presentation scores.

num_binsint

Base uniform-quantile bin budget. At most this many additional bins refine the top 1% with logarithmically spaced tail probabilities, down to one observation’s probability mass. Small calibration sets and repeated scores can result in fewer bins.

Returns:
numpy.ndarray

Strictly increasing histogram edges spanning the finite scores.

class mhcflurry.class1_presentation_predictor.Class1PresentationPredictor(affinity_predictor=None, processing_predictor_with_flanks=None, processing_predictor_without_flanks=None, weights_dataframe=None, metadata_dataframes=None, percent_rank_transform=None, provenance_string=None)[source]

Bases: object

A logistic regression model over predicted binding affinity (BA) and antigen processing (AP) score.

Instances of this class delegate to Class1AffinityPredictor and Class1ProcessingPredictor instances to generate BA and AP predictions. These predictions are combined using a logistic regression model to give a “presentation score” prediction.

Most users will call the load static method to get an instance of this class, then call the predict method to generate predictions.

model_inputs = ['affinity_score', 'processing_score']
property supported_alleles

List of alleles supported by the underlying Class1AffinityPredictor

property supported_peptide_lengths

(min, max) of supported peptide lengths, inclusive.

property supports_affinity_prediction

Is there an affinity predictor associated with this instance?

property supports_processing_prediction

Is there a processing predictor associated with this instance?

property supports_presentation_prediction

Can this instance predict presentation?

predict_sequences_columns(alleles, use_flanks=True, include_affinity_percentile=True)[source]

Column names that predict_sequences(..., result="all") will emit.

Used so the empty-input fast-path in mhcflurry-predict-scan can seed a DataFrame with the same schema the populated path produces. Mirrors the column set assembled in predict() plus the sequence_name / pos columns inserted in predict_sequences.

predict_columns(affinity_only=False, use_flanking=True, include_affinity_percentile=False)[source]

Column names that predict() / predict_affinity() emit when called with non-empty inputs.

Used by mhcflurry-predict to give empty inputs the same output schema as populated ones. Mirrors the columns assembled by predict_affinity and the additional columns layered on by predict.

predict_affinity(peptides, alleles, sample_names=None, include_affinity_percentile=True, verbose=1, throw=True, model_kwargs=None)[source]

Predict binding affinities across samples, each with an MHC allele set.

Two modes are supported: each peptide can be evaluated for binding to any of the alleles in any sample (this is what happens when sample_names is None), or the i’th peptide can be evaluated for binding the alleles of the sample given by the i’th entry in sample_names.

For example, if we don’t specify sample_names, then predictions are taken for all combinations of samples and peptides, for a result size of num peptides * num samples:

>>> predictor = Class1PresentationPredictor.load()
>>> predictions = predictor.predict_affinity(
...    peptides=["SIINFEKL", "PEPTIDE"],
...    alleles={
...        "sample1": ["A0201", "A0301", "B0702"],
...        "sample2": ["A0101", "C0202"],
...    },
...    verbose=0)
>>> list(zip(predictions.sample_name, predictions.peptide))
[('sample1', 'SIINFEKL'), ('sample1', 'PEPTIDE'), ('sample2', 'SIINFEKL'), ('sample2', 'PEPTIDE')]
>>> bool((predictions.affinity > 0).all())
True

In contrast, here we specify sample_names, so peptide is evaluated for binding the alleles in the corresponding sample, for a result size equal to the number of peptides:

>>> predictions = predictor.predict_affinity(
...    peptides=["SIINFEKL", "PEPTIDE"],
...    alleles={
...        "sample1": ["A0201", "A0301", "B0702"],
...        "sample2": ["A0101", "C0202"],
...    },
...    sample_names=["sample2", "sample1"],
...    verbose=0)
>>> list(zip(predictions.sample_name, predictions.peptide))
[('sample2', 'SIINFEKL'), ('sample1', 'PEPTIDE')]
>>> bool((predictions.affinity > 0).all())
True
Parameters:
peptideslist of string

Peptide sequences

allelesdict of string -> list of string

Keys are sample names, values are the MHC alleles for that sample

sample_nameslist of string [same length as peptides]

Sample names corresponding to each peptide. If None, then predictions are generated for all sample MHC allele sets across all peptides.

include_affinity_percentilebool

Whether to include affinity percentile ranks

verboseint

Set to 0 for quiet.

throwbool

Whether to throw exception (vs. just log a warning) on invalid peptides, etc.

model_kwargsdict, optional

Keyword arguments forwarded to Class1AffinityPredictor.predict.

Returns:
pandas.DataFramepredictions
predict_processing(peptides, n_flanks=None, c_flanks=None, throw=True, verbose=1, batch_size='auto')[source]

Predict antigen processing scores for individual peptides, optionally including flanking sequences for better cleavage prediction.

Parameters:
peptideslist of string
n_flankslist of string [same length as peptides]
c_flankslist of string [same length as peptides]
throwboolean

Whether to raise exception on unsupported peptides

verboseint
batch_sizeint or “auto”
Returns:
numpy.arrayAntigen processing scores for each peptide
fit(targets, peptides, sample_names, alleles, n_flanks=None, c_flanks=None, verbose=1)[source]

Fit the presentation score logistic regression model.

Parameters:
targetslist of int/float

1 indicates hit, 0 indicates decoy

peptideslist of string [same length as targets]
sample_nameslist of string [same length as targets]
allelesdict of string -> list of string

Keys are sample names, values are the alleles for that sample

n_flankslist of string [same length as targets]
c_flankslist of string [same length as targets]
verboseint
fit_from_scores(targets, affinities, processing_scores_by_model, verbose=1)[source]

Fit presentation logistic-regression weights from precomputed scores.

Parameters:
targetslist of int/float

1 indicates hit, 0 indicates decoy.

affinitieslist of float

Best binding affinity predictions aligned to targets.

processing_scores_by_modeldict

Mapping from model name ("with_flanks" or "without_flanks") to processing predictions aligned to targets.

verboseint
get_model(name=None)[source]

Load or instantiate a new logistic regression model. Private helper method.

Parameters:
namestring

If None (the default), an un-fit LR model is returned. Otherwise the weights are loaded for the specified model.

Returns:
sklearn.linear_model.LogisticRegression
predict(peptides, alleles, sample_names=None, n_flanks=None, c_flanks=None, include_affinity_percentile=False, verbose=1, throw=True, affinity_model_kwargs=None, processing_batch_size='auto')[source]

Predict presentation scores across a set of peptides.

Presentation scores combine predictions for MHC I binding affinity and antigen processing.

This method returns a pandas.DataFrame giving presentation scores plus the binding affinity and processing predictions and other intermediate results.

Example:

>>> predictor = Class1PresentationPredictor.load()
>>> predictions = predictor.predict(
...    peptides=["SIINFEKL", "PEPTIDE"],
...    n_flanks=["NNN", "SNS"],
...    c_flanks=["CCC", "CNC"],
...    alleles={
...        "sample1": ["A0201", "A0301", "B0702"],
...        "sample2": ["A0101", "C0202"],
...    },
...    verbose=0)
>>> list(zip(predictions.sample_name, predictions.peptide))
[('sample1', 'SIINFEKL'), ('sample1', 'PEPTIDE'), ('sample2', 'SIINFEKL'), ('sample2', 'PEPTIDE')]
>>> bool(predictions.presentation_score.between(0, 1).all())
True

You can also specify sample_names, in which case peptide is evaluated for binding the alleles in the corresponding sample only. See predict_affinity for examples.

Parameters:
peptideslist of string

Peptide sequences

alleleslist of string or dict of string -> list of string

If you are predicting for a single sample, pass a list of strings indicating the sample MHC allele set (at most six alleles in this list form). If you are predicting across multiple samples, pass a dict where the keys are (arbitrary) sample names and the values are the alleles to predict for that sample. Set to an empty list or dict to perform processing prediction only.

sample_nameslist of string [same length as peptides]

If you are passing a dict for ‘alleles’, you can use this argument to specify which peptides go with which samples. If it is None, then predictions will be performed for each peptide across all samples.

n_flankslist of string [same length as peptides]

Upstream sequences before the peptide. Sequences of any length can be given and a suffix of the size supported by the model will be used.

c_flankslist of string [same length as peptides]

Downstream sequences after the peptide. Sequences of any length can be given and a prefix of the size supported by the model will be used.

include_affinity_percentilebool

Whether to include affinity percentile ranks

verboseint

Set to 0 for quiet.

throwbool

Whether to throw exception (vs. just log a warning) on invalid peptides, etc.

affinity_model_kwargsdict, optional

Keyword arguments forwarded to Class1AffinityPredictor.predict.

processing_batch_sizeint or “auto”

Batch size for antigen processing neural network prediction.

Returns:
pandas.DataFrame
Presentation scores and intermediate results.
resolve_comparison_quantity(alleles, comparison_quantity=None)[source]

Resolve the column used to rank scan predictions.

This is the single source of truth for the comparison_quantity defaulting and validation used by predict_sequences(). It is also called by the predict-scan CLI’s parallel path so that chunked execution ranks on exactly the same column the serial path would pick (which depends on the predictor’s capabilities, not on which columns happen to be present in a given result).

Parameters:
alleles

The alleles argument as passed to predict_sequences() (string, list, or dict). Only its length / emptiness is used here.

comparison_quantitystring or None

If None, a default is chosen: presentation_score when alleles are given and presentation is supported, else affinity when alleles are given, else processing_score.

Returns:
string

The resolved (and validated) comparison quantity.

static sort_predictions(result_df, comparison_quantity)[source]

Globally sort scan predictions by comparison_quantity.

Score columns (those ending in "score") sort descending (stronger binders first); affinity / affinity_percentile sort ascending (lower is stronger). peptide is the secondary key. Rows tied on both keys retain their input order. The scan CLI preserves serial input order when combining parallel chunks before this sort.

Returns a new DataFrame; the index is not reset.

predict_sequences(sequences, alleles, result='best', comparison_quantity=None, filter_value=None, peptide_lengths=(8, 9, 10, 11), use_flanks=True, include_affinity_percentile=True, verbose=1, throw=True, affinity_model_kwargs=None, processing_batch_size='auto')[source]

Predict presentation across protein sequences.

Example:

>>> predictor = Class1PresentationPredictor.load()
>>> predictions = predictor.predict_sequences(
...    sequences={
...        'protein1': "MDSKGSSQKGSRLLLLLVVSNLL",
...        'protein2': "SSLPTPEDKEQAQQTHH",
...    },
...    alleles={
...        "sample1": ["A0201", "A0301", "B0702"],
...        "sample2": ["A0101", "C0202"],
...    },
...    result="filtered",
...    comparison_quantity="affinity",
...    filter_value=500,
...    verbose=0)
>>> bool((predictions.affinity <= 500).all())
True
>>> {"sequence_name", "pos", "peptide", "affinity"}.issubset(predictions.columns)
True
Parameters:
sequencesstr, list of string, or string -> string dict

Protein sequences. If a dict is given, the keys are arbitrary ( e.g. protein names), and the values are the amino acid sequences.

alleleslist of string, list of list of string, or dict of string -> list of string

MHC I alleles. Can be: (1) a string (a single allele), (2) a list of strings (a single MHC allele set), (3) a list of list of strings (multiple MHC allele sets, where the number of sets must equal the number of sequences), or (4) a dict giving multiple MHC allele sets, which will each be run over the sequences.

resultstring, default “best”

Specify ‘best’ to return the strongest peptide for each sequence and sample, ‘all’ to return predictions for all peptides, or ‘filtered’ to return predictions where the comparison_quantity is stronger or equal to filter_value (<= for affinity/percentile, >= for scores).

comparison_quantitystring, optional

One of “presentation_score”, “processing_score”, “affinity”, or “affinity_percentile”. Prediction to use to rank (if result is “best”) or filter (if result is “filtered”) results. With MHC alleles, defaults to presentation when supported, else affinity; without MHC alleles, defaults to processing.

filter_valuefloat

Threshold value to use, only relevant when result is “filtered”. Affinity and affinity-percentile values at or below the threshold are retained; presentation and processing scores at or above it are retained. Required when result is “filtered”.

peptide_lengthssequence of int, default (8, 9, 10, 11)

Peptide lengths to scan.

use_flanksbool, default True

Whether to include flanking sequences when running the AP predictor (for better cleavage prediction).

include_affinity_percentilebool

Whether to include affinity percentile ranks in output.

verboseint

Set to 0 for quiet mode.

throwboolean

Whether to throw exceptions (vs. log warnings) on invalid inputs.

affinity_model_kwargsdict, optional

Keyword arguments forwarded to Class1AffinityPredictor.predict.

processing_batch_sizeint or “auto”

Batch size for antigen processing neural network prediction.

Returns:
pandas.DataFrame

Includes sequence_name, zero-based pos, peptide and sample_name. Available predictor components determine affinity, best_allele, processing_score and presentation_score columns. Flank columns and percentile columns depend on inputs, options and calibration.

save(models_dir, write_affinity_predictor=True, write_processing_predictor=True, write_weights=True, write_percent_ranks=True, write_info=True, write_metadata=True)[source]

Save the predictor to a directory on disk. If the directory does not exist it will be created.

The wrapped Class1AffinityPredictor and Class1ProcessingPredictor instances are included in the saved data.

Parameters:
models_dirstring

Path to directory. It will be created if it doesn’t exist.

write_affinity_predictorbool, default True

Save the embedded affinity ensemble.

write_processing_predictorbool, default True

Save the available embedded processing ensembles.

write_weightsbool, default True

Save fitted logistic-regression coefficients; requires a fitted model.

write_percent_ranksbool, default True

Replace the presentation calibration with its current state.

write_infobool, default True

Write save-time package, host and release-provenance metadata.

write_metadatabool, default True

Write dataframes in metadata_dataframes.

classmethod load(models_dir=None, max_models=None)[source]

Deserialize a predictor from a directory on disk.

This will also load the wrapped Class1AffinityPredictor and Class1ProcessingPredictor instances.

Parameters:
models_dirstring

Path to directory. If unspecified the default downloaded models are used.

max_modelsint, optional

Maximum number of affinity and processing (counted separately) models to load

Returns:
Class1PresentationPredictor instance
percentile_ranks(presentation_scores, throw=True)[source]

Return percentile ranks for the given presentation scores.

Parameters:
presentation_scoressequence of float

Raw presentation scores, not peptide sequences.

throwbool, default True

Raise when calibration is absent. False warns and returns NaNs.

Returns:
numpy.array of float

Upper-tail percentiles from 0 to 100; lower means stronger.

calibrate_percentile_ranks(scores, bins=None, *, method=None, max_knots=128, groups=None)[source]

Compute the cumulative distribution of scores, to enable taking quantiles of this distribution later.

Parameters:
scoressequence of float

Presentation prediction scores

binsobject

Anything that can be passed to numpy.histogram’s “bins” argument can be used here, i.e. either an integer or a sequence giving bin edges. Explicit bins select the historical histogram method.

method{“compact”, “histogram”}, optional

Defaults to compact unless bins are specified. Loading a saved predictor never recalibrates it.

max_knots{64, 128}, default 128

Upper bound, not a starting size. Compact starts with 64; 128 requires a background-validation improvement beyond the tolerance. Ignored for histogram calibration.

groupssequence, optional

Background peptide identities to keep together during validation.

mhcflurry.class1_processing_neural_network module

Antigen processing neural network implementation - PyTorch version

class mhcflurry.class1_processing_neural_network.Class1ProcessingModel(sequence_dims, n_flank_length, c_flank_length, peptide_max_length, flanking_averages, convolutional_filters, convolutional_kernel_size, convolutional_activation, convolutional_kernel_l1_l2, dropout_rate, post_convolutional_dense_layer_sizes, sequence_input_is_indices=False, sequence_input_vector_encoding_name=None, init='glorot_uniform', normalization='none', cleavage_boundary_flank_length=0, cleavage_boundary_peptide_length=0, cleavage_boundary_hidden_size=32, cleavage_boundary_context_dropout=0.0, convolutional_padding_mode='zeros')[source]

Bases: Module

PyTorch module for antigen processing prediction.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

forward(inputs)[source]

Forward pass.

Parameters:
inputsdict

Dictionary with ‘sequence’ and ‘peptide_length’ keys

Returns:
torch.Tensor

Predictions of shape (batch,)

get_weights_list(state_dict=None)[source]

Copy weights in NPZ order, optionally from a retained module state.

set_weights_list(weights, auto_convert_keras=True)[source]

Set weights from a list of numpy arrays.

Supports automatic detection and conversion of Keras-format weights.

Parameters:
weightslist of numpy.ndarray
auto_convert_kerasbool

If True, automatically detect and convert Keras-format weights

class mhcflurry.class1_processing_neural_network.Class1ProcessingNeuralNetwork(**hyperparameters)[source]

Bases: object

A neural network for antigen processing prediction

network_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters (and their default values) that affect the neural network architecture.

fit_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters for neural network training.

early_stopping_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperparameters for early stopping.

compile_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Loss and optimizer hyperparameters.

auxiliary_input_hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Allele feature hyperparameters.

hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>
property sequence_lengths

Supported maximum sequence lengths

Returns:
dict of string -> int
Keys are “peptide”, “n_flank”, “c_flank”. Values give the maximum
supported sequence length.
get_device()[source]

Get the PyTorch device to use.

network()[source]

Return the PyTorch model associated with this network.

update_network_description()[source]

Update self.network_json and self.network_weights properties based on this instances’s neural network.

fit(sequences, targets, sample_weights=None, shuffle_permutation=None, verbose=1, progress_callback=None, progress_preamble='', progress_print_interval=5.0, seed=None, validation_mask=None, sample_ids=None)[source]

Fit the neural network.

Parameters:
sequencesFlankingEncoding

Peptides and upstream/downstream flanking sequences

targetslist of float

1 indicates hit, 0 indicates decoy

sample_weightslist of float

If not specified all samples have equal weight.

validation_maskarray of bool, optional

Explicit per-row validation membership, overriding validation_split. Used by matched processing training to keep complete samples together.

sample_idsarray of str, optional

Required for monitor_validation_ranking or checkpoint_metric= ‘val_macro_ap’. Samples must not cross the explicit training and stopping-validation mask. AP selects the earliest best-ranking epoch; early-stopping patience remains based on validation loss.

shuffle_permutationlist of int

Permutation of row indices, with the same length as targets. If None, then a random permutation will be generated.

verboseint

Verbosity level

progress_callbackfunction

No-argument function to call after each epoch.

progress_preamblestring

Optional string of information to include in each progress update

progress_print_intervalfloat

How often (in seconds) to print progress update. Set to None to disable.

seedint, optional

Master seed for this fit. When given, it seeds numpy’s and torch’s global RNGs at the start of the call, so every stochastic step downstream flows from this one value: weight initialization, the initial example shuffle, and the per-epoch training-batch shuffle. When None (the default) the RNGs are left unchanged. The caller or worker initializer is responsible for setting independent RNG states. Mirrors mhcflurry.class1_neural_network.Class1NeuralNetwork.fit()’s seed so one value can drive both trainers.

predict(peptides, n_flanks=None, c_flanks=None, batch_size='auto')[source]

Predict antigen processing.

Parameters:
peptideslist of string

Peptide sequences

n_flankslist of string

Upstream sequence before each peptide

c_flankslist of string

Downstream sequence after each peptide

batch_sizeint or “auto”

Prediction batch size, automatically sized by default.

Returns:
numpy.array
Processing scores. Range is 0-1, higher indicates more favorable
processing.
predict_encoded(sequences, throw=True, batch_size='auto')[source]

Predict antigen processing.

Parameters:
sequencesFlankingEncoding

Peptides and flanking sequences

throwboolean

Whether to throw exception on unsupported peptides

batch_sizeint or "auto"

Prediction batch size. "auto" (the default) auto-sizes per the current device — see mhcflurry.pytorch_sizing.compute_prediction_batch_size.

Returns:
numpy.array
predict_encoded_tensor(sequences, throw=True, batch_size='auto', device=None)[source]

Predict antigen processing and return a torch tensor.

This tensor-native path keeps encoded inputs resident on the target device when FlankingEncoding can provide a compatible tensor cache. predict_encoded delegates here and converts the final result to numpy for the public API.

network_input_tensors(sequences, device, throw=True)[source]

Encode peptides to the target-device tensors expected by the network.

network_input(sequences, throw=True)[source]

Encode peptides to the fixed-length encoding expected by the neural network (which depends on the architecture).

Parameters:
sequencesFlankingEncoding

Peptides and flanking sequences

throwboolean

Whether to throw exception on unsupported peptides

Returns:
dict
make_network(amino_acid_encoding, amino_acid_encoding_torch, peptide_max_length, n_flank_length, c_flank_length, flanking_averages, convolutional_filters, convolutional_kernel_size, convolutional_padding_mode, convolutional_activation, convolutional_kernel_l1_l2, dropout_rate, post_convolutional_dense_layer_sizes, init, normalization, cleavage_boundary_flank_length, cleavage_boundary_peptide_length, cleavage_boundary_hidden_size, cleavage_boundary_context_dropout)[source]

Helper function to make a PyTorch network given hyperparameters.

get_weights()[source]

Get the network weights

Returns:
list of numpy.array giving weights for each layer or None if there is no
network
get_config()[source]

serialize to a dict all attributes except model weights

Returns:
dict
classmethod from_config(config, weights=None)[source]

deserialize from a dict returned by get_config().

Parameters:
configdict
weightslist of array, optional

Network weights to restore

Returns:
Class1ProcessingNeuralNetwork

mhcflurry.class1_processing_predictor module

class mhcflurry.class1_processing_predictor.Class1ProcessingPredictor(models, manifest_df=None, metadata_dataframes=None, provenance_string=None, percent_rank_transform=None)[source]

Bases: object

User-facing interface to antigen processing prediction.

Delegates to an ensemble of Class1ProcessingNeuralNetwork instances.

Instantiate a new Class1ProcessingPredictor

Users will generally call load() to restore a saved predictor rather than using this constructor.

Parameters:
modelslist of Class1ProcessingNeuralNetwork

Neural networks in the ensemble.

manifest_dfpandas.DataFrame

Manifest dataframe. If not specified a new one will be created when needed.

metadata_dataframesdict of string -> pandas.DataFrame

Arbitrary metadata associated with this predictor

provenance_stringstring, optional

Optional info string to use in __str__.

percent_rank_transformtransform, optional

HistogramPercentRankTransform or CompactPercentRankTransform fitted to this ensemble’s background score distribution. Historical processing predictors may have no calibration.

calibrate_percentile_ranks(scores, bins=None, *, method=None, max_knots=128, groups=None)[source]

Calibrate from explicit background processing scores.

Parameters:
scoressequence of float

Independent background scores from the same ensemble and flank policy used at prediction time. Evaluation labels are not used.

binsint or sequence, optional

Explicit bins select historical histogram calibration.

method{“compact”, “histogram”}, optional

Compact unless explicit bins select histogram. Compact plus bins is rejected. Histogram with no bins uses score quantiles.

max_knots{64, 128}, default 128

Upper bound, not a starting size; retain 64 unless 128 improves background validation beyond the tolerance. Ignored for histogram.

groupssequence, optional

Reference peptide identities, kept together during validation.

percentile_ranks(processing_scores, throw=True)[source]

Return lower-is-stronger percentiles without changing raw scores.

Parameters:
processing_scoressequence of float

Raw processing scores, not peptide sequences.

throwbool, default True

Raise when calibration is absent. False warns and returns NaNs.

Returns:
numpy.ndarray

Upper-tail percentiles from 0 to 100. This separate method does not add a percentile column to raw prediction dataframes.

property sequence_lengths

Supported maximum sequence lengths.

Passing a peptide greater than the maximum supported length results in an error.

Passing an N- or C-flank sequence greater than the maximum supported length results in some part of it being ignored.

Returns:
dict of string -> int
Keys are “peptide”, “n_flank”, “c_flank”. Values give the maximum
supported sequence length.
add_models(models)[source]

Add models to the ensemble (in-place).

Parameters:
modelslist of Class1ProcessingNeuralNetwork
Returns:
list of string
Names of the new models.
property manifest_df

A pandas.DataFrame describing the models included in this predictor.

Returns:
pandas.DataFrame
static model_name(num)[source]

Generate a model name

Returns:
string
static weights_path(models_dir, model_name)[source]

Generate the path to the weights file for a model

Parameters:
models_dirstring
model_namestring
Returns:
string
predict(peptides, n_flanks=None, c_flanks=None, throw=True, batch_size='auto')[source]

Predict antigen processing.

Parameters:
peptideslist of string

Peptide sequences

n_flankslist of string

Upstream sequence before each peptide

c_flankslist of string

Downstream sequence after each peptide

throwboolean

If True, a ValueError will be raised in the case of unsupported peptides. If False, a warning will be logged and the predictions for those peptides will be NaN.

batch_sizeint or “auto”

Prediction batch size, automatically sized by default.

Returns:
numpy.array
Processing scores. Range is 0-1, higher indicates more favorable
processing.
predict_to_dataframe(peptides, n_flanks=None, c_flanks=None, throw=True, batch_size='auto')[source]

Predict antigen processing.

See predict method for parameter descriptions.

Returns:
pandas.DataFrame
Processing predictions are in the “score” column. Also includes
peptides and flanking sequences.
predict_to_dataframe_encoded(sequences, throw=True, batch_size='auto')[source]

Predict antigen processing.

See predict method for more information.

Parameters:
sequencesFlankingEncoding
batch_sizeint or “auto”
throwboolean
Returns:
pandas.DataFrame
predict_encoded_tensor(sequences, throw=True, batch_size='auto')[source]

Predict antigen processing and return a torch tensor.

Ensemble members consume the tensor cache on sequences when available, so encoded inputs only need to move to each target device once per encoding/device combination.

check_consistency()[source]

Verify that self.manifest_df is consistent with instance variables.

Currently only checks for agreement on the total number of models.

Throws AssertionError if inconsistent.

save(models_dir, model_names_to_write=None, write_metadata=True, write_percent_ranks=True)[source]

Serialize the predictor to a directory on disk. If the directory does not exist it will be created.

The serialization format consists of a file called “manifest.csv” with the configurations of each Class1ProcessingNeuralNetwork, along with per-network files giving the model weights.

Parameters:
models_dirstring

Path to directory. It will be created if it doesn’t exist.

model_names_to_writelist of string, optional

Only write the weights for the specified models. Useful for incremental updates during training: previously saved members of this predictor remain in the manifest. In a fresh directory, save only the requested members, in the requested order. Such a subset has no percentile calibration; calibrate the exported predictor separately. Passing an explicit empty list writes no model artifacts; this is used by calibration-only updates that replace percentile calibration without touching the manifest, weights, or retained checkpoints.

write_metadataboolean, optional

Whether to write optional metadata

write_percent_ranksboolean, optional

Whether to write the percentile calibration

classmethod load(models_dir=None, max_models=None)[source]

Deserialize a predictor from a directory on disk.

Parameters:
models_dirstring

Path to directory. If unspecified the default downloaded models are used.

max_modelsint, optional

Maximum number of models to load

Returns:
Class1ProcessingPredictor instance

mhcflurry.class1_training module

Training and validation helpers for class I neural networks.

mhcflurry.class1_training.validation_split_counts(total_rows, validation_split)[source]

Return train/validation row counts using Keras split semantics.

Keras assigns the last rows to validation and computes the boundary as floor(total_rows * (1 - validation_split)). Computing validation rows first is not equivalent for row counts that are not exact multiples of the split denominator.

mhcflurry.class1_training.torch_from_numpy(value)[source]

mhcflurry.cluster_parallelism module

Simple, relatively naive parallel map implementation for HPC clusters.

Used for training MHCflurry models.

mhcflurry.cluster_parallelism.add_cluster_parallelism_args(parser)[source]

Add commandline arguments controlling cluster parallelism to an argparse ArgumentParser.

Parameters:
parserargparse.ArgumentParser
mhcflurry.cluster_parallelism.cluster_results_from_args(args, work_function, work_items, constant_data=None, input_serialization_method='pickle', result_serialization_method='pickle', clear_constant_data=False)[source]

Parallel map configurable using commandline arguments. See the cluster_results() function for docs.

The args parameter should be an argparse.Namespace from an argparse parser generated using the add_cluster_parallelism_args() function.

Parameters:
argsargparse.Namespace

Parsed cluster configuration.

work_functioncallable

Function called with each item’s keyword arguments and constant_data.

work_itemsiterable of dict

Keyword arguments for each work item.

constant_dataobject, optional

Shared input made available to each job.

input_serialization_methodstr

Input serializer: ‘pickle’ or ‘dill’.

result_serialization_methodstr

Result serializer: ‘pickle’ or ‘save_predictor’.

clear_constant_databool

Clear the shared-input dictionary after serialization to free memory.

Returns:
generator
mhcflurry.cluster_parallelism.cluster_results(work_function, work_items, constant_data=None, submit_command='sh', results_workdir='./cluster-workdir', additional_complete_file=None, script_prefix_path=None, input_serialization_method='pickle', result_serialization_method='pickle', max_retries=3, clear_constant_data=False)[source]

Parallel map on an HPC cluster.

Returns [work_function(item) for item in work_items] where each invocation of work_function is performed as a separate HPC cluster job. Results are yielded as completed jobs are observed, not in input order.

Optionally, “constant data” can be specified, which will be passed to each work_function() invocation as a keyword argument called constant_data. This data is serialized once and all workers read it from the same source, which is more efficient than serializing it separately for each worker.

Each worker’s input is serialized to a shared NFS directory and the submit_command is used to launch a job to process that input. The shared filesystem is polled occasionally to watch for results, which are fed back to the user.

Parameters:
work_functionA -> B
work_itemslist of A
constant_dataobject
submit_commandstring

For running on LSF, we use “bsub” here.

results_workdirstring

Path to NFS shared directory where inputs and results can be written

script_prefix_pathstring

Path to script that will be invoked to run each worker. A line calling the _mhcflurry-cluster-worker-entry-point command will be appended to the contents of this file.

result_serialization_methodstring, one of “pickle” or “save_predictor”

The “save_predictor” works only when the return type of work_function is Class1AffinityPredictor

input_serialization_methodstr

Input/context serialization format (pickle or dill).

additional_complete_filestr, optional

Alternative worker-completion marker, relative to the job directory. Its presence also triggers result/error inspection.

max_retriesint

How many times to attempt to re-launch a failed worker

clear_constant_databool

If True, the constant data dict is cleared on the launching host after it is serialized to disk.

Returns:
generator of B
mhcflurry.cluster_parallelism.worker_entry_point(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

Entry point for the worker command.

Parameters:
argvlist of string

mhcflurry.cluster_worker_entry_point module

Module entry point for cluster workers to ensure the current interpreter is used.

mhcflurry.common module

mhcflurry.common.positive_int_arg(value)[source]

Parse an argparse value as an integer greater than zero.

mhcflurry.common.positive_float_arg(value)[source]

Parse an argparse value as a finite float greater than zero.

mhcflurry.common.fraction_arg(value)[source]

Parse an argparse value as a finite fraction in (0, 1].

mhcflurry.common.add_random_seed_arg(parser)[source]

Add the standard --random-seed argument to a CLI parser.

Training commands use this flag to record a shared source of random seeds. It does not guarantee identical results across devices or library versions. Pair with configure_random_seed() at the start of the command’s run/main.

mhcflurry.common.configure_random_seed(seed=None, name='mhcflurry')[source]

Resolve, apply, and log a master random seed.

Seeds numpy’s, Python’s, and torch’s global RNGs so every randomness source in this process derives from one value. When seed is None a value is drawn from system entropy. Returns the resolved seed so callers can derive worker-local sub-seeds via derive_seed().

mhcflurry.common.install_sigusr1_stack_trace_handler()[source]

Install a SIGUSR1 handler that prints this process’s stack trace.

mhcflurry.common.derive_seed(master_seed, *parts)[source]

Derive a stable sub-seed from a master seed and identity parts.

Gives independent units of work (e.g. one training fit, keyed by architecture/fold/replicate) decorrelated but reproducible seeds, all rooted in the run’s single master seed. master_seed may be None (e.g. a legacy run with no recorded seed); the result is still stable.

mhcflurry.common.normalize_allele_name(raw_name, forbidden_substrings=('MIC', 'HFE'), raise_on_error=True, default_value=None, use_allele_aliases=True)[source]

Parses a string into a normalized allele representation.

Parameters:
raw_namestr

Input string to normalize

forbidden_substringstuple of str

Legacy argument naming retained for compatibility. Values identify exact genes; MIC identifies the mhcgnomes class-Ic family. Input names are never rejected by substring matching.

raise_on_errorbool

If an allele fails to parse raise an exception if this argument is True

default_valuestr or None

If raise_on_error is False and allele fails to parse, return this value

use_allele_aliasesbool

If True, use mhcgnomes allele alias table (IMGT historical name reassignments). Some old allele names (e.g. B*44:01, Cw*0201) were retired by IMGT when the original sequences were found to contain errors. Defaults to True, so retired/aliased names resolve to their current canonical form. Callers that must preserve current IMGT nomenclature (e.g. pseudosequence-key matching, which is no-alias-first with explicit fallback) pass use_allele_aliases=False.

Returns:
str or None
mhcflurry.common.normalize_sequence_resolved_allele_name(raw_name)[source]

Return a canonical, sequence-resolved class-I allele name.

HLA allele groups require at least two fields because a one-field group can contain multiple protein sequences. Other species require at least one allele field. Serotypes, genes, class-II names, pseudogenes, and invalid spellings fail through normalize_allele_name() with its specific diagnostic.

mhcflurry.common.normalize_class1_genotype(value)[source]

Canonicalize whitespace-delimited class-I MHC alleles into a tuple.

mhcflurry.common.allele_locus_name(raw_name, raise_on_error=False, default_value='other', use_allele_aliases=True)[source]

Return a class-I MHC locus label using mhcgnomes parsing.

Human loci are returned as HLA-A, HLA-B, etc. Mouse H-2 loci are collapsed to H2 for the plotting/MHC-sampling code that only needs a species-level bucket. Unparseable inputs raise when raise_on_error is true. Valid but unhandled loci still return default_value.

mhcflurry.common.filter_canonicalizable_alleles(alleles, log_label='alleles')[source]

Drop alleles that normalize_allele_name refuses to canonicalize.

Returns the surviving names unchanged (raw input strings), having only removed the un-canonicalizable ones. predictor.supported_alleles (and any user-supplied --alleles-file) can contain pseudogenes / null alleles / questionable annotations — those are real entries in the public allele_sequences.csv (which aims to be exhaustive), but predict_to_dataframe raises on them mid-iteration. Filter once up front so iteration doesn’t crash partway through, and log the dropped sample so the missing rows in the resulting output table are explainable.

Survivors are returned verbatim rather than canonicalized: callers that need names to match a predictor’s pseudosequence keys must map them through predictor.canonicalize_allele_name (which prefers the no-alias form, matching how allele_to_sequence keys are built). A generic alias-applying normalization here would silently remap retired alleles (e.g. HLA-B*44:01 -> HLA-B*44:02) away from their own key.

A local memo keeps the per-allele normalize_allele_name cost bounded. mhcgnomes also caches its own parses, so even the full ~20K-allele predictor set is a one-time ~1-2 sec single-threaded pre-pass (measured), not the minutes a naive uncached parse would cost.

mhcflurry.common.build_allele_alias_map(valid_keys)[source]

Map mhcgnomes-aliased names back to the canonical keys in valid_keys.

For each key, compute its alias-applied normalization; if that differs from the key and isn’t itself a key, record alias -> key. Mirrors the map the affinity predictor builds at load time (allele_to_canonical), but for an arbitrary key set — e.g. an allele-sequences table at training time.

class mhcflurry.common.AlleleKeyResolver(valid_keys, alias_map=None)[source]

Bases: object

Resolves allele names to a fixed set of canonical keys, no-alias-first.

A name is resolved by this priority (each step checked against valid_keys):

  1. its own no-alias normalization, if that is already a key — so an allele with its own pseudosequence isn’t remapped onto an alias target (e.g. retired HLA-B*44:01 keeps its own entry rather than collapsing to HLA-B*44:02);

  2. its alias-applied normalization, if that is a key;

  3. the key it is a retired alias of, via the reverse alias map.

Two resolution modes, deliberately distinct:

  • resolve_to_key() — strict. Returns the resolved key, or None for any name that maps to no key (whether unsupported or unparseable). Use this when an unmatched name should be dropped (e.g. training ingestion).

  • resolve() — best effort. Like resolve_to_key for names that do match a key, but a name that normalizes yet matches no key is returned as its normalized form (not None), so callers can surface it as an unsupported allele downstream. Returns None only when the name can’t be normalized at all (and raise_on_error=False).

The reverse alias map (build_allele_alias_map, an O(len(valid_keys)) scan) is built once and cached on first use — so already-canonical inputs, which resolve at step 1 or 2, never pay for it. Pass it prebuilt (e.g. a predictor’s load-time allele_to_canonical) to skip the scan entirely.

valid_keys should support O(1) in (a dict or set); an empty/falsy value skips steps 1-2 (e.g. allele-specific predictors with no pseudosequences), so every name falls through to the reverse-map step.

reverse_alias_map()[source]

The alias -> key map, built once on first use and cached.

resolve(raw_name, raise_on_error=False)[source]

Best-effort resolution. See the class docstring for the contract.

resolve_to_key(raw_name)[source]

Strict resolution: a key in valid_keys, or None.

Drops the best-effort fallback of resolve() — an unsupported or unparseable name both return None.

mhcflurry.common.canonicalize_allele_series(alleles, valid_keys, log_label='alleles')[source]

Map allele names to canonical keys (no-alias-first), strictly.

Returns a list parallel to alleles with each name resolved to a key in valid_keys, or None when it resolves to no key (so the row can be dropped). Memoizes per unique input, so it is cheap over a long training column with few distinct alleles, and the reverse alias map is built lazily (only if some name is a current-name request for a retired key) — so already-canonical data never pays the ~O(len(valid_keys)) scan. Logs a sample of names that did not resolve. Use this for training ingestion.

mhcflurry.common.normalize_pytorch_backend(backend)[source]

Normalize a requested backend name and validate it.

Parameters:
backendstr or None
Returns:
str or None
mhcflurry.common.configure_pytorch(backend=None, gpu_device_nums=None, num_threads=None)[source]

Configure PyTorch device backend and threading.

Can be called multiple times. Each call updates the settings provided.

Parameters:
backendstr, optional

Device backend: “auto”, “gpu”, “mps”, or “cpu”. “auto” selects the best available device (GPU > MPS > CPU).

gpu_device_numslist of str or int, optional

CUDA device identifiers to expose via CUDA_VISIBLE_DEVICES. An empty list hides CUDA entirely for the current process.

num_threadsint, optional

Number of threads for PyTorch operations

mhcflurry.common.configure_tensorflow(backend=None, gpu_device_nums=None, num_threads=None)[source]

Backward-compatible configuration entry point from the TF backend era.

Parameters:
backendstr, optional

Legacy backend value retained for API compatibility. TensorFlow-era names such as “tensorflow-cpu” are translated to the equivalent PyTorch backend and emit a deprecation warning.

gpu_device_numslist of str or int, optional

GPU device identifiers to potentially use.

num_threadsint, optional

Number of threads for backend operations.

mhcflurry.common.get_pytorch_device()[source]

Get the PyTorch device based on the backend set by configure_pytorch.

Returns:
torch.device
mhcflurry.common.configure_logging(verbose=False)[source]

Configure logging module using defaults.

Parameters:
verboseboolean

If true, output will be at level DEBUG, otherwise, INFO.

mhcflurry.common.amino_acid_distribution(peptides, smoothing=0.0)[source]

Compute the fraction of each amino acid across a collection of peptides.

Parameters:
peptideslist of string
smoothingfloat, optional

Small number (e.g. 0.01) to add to all amino acid fractions. The higher the number the more uniform the distribution.

Returns:
pandas.Series indexed by amino acids
mhcflurry.common.random_peptides(num, length=9, distribution=None, rng=None)[source]

Generate random peptides (kmers).

Parameters:
numint

Number of peptides to return

lengthint

Length of each peptide

distributionpandas.Series

Maps 1-letter amino acid abbreviations to probabilities. If not specified a uniform distribution is used.

rngnumpy.random.Generator, optional

If provided, peptides are sampled from this generator instead of the global numpy.random state. Used by callers that need deterministic peptide generation, such as pre-generated random-negative pools. When None the global state is used, preserving legacy call-site semantics.

Returns:
list of string
mhcflurry.common.positional_frequency_matrix(peptides)[source]

Given a set of peptides, calculate a length x amino acids frequency matrix.

Parameters:
peptideslist of string

All of same length

Returns:
pandas.DataFrame

Index is position, columns are amino acids

mhcflurry.common.save_weights(weights_list, filename)[source]

Save model weights to the given filename using numpy’s “.npz” format.

Parameters:
weights_listlist of numpy array
filenamestring
mhcflurry.common.load_weights(filename)[source]

Restore model weights from the given filename, which should have been created with save_weights.

Parameters:
filenamestring
Returns:
list of array
class mhcflurry.common.NumpyJSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)[source]

Bases: JSONEncoder

JSON encoder (used with json module) that can handle numpy arrays.

Constructor for JSONEncoder, with sensible defaults.

If skipkeys is false, then it is a TypeError to attempt encoding of keys that are not str, int, float or None. If skipkeys is True, such items are simply skipped.

If ensure_ascii is true, the output is guaranteed to be str objects with all incoming non-ASCII characters escaped. If ensure_ascii is false, the output can contain non-ASCII characters.

If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to prevent an infinite recursion (which would cause an RecursionError). Otherwise, no such check takes place.

If allow_nan is true, then NaN, Infinity, and -Infinity will be encoded as such. This behavior is not JSON specification compliant, but is consistent with most JavaScript based encoders and decoders. Otherwise, it will be a ValueError to encode such floats.

If sort_keys is true, then the output of dictionaries will be sorted by key; this is useful for regression tests to ensure that JSON serializations can be compared on a day-to-day basis.

If indent is a non-negative integer, then JSON array elements and object members will be pretty-printed with that indent level. An indent level of 0 will only insert newlines. None is the most compact representation.

If specified, separators should be an (item_separator, key_separator) tuple. The default is (’, ‘, ‘: ‘) if indent is None and (‘,’, ‘: ‘) otherwise. To get the most compact JSON representation, you should specify (‘,’, ‘:’) to eliminate whitespace.

If specified, default is a function that gets called for objects that can’t otherwise be serialized. It should return a JSON encodable version of the object or raise a TypeError.

default(obj)[source]

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this:

def default(self, o):
    try:
        iterable = iter(o)
    except TypeError:
        pass
    else:
        return list(iterable)
    # Let the base class default method raise the TypeError
    return super().default(o)
mhcflurry.common.write_generate_sh(out_dir, argv=None, mhcflurry_version=None)[source]

Write a GENERATE.sh in out_dir recording how to reproduce the artifact directory and snapshot it as a tar.gz.

Called by every artifact-producing CLI (train/select/calibrate) so each output directory ships a one-liner snapshot script.

Parameters:
out_dirstr

Directory to write GENERATE.sh into. Created by the caller.

argvlist of str, optional

Command-line invocation to record. Defaults to sys.argv.

mhcflurry_versionstr, optional

Version string for the audit comment. Defaults to current.

Returns:
str

Absolute path to the GENERATE.sh that was written.

mhcflurry.compact_percent_rank_transform module

Compact percentile transforms for affinity, processing, and presentation.

Approximate the background survival function in logit coordinates. Unlike a histogram lookup, interpolation retains within-interval order. Extreme-tail extrapolation is a modeling assumption, not an empirical percentile guarantee.

mhcflurry.compact_percent_rank_transform.probability_logits(values)[source]

Convert probabilities to finite logits, preserving NaNs.

Exact zero/one scores use the nearest interior float64 values. This cannot recover distinctions already lost by rounding the underlying raw scores.

mhcflurry.compact_percent_rank_transform.select_monotonic_knots(x, y, budget)[source]

Greedily compress a strictly monotonic curve to at most budget knots.

The largest vertical interpolation error determines each next split. Endpoints are always retained; equal errors use the earliest source index.

class mhcflurry.compact_percent_rank_transform.CompactPercentRankTransform(score_transform='logit')[source]

Bases: object

Small, versioned monotonic approximation to background percentiles.

The knots store transformed raw scores and logit midrank survival probabilities. Linear interpolation in those coordinates followed by a sigmoid gives upper-tail percentiles; the complementary sigmoid gives CDF percentiles. Duplicate reference scores are weighted by their mass. No evaluation labels are required or accepted.

Parameters:
score_transform{“logit”, “log”}

Use logit for probability-valued processing/presentation scores and log for positive quantities such as affinity IC50. This selects the input coordinate, not the output direction: pass survival=True to transform processing/presentation scores into lower-is-stronger ranks.

Notes

Low-level fit uses a fixed budget (64 by default). Predictor calibration uses the shared validation selector to decide whether 128 is warranted. Tail extrapolation models, rather than establishes, rare frequencies.

FORMAT = 'compact-log-survival-linear-v1'
fit(scores, num_knots=64)[source]

Fit a curve with a fixed knot budget; return this instance.

Parameters:
scoresone-dimensional sequence of float

Finite, nonconstant background scores. Log coordinates require positive values; logit coordinates require values in [0, 1].

num_knotsint, default 64

Maximum knot count, including endpoints. This low-level method does not choose between budgets or use validation data.

Returns:
CompactPercentRankTransform

This fitted instance. Fewer knots may suffice for small or linear reference curves. Any previous automatic-selection metadata is cleared.

log_percentiles(scores, survival=False)[source]

Return natural logs of percentiles on the 0–100 scale.

Parameters:
scoresfloat or array-like

Scores in the fitted coordinate’s domain; NaNs propagate.

survivalbool, default False

False returns log CDF-percentile; True returns log upper-tail percentile directly. This is not the log of a 0–1 probability.

Returns:
numpy.ndarray or numpy scalar

Log-percentiles, retaining tiny-tail information before ordinary percentile exponentiation underflows. Extrapolation is not an empirical guarantee of extreme-tail accuracy.

transform(scores, survival=False)[source]

Return CDF or upper-tail percentiles in [0, 100].

Parameters:
scoresfloat or array-like

Raw scores in the fitted coordinate’s domain. NaNs propagate; infinities and out-of-domain values raise ValueError.

survivalbool, default False

Use False for affinity IC50 (lower raw values get lower ranks). Use True for processing/presentation probabilities (higher raw values get lower ranks). The upper tail is evaluated directly, without subtracting a rounded CDF percentile from 100.

Returns:
numpy.ndarray or numpy scalar

Percentiles. Float64 rounding and underflow can still create ties in extreme tails; use log_percentiles for tiny-tail analysis.

to_dict()[source]

Return a JSON-serializable, explicitly versioned representation.

classmethod from_dict(values)[source]

Load a curve, rejecting unsupported versions and invalid knots.

class mhcflurry.compact_percent_rank_transform.CompactPresentationPercentiles(score_transform='logit')[source]

Bases: CompactPercentRankTransform

Compatibility adapter for the original presentation-only experiment.

New callers should use CompactPercentRankTransform().fit(…) and pass survival=True explicitly. No separate fitting algorithm lives here.

classmethod from_scores(scores, num_knots=64)[source]

Fit a new adapter instance.

fit stays the base class’s instance method, which refits the receiver in place; overriding it with a constructor would silently discard in-place refits such as the knot-budget selection.

transform(scores, survival=True)[source]

Return CDF or upper-tail percentiles in [0, 100].

Parameters:
scoresfloat or array-like

Raw scores in the fitted coordinate’s domain. NaNs propagate; infinities and out-of-domain values raise ValueError.

survivalbool, default False

Use False for affinity IC50 (lower raw values get lower ranks). Use True for processing/presentation probabilities (higher raw values get lower ranks). The upper tail is evaluated directly, without subtracting a rounded CDF percentile from 100.

Returns:
numpy.ndarray or numpy scalar

Percentiles. Float64 rounding and underflow can still create ties in extreme tails; use log_percentiles for tiny-tail analysis.

log_percentiles(scores, survival=True)[source]

Return natural logs of percentiles on the 0–100 scale.

Parameters:
scoresfloat or array-like

Scores in the fitted coordinate’s domain; NaNs propagate.

survivalbool, default False

False returns log CDF-percentile; True returns log upper-tail percentile directly. This is not the log of a 0–1 probability.

Returns:
numpy.ndarray or numpy scalar

Log-percentiles, retaining tiny-tail information before ordinary percentile exponentiation underflows. Extrapolation is not an empirical guarantee of extreme-tail accuracy.

classmethod from_dict(values)[source]

Load a curve, rejecting unsupported versions and invalid knots.

mhcflurry.custom_loss module

Custom loss functions.

For losses supporting inequalities, each training data point is associated with one of (=), (<), or (>). For e.g. (>) inequalities, penalization is applied only if the prediction is less than the given value.

This module now delegates to pytorch_losses.py for the actual loss implementations.

mhcflurry.custom_loss.get_loss(name)[source]

Get a custom_loss.Loss instance by name.

Parameters:
namestring
Returns:
custom_loss.Loss
class mhcflurry.custom_loss.Loss(name=None)[source]

Bases: object

Thin wrapper to keep track of neural network loss functions, which could be custom or baked into PyTorch.

Each subclass or instance should define these properties/methods:

  • name : string

  • losscallable

    This is the PyTorch loss function

  • encode_ynumpy.ndarray -> numpy.ndarray

    Transformation to apply to regression target before fitting

loss(y_true, y_pred)[source]
get_keras_loss(reduction='sum_over_batch_size')[source]

Backward-compatible accessor from the TF/Keras backend era.

Parameters:
reductionstring

Ignored. Kept for API compatibility.

class mhcflurry.custom_loss.StandardKerasLoss(loss_name='mse')[source]

Bases: Loss

A standard loss function such as MSE.

supports_inequalities = False
supports_multiple_outputs = False
static encode_y(y)[source]
class mhcflurry.custom_loss.TransformPredictionsLossWrapper(loss, y_pred_transform=None)[source]

Bases: Loss

Wrapper that applies an arbitrary transform to y_pred before calling an underlying loss function.

The y_pred_transform function should be a tensor -> tensor function.

encode_y(*args, **kwargs)[source]
loss(y_true, y_pred)[source]
class mhcflurry.custom_loss.MSEWithInequalities[source]

Bases: Loss

Supports training a regression model on data that includes inequalities (e.g. x < 100). Mean square error is used as the loss for elements with an (=) inequality. For elements with e.g. a (> 0.5) inequality, then the loss for that element is (y - 0.5)^2 (standard MSE) if y < 0.5 and 0 otherwise.

This loss assumes that the normal range for y_true and y_pred is 0 - 1. As a hack, the implementation uses other intervals for y_true to encode the inequality information.

y_true is interpreted as follows:

between 0 - 1

Regular MSE loss is used. Penalty (y_pred - y_true)**2 is applied if y_pred is greater or less than y_true.

between 2 - 3:

Treated as a “>” inequality. Penalty (y_pred - (y_true - 2))**2 is applied only if y_pred is less than y_true - 2.

between 4 - 5:

Treated as a “<” inequality. Penalty (y_pred - (y_true - 4))**2 is applied only if y_pred is greater than y_true - 4.

name = 'mse_with_inequalities'
supports_inequalities = True
supports_multiple_outputs = False
static encode_y(y, inequalities=None)[source]
loss(y_true, y_pred)[source]
class mhcflurry.custom_loss.MSEWithInequalitiesAndMultipleOutputs[source]

Bases: Loss

Loss supporting inequalities and multiple outputs.

This loss assumes that the normal range for y_true and y_pred is 0 - 1. As a hack, the implementation uses other intervals for y_true to encode the inequality and output-index information.

Inequalities are encoded into the regression target as in the MSEWithInequalities loss.

Multiple outputs are encoded by mapping each regression target x (after transforming for inequalities) using the rule x -> x + i * 10 where i is the output index.

The reason for explicitly encoding multiple outputs this way (rather than just making the regression target a matrix instead of a vector) is that in our use cases we frequently have missing data in the regression target. This encoding gives a simple way to penalize only on (data point, output index) pairs that have labels.

name = 'mse_with_inequalities_and_multiple_outputs'
supports_inequalities = True
supports_multiple_outputs = True
static encode_y(y, inequalities=None, output_indices=None)[source]
loss(y_true, y_pred)[source]
class mhcflurry.custom_loss.MultiallelicMassSpecLoss(delta=0.2, multiplier=1.0)[source]

Bases: Loss

Multiallelic mass spec loss function.

name = 'multiallelic_mass_spec_loss'
supports_inequalities = True
supports_multiple_outputs = False
static encode_y(y)[source]
loss(y_true, y_pred)[source]
mhcflurry.custom_loss.check_shape(name, arr, expected_shape)[source]

Raise ValueError if arr.shape != expected_shape.

Parameters:
namestring

Included in error message to aid debugging

arrnumpy.ndarray
expected_shapetuple of int
mhcflurry.custom_loss.cls

alias of MultiallelicMassSpecLoss

mhcflurry.data_dependent_weights_initialization module

Layer-sequential unit-variance initialization for neural networks.

See:

Mishkin and Matas, “All you need is a good init”. 2016. https://arxiv.org/abs/1511.06422

mhcflurry.data_dependent_weights_initialization.svd_orthonormal(shape)[source]

Generate an orthonormal matrix using SVD.

Parameters:
shapetuple

Shape of the weight matrix (must have at least 2 dimensions)

Returns:
numpy.ndarray

Orthonormal matrix of the given shape

mhcflurry.data_dependent_weights_initialization.get_activations_pytorch(model, layer_name, x_dict, device=None, target='post_activation')[source]

Get activations from a specific layer in a PyTorch model.

Parameters:
modelnn.Module

PyTorch model

layer_namestr

Name of the layer to get activations from

x_dictdict

Input dictionary with tensors

devicetorch.device, optional

Device to run on

target{“post_activation”, “pre_activation”}

Which affine-layer output to return. Historical Keras LSUV used the post-activation Dense output.

Returns:
numpy.ndarray

Activations from the specified layer

mhcflurry.data_dependent_weights_initialization.get_activations(model, layer, X_batch)[source]

Backward-compatible activation helper from the TF backend era.

Parameters:
modelnn.Module
layerstr or object with name attribute
X_batchdict

Network input dictionary.

mhcflurry.data_dependent_weights_initialization.lsuv_init(model, batch, verbose=True, margin=0.1, max_iter=100, target='post_activation')[source]

Initialize neural network weights using layer-sequential unit-variance initialization.

See:

Mishkin and Matas, “All you need is a good init”. 2016. https://arxiv.org/abs/1511.06422

Parameters:
modelnn.Module

PyTorch model

batchdict

Training data batch (dict of numpy arrays or tensors)

verboseboolean

Whether to print progress to stdout

marginfloat

Acceptable variance margin

max_iterint

Maximum iterations per layer

target{“post_activation”, “pre_activation”}

Activation boundary whose variance LSUV normalizes.

Returns:
nn.Module

Same model, modified in-place

mhcflurry.device_footprint module

Measurement-driven per-worker GPU memory estimates.

The orchestrator decides how many workers to pack on each GPU from a per-worker VRAM estimate (device_worker_gb). Historically that was a static constant in the workload profile (e.g. 24 GB for calibration, 4 GB for training) — a value hand-tuned for one production config that is wrong for jobs / networks of other sizes. This module estimates it instead, from the model architecture (read from manifest.csv — no weights) and the job size, so the worker count adapts.

Every estimator returns None whenever it can’t read the model or lacks the job size, so the planner falls back to the static profile default. Estimates are deliberately conservative (a safety multiplier + a floor) so we never pack more aggressively than the validated baseline.

The per-row resident formulas track the genuinely-varying terms: full dataset / peptide-universe row count, the peptide encoding dims (max_length x feature width, which differ by vector_encoding_name — BLOSUM62=21, physchem/atchley/composite encodings differ), network width, ensemble size, and batch size.

mhcflurry.device_footprint.estimate_affinity_calibration_device_worker_gb(models_dir, prediction_rows)[source]

Per-worker VRAM (GB) for affinity percentile-rank calibration, or None.

Dominant consumer: the cached peptide-stage tensor (peptide-side activations precomputed for the whole peptide universe and reused across allele batches), ~ num_networks x stage_dim x num_peptides x 4.

mhcflurry.device_footprint.estimate_affinity_training_device_worker_gb(hyperparameters, num_rows, minibatch_size=None)[source]

Per-worker VRAM (GB) for device-resident affinity training, or None.

Takes the hyperparameters dict directly (the model doesn’t exist yet at training time — it’s read from the hyperparameters YAML the command loaded).

Peptides are stored device-resident as compact (N, L) int8 indices (default) and embedded per-batch, so unlike calibration the footprint is NOT dominated by the dataset — it is dominated by a fixed base plus per-batch activations. The terms:

  • resident dataset: rn_factor x rows x (peptide_index_bytes + scalars) — tiny at normal scale (int8), only material at extreme row counts.

  • per-batch activations: minibatch x (embedded_peptide + merge_width) x 4 x backward_factor — the live batch’s float32 embedded vectors and hidden activations. This is what scales with batch size / network width.

  • a fixed base (CUDA context + compile workspace + weights + optimizer + embedding table) that does not scale with either.

Forward-only validation is intentionally absent: its batch is selected at runtime from the same live per-worker budget as inference, after the fixed tensors represented here have been allocated.

A safety multiplier and a floor keep it conservative.

mhcflurry.device_footprint.estimate_device_worker_gb(workload_name, hints, models_dir=None)[source]

Unified per-worker VRAM (GB) estimate, or None to use the profile default.

Dispatches per workload. hints is a dict that may carry:
  • calibration: prediction_rows (+ models_dir for the trained model).

  • training: training_rows, hyperparameters (the model isn’t trained yet, so the architecture comes from the hyperparameters dict), minibatch_size.

mhcflurry.dla_evaluation module

Reproduce the exploratory DLA audit of Kaabinejadian et al. (PMID 42199926).

mhcflurry.dla_evaluation.prepare_observations(supplements_dir)[source]

Read checksum-pinned original sheets; retain source rows and all lengths.

Requires the optional openpyxl Excel reader. No workbook is modified. Lola’s two antibody captures retain one biological sample identity. All HCT116 transductants share their parental biological sample identity.

mhcflurry.dla_evaluation.peptide_overlap(cohort, source_paths)[source]

Audit all source rows/alleles/labels against exact and I/L-folded strings.

The returned row flags do not assert common study, donor or peptide–MHC identity. Absence from these tables cannot certify complete lineage.

mhcflurry.dla_evaluation.observation_diagnostics(frame)[source]

Report lengths and empirical 9-mer residue counts per capture.

Residue counts are descriptive motifs, without alignment or a background enrichment claim. Tumor motifs remain unassigned to individual alleles.

mhcflurry.dla_evaluation.score_observations(predictor, frame)[source]

Score fixed observations without inventing negatives or restrictions.

Binding is the predicted minimum IC50 across a sample’s stated genotype. The winning allele is explicitly a prediction. All genotype alleles must be supported; unsupported lengths/identities remain missing with reasons. Processing uses no flanks, because these observation sheets do not resolve protein mappings sufficiently to select unique source flanks.

mhcflurry.dla_evaluation.score_summary(scored, seed=490, bootstrap_replicates=2000)[source]

Summarize exploratory scores; bootstrap canine donors, never peptides.

Lola antibody captures are deduplicated within donor. Confidence intervals describe the mean of donor medians, not accuracy or canine calibration. There is no independent biological replicate for each monoallelic arm.

mhcflurry.dla_evaluation.evaluate_dla(models_dir, supplements_dir, out_dir)[source]

Write a frozen, conservative historical-bundle canine evaluation.

Parameters:
models_dirstr or pathlib.Path

Frozen presentation bundle to evaluate, without changing its weights.

supplements_dirstr or pathlib.Path

Original mmc2.xlsx through mmc7.xlsx from PMID 42199926.

out_dirstr or pathlib.Path

New output directory for observations, scores, evidence and sample audit.

Returns:
dict

Exploratory report. Historical bundled training tables alone never establish complete lineage; this recipe cannot certify a holdout.

mhcflurry.dla_evaluation.run_argv(argv, prog='mhcflurry eval dla')[source]

Run the checksum-pinned 2026 DLA observation audit.

mhcflurry.downloads module

Manage local downloaded data.

mhcflurry.downloads.get_downloads_dir(release=None)[source]

Return the download directory for a release, respecting custom overrides.

mhcflurry.downloads.get_current_release()[source]

Return the current downloaded data release

mhcflurry.downloads.get_downloads_metadata()[source]

Return the contents of downloads.yml as a dict

mhcflurry.downloads.resolve_release(release=None)[source]

Validate a catalogue identifier, defaulting to the configured release.

mhcflurry.downloads.get_download_urls(metadata)[source]

Return ordered archive URLs, including every part of split downloads.

mhcflurry.downloads.get_bundle_description(name)[source]

Return the purpose and category of a named download.

mhcflurry.downloads.get_bundle_versions(name)[source]

Group catalogue entries for one bundle by identical archive URLs.

URL equality identifies shared sources, not verified content equality.

mhcflurry.downloads.get_model_release_dir(release)[source]

Resolve explicitly selected presentation weights without model imports.

Explicit selection overrides default-model environment variables. Custom, unversioned download roots must record matching source URLs so a release selector cannot silently load a different set of weights.

mhcflurry.downloads.get_default_class1_models_dir(test_exists=True)[source]

Return the absolute path to the default class1 models dir.

If environment variable MHCFLURRY_DEFAULT_CLASS1_MODELS is set to an absolute path, return that path. If it’s set to a relative path (i.e. does not start with /) then return that path taken to be relative to the mhcflurry downloads dir.

If environment variable MHCFLURRY_DEFAULT_CLASS1_MODELS is NOT set, then return the pan-allele affinity path in the “models_class1_pan” download.

Parameters:
test_existsboolean, optional

Whether to raise an exception if the path does not exist

Returns:
stringabsolute path
mhcflurry.downloads.get_default_class1_presentation_models_dir(test_exists=True)[source]

Return the absolute path to the default class1 presentation models dir.

See get_default_class1_models_dir.

If environment variable MHCFLURRY_DEFAULT_CLASS1_PRESENTATION_MODELS_DIR is set to an absolute path, return that path. If it’s set to a relative path (does not start with /) then return that path taken to be relative to the mhcflurry downloads dir.

Parameters:
test_existsboolean, optional

Whether to raise an exception if the path does not exist

Returns:
stringabsolute path
mhcflurry.downloads.get_default_class1_processing_models_dir(test_exists=True)[source]

Return the absolute path to the default class1 processing models dir.

See get_default_class1_models_dir.

If environment variable MHCFLURRY_DEFAULT_CLASS1_PROCESSING_MODELS_DIR is set to an absolute path, return that path. If it’s set to a relative path (does not start with /) then return that path taken to be relative to the mhcflurry downloads dir.

Parameters:
test_existsboolean, optional

Whether to raise an exception if the path does not exist

Returns:
stringabsolute path
mhcflurry.downloads.get_release_downloads(release)[source]

Return a dict of all available downloads in a release.

Parameters:
releasestring

Release whose download metadata to return.

Returns:
collections.OrderedDict

Download names mapped to dictionaries with three entries: downloaded (bool), whether the local directory exists; metadata (dict), catalogue metadata such as URLs; and up_to_date (bool or None), whether the recorded download URLs match the catalogue, or None when unknown. This does not verify the integrity of installed files.

mhcflurry.downloads.get_current_release_downloads()[source]

Return a dict of all available downloads in the current release.

mhcflurry.downloads.get_path(download_name, filename='', test_exists=True, release=None)[source]

Get the local path to a file in a MHCflurry download

Parameters:
download_namestring
filenamestring

Relative path within the download to the file of interest

test_existsboolean

If True (default) throw an error telling the user how to download the data if the file does not exist

releasestring, optional

Requested release; defaults to the configured current release.

Returns:
string giving local absolute path
mhcflurry.downloads.configure()[source]

Setup various global variables based on environment variables.

mhcflurry.downloads_command module

Compatibility wrapper for mhcflurry.cli.downloads_command.

mhcflurry.downloads_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.encodable_sequences module

Class for encoding variable-length peptides to fixed-size numerical matrices

exception mhcflurry.encodable_sequences.EncodingError(message, supported_peptide_lengths)[source]

Bases: ValueError

Exception raised when peptides cannot be encoded

class mhcflurry.encodable_sequences.EncodableSequences(sequences)[source]

Bases: object

Class for encoding variable-length peptides to fixed-size numerical matrices

This class caches various encodings of a list of sequences.

In practice this is used only for peptides. To encode MHC allele sequences, see AlleleEncoding.

unknown_character = 'X'
classmethod create(sequences)[source]

Factory that returns an EncodableSequences given a list of strings. As a convenience, you can also pass it an EncodableSequences instance, in which case the object is returned unchanged.

variable_length_to_fixed_length_categorical(alignment_method='pad_middle', left_edge=4, right_edge=4, max_length=15, trim=False, allow_unsupported_amino_acids=False)[source]

Encode variable-length sequences to a fixed-size index-encoded (integer) matrix.

See sequences_to_fixed_length_index_encoded_array for details.

Parameters:
alignment_methodstring

One of “pad_middle”, “left_pad_right_pad”, “left_pad_centered_right_pad”, “left_pad”, or “right_pad”

left_edgeint, size of fixed-position left side

Only relevant for pad_middle alignment method

right_edgeint, size of the fixed-position right side

Only relevant for pad_middle alignment method

max_lengthmaximum supported peptide length
trimbool

If True, longer sequences will be trimmed to fit the maximum supported length. Not supported for all alignment methods.

allow_unsupported_amino_acidsbool

If True, non-canonical amino acids will be replaced with the X character before encoding.

Returns:
numpy.array of integers with shape (num sequences, encoded length)
For pad_middle, left_pad and right_pad, the encoded length is max_length.
For left_pad_right_pad it is 2 * max_length; for
left_pad_centered_right_pad it is 3 * max_length.
variable_length_to_fixed_length_vector_encoding(vector_encoding_name, alignment_method='pad_middle', left_edge=4, right_edge=4, max_length=15, trim=False, allow_unsupported_amino_acids=False)[source]

Encode variable-length sequences to a fixed-size matrix. Amino acids are encoded as specified by the vector_encoding_name argument.

DEPRECATED (scheduled for removal): the dense (N, L, V) peptide/ sequence vector path has been retired — models always index-encode peptides ((N, L) int8) and embed on device. This method has no production caller; it is retained only for benchmark/encoding-cache tests and will be removed once those migrate to the categorical path. Use variable_length_to_fixed_length_categorical instead.

See sequences_to_fixed_length_index_encoded_array for details.

See also: variable_length_to_fixed_length_categorical.

Parameters:
vector_encoding_namestring

How to represent amino acids. Registered names include “BLOSUM62”, “one-hot”, “PMBEC”, “contact”, “physchem”, and “atchley”; +-joined composites such as “BLOSUM62+physchem” are also accepted. Add the :minmax suffix to a component to scale its non-X values to [-1, 1], for example “PMBEC:minmax+contact:minmax”.

alignment_methodstring

One of “pad_middle”, “left_pad_right_pad”, “left_pad_centered_right_pad”, “left_pad”, or “right_pad”

left_edgeint

Size of fixed-position left side. Only relevant for pad_middle alignment method

right_edgeint

Size of the fixed-position right side. Only relevant for pad_middle alignment method

max_lengthint

Maximum supported peptide length

trimbool

If True, longer sequences will be trimmed to fit the maximum supported length. Not supported for all alignment methods.

allow_unsupported_amino_acidsbool

If True, non-canonical amino acids will be replaced with the X character before encoding.

Returns:
numpy.array with shape (num sequences, encoded length, m)
where
  • m is the vector encoding length (usually 21).

  • encoded length is max_length if alignment_method is pad_middle; 2 * max_length for left_pad_right_pad and 3 * max_length for left_pad_centered_right_pad; left_pad/right_pad use max_length.

classmethod sequences_to_fixed_length_index_encoded_array(sequences, alignment_method='pad_middle', left_edge=4, right_edge=4, max_length=15, trim=False, allow_unsupported_amino_acids=False)[source]

Encode variable-length sequences to a fixed-size index-encoded (integer) matrix.

How variable length sequences get mapped to fixed length is set by the “alignment_method” argument. Supported alignment methods are:

pad_middle

Encoding designed for preserving the anchor positions of class I peptides. This is what is used in allele-specific models.

Each string must be of length at least left_edge + right_edge and at most max_length. The first left_edge characters in the input always map to the first left_edge characters in the output. Similarly for the last right_edge characters. The middle characters are filled in based on the length, with the X character filling in the blanks.

Example:

AAAACDDDD -> AAAAXXXCXXXDDDD

left_pad_centered_right_pad

Encoding that makes no assumptions on anchor positions but is 3x larger than pad_middle, since it duplicates the peptide (left aligned + centered + right aligned). This is what is used for the pan-allele models.

Example:

AAAACDDDD -> AAAACDDDDXXXXXXXXXAAAACDDDDXXXXXXXXXAAAACDDDD

left_pad_right_pad

Same as left_pad_centered_right_pad but only includes left- and right-padded peptide.

Example:

AAAACDDDD -> AAAACDDDDXXXXXXXXXXXXAAAACDDDD

Parameters:
sequenceslist of string
alignment_methodstring

One of “pad_middle”, “left_pad_right_pad”, “left_pad_centered_right_pad”, “left_pad”, or “right_pad”

left_edgeint

Size of fixed-position left side. Only relevant for pad_middle alignment method

right_edgeint

Size of the fixed-position right side. Only relevant for pad_middle alignment method

max_lengthint

maximum supported peptide length

trimbool

If True, longer sequences will be trimmed to fit the maximum supported length. Not supported for all alignment methods.

allow_unsupported_amino_acidsbool

If True, non-canonical amino acids will be replaced with the X character before encoding.

Returns:
numpy.array of integers with shape (num sequences, encoded length)
For pad_middle, the encoded length is max_length. For left_pad_right_pad,
it’s 2 * max_length. For left_pad_centered_right_pad, it’s
3 * max_length.

mhcflurry.ensemble_centrality module

Measures of centrality (e.g. mean) used to combine predictions across an ensemble. The input to these functions are log affinities, and they are expected to return a centrality measure also in log-space.

mhcflurry.ensemble_centrality.robust_mean(log_values)[source]

Mean of values falling within the 25-75 percentiles.

Parameters:
log_values2-d numpy.array

Center is computed along the second axis (i.e. per row).

Returns:
centernumpy.array of length log_values.shape[0]

mhcflurry.experiment_archive module

Create portable, plot-reconstructable snapshots of training experiments.

mhcflurry.experiment_archive.sha256_file(path, chunk_size=1048576)[source]

Return the SHA256 digest of path without loading it into memory.

mhcflurry.experiment_archive.export_training_tables(source_dir, out_dir)[source]

Export normalized model, fit, and per-epoch tables from manifests.

The source manifests remain authoritative. These tables deliberately omit serialized network graphs and weights so ordinary plotting and audit code can consume the histories without loading model implementations.

mhcflurry.experiment_archive.snapshot_experiment(source_dir, experiments_dir, name, *, source_commit=None, collector_commit=None, source_archive=None, command_files=(), input_files=(), captured_at=None, max_copy_bytes=67108864)[source]

Create and return one immutable timestamped experiment snapshot.

mhcflurry.fasta module

Adapted from pyensembl, github.com/openvax/pyensembl Original implementation by Alex Rubinsteyn.

The worse sin in bioinformatics is to write your own FASTA parser. We’re doing this to avoid adding another dependency to MHCflurry, however.

mhcflurry.fasta.read_fasta_to_dataframe(filename, full_descriptions=False)[source]

Parse a fasta file to a pandas DataFrame.

Parameters:
filenamestring
full_descriptionsbool

If true, instead of returning sequence IDs (the first space-separated token), return the full description associated with each record.

Returns
——-
pandas.DataFrame with columns “sequence_id” and “sequence”.
class mhcflurry.fasta.FastaParser[source]

Bases: object

FastaParser object consumes lines of a FASTA file incrementally.

iterate_over_file(fasta_path, full_descriptions=False)[source]

Generator that yields identifiers paired with sequences.

static open_file(fasta_path)[source]

Open either a text file or compressed gzip file as a stream of bytes.

mhcflurry.flanking_encoding module

Class for encoding variable-length flanking and peptides to fixed-size numerical matrices

class mhcflurry.flanking_encoding.EncodingResult(array, peptide_lengths, unsupported_mask)

Bases: tuple

Create new instance of EncodingResult(array, peptide_lengths, unsupported_mask)

array

Alias for field number 0

peptide_lengths

Alias for field number 1

unsupported_mask

Alias for field number 2

class mhcflurry.flanking_encoding.FlankingEncoding(peptides, n_flanks, c_flanks)[source]

Bases: object

Encode peptides and optionally their N- and C-flanking sequences into fixed size numerical matrices. Similar to EncodableSequences but with support for flanking sequences and the encoding scheme used by the processing predictor.

Instances of this class have an immutable list of peptides with flanking sequences. Encodings are cached in the instances for faster performance when the same set of peptides needs to be encoded more than once.

Constructor. Sequences of any lengths can be passed.

Parameters:
peptideslist of string

Peptide sequences

n_flankslist of string [same length as peptides]

Upstream sequences

c_flankslist of string [same length as peptides]

Downstream sequences

unknown_character = 'X'
clear_tensor_cache()[source]

Release cached torch tensors held by this encoding.

vector_encode(vector_encoding_name, peptide_max_length, n_flank_length, c_flank_length, allow_unsupported_amino_acids=True, throw=True)[source]

Encode variable-length sequences to a fixed-size dense matrix.

DEPRECATED (scheduled for removal): the processing model always index-encodes sequences ((N, L) int8) and embeds on device. This dense (N, L, V) encoder has no remaining caller — use categorical_encode (or categorical_encode_tensors) instead.

Parameters:
vector_encoding_namestring

How to represent amino acids. One of “BLOSUM62”, “one-hot”, etc. See amino_acid.available_vector_encodings().

peptide_max_lengthint

Maximum supported peptide length.

n_flank_lengthint

Maximum supported N-flank length

c_flank_lengthint

Maximum supported C-flank length

allow_unsupported_amino_acidsbool

If True, non-canonical amino acids will be replaced with the X character before encoding.

throwbool

Whether to raise exception on unsupported peptides

Returns:
numpy.array with shape (num sequences, length, m)
where
  • num sequences is number of peptides, i.e. len(self)

  • length is peptide_max_length + n_flank_length + c_flank_length

  • m is the vector encoding length (usually 21).

categorical_encode(peptide_max_length, n_flank_length, c_flank_length, allow_unsupported_amino_acids=True, throw=True)[source]

Encode variable-length sequences to fixed-size amino-acid indices.

This mirrors vector_encode() but stops before expanding amino acids to dense vector encodings. The resulting integer array is suited for torch-side embedding lookup.

categorical_encode_tensors(peptide_max_length, n_flank_length, c_flank_length, device, allow_unsupported_amino_acids=True, throw=True)[source]

Encode variable-length sequences to cached torch tensors.

The CPU numpy encoding remains the source of truth. This method keeps a device-resident view/copy keyed by encoding parameters and device so repeated processing models can slice the same tensors without per-batch host-to-device transfers.

static encode_indices(df, peptide_max_length, n_flank_length, c_flank_length, allow_unsupported_amino_acids=False, throw=True)[source]

Encode variable-length sequences to fixed-size amino-acid indices.

static encode(vector_encoding_name, df, peptide_max_length, n_flank_length, c_flank_length, allow_unsupported_amino_acids=False, throw=True)[source]

Encode variable-length sequences to a fixed-size matrix.

Helper function. Users should use vector_encode.

Parameters:
vector_encoding_namestring
dfpandas.DataFrame
peptide_max_lengthint
n_flank_lengthint
c_flank_lengthint
allow_unsupported_amino_acidsbool
throwbool
Returns:
numpy.array

mhcflurry.histogram_percent_rank_transform module

Class for transforming arbitrary values into percent ranks given a distribution.

class mhcflurry.histogram_percent_rank_transform.HistogramPercentRankTransform[source]

Bases: object

Historical histogram-based CDF lookup, with preserved bin semantics.

The old PercentRankTransform name remains an alias. New predictor calibration defaults to CompactPercentRankTransform; use this class for saved-table compatibility or explicitly selected histogram calibration. Distinct raw scores can share one step value. Use survival=True for upper-tail percentiles, as required by processing/presentation predictors.

fit(values, bins)[source]

Fit the transform using the given values (e.g. ic50s).

Parameters:
valuespredictions (e.g. ic50 values)
binsbins for the cumulative distribution function

Anything that can be passed to numpy.histogram’s “bins” argument can be used here.

Returns:
HistogramPercentRankTransform

This fitted instance. Fit a fresh instance for each distribution.

classmethod fit_batch_torch(values_2d, bin_edges_1d)[source]

Batched GPU fit across multiple distributions.

Equivalent to calling fit(values_2d[i], bins=bin_edges_1d) for each row i, but vectorized across the row dim — eliminates the per-allele Python loop in calibrate’s hot path. Rows with no values inside the bin range are invalid and raise instead of fabricating an empty CDF.

Parameters:
values_2dtorch.Tensor of shape (n_distributions, n_values).

Stays on whatever device it’s on; histogram bucketing happens there.

bin_edges_1dtorch.Tensor of shape (n_edges,), monotonically

increasing. Same device as values_2d.

Returns:
list of HistogramPercentRankTransform

One transform per input distribution.

Numerically equivalent to the per-row numpy.histogram path
(matching to ≤1e-12, not bit-for-bit – division/cumsum ordering on
CUDA drifts in the last ULPs, far below bin resolution): same bin
assignment (right-open intervals, last bin inclusive), same CDF
normalization (% out of in-range count), and an identical cdf
array layout (length n_bins+3, sentinels at [0]=[1]=0, [-1]=100,
cumsum in [2:-1]).
transform(values, survival=False)[source]

Return percent ranks (range [0, 100]) for the given values.

Parameters:
valuessequence of float

Raw scores. Input NaNs become output NaNs.

survivalbool, default False

False returns the historical CDF lookup. True returns 100 minus that lookup, retaining the historical upper-tail behavior.

Returns:
numpy.ndarray

Percentiles using the saved histogram, without interpolation.

to_dict()[source]

Serialize without the NaN sentinels used in the historical CSV index.

classmethod from_dict(values)[source]

Restore a versioned histogram transform.

to_series()[source]

Serialize the fit to a pandas.Series.

The index on the series gives the bin edges and the values give the CDF.

Returns:
pandas.Series
static from_series(series)[source]

Deserialize a histogram transform from a pandas.Series, as returned by to_series().

Parameters:
seriespandas.Series
Returns:
HistogramPercentRankTransform

mhcflurry.hyperparameters module

Hyperparameter (neural network options) management

class mhcflurry.hyperparameters.HyperparameterDefaults(**defaults)[source]

Bases: object

Class for managing hyperparameters. Thin wrapper around a dict.

Instances of this class are a specification of the hyperparameters supported by a model and their defaults. The particular hyperparameter settings to be used, for example, to train a model are kept in plain dicts.

extend(other)[source]

Return a new HyperparameterDefaults instance containing the hyperparameters from the current instance combined with those from other.

It is an error if self and other have any hyperparameters in common.

with_defaults(obj)[source]

Given a dict of hyperparameter settings, return a dict containing those settings augmented by the defaults for any keys missing from the dict.

subselect(obj)[source]

Filter a dict of hyperparameter settings to only those keys defined in this HyperparameterDefaults .

check_valid_keys(obj)[source]

Given a dict of hyperparameter settings, throw an exception if any keys are not defined in this HyperparameterDefaults instance.

models_grid(**kwargs)[source]

Make a grid of models by taking the cartesian product of all specified model parameter lists.

Parameters:
The valid kwarg parameters are the entries of this
HyperparameterDefaults instance. Each parameter must be a list
giving the values to search across.
Returns:
list of dict giving the parameters for each model. The length of the
list is the product of the lengths of the input lists.

mhcflurry.keras_optimizers module

PyTorch optimizers implementing the historical Keras update equations.

class mhcflurry.keras_optimizers.KerasRMSprop(params, lr=0.001, rho=0.9, epsilon=1e-07)[source]

Bases: Optimizer

RMSprop with Keras’ sqrt(velocity + epsilon) denominator.

step(closure=None)[source]

Perform one Keras-compatible RMSprop update.

class mhcflurry.keras_optimizers.KerasAdam(params, lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-07)[source]

Bases: Optimizer

Adam with Keras’ non-adaptive epsilon placement.

step(closure=None)[source]

Perform one Keras-compatible Adam update.

mhcflurry.memory_budget module

Shared memory-budget calculations for training and inference.

Launch-time worker packing and runtime batch sizing must use the same budget. Otherwise each layer can independently claim the same free memory and a plan that looks conservative on paper can still OOM. This module is deliberately free of torch imports so the parent process can size a spawn/fork worker pool without initializing CUDA.

mhcflurry.memory_budget.memory_reserve_bytes(available_bytes, *, min_reserve_bytes=1073741824, reserve_fraction=0.1)[source]

Return the shared reserve to leave outside an automatic plan.

mhcflurry.memory_budget.usable_memory_bytes(available_bytes, *, min_reserve_bytes=1073741824, reserve_fraction=0.1)[source]

Memory an automatic plan may spend after the shared reserve.

mhcflurry.memory_budget.per_worker_memory_budget_bytes(available_bytes, num_workers, *, min_reserve_bytes=1073741824, reserve_fraction=0.1)[source]

Split usable memory evenly between co-resident workers.

mhcflurry.memory_budget.memory_worker_capacity(available_gb, per_worker_gb, *, min_reserve_bytes=1073741824, reserve_fraction=0.1)[source]

Return how many complete worker working sets fit in available memory.

At least one worker is returned: a caller with a GPU should attempt one worker and let its normal preflight produce the detailed undersized-device warning. There is intentionally no default performance hard cap here.

mhcflurry.memory_budget.module_tensor_bytes(module)[source]

Return unique parameter and buffer bytes for a torch-like module.

mhcflurry.memory_budget.training_module_bytes(module, optimizer_state_copies=2)[source]

Estimate model, gradient, and optimizer-state bytes for training.

Parameters and buffers are counted exactly. Trainable parameters also need one gradient tensor and, for Adam/RMSProp-like optimizers, one or more parameter-sized state tensors. The caller supplies that state count.

mhcflurry.model_provenance module

Release provenance fields embedded in trained model metadata.

mhcflurry.model_provenance.add_release_provenance(rows, environ=environ({'JAVA_HOME': '/usr/lib/jvm/temurin-17-jdk-amd64', 'GHCUP_INSTALL_BASE_PREFIX': '/usr/local', 'MEMORY_PRESSURE_WRITE': 'c29tZSAyMDAwMDAgMjAwMDAwMAA=', 'RUNNER_NAME': 'GitHub Actions 1000032570', 'GITHUB_REF_NAME': 'master', 'ACCEPT_EULA': 'Y', 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE': '1', 'GITHUB_ENV': '/home/runner/work/_temp/_runner_file_commands/set_env_77245a0d-5174-43fd-aebc-80d1f81c5752', 'GITHUB_REPOSITORY_ID': '38223600', 'RUNNER_TRACKING_ID': 'github_ff5f8ed4-a9b7-42c0-ad64-008e6a407f8e', 'ACTIONS_RUNNER_RETURN_JOB_RESULT_FOR_HOSTED': '1', 'NVM_DIR': '/home/runner/.nvm', 'GITHUB_REPOSITORY_OWNER': 'openvax', 'JAVA_HOME_17_X64': '/usr/lib/jvm/temurin-17-jdk-amd64', 'GITHUB_EVENT_NAME': 'push', 'SGX_AESM_ADDR': '1', 'PWD': '/home/runner/work/mhcflurry/mhcflurry', 'GITHUB_ACTION_REPOSITORY': '', 'RUNNER_WORKSPACE': '/home/runner/work/mhcflurry', 'GITHUB_WORKFLOW_SHA': '7989643184e0ffb4c6ce5f946c578289e30096f3', 'RUNNER_OS': 'Linux', 'ACTIONS_ORCHESTRATION_ID': '8ba3e5d9-79bf-8b06-8016-05bd4c660bf0.build.__default', 'EDGEWEBDRIVER': '/usr/local/share/edge_driver', 'CI': 'true', 'LANG': 'C.UTF-8', 'RUNNER_TEMP': '/home/runner/work/_temp', 'ENABLE_RUNNER_TRACING': 'true', 'GITHUB_SERVER_URL': 'https://github.com', 'GITHUB_API_URL': 'https://api.github.com', 'MEMORY_PRESSURE_WATCH': '/sys/fs/cgroup/system.slice/hosted-compute-agent.service/memory.pressure', 'MAKEFLAGS': 'w -- SPHINXOPTS=-W', 'CHROME_BIN': '/usr/bin/google-chrome', 'PKG_CONFIG_PATH': '/opt/hostedtoolcache/Python/3.11.17/x64/lib/pkgconfig', 'Python2_ROOT_DIR': '/opt/hostedtoolcache/Python/3.11.17/x64', 'GITHUB_SHA': '7989643184e0ffb4c6ce5f946c578289e30096f3', 'ANDROID_NDK_HOME': '/usr/local/lib/android/sdk/ndk/27.3.13750724', 'GITHUB_ACTOR_ID': '48441', 'POWERSHELL_DISTRIBUTION_CHANNEL': 'GitHub-Actions-Linux', 'SELENIUM_JAR_PATH': '/usr/share/java/selenium-server.jar', 'pythonLocation': '/opt/hostedtoolcache/Python/3.11.17/x64', 'MFLAGS': '-w', 'GOROOT_1_24_X64': '/opt/hostedtoolcache/go/1.24.13/x64', 'PSModulePath': '/root/.local/share/powershell/Modules:/usr/local/share/powershell/Modules:/opt/microsoft/powershell/7/Modules:/usr/share/az_15.6.1', 'GITHUB_ARTIFACTS': '/home/runner/work/_temp/_runner_file_commands/artifacts_77245a0d-5174-43fd-aebc-80d1f81c5752', 'ANDROID_NDK_LATEST_HOME': '/usr/local/lib/android/sdk/ndk/30.0.16248370', 'BOOTSTRAP_HASKELL_NONINTERACTIVE': '1', 'JAVA_HOME_8_X64': '/usr/lib/jvm/temurin-8-jdk-amd64', 'PIPX_HOME': '/opt/pipx', 'GITHUB_RUN_ATTEMPT': '1', 'GITHUB_TRIGGERING_ACTOR': 'iskandr', 'DOTNET_NOLOGO': '1', 'DOTNET_MULTILEVEL_LOOKUP': '0', 'JAVA_HOME_11_X64': '/usr/lib/jvm/temurin-11-jdk-amd64', 'GOROOT_1_26_X64': '/opt/hostedtoolcache/go/1.26.8/x64', 'GITHUB_REF': 'refs/heads/master', 'GITHUB_RUN_NUMBER': '129', 'Python3_ROOT_DIR': '/opt/hostedtoolcache/Python/3.11.17/x64', 'ANDROID_SDK_ROOT': '/usr/local/lib/android/sdk', 'GITHUB_JOB': 'build', 'ANDROID_HOME': '/usr/local/lib/android/sdk', 'SHELL': '/bin/bash', 'LD_LIBRARY_PATH': '/opt/hostedtoolcache/Python/3.11.17/x64/lib', 'GITHUB_STATE': '/home/runner/work/_temp/_runner_file_commands/save_state_77245a0d-5174-43fd-aebc-80d1f81c5752', 'SHLVL': '1', 'ANDROID_NDK': '/usr/local/lib/android/sdk/ndk/27.3.13750724', 'ImageVersion': '20261004.327.1', 'PATH': '/opt/hostedtoolcache/Python/3.11.17/x64/bin:/opt/hostedtoolcache/Python/3.11.17/x64:/snap/bin:/home/runner/.local/bin:/opt/pipx_bin:/home/runner/.cargo/bin:/home/runner/.config/composer/vendor/bin:/usr/local/.ghcup/bin:/home/runner/.dotnet/tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin', 'GITHUB_EVENT_PATH': '/home/runner/work/_temp/_github_workflow/event.json', 'GRADLE_HOME': '/usr/share/gradle-9.8.0', 'GITHUB_RETENTION_DAYS': '90', 'XDG_CONFIG_HOME': '/home/runner/.config', 'INVOCATION_ID': '98f929a49e004931af43ce1cca20286b', 'GITHUB_ACTIONS': 'true', 'GITHUB_WORKFLOW_REF': 'openvax/mhcflurry/.github/workflows/docs.yml@refs/heads/master', 'CONDA': '/usr/share/miniconda', 'GITHUB_HEAD_REF': '', 'CHROMEWEBDRIVER': '/usr/local/share/chromedriver-linux64', 'PIPX_BIN_DIR': '/opt/pipx_bin', 'GITHUB_REF_PROTECTED': 'false', 'GITHUB_REF_TYPE': 'branch', 'LOGNAME': 'runner', 'GECKOWEBDRIVER': '/usr/local/share/gecko_driver', 'HCA_CLOUD_PROVIDER': 'azure', 'SYSTEMD_EXEC_PID': '2110', 'GITHUB_ACTION_REF': '', 'GITHUB_WORKSPACE': '/home/runner/work/mhcflurry/mhcflurry', 'USER': 'runner', 'SWIFT_PATH': '/usr/share/swift/usr/bin', 'MAKEOVERRIDES': '${-*-command-variables-*-}', 'SPHINXOPTS': '-W', 'GITHUB_STEP_SUMMARY': '/home/runner/work/_temp/_runner_file_commands/step_summary_77245a0d-5174-43fd-aebc-80d1f81c5752', 'RUNNER_ARCH': 'X64', 'GITHUB_PATH': '/home/runner/work/_temp/_runner_file_commands/add_path_77245a0d-5174-43fd-aebc-80d1f81c5752', 'RUNNER_TOOL_CACHE': '/opt/hostedtoolcache', '_': '/usr/bin/make', 'ANDROID_NDK_ROOT': '/usr/local/lib/android/sdk/ndk/27.3.13750724', 'XDG_RUNTIME_DIR': '/run/user/1001', 'JAVA_HOME_25_X64': '/usr/lib/jvm/temurin-25-jdk-amd64', 'AGENT_TOOLSDIRECTORY': '/opt/hostedtoolcache', 'GITHUB_REPOSITORY': 'openvax/mhcflurry', 'VCPKG_INSTALLATION_ROOT': '/usr/local/share/vcpkg', 'JOURNAL_STREAM': '9:11934', 'GITHUB_ACTION': '__run_4', 'DEBIAN_FRONTEND': 'noninteractive', 'HOME': '/home/runner', 'GITHUB_GRAPHQL_URL': 'https://api.github.com/graphql', 'GITHUB_WORKFLOW': 'Documentation', 'GITHUB_RUN_ID': '38491316993', 'HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS': '3650', 'GITHUB_ACTOR': 'iskandr', 'ANT_HOME': '/usr/share/ant', 'ImageOS': 'ubuntu24', 'Python_ROOT_DIR': '/opt/hostedtoolcache/Python/3.11.17/x64', 'ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE': '/opt/actionarchivecache', 'GITHUB_OUTPUT': '/home/runner/work/_temp/_runner_file_commands/set_output_77245a0d-5174-43fd-aebc-80d1f81c5752', 'GITHUB_BASE_REF': '', 'USE_BAZEL_FALLBACK_VERSION': 'silent:', 'GITHUB_REPOSITORY_OWNER_ID': '33269729', 'AZURE_EXTENSION_DIR': '/opt/az/azcliextensions', 'GITHUB_ARTIFACTS_LIST': '/home/runner/work/_temp/_runner_file_commands/artifacts_list_77245a0d-5174-43fd-aebc-80d1f81c5752', 'RUNNER_ENVIRONMENT': 'github-hosted', 'GOROOT_1_25_X64': '/opt/hostedtoolcache/go/1.25.14/x64', 'HOMEBREW_NO_AUTO_UPDATE': '1', 'MHCFLURRY_DATA_DIR': '/home/runner/work/mhcflurry/mhcflurry/.mhcflurry-data', 'JAVA_HOME_21_X64': '/usr/lib/jvm/temurin-21-jdk-amd64', 'MHCFLURRY_DOWNLOADS_CURRENT_RELEASE': '', 'MAKELEVEL': '1', 'DOCUTILSCONFIG': '/home/runner/work/mhcflurry/mhcflurry/docs/docutils.conf', 'MKL_THREADING_LAYER': 'GNU', 'KMP_DUPLICATE_LIB_OK': 'True', 'KMP_INIT_AT_FORK': 'FALSE'}))[source]

Append release commit/workflow metadata when supplied by a launcher.

mhcflurry.motif_summary module

GPU motif-summary helpers used by the fast percentile-rank calibration path.

These are stateless tensor/numpy routines: given a chunk of predicted IC50s for a set of (allele, peptide) pairs, they reproduce the per-allele DataFrame(...).drop_duplicates().groupby('length').nsmallest(...) motif summary (top-binder amino-acid frequency matrices + length distributions) of the legacy slow path, but vectorized on the calibration device.

They live in their own module — rather than on Class1AffinityPredictor — because they hold no predictor state and are unit-tested in isolation (see test/test_calibrate_percentile_ranks_fast.py). The predictor only orchestrates: it builds the per-worker state once via prepare_motif_summary_state_gpu() and then calls motif_summary_chunk_gpu() per allele chunk.

mhcflurry.motif_summary.prepare_motif_summary_state_gpu(encoded_peptides, device)[source]

One-time setup for GPU motif_summary; lifts the per-allele drop_duplicates + length-bucket + AA-encoding work out of the calibrate chunk loop so each chunk is pure tensor math.

Returns:
dict

Device-resident tensors and their unique-peptide count:

  • unique_idx_t: (n_unique,) long first-occurrence indices into the full peptide list. Selecting columns from ic50_device reproduces drop_duplicates('peptide') semantics (first row wins).

  • length_groups: dict[L] of (n_at_L,) long indices into the unique peptide axis for peptides of length L.

  • aa_codes_per_length: dict[L] of (n_at_L, L) long tensors of amino acid index codes, matching AMINO_ACID_INDEX (X = 20).

  • unique_lengths_t: (n_unique,) long peptide lengths, used for the per-allele length distribution.

  • n_unique: integer count of unique peptides.

mhcflurry.motif_summary.topk_first_tie_indices(values, k)[source]

Return k smallest column indices per row with pandas tie semantics.

torch.topk is fast but does not promise which entries it returns when the kth value is tied. Pandas Series.nsmallest defaults to keep='first'; after drop_duplicates('peptide'), “first” means lower position on the unique-peptide axis. Keep the fast topk path for normal continuous predictions and repair only rows whose cutoff falls inside an exact tie block.

mhcflurry.motif_summary.motif_summary_chunk_gpu(ic50_device, state, summary_top_peptide_fractions, batch_alleles)[source]

GPU motif_summary for one allele chunk.

Replaces the per-allele DataFrame(...).drop_duplicates().groupby('length').nsmallest(...) block in the fast path with vectorized tensor ops:

  • torch.topk(largest=False) selects top-k tightest binders per (allele, length), with a small tie repair to match pandas nsmallest(keep='first') at exact cutoff ties.

  • AA frequency matrices are computed by gathering precomputed per-length AA-code tensors and scatter_add into a one-hot counts buffer of shape (a_size, L, 21); pandas only assembles the final per-row schema.

  • Length distributions are topk over the full unique-peptide axis followed by a per-row scatter_add (a row-wise bincount).

All math runs on the calibration device; per-batch .cpu() transfers happen once per (cutoff_fraction, length) at chunk-end instead of inside the per-allele Python loop, and pandas only stamps the persistent per-row schema on the consolidated per-block tensors. Returns (freq_matrix_dfs, length_dist_dfs) — lists of pandas.DataFrame matching the legacy slow path’s per-row schema, ready to pandas.concat once all chunks are done.

mhcflurry.numeric_proteome module

Reusable numeric processing candidates; strings are an export operation.

mhcflurry.numeric_proteome.sequence_keys(indices)[source]

Collision-free fixed-width numeric identity, including X padding.

class mhcflurry.numeric_proteome.ProcessingProteome(sequences)[source]

Bases: object

Encode source proteins once; sample numeric positions and gather on device.

CPU sampling preserves the historical eligible-window population and RNG stream when passed an equivalent numpy.random.RandomState. A device copy is created lazily by the scoring owner, never by CPU preparation threads.

raw_rows(proteins, starts, lengths)[source]

Gather CPU numeric identities for filtering without string creation.

gather(windows, device='cpu')[source]

Gather selected peptide rows into Torch directly from encoded proteins.

sample(accessions, length, n, excluded, rng)[source]

Draw n eligible windows without replacement, then deduplicate peptides.

Exhaustion returns the available population. As in the previous caller, duplicate sequences are removed after n position draws, keeping the first retained source position. No peptide/flank strings are constructed.

class mhcflurry.numeric_proteome.ProteinWindows(proteome: ProcessingProteome, proteins: ndarray, starts: ndarray, lengths: ndarray)[source]

Bases: object

Selected source positions with collision-free numeric peptide identities.

proteins, starts and lengths are equally sized one-dimensional integer arrays. Starts are zero-based; each window must fit its protein and have a length between one and MAX_PROCESSING_LENGTH.

proteome: ProcessingProteome
proteins: ndarray
starts: ndarray
lengths: ndarray
property keys
take(rows)[source]
classmethod concatenate(parts)[source]
to_frame(flank_length)[source]

Construct sequence/flank strings only when exporting scored artifacts.

class mhcflurry.numeric_proteome.NumericCandidatePool(hits, windows, sample, flank_length)[source]

Bases: object

Observed rows plus numeric negatives, ready for scoring then export.

prediction_input(device)[source]

Use the scoring owner’s device; no strings or host round trip.

with_scores(values)[source]

Export a scored pool in the established observed-then-decoy order.

mhcflurry.numeric_sequences module

String-free peptide inputs with the existing class-I alignment semantics.

class mhcflurry.numeric_sequences.NumericSequences(indices, lengths)[source]

Bases: object

Unaligned integer residue rows and actual lengths, on CPU or accelerator.

Parameters:
indicesarray-like or torch.Tensor

Shape (N, width); entries index AMINO_ACID_INDEX. Padding is ignored.

lengthsarray-like or torch.Tensor

N integer lengths between zero and width.

classmethod from_strings(sequences, width=None)[source]

Encode existing strings once, with vectorized ASCII lookup.

take(rows)[source]

Select a vector of integer row indices or a same-length boolean mask.

to_strings()[source]

Materialize strings for export or diagnostics, never for scoring.

aligned_tensor(peptide_encoding, device=None)[source]

Gather the exact categorical network input on the requested device.

mhcflurry.peptide_reference module

Helpers for matching observed peptides to reference proteins.

mhcflurry.peptide_reference.normalize_reference_dataframe(reference_df)[source]

Return reference proteins indexed by accession.

mhcflurry.peptide_reference.annotate_peptide_references(peptide_df, reference_df, flanking_length=15, debug_max_rows=None)[source]

Annotate peptides with matching reference proteins and flanks.

Parameters:
peptide_dfpandas.DataFrame

DataFrame with a peptide column. Its index is carried into the output as hit_id.

reference_dfpandas.DataFrame

DataFrame with protein accession and seq columns.

flanking_lengthint

Number of residues to include on each side of the peptide.

debug_max_rowsint, optional

Stop building annotations after this many reference rows have been produced. Intended only for generation-script debugging.

Returns:
pandas.DataFrame

Original peptide rows joined to their reference protein annotations.

mhcflurry.percent_rank_transform module

Backward-compatible import for the historical histogram implementation.

New code should use the explicit HistogramPercentRankTransform name. The alias also allows historical pickle references to resolve.

class mhcflurry.percent_rank_transform.HistogramPercentRankTransform[source]

Bases: object

Historical histogram-based CDF lookup, with preserved bin semantics.

The old PercentRankTransform name remains an alias. New predictor calibration defaults to CompactPercentRankTransform; use this class for saved-table compatibility or explicitly selected histogram calibration. Distinct raw scores can share one step value. Use survival=True for upper-tail percentiles, as required by processing/presentation predictors.

fit(values, bins)[source]

Fit the transform using the given values (e.g. ic50s).

Parameters:
valuespredictions (e.g. ic50 values)
binsbins for the cumulative distribution function

Anything that can be passed to numpy.histogram’s “bins” argument can be used here.

Returns:
HistogramPercentRankTransform

This fitted instance. Fit a fresh instance for each distribution.

classmethod fit_batch_torch(values_2d, bin_edges_1d)[source]

Batched GPU fit across multiple distributions.

Equivalent to calling fit(values_2d[i], bins=bin_edges_1d) for each row i, but vectorized across the row dim — eliminates the per-allele Python loop in calibrate’s hot path. Rows with no values inside the bin range are invalid and raise instead of fabricating an empty CDF.

Parameters:
values_2dtorch.Tensor of shape (n_distributions, n_values).

Stays on whatever device it’s on; histogram bucketing happens there.

bin_edges_1dtorch.Tensor of shape (n_edges,), monotonically

increasing. Same device as values_2d.

Returns:
list of HistogramPercentRankTransform

One transform per input distribution.

Numerically equivalent to the per-row numpy.histogram path
(matching to ≤1e-12, not bit-for-bit – division/cumsum ordering on
CUDA drifts in the last ULPs, far below bin resolution): same bin
assignment (right-open intervals, last bin inclusive), same CDF
normalization (% out of in-range count), and an identical cdf
array layout (length n_bins+3, sentinels at [0]=[1]=0, [-1]=100,
cumsum in [2:-1]).
transform(values, survival=False)[source]

Return percent ranks (range [0, 100]) for the given values.

Parameters:
valuessequence of float

Raw scores. Input NaNs become output NaNs.

survivalbool, default False

False returns the historical CDF lookup. True returns 100 minus that lookup, retaining the historical upper-tail behavior.

Returns:
numpy.ndarray

Percentiles using the saved histogram, without interpolation.

to_dict()[source]

Serialize without the NaN sentinels used in the historical CSV index.

classmethod from_dict(values)[source]

Restore a versioned histogram transform.

to_series()[source]

Serialize the fit to a pandas.Series.

The index on the series gives the bin edges and the values give the CDF.

Returns:
pandas.Series
static from_series(series)[source]

Deserialize a histogram transform from a pandas.Series, as returned by to_series().

Parameters:
seriespandas.Series
Returns:
HistogramPercentRankTransform
mhcflurry.percent_rank_transform.PercentRankTransform

alias of HistogramPercentRankTransform

mhcflurry.percentile_calibration module

Shared method selection and persistence for predictor percentile ranks.

mhcflurry.percentile_calibration.calibration_method(method, bins)[source]

Resolve the default without changing historical explicit-bin calls.

mhcflurry.percentile_calibration.factorize_calibration_groups(groups)[source]

Return (inverse, group_count) codes reusable across aligned fits.

Calibrating many alleles against one peptide reference repeats the same grouping. Factorize it once and pass the result as group_codes; the fitted transforms are identical to passing groups each time.

mhcflurry.percentile_calibration.fit_percent_rank_transform(values, *, method=None, bins=None, score_transform='logit', survival=False, max_knots=128, groups=None, group_codes=None)[source]

Fit a histogram or a label-free, validation-selected compact curve.

Compact fitting starts with 64 knots. A deterministic 80/20 background split permits 128 only for a meaningful reduction in cutoff-mass error. Groups (normally peptides) cannot cross that split. The selected budget is refitted on the full reference; no evaluation labels are accepted.

Parameters:
valuesone-dimensional sequence of float

Independent reference scores, not case/control labels.

method{“compact”, “histogram”}, optional

Compact unless explicit bins select histogram. Compact plus bins is invalid. This low-level helper requires bins for histogram fitting.

binsint or sequence, optional

Histogram bin definition, forwarded without changing its semantics.

score_transform{“logit”, “log”}

Compact input coordinate: log for positive affinity IC50, logit for probability-valued processing/presentation scores.

survivalbool, default False

Percentile direction for budget validation: True for upper-tail processing/presentation ranks, False for affinity CDF ranks. This does not change the returned transform’s default direction; pass survival=True explicitly when evaluating upper-tail percentiles.

max_knots{64, 128}, default 128

Compact ceiling. Fit 64 unless held-out cutoff-mass error improves beyond max(0.01, 10% of the better error). Ignored for histograms.

groupssequence, optional

Aligned identities that must not cross the selection split. If absent, each row is a separate group. Selection uses fixed seed 403, requires at least 1,000 groups and two cutoffs with ten expected observations.

group_codestuple of (array of int, int), optional

Precomputed factorize_calibration_groups(groups) for the same aligned reference rows. Mutually exclusive with groups.

Returns:
HistogramPercentRankTransform or CompactPercentRankTransform

Fitted transform. Compact selection metadata records the decision and available reference-validation diagnostics.

mhcflurry.percentile_calibration.save_percent_rank_transforms(models_dir, transforms)[source]

Save calibrations with atomic replacement of the target file.

CSV is retained when all histograms share an edge grid. JSON is authoritative for compact, mixed, or differing-grid collections. Remove the old alternate calibration only after its replacement is successfully written. An empty collection leaves existing calibration files untouched, as historical saves did, so an uncalibrated or incremental save cannot erase a calibration. Files get ordinary umask permissions. Neural-network files are never touched. This does not make the entire model-directory save a transaction across multiple files.

mhcflurry.percentile_calibration.load_percent_rank_transforms(models_dir)[source]

Read new calibrations or historical CSV without refitting either.

mhcflurry.predict_command module

Compatibility wrapper for mhcflurry.cli.predict_command.

mhcflurry.predict_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.predict_scan_command module

Compatibility wrapper for mhcflurry.cli.predict_scan_command.

mhcflurry.predict_scan_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.processing_evaluation module

Integrity checks for a frozen, expanded processing evaluation cohort.

mhcflurry.processing_evaluation.hit_identity(frame)[source]

Ordered hit identities, including MHC alleles and protein context.

mhcflurry.processing_evaluation.verify_hits(original, matched)[source]

Fail if matching removes, duplicates, reorders or changes a held-out hit.

mhcflurry.processing_evaluation.load_processing_cohort(directory, original)[source]

Read a checksummed 10:1 cohort and prove it retains the benchmark hits.

mhcflurry.processing_initialization module

Explicit hidden-layer initialization for processing recipe experiments.

LSUV follows orthogonal initialization with sequential variance adjustment (Mishkin and Matas, https://arxiv.org/abs/1511.06422). Scalar processing heads and the final aggregation/gating weights are deliberately not reinitialized.

mhcflurry.processing_initialization.processing_hidden_layers(model)[source]

Return eligible named affine layers in the actual forward order.

mhcflurry.processing_initialization.processing_activation_variance(model, layer, inputs, post_activation=False)[source]

Measure a hidden output, excluding positions beyond each input sequence.

Post-activation means the configured activation immediately after the affine layer, before any normalization/dropout. Missing-context X tokens inside configured windows are included; maximum-length tail padding is not. The caller owns eval mode. Hooks are removed even if forward fails.

mhcflurry.processing_initialization.initialize_processing_network(model, inputs, method='none', margin=0.05, max_iter=32)[source]

Initialize eligible hidden layers, with auditable pre/post-LSUV results.

Parameters:
modelClass1ProcessingModel

Fresh eager network. Output/scalar-head parameters remain untouched.

inputsdict

Fixed calibration batch containing training rows only, on model device.

method{“none”, “orthogonal”, “lsuv_pre”, “lsuv_post”}

Explicit initialization policy. None is an exact no-op, including RNG.

marginfloat

Maximum absolute deviation of the measured variance from one.

max_iterint

Maximum scaling iterations per layer; failure is explicit.

Returns:
dict

Effective policy, variance mask, and per-layer initialization diagnostics.

mhcflurry.processing_matching module

Shared, auditable affinity/length matching for processing data.

exception mhcflurry.processing_matching.IncompleteProcessingMatches(message, failures)[source]

Bases: ValueError

A valid scored pool lacks enough negatives for the listed hit rows.

mhcflurry.processing_matching.add_processing_matching_args(parser)[source]

Shared processing-data CLI policy; legacy filtering is opt-in.

mhcflurry.processing_matching.initialize_matching_artifacts(args)[source]

Fingerprint the reference and data before generating any matched table.

mhcflurry.processing_matching.validate_preparation_provenance(saved, current)[source]

Allow relocated caches only when scientific inputs and policy agree.

mhcflurry.processing_matching.prepare_processing_training_sample(frame, args, reference)[source]

Save the scored pool before matching; retain failure evidence too.

mhcflurry.processing_matching.make_affinity_controlled_risk_sets(frame, decoys_per_hit=10, same_protein_caliper=0.25, max_distance=0.25, random_seed=42)[source]

Return seeded random risk sets without reusing negatives per sample.

Draw uniformly among available negatives within the affinity caliper, preferring the same source protein. Randomized assignment order and augmenting-path repair avoid false failures caused by greedy competition. This does not sample complete matchings uniformly. random_seed is recorded in diagnostics; identical ordered inputs and seed reproduce the assignments independently of sample batching.

mhcflurry.processing_matching.affinity_reference_fingerprint(directory)[source]

Identify the frozen reference using its manifest, weights and sequences.

mhcflurry.processing_matching.matched_training_data(frame, reference, decoys_per_hit=1, max_distance=0.25, random_seed=42)[source]

Retain hits and construct a fixed number of matched negatives per hit.

mhcflurry.processing_matching.validate_matched_training_data(frame, policy='matched')[source]

Reject unmatched/corrupt cached tables before training or resuming.

mhcflurry.processing_matching.validate_matching_assignments(frame, affinity_column, count, caliper=0.25)[source]

Recompute matching invariants instead of trusting saved distances.

mhcflurry.processing_matching.sample_validation_mask(frame, fraction, seed)[source]

Choose complete samples, independently of architecture-specific fit seeds.

mhcflurry.processing_preparation module

Resumable, bounded preparation of scored processing-negative pools.

class mhcflurry.processing_preparation.ScoredValues(values: object, seconds: float)[source]

Bases: object

Prediction values and actual scoring time, excluding pipeline queue waits.

values: object
seconds: float
mhcflurry.processing_preparation.add_processing_preparation_args(parser)[source]

Options for the adaptive, resumable processing-data command.

mhcflurry.processing_preparation.write_json_atomic(path, value)[source]

Publish metadata only after the corresponding data files are closed.

mhcflurry.processing_preparation.write_csv_atomic(path, frame)[source]

Keep interrupted compression from looking like a completed artifact.

mhcflurry.processing_preparation.validate_pool_hits(frame, hits)[source]

Require exactly the current ordered observed rows and finite scores.

class mhcflurry.processing_preparation.SamplePreparation(args, sample, hits)[source]

Bases: object

Immutable scored rounds plus a checksummed final matched sample.

path(suffix)[source]
load_pool()[source]

Recover committed rounds, or import a verified prior sample pool.

save_round(frame, record, source=None)[source]
load_result()[source]
finish(frame, diagnostics)[source]
mhcflurry.processing_preparation.sample_preparation_steps(args, sample, hits, seed, initial_pool, additional_candidates)[source]

CPU coroutine yielding unscored peptides and receiving affinity scores.

Callbacks keep proteome access and affinity model ownership in the worker. Initial/additional pools contain unscored rows. Yielded requests contain only peptides absent from committed rounds. Each continuation commits its scored round before matching, expanding, or publishing sample completion.

mhcflurry.processing_preparation.prepare_sample(args, sample, hits, seed, initial_pool, additional_candidates, score)[source]

Synchronous adapter for the same resumable sample workflow.

mhcflurry.processing_ranking module

Sample-balanced ranking metrics for processing stopping-validation data.

class mhcflurry.processing_ranking.SampleRankingMonitor(targets, sample_ids)[source]

Bases: object

Validate a fixed binary cohort and compute equal-sample AP and PPV@N.

Parameters:
targetsarray-like

Binary labels in the fixed validation prediction order.

sample_idsarray-like

Nonempty string sample identifiers, one per label. Each sample must contain both labels. No rows or samples are silently excluded.

Notes

AP uses sklearn’s threshold-grouped treatment of ties. PPV uses stable descending score order, with original validation-row order breaking ties. Neither metric uses training sample weights.

mhcflurry.proteome_decoys module

Utilities for generating proteome peptide decoy candidates.

mhcflurry.proteome_decoys.unique_in_order(values)[source]

Return unique non-null values while preserving first-seen order.

mhcflurry.proteome_decoys.infer_flanking_length(hit_df)[source]

Infer the fixed flanking sequence length used for peptide decoys.

mhcflurry.proteome_decoys.load_reference_sequences(reference_csv, accessions)[source]

Load protein sequences keyed by accession for the requested accessions.

mhcflurry.proteome_decoys.iter_protein_peptide_records(accession, sequence, lengths=(8, 9, 10, 11), flanking_length=15, valid_amino_acids=None)[source]

Yield peptide/flank records for one protein sequence.

The start-position range intentionally matches the historical write_proteome_peptides.py behavior so release data generation remains comparable. Concretely, range(0, len(sequence) - min_length) has an exclusive upper bound, so the last start position is len(sequence) - min_length - 1 and the single min_length-mer that would start at len(sequence) - min_length (the C-terminal min_length-mer) is NOT emitted. This off-by-one is deliberate bug-for-bug parity, not an oversight: changing it would alter the decoy set used to generate released models. test_iter_protein_peptide_records_* pins the resulting counts so the behavior can’t drift silently.

mhcflurry.proteome_decoys.make_peptide_frame_for_accessions(accessions, sequences_by_accession, lengths=(8, 9, 10, 11), flanking_length=15, valid_amino_acids=None)[source]

Generate a peptide/flank DataFrame for the requested accessions.

mhcflurry.proteome_decoys.sample_peptide_frame_for_accessions(accessions, sequences_by_accession, lengths=(8, 9, 10, 11), flanking_length=15, exclude_peptides=(), n=1, valid_amino_acids=None, sampling_method='positions', allow_smaller=False)[source]

Sample windows without replacement; build flanks only for retained rows.

Position sampling preserves the eligible population, not the historical reservoir’s RNG sequence. Use sampling_method='reservoir' for replay. allow_smaller returns the complete eligible population on exhaustion.

mhcflurry.proteome_decoys.peptides_by_length_from_frame(peptide_df)[source]

Return peptide DataFrames keyed by peptide length.

mhcflurry.pseudosequences module

Class I pseudosequence artifact names and lookup helpers.

This module is the canonical registry for pseudosequence CSV filenames used by MHCflurry training and model serialization.

Canonical pseudosequence files:

  • pseudosequences.netmhcpan.34aa.csv: NetMHCpan-derived 34 amino acid pseudosequences.

  • pseudosequences.mhcflurry.37aa.csv: MHCflurry-generated 37 amino acid pseudosequences used by older public pan-allele model bundles.

  • pseudosequences.mhcflurry.39aa.csv: MHCflurry-generated 39 amino acid pseudosequences from the aligned full-sequence pipeline.

Compatibility aliases:

  • allele_sequences.csv: legacy runtime/model artifact filename.

  • class1_pseudosequences.csv: legacy NetMHCpan 34aa filename.

  • allele_sequences.no_differentiation.csv: legacy pan-variant experiment output; not a canonical pseudosequence artifact name.

Trained model directories should ship the exact pseudosequence CSV used during training. The saved weights depend on both the representation width and the position definition.

Expected locations:

  • downloads-generation/*/pseudosequences.netmhcpan.34aa.csv: checked-in generation seed tables.

  • standalone allele_sequences download: should contain pseudosequences.mhcflurry.39aa.csv plus allele_sequences.csv as a compatibility copy.

  • trained model directories: should contain allele_sequences.csv and, for newly-saved models, the matching canonical pseudosequences.*.*aa.csv.

class mhcflurry.pseudosequences.PseudosequenceDefinition(source: str, length: int, filename: str, description: str)[source]

Bases: object

A named pseudosequence CSV definition.

source: str
length: int
filename: str
description: str
mhcflurry.pseudosequences.pseudosequence_length(allele_to_sequence)[source]

Return the common pseudosequence length, or None if ambiguous.

mhcflurry.pseudosequences.pseudosequence_filename_for_length(length)[source]

Return the canonical pseudosequence filename for a representation length.

mhcflurry.pseudosequences.pseudosequence_filename_for_mapping(allele_to_sequence)[source]

Return the canonical pseudosequence filename for a saved mapping.

mhcflurry.pseudosequences.pseudosequence_filename_candidates(models_dir)[source]

Pseudosequence files accepted when loading a saved predictor.

allele_sequences.csv and class1_pseudosequences.csv are legacy artifact filenames. The pseudosequences.*.*aa.csv names make the source and representation width explicit for newly-generated artifacts.

mhcflurry.pseudosequences.pseudosequence_path(directory, length, fallback_legacy=True)[source]

Return the preferred pseudosequence path in directory.

When the canonical pseudosequences.*.<length>aa.csv is absent and fallback_legacy is true, returns the legacy allele_sequences.csv path and logs a warning so callers don’t silently read a different sequence set than requested.

mhcflurry.pseudosequences.main(argv=None, prog=None)[source]

Command-line access for shell generation scripts.

mhcflurry.pytorch_layers module

PyTorch custom layers for mhcflurry.

mhcflurry.pytorch_layers.get_activation(name)[source]

Map activation name string to a PyTorch activation function.

Parameters:
namestr

Activation name: “tanh”, “sigmoid”, “relu”, “silu”/”swish”, “gelu”, “linear”, or “”

Returns:
callable or None

Activation function, or None for no activation

class mhcflurry.pytorch_layers.KerasBatchNorm1d(num_features: int, eps: float = 1e-05, momentum: float | None = 0.1, affine: bool = True, track_running_stats: bool = True, device=None, dtype=None, *, bias: bool = True)[source]

Bases: BatchNorm1d

BatchNorm1d with Keras-compatible running-statistics updates.

PyTorch normalizes with the biased batch variance but updates running_var with an unbiased estimate. Keras uses the biased population variance for both. momentum retains PyTorch’s new-batch-coefficient convention so 0.01 corresponds to Keras momentum=0.99.

Supports both (batch, features) dense outputs and (batch, channels, positions) sequence outputs. In the sequence case, statistics are accumulated over batch and position, matching Keras BatchNormalization(axis=-1) on the equivalent channels-last tensor.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

forward(inputs)[source]

Define the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class mhcflurry.pytorch_layers.LocallyConnected1D(in_channels, out_channels, input_length, kernel_size, activation='tanh')[source]

Bases: Module

A locally connected 1D layer (unshared convolution).

Unlike Conv1D, this layer uses different filter weights at each position in the input sequence. This is equivalent to Keras’ LocallyConnected1D.

Parameters:
in_channelsint

Number of input channels

out_channelsint

Number of output channels (filters)

input_lengthint

Length of the input sequence

kernel_sizeint

Size of the convolution kernel

activationstr

Activation function name

Initialize internal Module state, shared by both nn.Module and ScriptModule.

forward(x)[source]

Forward pass.

Parameters:
xtorch.Tensor

Input tensor of shape (batch, sequence_length, in_channels)

Returns:
torch.Tensor

Output tensor of shape (batch, output_length, out_channels)

mhcflurry.pytorch_losses module

PyTorch loss functions for mhcflurry.

Supports inequality constraints where training data includes (=), (<), and (>) relationships. For inequality constraints, penalization is applied only when predictions violate the constraint.

class mhcflurry.pytorch_losses.MSEWithInequalities(*args: Any, **kwargs: Any)[source]

Bases: Module

MSE loss with inequality support.

y_true is encoded as follows:
  • [0, 1]: equality constraint, standard MSE

  • [2, 3]: greater-than constraint (value = y_true - 2), penalize if pred < value

  • [4, 5]: less-than constraint (value = y_true - 4), penalize if pred > value

Initialize internal Module state, shared by both nn.Module and ScriptModule.

supports_inequalities = True
supports_multiple_outputs = False
static encode_y(y, inequalities=None)[source]

Encode targets with inequality information.

Parameters:
yarray-like

Target values in [0, 1]

inequalitiesarray-like of str, optional

One of “=”, “>”, “<” for each target

Returns:
numpy.ndarray
forward(y_pred, y_true, sample_weights=None)[source]

Compute loss.

Parameters:
y_predtorch.Tensor

Predictions, shape (batch,) or (batch, 1)

y_truetorch.Tensor

Encoded targets, shape (batch,) or (batch, 1)

sample_weightstorch.Tensor or None

Optional per-example weights.

Returns:
torch.Tensor

Scalar loss value

loss_numerator_and_denominator(y_pred, y_true, sample_weights=None)[source]

Return additive reduction terms for exact batched validation.

class mhcflurry.pytorch_losses.MSEWithInequalitiesAndMultipleOutputs(*args: Any, **kwargs: Any)[source]

Bases: Module

MSE loss with inequality and multiple output support.

Extends MSEWithInequalities by encoding the output index into the target: encoded_target = inequality_encoded_value + output_index * 10

Initialize internal Module state, shared by both nn.Module and ScriptModule.

supports_inequalities = True
supports_multiple_outputs = True
static encode_y(y, inequalities=None, output_indices=None)[source]

Encode targets with inequality and output index information.

Parameters:
yarray-like

Target values in [0, 1]

inequalitiesarray-like of str, optional

One of “=”, “>”, “<” for each target

output_indicesarray-like of int, optional

Output index for each target

Returns:
numpy.ndarray
forward(y_pred, y_true, sample_weights=None)[source]

Compute loss.

Parameters:
y_predtorch.Tensor

Predictions, shape (batch, num_outputs)

y_truetorch.Tensor

Encoded targets, shape (batch,) or (batch, 1)

sample_weightstorch.Tensor or None

Optional per-example weights.

Returns:
torch.Tensor

Scalar loss value

loss_numerator_and_denominator(y_pred, y_true, sample_weights=None)[source]

Return additive reduction terms for exact batched validation.

class mhcflurry.pytorch_losses.MultiallelicMassSpecLoss(delta=0.2, multiplier=1.0)[source]

Bases: Module

Loss function for multiallelic mass spectrometry data.

For each (hit, decoy) pair, penalizes when any decoy allele prediction is greater than the best hit allele prediction minus delta. The squared hinge encourages each hit to exceed every decoy allele by at least delta.

y_true encoding:
  • 1.0: hit (positive)

  • 0.0: decoy (negative)

  • -1.0: ignored

Initialize internal Module state, shared by both nn.Module and ScriptModule.

supports_inequalities = True
supports_multiple_outputs = False
supports_independent_samples = False
static encode_y(y)[source]

Encode y (no-op for this loss).

forward(y_pred, y_true, sample_weights=None)[source]

Compute loss.

Parameters:
y_predtorch.Tensor

Predictions, shape (batch, num_alleles)

y_truetorch.Tensor

Labels, shape (batch,) or (batch, 1)

sample_weightstorch.Tensor or None

Accepted for interface compatibility; ignored by this pairwise loss.

Returns:
torch.Tensor

Scalar loss value

class mhcflurry.pytorch_losses.StandardLoss(loss_name='mse')[source]

Bases: Module

Wrapper for standard PyTorch loss functions (MSE, MAE, etc).

Initialize internal Module state, shared by both nn.Module and ScriptModule.

supports_inequalities = False
supports_multiple_outputs = False
static encode_y(y)[source]

Encode y (simple cast to float32).

forward(y_pred, y_true, sample_weights=None)[source]

Compute loss.

Parameters:
y_predtorch.Tensor
y_truetorch.Tensor
sample_weightstorch.Tensor | None

Optional per-example weights.

Returns:
torch.Tensor

Scalar loss value

mhcflurry.pytorch_losses.get_pytorch_loss(name)[source]

Get a PyTorch loss object by name.

Parameters:
namestr

Loss name. Prefix with “custom:” for custom losses, otherwise a standard loss name like “mse”.

Returns:
nn.Module

Loss module with encode_y, supports_inequalities, and supports_multiple_outputs attributes.

mhcflurry.pytorch_sizing module

Prediction and training batch-size helpers.

mhcflurry.pytorch_sizing.default_prediction_batch_is_auto()[source]

Whether the effective default prediction batch can shrink on OOM.

mhcflurry.pytorch_sizing.begin_peak_memory_measurement()[source]

Reset CUDA peak counters and return an opaque measurement token.

mhcflurry.pytorch_sizing.cuda_process_memory_bytes(pid=None)[source]

Return this process’s CUDA memory from nvidia-smi, if available.

PyTorch allocator counters omit the CUDA context and other non-PyTorch allocations. Those bytes matter when many worker processes share a GPU. Querying the driver gives resource probes a complete steady-state working set without initializing CUDA in the parent process.

mhcflurry.pytorch_sizing.cuda_free_memory_before_context_bytes(device_id)[source]

Query one physical CUDA device’s free memory without importing torch.

mhcflurry.pytorch_sizing.end_peak_memory_measurement(token)[source]

Finish a measurement begun by begin_peak_memory_measurement().

mhcflurry.pytorch_sizing.is_device_out_of_memory_error(exc)[source]

Whether exc is a CUDA/MPS allocator out-of-memory error.

mhcflurry.pytorch_sizing.release_cached_device_memory(device)[source]

Return unused accelerator allocator blocks to the shared device.

mhcflurry.pytorch_sizing.release_device_memory_after_oom(device)[source]

Release cached allocator blocks before retrying a smaller auto batch.

mhcflurry.pytorch_sizing.synchronize_device(device)[source]

Wait for accelerator work so deferred errors surface at their source.

CUDA and MPS kernels are asynchronous. Without an explicit synchronization at the end of an elastic prediction attempt, an OOM from a network forward can be reported by an unrelated later tensor transfer, outside the retry loop that can safely reduce the batch size.

mhcflurry.pytorch_sizing.release_unused_torch_memory()[source]

Collect dead tensors and return unused accelerator cache memory.

Resource probes deliberately reuse one worker for several architectures. Python reference cycles can otherwise keep the previous fit’s tensors alive until a later, unrelated collection, while allocator cache blocks continue to hide global device headroom. Collect cycles before emptying the backend cache so the next probe observes only its own residency.

mhcflurry.pytorch_sizing.estimate_peak_bytes_per_row(model)[source]

Worst-case peak activation bytes per sample during a forward.

Walks the model’s configured layers and returns the maximum hidden- layer width (in fp32 bytes) × 2 (one input + one output of the current layer stay live under torch’s eval-time no_grad reuse). A 4× multiplier covers framework overhead, cuDNN scratch buffers, and Python-side tensor bookkeeping. Used by compute_prediction_batch_size.

mhcflurry.pytorch_sizing.free_device_memory_bytes(device)[source]

Best-effort free-memory query. Returns a conservative value when the device doesn’t expose a direct free-memory API.

  • CUDA: torch.cuda.mem_get_info (exposed free + reserved tracking).

  • MPS: Apple’s recommended_max_memory on unified memory, minus whatever the MPS driver has already handed us. Cap by psutil available RAM when present so other apps aren’t evicted. Falls back to 4 GB if neither API is reachable.

  • CPU / unknown: 2 GB conservative budget (the helper short-circuits for CPU anyway, but keep a sensible value in case callers pass a foreign device).

class mhcflurry.pytorch_sizing.DeviceMemoryBudget(free_bytes: int, total_bytes: int, reserve_bytes: int, worker_entitlement_bytes: int, process_bytes: int, available_bytes: int)[source]

Bases: object

Stable per-worker device-memory entitlement and remaining headroom.

free_bytes: int
total_bytes: int
reserve_bytes: int
worker_entitlement_bytes: int
process_bytes: int
available_bytes: int
mhcflurry.pytorch_sizing.device_memory_budget(device, num_workers_per_gpu=1, free_memory_fraction=None, reserve_fraction=0.1, reserve_min_bytes=1073741824)[source]

Return a race-free memory budget for one co-resident worker.

The old calculation divided live free memory by the declared worker count. Live free memory already reflects allocations made by workers that initialized earlier, so that calculation double-discounted memory and made the resulting batch size depend on startup order. Here every worker gets a fixed entitlement captured from launch-time free capacity (falling back to total device capacity for direct API calls), subtracts its own resident working set, and finally caps the result by live global headroom. Managed workers therefore cannot collectively claim more than the shared launch budget.

mhcflurry.pytorch_sizing.compute_prediction_batch_size(device, model=None, num_workers_per_gpu=1, free_memory_fraction=None, max_rows=9223372036854775807, min_rows=1024, cpu_fallback=32768, total_rows=None)[source]

Auto-size a prediction batch for device and model.

Uses the worker’s remaining fixed device-memory entitlement and the model’s per-row peak activation estimate, capped by current global headroom. max_rows is only an optional caller limit; the default auto path has no hardwired batch cap.

CPU: returns cpu_fallback — large batches on CPU thrash L3 cache and rarely help for the small networks mhcflurry trains.

mhcflurry.pytorch_sizing.env_workers_per_gpu(default=1)[source]

Read the MHCFLURRY_MAX_WORKERS_PER_GPU env var.

The local parallelism pool sets this in each training worker so auto-sized batching + training-memory checks can partition VRAM across co-resident workers without the caller wiring it explicitly.

mhcflurry.pytorch_sizing.resolve_prediction_batch_size(value, device, model=None, num_workers_per_gpu=1, total_rows=None)[source]

Resolve an explicit int or "auto" to a concrete batch size.

Accepts None as a synonym for "auto". Propagates an explicit int through unchanged so callers can always pin the size when they know better than the heuristic.

mhcflurry.pytorch_sizing.calibrate_prediction_batch_size(batch_size, device, model, inputs, num_workers_per_gpu=1, total_rows=None, probe_rows=4096, safety_multiplier=2.0, transfer_inputs_to_device=False)[source]

Tighten an automatic CUDA prediction batch from a real forward probe.

The analytic estimator cannot know the exact allocator and convolution workspace chosen for every model shape and CUDA runtime. This function measures the incremental peak of the loaded model with its real resident input tensors, then recomputes the batch from the worker’s remaining fixed device-memory entitlement. The result never exceeds either batch_size or the largest batch exercised successfully by the probe. CUDA convolution workspaces are not reliably linear in batch size, especially while peer workers initialize, so extrapolating above a measured batch is unsafe.

CPU and MPS return batch_size unchanged. MPS does not expose an equivalent resettable peak allocator counter, so it retains the analytic estimate and the caller’s elastic OOM retry. Explicit batches should not be passed to this function; callers retain authority over pinned values.

Parameters:
batch_sizeint

Analytically selected automatic batch size.

devicetorch.device

Device on which model and inputs reside.

modelcallable

Eval-mode model accepting the sliced inputs mapping.

inputsmapping

Tensor inputs with a shared leading row dimension. They may remain on the host when transfer_inputs_to_device is true.

num_workers_per_gpuint

Co-resident workers sharing the device entitlement.

total_rowsint, optional

Number of available rows. Inferred from inputs when omitted.

probe_rowsint

Maximum rows in the measurement forward. The actual probe is also capped at one eighth of the analytic entitlement so measurement cannot consume the batch it is meant to protect.

safety_multiplierfloat

Margin applied to the measured per-row peak when deciding whether the verified probe batch must be tightened further.

transfer_inputs_to_devicebool

Move each probe slice to device inside the protected measurement. This models streaming inference and makes transfer OOMs recoverable.

Returns:
int

A calibrated batch no larger than batch_size or the successfully exercised probe batch.

mhcflurry.pytorch_sizing.check_training_batch_fits(requested_batch_size, device, model, num_workers_per_gpu=1, free_memory_fraction=None, min_batch=64, logger=None)[source]

Verify that requested_batch_size will fit on device.

Training peak memory = activations kept alive across the forward pass (for backward), plus gradients, plus optimizer state. That’s roughly 4 × estimate_peak_bytes_per_row (inference peak).

Returns (effective_batch_size, shrunk: bool). When the requested batch is too large for the available VRAM — partitioned across co-resident workers — the batch is shrunk to the largest power-of-two that fits. min_batch is a normal-performance floor, not a memory-safety floor: under severe pressure the result may be smaller so the guard does not knowingly force an OOM. A loud warning is emitted via logger / stderr explaining that the training dynamics (BN running stats, gradient noise scale) now differ from what the caller configured.

CPU short-circuits — no OOM risk there that a size-based heuristic can catch. Returns (requested_batch_size, False) in that case.

mhcflurry.pytorch_training module

Shared PyTorch training helpers used by multiple mhcflurry trainers.

These helpers are model-agnostic: they assume only that the caller has a torch.nn.Module network and a torch.device. They provide checkpoint copying, numerical settings, compilation and validation sizing for Class1NeuralNetwork (affinity) and Class1ProcessingNeuralNetwork.

Anything that touches affinity-specific machinery (random-negative resampling, multi-output / inequality losses, allele encoding, percentile-rank calibration) stays in the class I modules.

mhcflurry.pytorch_training.copy_module_state_dict_to_cpu(module)[source]

Return an independent CPU checkpoint of a module’s complete state.

mhcflurry.pytorch_training.configure_matmul_precision(device)[source]

Apply an explicitly requested CUDA matmul precision and cuDNN autotuning.

MHCFLURRY_MATMUL_PRECISION accepts highest, high or medium. When unset, this helper leaves PyTorch settings unchanged. CPU and MPS calls are no-ops. On CUDA it sets float32 matmul precision and enables cuDNN benchmarking when cuDNN is available. highest retains full float32 matmul precision; the other modes may use reduced-precision internal operations on supported hardware.

cuDNN benchmarking chooses algorithms for observed input shapes and can add initial search time or affect reproducibility. This helper does not enable deterministic algorithms or guarantee identical seeded results.

mhcflurry.pytorch_training.maybe_compile_network(network, device)[source]

Wrap network with torch.compile when the env asks for it.

Gated on MHCFLURRY_TORCH_COMPILE=1 and a CUDA device. torch.compile is heavy: JIT graph capture + kernel fusion + on- disk cache + recompile-on-shape-change. The TF32 knob is cheaper and independent — see configure_matmul_precision.

MHCFLURRY_TORCH_COMPILE_MODE picks the mode= kwarg (default, reduce-overhead, max-autotune). Default is “default” — codegen time is already heavy without max-autotune, and our shape-stable batching is what unlocks the big wins regardless of mode.

Returns the compiled module (an OptimizedModule that forwards .train(), .eval(), .state_dict(), .parameters() to the wrapped original) so call sites can swap it in without threading a second reference through the training loop.

Compilation cost: first forward pass triggers graph capture + codegen (typically 30 s – 2 min on a 2-layer MLP like ours). Subsequent calls with the same input shapes hit the in-process cache; subsequent processes hit the on-disk cache (~/.cache/torch) as long as the graph matches.

mhcflurry.pytorch_training.maybe_compile_loss(loss_obj, device)[source]

Wrap a loss module with torch.compile when the env asks for it.

Gated on MHCFLURRY_TORCH_COMPILE=1 and a CUDA device — same criteria as maybe_compile_network. MSEWithInequalities issues ~10 small elementwise kernels per step in eager mode (reshape → subtract → compare → cast → multiply → compare → cast → multiply → square → sum), each with its own launch overhead that adds up to meaningful wall-clock on A100 with a sub-ms compute budget. Dynamo fuses those into a couple of kernels and cuts the loss’s share of step time to near-zero.

Dispatch via MHCFLURRY_TORCH_COMPILE_LOSS_MODE (falls back to MHCFLURRY_TORCH_COMPILE_MODE) so the loss’s compile mode can be tuned independently of the network’s — loss ops are tiny and “reduce-overhead” makes less sense than on the full forward pass.

Idempotent: a second call on an already-wrapped loss returns it unchanged.

mhcflurry.pytorch_training.uncompiled_network(network)[source]

Return the eager module behind network.

mhcflurry.pytorch_training.validation_forward_network(network, eager_network)[source]

Choose the module used for validation forward passes during training.

mhcflurry.pytorch_training.effective_validation_batch_size(device, configured_batch_size, minibatch_size, model=None, num_workers_per_gpu=1, total_rows=None)[source]

Return the validation batch size to use for the current device.

CUDA validation uses the same live-memory budget as inference. Callers compute this once per fit and persist it in fit_info so torch.compile sees a stable shape across epochs. Explicit configured values are never changed.

mhcflurry.random_negative_peptides module

class mhcflurry.random_negative_peptides.RandomNegativePeptides(**hyperparameters)[source]

Bases: object

Generate random negative (peptide, allele) pairs. These are used during model training, where they are resampled at each epoch.

hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDefaults object>

Hyperperameters for random negative peptides.

Number of random negatives will be:

random_negative_rate * (num measurements) + random_negative_constant

where the exact meaning of (num measurements) depends on the particular random_negative_method in use.

If random_negative_match_distribution is True, then the amino acid frequencies of the training data peptides are used to generate the random peptides.

Valid values for random_negative_method are:
“by_length”: used for allele-specific prediction. See description in

RandomNegativePeptides.plan_by_length method.

“by_allele”: used for pan-allele prediction. See

RandomNegativePeptides.plan_by_allele method.

“by_allele_equalize_nonbinders”: used for pan-allele prediction. See

RandomNegativePeptides.plan_by_allele_equalize_nonbinders method.

“recommended”: the default. Use by_length if the predictor is allele-

specific and by_allele if it’s pan-allele.

plan(peptides, affinities, alleles=None, inequalities=None)[source]

Calculate the number of random negatives for each allele and peptide length. Call this once after instantiating the object.

Parameters:
peptideslist of string
affinitieslist of float
alleleslist of string, optional
inequalitieslist of string (“>”, “<”, or “=”), optional
Returns:
pandas.DataFrame indicating number of random negatives for each length
and allele.
plan_by_length(df_all, df_binders=None, df_nonbinders=None)[source]

Generate a random negative plan using the “by_length” policy.

Parameters are as in the plan method. No return value.

Used for allele-specific predictors. Does not work well for pan-allele.

Different numbers of random negatives per length. Alleles are sampled proportionally to the number of times they are used in the training data.

plan_by_allele(df_all, df_binders=None, df_nonbinders=None)[source]

Generate a random negative plan using the “by_allele” policy.

Parameters are as in the plan method. No return value.

For each allele, a particular number of random negatives are used for all lengths. Across alleles, the number of random negatives varies; within an allele, the number of random negatives for each length is a constant

plan_by_allele_equalize_nonbinders(df_all, df_binders, df_nonbinders)[source]

Generate a random negative plan using the “by_allele_equalize_nonbinders” policy.

Parameters are as in the plan method. No return value.

Requires that the random_negative_binder_threshold hyperparameter is set.

In a first step, the number of random negatives selected by the “by_allele” method are added (see plan_by_allele). Then, the total number of non-binders are calculated for each allele and length. This total includes non-binder measurements in the training data plus the random negative peptides added in the first step. In a second step, additional random negative peptides are added so that for each allele, all peptide lengths have the same total number of non-binders.

get_alleles()[source]

Get the list of alleles corresponding to each random negative peptide as returned by get_peptides. This does NOT change and can be safely called once and reused.

Returns:
list of string
get_peptides(rng=None)[source]

Get the list of random negative peptides. This will be different each time the method is called.

Parameters:
rngnumpy.random.Generator, optional

When supplied, all random draws go through this generator. Lets a caller make the returned peptide list deterministic — used by RandomNegativesPool to build reproducible multi-epoch pools. When None the numpy global state is used, preserving the historical “fresh peptides every call” behavior.

Returns:
list of string
get_total_count()[source]

Total number of planned random negative peptides.

Returns:
int
class mhcflurry.random_negative_peptides.RandomNegativesPool(planner, peptide_encoder, pool_epochs=1, seed=None, device=None, peptide_encoding=None)[source]

Bases: object

Amortize random-negative generation and encoding across N epochs.

Class1NeuralNetwork.fit needs random-negative peptides each epoch. Generating them and encoding them into network inputs can dominate training time for large pan-allele runs. This class generates pool_epochs worth of random peptides in one call to the planner, encodes the whole pool once, and hands back an O(1) slice per epoch.

Setting pool_epochs=1 samples and encodes fresh negatives every epoch. Setting pool_epochs>1 amortizes generation and encoding across the pool; the trade-off is that consecutive epochs in a pool cycle see distinct slices of the same generated pool rather than independently generated peptides. A new pool is generated at each epoch // pool_epochs boundary.

Seeding is optional. When seed is None the peptides are drawn from the process’s numpy global state, matching the pre-pool semantics. Worker initialization is responsible for independent RNG states; separate processes alone do not guarantee them. Supplying an explicit seed makes pool contents reproducible — useful for debugging and for regression tests.

Parameters:
plannerRandomNegativePeptides

A planner that has already had plan(...) called on it.

peptide_encodercallable

Receives an EncodableSequences and returns an encoded numpy array (typically Class1NeuralNetwork .peptides_to_network_input). Called once per cycle on the full pool. Ignored when device is set — the device path samples and encodes integer indices directly.

pool_epochsint

Number of consecutive epochs that share a pool. 1 means fresh random negatives every epoch.

seedint, optional

Seed for the per-cycle RNG. When None, draws go through numpy’s global state (or torch’s global state on the device path).

devicetorch.device or str, optional

When set, the pool builds device-resident int8 tensors via encode_random_negatives_on_device() instead of the host-side string-→encoder path. peptide_encoding must be provided alongside; peptide_encoder is unused on this path. Peptide strings are not materialized (get_epoch_inputs returns (None, encoded_slice)).

peptide_encodingdict, optional

Required when device is set. Subset of the model’s peptide_encoding hyperparameter — at minimum alignment_method and max_length (plus left_edge / right_edge for pad_middle).

get_epoch_inputs(epoch)[source]

Return (peptides_list, encoded_slice) for epoch.

The returned encoded_slice is a view into the pool-level encoded array — no copy — so downstream assignments that expect to own the memory should .copy() it first. The list of raw peptide strings is included for callers that need it (e.g. logging / diagnostics).

On the device-resident path peptides_list is None (the strings are never materialized; recover them via amino_acid.indices_to_peptide() against the int8 encoded slice if a logging caller needs them).

property total_count
mhcflurry.random_negative_peptides.supports_device_random_negative_encoding(peptide_encoding)[source]

Return whether random negatives can be encoded directly on device.

mhcflurry.random_negative_peptides.encoded_length_for_alignment(alignment, max_length)[source]

Return the per-row encoded length for an alignment method.

Mirrors the shape contract of EncodableSequences.sequences_to_fixed_length_index_encoded_array(). Covers every alignment method for shape bookkeeping / host-path parity; note the device random-negative encoder only supports the subset in _SUPPORTED_DEVICE_ALIGNMENTS (left_pad_centered_right_pad / pad_middle), so the left_pad_right_pad / right_pad / left_pad branches here are reachable only on the host path, not on device.

mhcflurry.random_negative_peptides.aa_distribution_to_index_weights(distribution, device=None, dtype=None)[source]

Convert a letter-indexed AA distribution to a torch index-weight vector.

Parameters:
distributionpandas.Series or None

Letter→probability map (typically the planner’s aa_distribution). When None, weights are uniform over the 20 common amino acids.

device, dtypeforwarded to the result tensor. dtype defaults

to torch.float32 (multinomial requires float).

Returns:
torch.Tensor of shape (len(amino_acid.AMINO_ACIDS),) — index 20
  1. is always zero so X is never sampled. ..

mhcflurry.random_negative_peptides.encode_random_negatives_on_device(*, planner, pool_epochs, peptide_encoding, device, generator=None, dtype=None, out=None)[source]

Sample + encode pool_epochs cycles of random negatives on device.

Parameters:
plannerRandomNegativePeptides

Already had plan(...) called.

pool_epochsint

Number of consecutive get_peptides() epochs to materialize. The result has pool_epochs * planner.get_total_count() rows.

peptide_encodingdict

Subset of Class1NeuralNetwork.network_hyperparameter_defaults that controls peptide encoding. Required keys: alignment_method, max_length. For pad_middle, left_edge and right_edge are also consulted (default 4 each, matching the historical defaults).

devicetorch.device or str

Output tensor device. Sampling and alignment writes happen here (no host round-trip).

generatortorch.Generator, optional

When supplied, all multinomial draws are routed through it. The caller is responsible for seeding (the numpy / torch RNG streams are not bridged — for reproducible parity tests, seed both).

dtypetorch.dtype, optional

Output dtype. Default torch.int8 (alphabet size 21 fits with room to spare).

outtorch.Tensor, optional

Pre-allocated output tensor of the correct shape, dtype, and device. When supplied, this function refills it in place — the usual pattern for the device-resident fit path, where the per-fit RN buffer is allocated once and reused per cycle.

Returns:
torch.Tensor of shape (pool_epochs * total_count, encoded_length),
dtype int8 by default, on device. Rows are the per-(allele,
length) blocks in canonical planner.plan_df row-major order,
repeated pool_epochs times — same layout the host path produces
after encoding planner.get_peptides().

mhcflurry.regression_target module

mhcflurry.regression_target.from_ic50(ic50, max_ic50=50000.0)[source]

Convert ic50s to regression targets in the range [0.0, 1.0].

Parameters:
ic50numpy.array of float

Affinities in nM; values outside [1, max_ic50] saturate the target.

max_ic50float, default 50000.0

Upper affinity scale in nM (must be greater than 1).

Returns:
numpy.array of float
mhcflurry.regression_target.to_ic50(x, max_ic50=50000.0)[source]

Convert regression targets in the range [0.0, 1.0] to ic50s in the range [1, max_ic50] nM. Values outside [0, 1] are not clipped.

Parameters:
xnumpy.array of float
max_ic50float, default 50000.0

Upper affinity scale in nM (must be greater than 1).

Returns:
numpy.array of float

mhcflurry.release_holdout module

Build and validate the frozen evaluation holdout for model releases.

mhcflurry.release_holdout.canonical_allele_mapping(values)[source]

Map raw class-I allele names to sequence-resolved canonical names.

mhcflurry.release_holdout.build_release_holdout(data_dir, training_data, mass_spec_data, out_dir, presentation_holdout_pmids=('31154438',), chunksize=500000)[source]

Derive release exclusions for one frozen source-study holdout.

Affinity metrics are evaluated on every monoallelic benchmark sample. Every pMHC from current affinity training that appears in those rows or in the selected multiallelic holdout (hit or decoy) is excluded. A separate source-sample manifest covers the union of these evaluation samples. Neither manifest alone proves complete biological-sample separation when historical training lineage or cross-study specimen aliases are missing. Processing and presentation are evaluated only on the named multiallelic source-study holdout; presentation excludes those samples from training in full.

mhcflurry.release_holdout.load_excluded_samples(path)[source]

Load a generated one-column sample exclusion manifest.

mhcflurry.release_holdout.exclude_samples(frame, manifest, label)[source]

Remove rows belonging to samples in manifest and report counts.

mhcflurry.release_holdout.exclude_affinity_pmhcs(frame, manifest)[source]

Remove affinity rows whose canonical pMHC is in manifest.

mhcflurry.release_holdout.validate_holdout_manifests(holdout_dir)[source]

Validate the exclusion manifests against the frozen policy record.

mhcflurry.release_holdout.validate_release_holdout(holdout_dir, affinity_training_data, processing_training_data, presentation_training_data, out=None)[source]

Check recorded pMHC/sample IDs, without asserting complete lineage.

Whole biological-sample separation additionally requires audit-samples across pretraining, training, development and selection for every model.

mhcflurry.release_holdout.make_parser(prog='mhcflurry train release-holdout')[source]
mhcflurry.release_holdout.run_argv(argv=None, prog='mhcflurry train release-holdout')[source]

mhcflurry.sample_disjointness module

Conservative biological-sample audits of explicitly inventoried lineage.

mhcflurry.sample_disjointness.read_identities(path)[source]

Read literal identity strings, including leading zeroes and ‘NA’.

class mhcflurry.sample_disjointness.SampleAliases(path=None)[source]

Bases: object

Resolve explicit specimen and study aliases; reject ambiguous cycles.

resolve(study, sample)[source]

Return the canonical study/sample pair for one source identity.

mhcflurry.sample_disjointness.source_identities(frame, aliases, *, identity_mode='source_provenance', study_column='study_id', sample_column='sample_id')[source]

Yield contributor identities and provenance completeness for each row.

Direct sample tables require an explicit inventory declaration. Assay IDs and source row numbers never substitute for biological samples.

mhcflurry.sample_disjointness.exclude_source_samples(frame, manifest, aliases=None)[source]

Exclude whole held-out samples, or whole studies if samples are unknown.

Any overlapping contributor removes the entire deduplicated measurement. Unknown lineage remains reported as unresolved. Missing study metadata on an exclusion conservatively matches that sample ID in every study.

mhcflurry.sample_disjointness.audit_samples(inventory_path, cohort_path, out_dir, *, aliases_path=None, sample_metadata=None)[source]

Write a new lineage audit and one shared sample-filtered cohort.

Separation is conditional on the supplied inventory and identity review. Only samples disjoint from every inventoried MHCflurry model enter the exported cohort. External uncertainty is reported separately. Passing an audit does not make a previously inspected benchmark an untouched test set.

mhcflurry.scoring module

Measures of prediction accuracy

mhcflurry.scoring.make_scores(ic50_y, ic50_y_pred, sample_weight=None, threshold_nm=500, max_ic50=50000)[source]

Calculate AUC, F1, and Kendall Tau scores.

Parameters:
ic50_yfloat list

true IC50s (i.e. affinities)

ic50_y_predfloat list

predicted IC50s

sample_weightfloat list [optional]
threshold_nmfloat [optional]
max_ic50float [optional]
Returns:
dict with entries “auc”, “f1”, “tau”

mhcflurry.scoring_pipeline module

Bounded CPU preparation/persistence around one accelerator scoring owner.

mhcflurry.scoring_pipeline.scoring_pipeline(workflows, score, max_in_flight=3, cpu_workers=2)[source]

Run resumable CPU workflows around serial caller-owned scoring.

Parameters:
workflowsiterable of (key, generator)

Each generator prepares a request, yields it to scoring, receives the returned scores, then persists/matches them. It may request additional scoring rounds, or return its completed result without requesting scores. Generators must own their mutable state and use independent RNGs.

scorecallable

score(key, request) runs only on the caller’s thread. The accelerator and predictor need not be thread-safe.

max_in_flightint

Maximum active sample workflows, including queued work and scored writes.

cpu_workersint

Maximum concurrently running CPU continuations.

Yields:
(key, result)

Completed samples in completion order. Callers restore scientific row order using keys, not completion order.

Notes

Backpressure bounds executor submission, not just worker count. On error or iterator close, queued work is cancelled and already running CPU stages are joined before generators close. Successful atomic writes remain resumable.

mhcflurry.select_allele_specific_models_command module

Compatibility wrapper for mhcflurry.cli.select_allele_specific_models_command.

mhcflurry.select_allele_specific_models_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.select_pan_allele_models_command module

Compatibility wrapper for mhcflurry.cli.select_pan_allele_models_command.

mhcflurry.select_pan_allele_models_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.select_processing_models_command module

Compatibility wrapper for mhcflurry.cli.select_processing_models_command.

mhcflurry.select_processing_models_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.testing_utils module

Utilities used in MHCflurry unit tests.

mhcflurry.testing_utils.startup()[source]

Configure PyTorch for running unit tests.

mhcflurry.testing_utils.cleanup()[source]

Clear PyTorch session and other process-wide resources.

mhcflurry.train_allele_specific_models_command module

Compatibility wrapper for mhcflurry.cli.train_allele_specific_models_command.

mhcflurry.train_allele_specific_models_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.train_pan_allele_models_command module

Compatibility wrapper for mhcflurry.cli.train_pan_allele_models_command.

mhcflurry.train_pan_allele_models_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.train_presentation_models_command module

Compatibility wrapper for mhcflurry.cli.train_presentation_models_command.

mhcflurry.train_presentation_models_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.train_processing_models_command module

Compatibility wrapper for mhcflurry.cli.train_processing_models_command.

mhcflurry.train_processing_models_command.run(argv=['-b', 'html', '-v', '-d', '_build/doctrees', '-W', '.', '_build/html'])[source]

mhcflurry.training_benchmark module

Training benchmark / profiling harness for pan-allele runs.

mhcflurry.training_benchmark.analyze_training_run(models_dir: str | PathLike[str], *, train_log: str | PathLike[str] | None = None, selection_log: str | PathLike[str] | None = None)[source]
mhcflurry.training_benchmark.build_arg_parser()[source]
mhcflurry.training_benchmark.main(argv=None)[source]

mhcflurry.training_folds module

Preserve explicit training folds when replaying archived model inputs.

mhcflurry.training_folds.read_processing_training_data(path)[source]

Read frozen processing data without numeric drift across CSV rewrites.

The round-trip parser preserves the binary float represented by the saved decimal, including matching-reference scores that are not model inputs. Sample identifiers stay strings, including purely numeric identifiers.

mhcflurry.training_folds.extract_training_folds(data, num_folds, reuse=False)[source]

Return data without fold columns and optionally validated stored folds.

mhcflurry.training_provenance module

Preserve source identities without changing curated measurement weights.

mhcflurry.training_provenance.file_sha256(path)[source]

Return the SHA-256 of an artifact’s bytes.

mhcflurry.training_provenance.identity_text(value)[source]

Return a literal identity, preserving meaningful leading zeroes.

mhcflurry.training_provenance.study_identity(value)[source]

Normalize numeric PubMed identifiers; retain explicit namespaces.

mhcflurry.training_provenance.encode_sources(records)[source]

Serialize distinct source records in canonical order.

mhcflurry.training_provenance.decode_sources(value)[source]

Read source records, refusing malformed JSON schemas.

mhcflurry.training_provenance.annotate_sources(frame, path, source, *, study_column=None, sample_column=None, assay_column=None)[source]

Attach raw identities before filtering or deduplication.

Missing study/sample IDs stay empty. File and row IDs support reconstruction but never substitute for biological samples. complete records retention of all source contributors, not availability of every sample identity.

mhcflurry.training_provenance.deduplicate_measurements(frame, subset)[source]

Keep the historical first measurement and union all source contributors.

Values, weighting and row order match drop_duplicates(subset). Unknown provenance on any contributor stays explicit beside known duplicates.

mhcflurry.version module

mhcflurry.workload_planning module

Central workload planning for local GPU/CPU orchestration.

mhcflurry.workload_planning.env_float(name, default, bounds=None)[source]

Read name from the environment as float, falling back to default.

bounds is an optional (low, high) tuple; either side may be None. Both endpoints are inclusive. Bad values are reported with the offending variable name so users don’t get a bare ValueError.

mhcflurry.workload_planning.env_int(name, default, bounds=None)[source]

Read name from the environment as int, falling back to default.

Bad values surface with the offending variable name. bounds works the same as env_float().

class mhcflurry.workload_planning.WorkloadProfile(name: str, device_worker_gb: float | None, data_pressure_start_gb: float = 0.0, data_pressure_factor: float = 0.0, data_pressure_cap_gb: float = 0.0, host_worker_gb: float = 2.0, host_data_multiplier: float = 0.0, host_data_cap_gb: float = 32.0, description: str = '')[source]

Bases: object

Policy defaults for one workload family.

name: str
device_worker_gb: float | None
data_pressure_start_gb: float = 0.0
data_pressure_factor: float = 0.0
data_pressure_cap_gb: float = 0.0
host_worker_gb: float = 2.0
host_data_multiplier: float = 0.0
host_data_cap_gb: float = 32.0
description: str = ''
class mhcflurry.workload_planning.LocalParallelismPlan(workload_name: str, backend: str, gpus: int, gpus_was_auto: bool, max_workers_per_gpu: int, max_workers_per_gpu_was_auto: bool, num_jobs: int, num_jobs_was_auto: bool, dataloader_num_workers: int, dataloader_num_workers_was_auto: bool, random_negative_pool_epochs: int | None, random_negative_pool_epochs_was_auto: bool, torch_compile: str, torch_compile_loss: str, matmul_precision: str, enable_timing: bool, capacity: int, device_worker_gb: float | None, data_pressure_gb: float, host_worker_gb: float, host_memory_total_gb: float | None, host_memory_available_gb: float | None, host_memory_source: str, host_memory_num_jobs_cap: int | None, cli_overrides: Tuple[str, ...] = (), warnings: Tuple[str, ...] = (), hints: Tuple[Tuple[str, object], ...] = (), warmup_device_peak_gb: float | None = None, warmup_host_peak_gb: float | None = None, cpu_threads_per_worker: int | None = None, cpu_threads_per_worker_was_auto: bool = True, device_memory_available_gb: float | None = None, device_memory_budget_gb: float | None = None)[source]

Bases: object

Resolved local orchestration plan.

This is the single object readers need to understand: it records the workload, hardware facts, CLI overrides, planner estimates, and final values that get written back onto argparse args.

workload_name: str
backend: str
gpus: int
gpus_was_auto: bool
max_workers_per_gpu: int
max_workers_per_gpu_was_auto: bool
num_jobs: int
num_jobs_was_auto: bool
dataloader_num_workers: int
dataloader_num_workers_was_auto: bool
random_negative_pool_epochs: int | None
random_negative_pool_epochs_was_auto: bool
torch_compile: str
torch_compile_loss: str
matmul_precision: str
enable_timing: bool
capacity: int
device_worker_gb: float | None
data_pressure_gb: float
host_worker_gb: float
host_memory_total_gb: float | None
host_memory_available_gb: float | None
host_memory_source: str
host_memory_num_jobs_cap: int | None
cli_overrides: Tuple[str, ...] = ()
warnings: Tuple[str, ...] = ()
hints: Tuple[Tuple[str, object], ...] = ()
warmup_device_peak_gb: float | None = None
warmup_host_peak_gb: float | None = None
cpu_threads_per_worker: int | None = None
cpu_threads_per_worker_was_auto: bool = True
device_memory_available_gb: float | None = None
device_memory_budget_gb: float | None = None
mhcflurry.workload_planning.get_workload_profile(workload_name)[source]

Return a workload profile, falling back to generic for unknown names.

mhcflurry.workload_planning.path_size_bytes(path)[source]

Best-effort file size lookup for planner hints.

mhcflurry.workload_planning.model_artifact_size_bytes(path)[source]

Best-effort uncompressed bytes for a model file or directory.

NumPy .npz weights are ZIP containers, so their on-disk size can be much smaller than their resident parameter tensors. Summing ZIP member sizes gives the planner a closer parameter-byte input without importing torch or loading a predictor in the parent process.

mhcflurry.workload_planning.system_memory_info_gb()[source]

Return host memory totals without importing heavy optional packages.

mhcflurry.workload_planning.available_or_total_memory_gb(memory)[source]

Return available RAM when measured, including a valid zero value.

mhcflurry.workload_planning.normalize_workload_hints(hints=None, **extra_hints)[source]

Merge workload hints, dropping unset additions.

Explicit keyword additions replace same-named values from hints. This is the normalization boundary shared by workload estimation and local parallelism planning.

mhcflurry.workload_planning.estimate_workload_memory(workload_name='generic', hints=None)[source]

Estimate device and host memory for a workload.

mhcflurry.workload_planning.host_memory_num_jobs_cap(memory, host_worker_gb, dataloader_num_workers=0, safety_fraction=None)[source]

Return worker cap from currently available host memory.

mhcflurry.workload_planning.is_auto_value(value)[source]

Return whether a CLI/programmatic sizing value delegates to auto.

mhcflurry.workload_planning.capacity_warnings(*, workload_name, backend, gpus, num_jobs, per_gpu_free_vram_gb, device_worker_gb, available_ram_gb, host_worker_gb, cpu_count)[source]

Compare a resolved plan against measured machine capacity.

Returns a list of human-readable warning strings for resources that are below a safe operating range (small / uneven / undetectable GPU VRAM, host RAM below the per-worker estimate, more workers than CPUs). Pure: no I/O and no side effects — the caller decides how to surface the strings. All measured inputs may be None when detection failed; each check is skipped when its inputs are missing.

mhcflurry.workload_planning.plan_local_parallelism(args, *, workload_name='generic', workload_hints=None, per_worker_gb=None, cap_auto_num_jobs=True, normalize_backend, detect_num_cuda_devices, auto_max_workers_per_gpu, auto_num_jobs, resolve_dataloader_num_workers, auto_random_negative_pool_epochs)[source]

Resolve all local-parallelism CLI flags into a plan.

Explicit CLI values override planner estimates. For explicit values that exceed estimated capacity, the planner records a warning and still returns the explicit value.