From 5d0bf7d5b650ce524727cdc6411d5bdab4ac2a7c Mon Sep 17 00:00:00 2001
From: Tim O'Donnell <timodonnell@gmail.com>
Date: Fri, 17 Mar 2017 00:34:03 -0400
Subject: [PATCH] small fixes

---
 examples/class1_allele_specific_models.ipynb  | 14 ++-------
 .../mhcflurry_released.py                     | 20 +++++++++----
 mhcflurry/class1_allele_specific/__init__.py  |  8 ++++-
 ...ss1_single_model_multi_allele_predictor.py |  8 +++--
 .../__init__.py                               |  2 ++
 .../class1_ensemble_multi_allele_predictor.py | 30 +++++++++++++++++++
 mhcflurry/downloads.yml                       |  2 +-
 7 files changed, 62 insertions(+), 22 deletions(-)

diff --git a/examples/class1_allele_specific_models.ipynb b/examples/class1_allele_specific_models.ipynb
index 0fda9cd6..f9942936 100644
--- a/examples/class1_allele_specific_models.ipynb
+++ b/examples/class1_allele_specific_models.ipynb
@@ -2,21 +2,11 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {
     "collapsed": false
    },
-   "outputs": [
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Using Theano backend.\n",
-      "/Users/tim/miniconda3/envs/py3k/lib/python3.5/site-packages/matplotlib/__init__.py:872: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.\n",
-      "  warnings.warn(self.msg_depr % (key, alt_key))\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "import mhcflurry\n",
     "import numpy\n",
diff --git a/mhcflurry/antigen_presentation/presentation_component_models/mhcflurry_released.py b/mhcflurry/antigen_presentation/presentation_component_models/mhcflurry_released.py
index fc401e32..cb08000d 100644
--- a/mhcflurry/antigen_presentation/presentation_component_models/mhcflurry_released.py
+++ b/mhcflurry/antigen_presentation/presentation_component_models/mhcflurry_released.py
@@ -21,15 +21,22 @@ class MHCflurryReleased(PresentationComponentModel):
     random_peptides_for_percent_rank : list of string
         If specified, then percentile rank will be calibrated and emitted
         using the given peptides.
+
+    predictor : Class1EnsembleMultiAllelePredictor-like object
+        Predictor to use.
     """
 
     def __init__(
             self,
             experiment_to_alleles,
             random_peptides_for_percent_rank=None,
+            predictor=None,
+            predictor_name="mhcflurry_released",
             **kwargs):
         PresentationComponentModel.__init__(self, **kwargs)
         self.experiment_to_alleles = experiment_to_alleles
+        self.predictor = predictor
+        self.predictor_name = predictor_name
         if random_peptides_for_percent_rank is None:
             self.percent_rank_transforms = None
             self.random_peptides_for_percent_rank = None
@@ -39,9 +46,9 @@ class MHCflurryReleased(PresentationComponentModel):
                 random_peptides_for_percent_rank)
 
     def column_names(self):
-        columns = ['mhcflurry_released_affinity']
+        columns = [self.predictor_name + '_affinity']
         if self.percent_rank_transforms is not None:
-            columns.append('mhcflurry_released_percentile_rank')
+            columns.append(self.predictor_name + '_percentile_rank')
         return columns
 
     def requires_fitting(self):
@@ -63,11 +70,14 @@ class MHCflurryReleased(PresentationComponentModel):
             normalize_allele_name(allele)
             for allele in alleles
         ]
-        df = predict(alleles, numpy.unique(numpy.array(peptides)))
+        df = predict(
+            alleles,
+            numpy.unique(numpy.array(peptides)),
+            predictor=self.predictor)
         pivoted = df.pivot(index='Peptide', columns='Allele')
         pivoted.columns = pivoted.columns.droplevel()
         result = {
-            'mhcflurry_released_affinity': (
+            self.predictor_name + '_affinity': (
                 pivoted.min(axis=1).ix[peptides].values)
         }
         if self.percent_rank_transforms is not None:
@@ -77,7 +87,7 @@ class MHCflurryReleased(PresentationComponentModel):
                 percentile_ranks[allele] = (
                     self.percent_rank_transforms[allele]
                     .transform(pivoted[allele].values))
-            result['mhcflurry_released_percentile_rank'] = (
+            result[self.predictor_name + '_percentile_rank'] = (
                 percentile_ranks.min(axis=1).ix[peptides].values)
         return result
 
diff --git a/mhcflurry/class1_allele_specific/__init__.py b/mhcflurry/class1_allele_specific/__init__.py
index 55b703f3..228b33d9 100644
--- a/mhcflurry/class1_allele_specific/__init__.py
+++ b/mhcflurry/class1_allele_specific/__init__.py
@@ -3,7 +3,11 @@ from __future__ import absolute_import
 from .class1_binding_predictor import Class1BindingPredictor
 from .train import train_across_models_and_folds, AlleleSpecificTrainTestFold
 from .cross_validation import cross_validation_folds
-from .class1_single_model_multi_allele_predictor import from_allele_name, supported_alleles
+from .class1_single_model_multi_allele_predictor import (
+    from_allele_name,
+    supported_alleles,
+    get_downloaded_predictor,
+    Class1SingleModelMultiAllelePredictor)
 
 __all__ = [
     'Class1BindingPredictor',
@@ -12,4 +16,6 @@ __all__ = [
     'train_across_models_and_folds',
     'from_allele_name',
     'supported_alleles',
+    'get_downloaded_predictor',
+    'Class1SingleModelMultiAllelePredictor',
 ]
diff --git a/mhcflurry/class1_allele_specific/class1_single_model_multi_allele_predictor.py b/mhcflurry/class1_allele_specific/class1_single_model_multi_allele_predictor.py
index 30f53d3f..1dca8766 100644
--- a/mhcflurry/class1_allele_specific/class1_single_model_multi_allele_predictor.py
+++ b/mhcflurry/class1_allele_specific/class1_single_model_multi_allele_predictor.py
@@ -32,7 +32,7 @@ CACHED_PREDICTOR = None
 
 def from_allele_name(allele_name):
     """
-    Load a predictor for an allele using the default loader.
+    Load a single-allele predictor.
 
     Parameters
     ----------
@@ -42,7 +42,7 @@ def from_allele_name(allele_name):
     ----------
     Class1BindingPredictor
     """
-    return get_downloaded_predictor().from_allele_name(allele_name)
+    return get_downloaded_predictor().predictor_for_allele(allele_name)
 
 
 def supported_alleles():
@@ -65,7 +65,9 @@ def get_downloaded_predictor():
     # different.
     path = get_path("models_class1_allele_specific_single")
     if CACHED_PREDICTOR is None or path != CACHED_PREDICTOR.path:
-        CACHED_PREDICTOR = Class1SingleModelMultiAllelePredictor(path)
+        CACHED_PREDICTOR = (
+            Class1SingleModelMultiAllelePredictor
+                .load_from_download_directory(path))
     return CACHED_PREDICTOR
 
 
diff --git a/mhcflurry/class1_allele_specific_ensemble/__init__.py b/mhcflurry/class1_allele_specific_ensemble/__init__.py
index c262840a..c9dd8949 100644
--- a/mhcflurry/class1_allele_specific_ensemble/__init__.py
+++ b/mhcflurry/class1_allele_specific_ensemble/__init__.py
@@ -1,8 +1,10 @@
 from .class1_ensemble_multi_allele_predictor import (
     Class1EnsembleMultiAllelePredictor,
+    get_downloaded_predictor,
     HYPERPARAMETER_DEFAULTS)
 
 __all__ = [
     "Class1EnsembleMultiAllelePredictor",
+    "get_downloaded_predictor",
     "HYPERPARAMETER_DEFAULTS",
 ]
diff --git a/mhcflurry/class1_allele_specific_ensemble/class1_ensemble_multi_allele_predictor.py b/mhcflurry/class1_allele_specific_ensemble/class1_ensemble_multi_allele_predictor.py
index 8058b7c2..3192fbd1 100644
--- a/mhcflurry/class1_allele_specific_ensemble/class1_ensemble_multi_allele_predictor.py
+++ b/mhcflurry/class1_allele_specific_ensemble/class1_ensemble_multi_allele_predictor.py
@@ -34,6 +34,7 @@ import pandas
 
 from ..hyperparameters import HyperparameterDefaults
 from ..class1_allele_specific import Class1BindingPredictor, scoring
+from ..downloads import get_path
 from .. import parallelism, common
 
 MEASUREMENT_COLLECTION_HYPERPARAMETER_DEFAULTS = HyperparameterDefaults(
@@ -56,6 +57,35 @@ HYPERPARAMETER_DEFAULTS = (
     .extend(Class1BindingPredictor.hyperparameter_defaults))
 
 
+CACHED_PREDICTOR = None
+
+
+def supported_alleles():
+    """
+    Return a list of the names of the alleles for which there are trained
+    predictors in the default laoder.
+    """
+    return get_downloaded_predictor().supported_alleles
+
+
+def get_downloaded_predictor():
+    """
+    Return a Class1AlleleSpecificPredictorLoader that uses downloaded models.
+    """
+    global CACHED_PREDICTOR
+
+    # Some of the unit tests manipulate the downloads directory configuration
+    # so get_path here may return different results in the same Python process.
+    # For this reason we check the path and invalidate the loader if it's
+    # different.
+    path = get_path("models_class1_allele_specific_ensemble")
+    if CACHED_PREDICTOR is None or path != CACHED_PREDICTOR.path:
+        CACHED_PREDICTOR = (
+            Class1EnsembleMultiAllelePredictor
+                .load_from_download_directory(path))
+    return CACHED_PREDICTOR
+
+
 def call_fit_and_test(args):
     return fit_and_test(*args)
 
diff --git a/mhcflurry/downloads.yml b/mhcflurry/downloads.yml
index 98b08ee6..aa8ad6b1 100644
--- a/mhcflurry/downloads.yml
+++ b/mhcflurry/downloads.yml
@@ -8,7 +8,7 @@
 # by name, the downloads with "default=true" are downloaded.
 
 # This should usually be the latest release.
-current-release: 0.0.8
+current-release: 0.1.0
 
 # An integer indicating what models the current MHCflurry code base is compatible
 # with. Increment this integer when changes are made to MHCflurry that would break
-- 
GitLab