 
   read = (value) -> if value is 'NaN' then null else value
 
-  inspectMultinomialPrediction2 = (frameLabel, prediction) -> ->
-    { frame, model } = prediction
-    origin = "getModel #{stringify prediction.model.name}"
-
-    vectors = [
-      createFactor 'model_category', TString, [ prediction.model_category ]
-      createVector 'mse', TNumber, [ prediction.mse ]
-      createVector 'logloss', TNumber, [ prediction.logloss ]
-      createVector 'duration_in_ms', TNumber, [ prediction.duration_in_ms ]
-      createVector 'scoring_time', TNumber, [ prediction.scoring_time ]
-    ]
-
-    createDataframe frameLabel, vectors, (sequence 1), null,
-      description: frameLabel
-      origin: origin
-
-  inspectRegressionPrediction2 = (frameLabel, prediction) -> ->
-    { frame, model } = prediction
-    origin = "getModel #{stringify prediction.model.name}"
-
-    vectors = [
-      createFactor 'model_category', TString, [ prediction.model_category ]
-      createVector 'mse', TNumber, [ prediction.mse ]
-      createVector 'sigma', TNumber, [ prediction.sigma ]
-      createVector 'logloss', TNumber, [ prediction.logloss ]
-      createVector 'duration_in_ms', TNumber, [ prediction.duration_in_ms ]
-      createVector 'scoring_time', TNumber, [ prediction.scoring_time ]
-    ]
-
-    createDataframe frameLabel, vectors, (sequence 1), null,
-      description: frameLabel
-      origin: origin
-
-  inspectRegressionPrediction = (prediction) -> ->
-    { frame, model } = prediction
-
-    vectors = [
-      createFactor 'key', TString, [ model.name ]
-      createFactor 'frame', TString, [ frame.name ]
-      createFactor 'model_category', TString, [ prediction.model_category ]
-      createVector 'mse', TNumber, [ prediction.mse ]
-      createVector 'sigma', TNumber, [ prediction.sigma ]
-      createVector 'logloss', TNumber, [ prediction.logloss ]
-      createVector 'duration_in_ms', TNumber, [ prediction.duration_in_ms ]
-      createVector 'scoring_time', TNumber, [ prediction.scoring_time ]
-    ]
-
-    createDataframe 'prediction', vectors, (sequence 1), null,
-      description: "Prediction output for model '#{model.name}' on frame '#{frame.name}'"
-      origin: "getPrediction model: #{stringify model.name}, frame: #{stringify frame.name}"
-
-  inspectBinomialPrediction2 = (frameLabel, prediction) -> ->
-    origin = "getModel #{stringify prediction.model.name}"
-    { frame, model } = prediction
-
-    vectors = [
-      createFactor 'model_category', TString, [ prediction.model_category ]
-      createVector 'AUC', TNumber, [ prediction.AUC ]
-      createVector 'Gini', TNumber, [ prediction.Gini ]
-      createVector 'mse', TNumber, [ prediction.mse ]
-      createVector 'logloss', TNumber, [ prediction.logloss ]
-      createVector 'duration_in_ms', TNumber, [ prediction.duration_in_ms ]
-      createVector 'scoring_time', TNumber, [ prediction.scoring_time ]
-    ]
-
-    createDataframe frameLabel, vectors, (sequence 1), null,
-      description: frameLabel
-      origin: origin
-
-  inspectBinomialPrediction = (prediction) -> ->
-    { frame, model } = prediction
-
-    vectors = [
-      createFactor 'key', TString, [ model.name ]
-      createFactor 'frame', TString, [ frame.name ]
-      createFactor 'model_category', TString, [ prediction.model_category ]
-      createVector 'AUC', TNumber, [ prediction.AUC ]
-      createVector 'Gini', TNumber, [ prediction.Gini ]
-      createVector 'mse', TNumber, [ prediction.mse ]
-      createVector 'logloss', TNumber, [ prediction.logloss ]
-      createVector 'duration_in_ms', TNumber, [ prediction.duration_in_ms ]
-      createVector 'scoring_time', TNumber, [ prediction.scoring_time ]
-    ]
-
-    createDataframe 'Prediction', vectors, (sequence 1), null,
-      description: "Prediction output for model '#{model.name}' on frame '#{frame.name}'"
-      origin: "getPrediction model: #{stringify model.name}, frame: #{stringify frame.name}"
-
-  inspectMultinomialConfusionMatrix = (name, table, origin, inspections) ->
-    table.name = name
-    inspections[ table.name ] = ->
-      convertTableToFrame table,
-        description: table.name
-        origin: origin
-
-  inspectBinomialConfusionMatrices2 = (frameLabel, prediction) -> ->
-    origin = "getModel #{stringify prediction.model.name}"
-    vectors = [
-      createList 'CM', prediction.confusion_matrices, formatConfusionMatrix
-      createVector 'TPR', TNumber, map prediction.confusion_matrices, computeTruePositiveRate
-      createVector 'FPR', TNumber, map prediction.confusion_matrices, computeFalsePositiveRate
-    ]
-    createDataframe frameLabel, vectors, (sequence prediction.confusion_matrices.length), null,
-      description: frameLabel
-      origin: origin
-      plot: "plot inspect '#{frameLabel}', #{origin}"
-
-
+  #TODO obsolete
   inspectBinomialConfusionMatrices = (opts, predictions) -> ->
     vectors = [
       createList 'CM', (concatArrays (prediction.confusion_matrices for prediction in predictions)), formatConfusionMatrix

      description: "Parameters for model '#{model.key.name}'" #TODO frame key
      origin: "getModel #{stringify model.key.name}"

  inspectGLMModelOutput = (model) -> ->
    output = model.output

    vectors = [
      createFactor 'model_category', TString, [ output.model_category ]
      createFactor 'binomial', TString, [ output.binomial ]
      createVector 'aic', TNumber, [ output.aic ]
      createVector 'auc', TNumber, [ output.auc ]
      createVector 'best_lambda_idx', TNumber, [ output.best_lambda_idx ]
      createVector 'null_degrees_of_freedom', TNumber, [ output.null_degrees_of_freedom ]
      createVector 'null_deviance', TNumber, [ output.null_deviance ]
      createVector 'rank', TNumber, [ output.rank ]
      createVector 'residual_degrees_of_freedom', TNumber, [ output.residual_degrees_of_freedom ]
      createVector 'residual_deviance', TNumber, [ output.residual_deviance ]
      createVector 'threshold', TNumber, [ output.threshold ]
    ]

    createDataframe 'output', vectors, (sequence 1), null,
      description: "Output for GLM model '#{model.key.name}'"
      origin: "getModel #{stringify model.key.name}"

  inspectGLMCoefficientsMagnitude = (model) -> ->
    convertTableToFrame model.output.coefficients_magnitude,
      description: "#{model.output.coefficients_magnitude.name} for GLM model #{model.key.name}"
      origin: "getModel #{stringify model.key.name}"

  inspectGLMCoefficientsTable = (model) -> ->
    convertTableToFrame model.output.coefficients_table,
      description: "#{model.output.coefficients_table.name} for GLM model #{model.key.name}"
      origin: "getModel #{stringify model.key.name}"

  inspectGBMModelOutput = (model) -> ->
    output = model.output

    size = output.mse_train.length

    vectors = [
      createVector 'tree', TNumber, (sequence size)
      createVector 'mse_train', TNumber, parseNaNs output.mse_train
    ]

    if output.mse_valid
      vectors.push createVector 'mse_valid', TNumber, parseNaNs output.mse_valid

    createDataframe 'output', vectors, (sequence size), null,
      description: "Output for GBM model '#{model.key.name}'"
      origin: "getModel #{stringify model.key.name}"

  inspectKMeansModelOutput = (model) -> ->
    output = model.output

    vectors = [
      createVector 'avg_between_ss', TNumber, [ output.avg_between_ss ]
      createVector 'avg_ss', TNumber, [ output.avg_ss ]
      createVector 'avg_within_ss', TNumber, [ output.avg_within_ss ]
      createVector 'categorical_column_count', TNumber, [ output.categorical_column_count ]
      createVector 'iterations', TNumber, [ output.iterations ]
      createFactor 'model_category', TString, [ output.model_category ]
    ]

    createDataframe 'output', vectors, (sequence 1), null,
      description: "Output for k-means model '#{model.key.name}'"
      origin: "getModel #{stringify model.key.name}"

  inspectKmeansModelClusters = (model) -> ->
    output = model.output

    vectors = [
      createFactor 'cluster', TString, head output.centers.data
      createVector 'size', TNumber, output.size
      createVector 'within_mse', TNumber, output.within_mse
    ]

    createDataframe 'clusters', vectors, (sequence output.size.length), null, 
      description: "Clusters for k-means model '#{model.key.name}'"
      origin: "getModel #{stringify model.key.name}"

  inspectKmeansModelClusterMeans = (model) -> ->
    convertTableToFrame model.output.centers, 
      description: "Cluster means for k-means model '#{model.key.name}'"
      origin: "getModel #{stringify model.key.name}"

  extendKMeansModel = (model) ->
    inspect_ model,
      parameters: inspectModelParameters model
      output: inspectKMeansModelOutput model
      clusters: inspectKmeansModelClusters model
      'Cluster means': inspectKmeansModelClusterMeans model

  extendDeepLearningModel = (model) ->

    origin = "getModel #{stringify model.key.name}"

    inspections = {}
    inspections.parameters = inspectModelParameters model

    modelCategory = model.output.model_category

    if modelCategory is 'Binomial' or modelCategory is 'Multinomial' or modelCategory is 'Regression' or modelCategory is 'AutoEncoder'
      tables = [ model.output.model_summary, model.output.scoring_history ]
      tables.forEach (table) ->
        inspections[ table.name ] = ->
          convertTableToFrame table,
            description: table.name 
            origin: origin
            plot: "plot inspect '#{table.name}', #{origin}"

      if variableImportances = model.output.variable_importances
        inspections[ variableImportances.name ] = ->
          convertTableToFrame variableImportances,
            description: variableImportances.name
            origin: origin
            plot: "plot inspect '#{variableImportances.name}', #{origin}"

    if modelCategory is 'Binomial'
      if trainMetrics = model.output.training_metrics
        trainMetrics.thresholds_and_metric_scores.name = 'Training ' + trainMetrics.thresholds_and_metric_scores.name
        trainMetrics.max_criteria_and_metric_scores.name = 'Training ' + trainMetrics.max_criteria_and_metric_scores.name

        inspections[ 'Training Metrics' ] = inspectBinomialPrediction2 'Training Metrics', trainMetrics

        inspections[ trainMetrics.thresholds_and_metric_scores.name ] = -> 
          convertTableToFrame trainMetrics.thresholds_and_metric_scores,
            description: trainMetrics.thresholds_and_metric_scores.name
            origin: origin
            plot: "plot inspect '#{trainMetrics.thresholds_and_metric_scores.name}', #{origin}"

        inspections[ trainMetrics.max_criteria_and_metric_scores.name ] = -> 
          convertTableToFrame trainMetrics.max_criteria_and_metric_scores,
            description: trainMetrics.max_criteria_and_metric_scores.name
            origin: origin
            plot: "plot inspect '#{trainMetrics.max_criteria_and_metric_scores.name}', #{origin}"

        inspections[ 'Training Confusion Matrices' ] = inspectBinomialConfusionMatrices2 'Training Confusion Matrices', trainMetrics

      if validMetrics = model.output.validation_metrics
        validMetrics.thresholds_and_metric_scores.name = 'Validation ' + validMetrics.thresholds_and_metric_scores.name
        validMetrics.max_criteria_and_metric_scores.name = 'Validation ' + validMetrics.max_criteria_and_metric_scores.name

        inspections[ 'Validation Metrics' ] = inspectBinomialPrediction2 'Validation Metrics', validMetrics
        inspections[ validMetrics.thresholds_and_metric_scores.name ] = -> 
          convertTableToFrame validMetrics.thresholds_and_metric_scores,
            description: validMetrics.thresholds_and_metric_scores.name
            origin: origin
            plot: "plot inspect '#{validMetrics.thresholds_and_metric_scores.name}', #{origin}"

        inspections[ validMetrics.max_criteria_and_metric_scores.name ] = -> 
          convertTableToFrame validMetrics.max_criteria_and_metric_scores,
            description: validMetrics.max_criteria_and_metric_scores.name
            origin: origin
            plot: "plot inspect '#{validMetrics.max_criteria_and_metric_scores.name}', #{origin}"

        inspections[ 'Validation Confusion Matrices' ] = inspectBinomialConfusionMatrices2 'Validation Confusion Matrices', validMetrics

    else if modelCategory is 'Multinomial'

      if trainMetrics = model.output.training_metrics
        inspections[ 'Training Metrics' ] = inspectMultinomialPrediction2 'Training Metrics', trainMetrics
        if table = trainMetrics.cm.table
          inspectMultinomialConfusionMatrix 'Training Confusion Matrix', table, origin, inspections

      if validMetrics = model.output.validation_metrics
        inspections[ 'Validation Metrics' ] = inspectMultinomialPrediction2 'Validation Metrics', validMetrics
        if table = validMetrics.cm.table
          inspectMultinomialConfusionMatrix 'Validation Confusion Matrix', table, origin, inspections

    else if modelCategory is 'Regression'
      if trainMetrics = model.output.training_metrics
        inspections[ 'Training Metrics' ] = inspectRegressionPrediction2 'Training Metrics', trainMetrics

      if validMetrics = model.output.validation_metrics
        inspections[ 'Validation Metrics' ] = inspectRegressionPrediction2 'Validation Metrics', validMetrics

    inspect_ model, inspections
  
  extendGBMModel = (model) ->
    origin = "getModel #{stringify model.key.name}"

    inspections = {}
    inspections.parameters = inspectModelParameters model
    inspections.output = inspectGBMModelOutput model

    if variableImportances = model.output.variable_importances
      inspections[variableImportances.name] = ->
        convertTableToFrame variableImportances,
          description: variableImportances.name
          origin: origin
          plot: "plot inspect '#{variableImportances.name}', #{origin}"

    inspect_ model, inspections

  extendGLMModel = (model) ->
    inspections = {}
    inspections.parameters = inspectModelParameters model
    inspections.output = inspectGLMModelOutput model
    if model.output.coefficients_magnitude
      inspections[model.output.coefficients_magnitude.name] = inspectGLMCoefficientsMagnitude model 
    if model.output.coefficients_table
      inspections[model.output.coefficients_table.name] = inspectGLMCoefficientsTable model
    inspect_ model, inspections

  extendJob = (job) ->
    render_ job, H2O.JobOutput, job


      origin: formulateGetPredictionsOrigin opts
      plot: "plot inspect 'Confusion Matrices', #{formulateGetPredictionsOrigin opts}"

  extendPredictions = (opts, predictions) ->
    render_ predictions, H2O.PredictsOutput, opts, predictions
    predictions

  extendPrediction = (modelKey, frameKey, prediction) ->
    inspections = {}
