class_docstr: This class is responsible for analyzing the results and outputting various types of analysis to the results folder.
class_docstr_tok: ["This","class","is","responsible","for","analyzing","the","results","and","outputting","various","types","of","analysis","to","the","results","folder","."]
code: def exportTwoParameterScatter(
      self,
      fileName,
      results,
      parameter1,
      parameter2,
      valueKey="loss",
      cutoff=1.0,
      title="Scatter",
  ):
      parameter1Key = parameter1.root[5:]
      parameter2Key = parameter2.root[5:]
  
      losses = [
          result[valueKey]
          for result in results
          if result[valueKey] is not None
      ]
      threshhold = numpy.percentile(losses, cutoff * 100)
  
      # Put all of the results into buckets based on their value for parameter1 / parameter2
      resultsMerged = {}
      for result in results:
          if (
              result[valueKey] is not None
              and result[valueKey] <= threshhold
          ):
              if (
                  isinstance(result[parameter1Key], float)
                  or isinstance(result[parameter1Key], int)
                  or isinstance(result[parameter1Key], bool)
              ):
                  if (
                      isinstance(result[parameter2Key], float)
                      or isinstance(result[parameter2Key], int)
                      or isinstance(result[parameter2Key], bool)
                  ):
                      key = (
                          result[parameter1Key],
                          result[parameter2Key],
                      )
  
                      if key not in resultsMerged:
                          resultsMerged[key] = []
  
                      resultsMerged[key].append(result[valueKey])
  
      losses = [numpy.min(vals) for key, vals in resultsMerged.items()]
  
      xCoords = []
      yCoords = []
      scores = []
      sizes = []
  
      minVal = float(numpy.min(losses))
      maxVal = float(numpy.max(losses))
      redVal = float(numpy.percentile(losses, q=90))
      yellowVal = float(numpy.percentile(losses, q=40))
      greenVal = float(numpy.percentile(losses, q=20))
      blueVal = float(numpy.percentile(losses, q=5))
  
      if (maxVal - minVal) > 0:
          redVal = (redVal - minVal) / (maxVal - minVal)
          yellowVal = (yellowVal - minVal) / (maxVal - minVal)
          greenVal = (greenVal - minVal) / (maxVal - minVal)
          blueVal = (blueVal - minVal) / (maxVal - minVal)
      else:
          redVal = 0.9
          yellowVal = 0.6
          greenVal = 0.3
          blueVal = 0.1
  
      green = numpy.array([0, 1, 0, 1])
      yellow = numpy.array([1, 1, 0, 1])
      red = numpy.array([1, 0, 0, 1])
      blue = numpy.array([0.3, 0.3, 1, 1])
  
      if self.twoParameterScatterFigure is None:
          fig, ax = plt.subplots()
          self.twoParameterScatterFigure = fig
          self.twoParameterScatterAxes = ax
      else:
          fig = self.twoParameterScatterFigure
          ax = self.twoParameterScatterAxes
          ax.clear()
  
      # We shuffle the results here because the scatter plot will by default draw later points over earlier ones, and later results will be on average better
      # anyhow, skewing the graphic
      resultsShuffled = list(results)
      random.shuffle(resultsShuffled)
      for key, resultScores in resultsMerged.items():
          xCoords.append(key[0])
          yCoords.append(key[1])
          if (maxVal - minVal) > 0:
              value = float(
                  (numpy.min(resultScores) - minVal) / (maxVal - minVal)
              )
              scores.append(value)
              sizeAdjust = 1.0 - min(
                  1, ((value * value)) / (redVal * redVal)
              )
              sizes.append(10 + sizeAdjust * 25)
          else:
              value = float((numpy.min(resultScores) - minVal))
              scores.append(value)
              sizes.append(20.0)
  
      if parameter1.config.get("scaling", "linear") == "logarithmic":
          ax.set_xscale("log")
      else:
          ax.set_xscale("linear")
  
      if parameter2.config.get("scaling", "linear") == "logarithmic":
          ax.set_yscale("log")
      else:
          ax.set_yscale("linear")
  
      minVal = parameter1.config.get("min")
      maxVal = parameter1.config.get("max")
      if (
          minVal > 0.001
          and minVal < 10000
          and maxVal > 0.001
          and maxVal < 10000
      ):
          ax.xaxis.set_minor_formatter(mticker.ScalarFormatter())
          ax.xaxis.set_major_formatter(mticker.ScalarFormatter())
      else:
          ax.xaxis.set_minor_formatter(
              mticker.LogFormatterSciNotation()
          )
          ax.xaxis.set_major_formatter(
              mticker.LogFormatterSciNotation()
          )
  
      minVal = parameter2.config.get("min")
      maxVal = parameter2.config.get("max")
      if (
          minVal > 0.001
          and minVal < 10000
          and maxVal > 0.001
          and maxVal < 10000
      ):
          ax.yaxis.set_minor_formatter(mticker.ScalarFormatter())
          ax.yaxis.set_major_formatter(mticker.ScalarFormatter())
      else:
          ax.yaxis.set_minor_formatter(
              mticker.LogFormatterSciNotation()
          )
          ax.yaxis.set_major_formatter(
              mticker.LogFormatterSciNotation()
          )
  
      colorList = [
          (0, blue),
          (blueVal, blue),
          (greenVal, green),
          (yellowVal, yellow),
          (redVal, red),
          (1.0, red),
      ]
      ax.scatter(
          xCoords,
          yCoords,
          c=numpy.array(scores),
          s=numpy.array(sizes),
          cmap=matplotlib.colors.LinearSegmentedColormap.from_list(
              "loss_matrix", colorList, N=50000
          ),
          alpha=0.7,
      )
  
      fig.suptitle(
          title
          + " of "
          + parameter1.root[5:]
          + " vs "
          + parameter2.root[5:],
          fontdict={"fontsize": 10},
      )
  
      ax.set_xlabel(parameter1Key)
      ax.set_ylabel(parameter2Key)
  
      fig.set_tight_layout(True)
      fig.savefig(fileName, dpi=200)
      plt.close(fig)
  
imports: import jsonschema
  import os
  import os.path
  import math
  import csv
  from hypermax.hyperparameter import Hyperparameter
  import sklearn.covariance
  import numpy
  from hypermax.utils import roundPrecision
  import matplotlib
  import matplotlib.cm
  import matplotlib.style
  import matplotlib.pyplot
  from pprint import pprint
  import concurrent.futures
  import colors
  import traceback
  import functools
  import warnings
  import scipy.optimize
  import random
  import json
  import atexit
  import matplotlib.ticker
  import traceback
  import copy
label_desc: Use image node_id 9 for calling the ResultsAnalyzer obj's underlying member method code with example usage: obj.exportTwoParameterScatter(fileName, results, parameter1, parameter2, valueKey, cutoff, title) without return types