예제 #1
0
def doParse(dataArray,lk,outputBaseFilename,setOfRequestedColumns,column_names,dataRanges,all_best_fit_data,nBins,alt_best_fit):
  #Perform all numerical operations required for chain parsing

  # Determine the minimum log-likelihood requested as an isocontour in 2D plots
  min_contour = None
  if doProfile.value and twoDplots.value and contours2D.value:
    min_contour = deltaLnLike(1.0,0.01*max(contours2D.value))

  # Standardise likelihood, prior and multiplicity labels, and rescale likelihood and columns if necessary
  standardise(dataArray,lk)
  # Sort array if required
  doSort(dataArray,lk)
  # Find best-fit point
  [bestFit,worstFit,bestFitIndex] = getBestFit(dataArray,lk,outputBaseFilename,column_names,all_best_fit_data,alt_best_fit,min_contour)
  # Find posterior mean
  [totalMult, posteriorMean] = getPosteriorMean(dataArray,lk,outputBaseFilename)
  # Get evidence for mcmc
  [lnZMain,lnZMainError] = getEvidence(dataArray,lk,bestFit,totalMult,outputBaseFilename)
  # Save data minima and maxima
  saveExtrema(dataArray,lk,outputBaseFilename,setOfRequestedColumns,dataRanges)
  # Save variables to plot in log scale
  saveLogVars(lk,outputBaseFilename,logPlots)
  # Save lookup keys for parameters
  saveLookupKeys(lk,outputBaseFilename)
  # Do binning for 1D plots
  oneDsampler(dataArray,lk,bestFit,worstFit,outputBaseFilename,dataRanges,nBins)
  # Do binning for 2D plots
  twoDsampler(dataArray,lk,bestFit,worstFit,outputBaseFilename,dataRanges,nBins)
예제 #2
0
def doParse(dataArray,lk,outputBaseFilename,setOfRequestedColumns,column_names,dataRanges,all_best_fit_data,nBins,alt_best_fit):
  #Perform all numerical operations required for chain parsing

  # Determine the minimum log-likelihood requested as an isocontour in 2D plots
  min_contour = None
  if doProfile.value and twoDplots.value and contours2D.value:
    min_contour = deltaLnLike(1.0,0.01*max(contours2D.value))

  # Standardise likelihood, prior and multiplicity labels, and rescale likelihood and columns if necessary
  standardise(dataArray,lk)
  # Sort array if required
  doSort(dataArray,lk)
  # Find best-fit point
  [bestFit,worstFit,bestFitIndex] = getBestFit(dataArray,lk,outputBaseFilename,column_names,all_best_fit_data,alt_best_fit,min_contour)
  # Find posterior mean
  [totalMult, posteriorMean] = getPosteriorMean(dataArray,lk,outputBaseFilename)
  # Get evidence for mcmc
  [lnZMain,lnZMainError] = getEvidence(dataArray,lk,bestFit,totalMult,outputBaseFilename)
  # Save data minima and maxima
  saveExtrema(dataArray,lk,outputBaseFilename,setOfRequestedColumns,dataRanges)
  # Save lookup keys for parameters
  saveLookupKeys(lk,outputBaseFilename)
  # Do binning for 1D plots
  oneDsampler(dataArray,lk,bestFit,worstFit,outputBaseFilename,dataRanges,nBins)
  # Do binning for 2D plots
  twoDsampler(dataArray,lk,bestFit,worstFit,outputBaseFilename,dataRanges,nBins)
예제 #3
0
def twoDsampler(dataArray, lk, bestFit, worstFit, outputBaseFilename, dataRanges, nAllBins):
    # Do sample sorting for 2D plots

    if twoDplots.value is None:
        return

    # Determine profile likelihood contour levels (same for all plots of a given dimensionality)
    if contours.value is not None:
        profContourLevels = [np.exp(-deltaLnLike(1.0, 0.01 * contour)) for contour in contours.value]
        outName = outputBaseFilename + "_like2D.contours"
        outfile = smart_open(outName, "w")
        outfile.write(
            "# This 2D profile likelihood ratio contours file created by pippi "
            + pippiVersion
            + " on "
            + datetime.datetime.now().strftime("%c")
            + "\n"
        )
        outfile.write(" ".join([str(x) for x in profContourLevels]))
        outfile.close

    for plot in twoDplots.value:

        print "    Parsing data for 2D plots of quantities ", plot

        nBins = [nAllBins[plot[j]] for j in range(2)]

        likeGrid = np.empty((nBins[0], nBins[1]), dtype=np.float64)
        likeGrid[:, :] = worstFit + 100.0
        postGrid = np.zeros((nBins[0], nBins[1]), dtype=np.float64)

        # Work out maximum and minimum values of parameters/derived quantities
        minVal = [dataRanges[plot[j]][0] for j in range(2)]
        maxVal = [dataRanges[plot[j]][1] for j in range(2)]
        rangeOfVals = [maxVal[j] - minVal[j] for j in range(2)]
        # Pad edges of grid
        binSep = [rangeOfVals[j] / (nBins[j] - 2) for j in range(2)]
        minVal = [minVal[j] - binSep[j] for j in range(2)]
        maxVal = [maxVal[j] + binSep[j] for j in range(2)]
        rangeOfVals = [rangeOfVals[j] + 2.0 * binSep[j] for j in range(2)]

        # Calculate bin centres
        binCentresOrig = []
        binCentresInterp = []
        for j in range(2):
            binCentresOrig.append(
                np.array([minVal[j] + (x + 0.5) * rangeOfVals[j] / nBins[j] for x in range(nBins[j])])
            )
        for j in range(2):
            binCentresInterp.append(
                np.array(
                    [
                        binCentresOrig[j][0]
                        + x * (binCentresOrig[j][-1] - binCentresOrig[j][0]) / (resolution.value - 1)
                        for x in range(resolution.value)
                    ]
                )
            )

        # Loop over points in chain
        for i in range(dataArray.shape[0] - 1, -1, -1):
            [in1, in2] = [
                min(int((dataArray[i, lk[plot[j]]] - minVal[j]) / rangeOfVals[j] * nBins[j]), nBins[j] - 2)
                for j in range(2)
            ]

            # Profile over likelihoods
            if doProfile.value:
                likeGrid[in1, in2] = min(dataArray[i, lk[labels.value[refLike]]], likeGrid[in1, in2])

            # Marginalise by addding to posterior sample count
            if doPosterior.value:
                postGrid[in1, in2] += dataArray[i, lk[labels.value[refMult]]]

        # Convert -log(profile likelihoods) to profile likelihood ratio
        likeGrid = np.exp(bestFit - likeGrid)

        # Precompute co-ordinate grids for splines to avoid repetition
        if intMethod.value == "spline":
            oldCoords = np.array(
                [[binCentresOrig[0][i], binCentresOrig[1][j]] for i in range(nBins[0]) for j in range(nBins[1])]
            )
            newCoords = [
                [binCentresInterp[0][i], binCentresInterp[1][j]]
                for i in range(resolution.value)
                for j in range(resolution.value)
            ]

        # Interpolate posterior pdf and profile likelihood to requested display resolution
        if doProfile.value:
            if intMethod.value == "spline":
                likeGrid = np.array(likeGrid).reshape(nBins[0] * nBins[1])
                interpolator = twoDspline(oldCoords, likeGrid)
                likeGrid = np.array(interpolator(newCoords)).reshape(resolution.value, resolution.value)
            else:
                interpolator = twoDbilinear(binCentresOrig[0], binCentresOrig[1], likeGrid, ky=1, kx=1)
                likeGrid = np.array(
                    [
                        interpolator(binCentresInterp[0][j], binCentresInterp[1][i])
                        for j in range(resolution.value)
                        for i in range(resolution.value)
                    ]
                ).reshape(resolution.value, resolution.value)

            # Fix any points sent NaN by scipy's crappy interpolators
            likeGrid[np.isnan(likeGrid)] = 0.0
            # Kill off any points that have been sent negative due to ringing
            likeGrid[np.isneginf(likeGrid)] = 0.0
            likeGrid[likeGrid < 0] = 0.0
            # Fix any points that have been sent >1 due to ringing
            likeGrid[np.isposinf(likeGrid)] = 1.0
            likeGrid[likeGrid > 1] = 1.0
            # Make sure we haven't erased the best-fit point by interpolating over it
            likeGrid[np.unravel_index(likeGrid.argmax(), likeGrid.shape)] = 1.0

        if doPosterior.value:
            if intMethod.value == "spline":
                postGrid = np.array(postGrid).reshape(nBins[0] * nBins[1])
                interpolator = twoDspline(oldCoords, postGrid)
                postGrid = np.array(interpolator(newCoords)).reshape(resolution.value, resolution.value)
            else:
                interpolator = twoDbilinear(binCentresOrig[0], binCentresOrig[1], postGrid, ky=1, kx=1)
                postGrid = np.array(
                    [
                        interpolator(binCentresInterp[0][j], binCentresInterp[1][i])
                        for j in range(resolution.value)
                        for i in range(resolution.value)
                    ]
                ).reshape(resolution.value, resolution.value)

            # Kill off any points that have been sent negative due to ringing
            postGrid[~np.isfinite(postGrid)] = 0.0
            postGrid[postGrid < 0] = 0.0
            # Rescale posterior pdf back into the range [0,1]
            postGrid = postGrid / postGrid.max()

        # Find posterior pdf contour levels
        if contours.value is not None and doPosterior.value:
            # Zero posterior contour levels
            postContourLevels = [None for contour in contours.value]
            # Zero posterior integral
            integratedPosterior = 0.0
            # Sort bins in order of posterior mass
            sortedPostGrid = np.ma.sort(postGrid.flatten())
            # Work out the new total multiplicity
            totalMult = np.sum(sortedPostGrid)
            # Work through bins backwards until total posterior mass adds up to the requested confidence levels
            for i in range(sortedPostGrid.shape[0] - 1, -1, -1):
                integratedPosterior += sortedPostGrid[i] / totalMult
                for j, contour in enumerate(contours.value):
                    if 100 * integratedPosterior >= contour and postContourLevels[j] is None:
                        postContourLevels[j] = sortedPostGrid[i]
                if all([x is not None for x in postContourLevels]):
                    break

        # Write profile likelihood to file
        if doProfile.value:
            outName = outputBaseFilename + "_" + "_".join([str(x) for x in plot]) + "_like2D.ct2"
            outfile = smart_open(outName, "w")
            outfile.write(
                "# This 2D binned profile likelihood ratio file created by pippi "
                + pippiVersion
                + " on "
                + datetime.datetime.now().strftime("%c")
                + "\n"
            )
            outfile.write(
                "\n".join(
                    [
                        str(binCentresInterp[0][i]) + "\t" + str(binCentresInterp[1][j]) + "\t" + str(likeGrid[i, j])
                        for i in range(likeGrid.shape[0])
                        for j in range(likeGrid.shape[1])
                    ]
                )
            )
            outfile.close

        # Write posterior pdf and contours to file
        if doPosterior.value:
            outName = outputBaseFilename + "_" + "_".join([str(x) for x in plot]) + "_post2D.ct2"
            outfile = smart_open(outName, "w")
            outfile.write(
                "# This 2D binned posterior pdf file created by pippi "
                + pippiVersion
                + " on "
                + datetime.datetime.now().strftime("%c")
                + "\n"
            )
            outfile.write(
                "\n".join(
                    [
                        str(binCentresInterp[0][i]) + "\t" + str(binCentresInterp[1][j]) + "\t" + str(postGrid[i, j])
                        for i in range(postGrid.shape[0])
                        for j in range(postGrid.shape[1])
                    ]
                )
            )
            outfile.close
            if contours.value is not None:
                outName = outputBaseFilename + "_" + "_".join([str(x) for x in plot]) + "_post2D.contours"
                outfile = smart_open(outName, "w")
                outfile.write(
                    "# This 2D posterior pdf contours file created by pippi "
                    + pippiVersion
                    + " on "
                    + datetime.datetime.now().strftime("%c")
                    + "\n"
                )
                outfile.write(" ".join([str(x) for x in postContourLevels]))
                outfile.close
예제 #4
0
def oneDsampler(dataArray, lk, bestFit, worstFit, outputBaseFilename, dataRanges, nAllBins):
    # Do sample sorting for 1D plots

    if oneDplots.value is None:
        return

    if contours.value is not None:
        # Determine profile likelihood contour levels (same for all plots of a given dimensionality)
        profContourLevels = [np.exp(-deltaLnLike(0.5, 0.01 * contour)) for contour in contours.value]
        outfile = smart_open(outputBaseFilename + "_like1D.contours", "w")
        outfile.write(
            "# This 1D profile likelihood ratio contours file created by pippi "
            + pippiVersion
            + " on "
            + datetime.datetime.now().strftime("%c")
            + "\n"
        )
        outfile.write(" ".join([str(x) for x in profContourLevels]) + "\n")
        outfile.close

    for plot in oneDplots.value:

        print "    Parsing data for 1D plots of quantity ", plot

        nBins = nAllBins[plot]

        likeGrid = np.empty((nBins), dtype=np.float64)
        likeGrid[:] = worstFit + 100.0
        postGrid = np.zeros((nBins), dtype=np.float64)

        # Work out maximum and minimum values of parameter/derived quantity
        minVal = dataRanges[plot][0]
        maxVal = dataRanges[plot][1]
        rangeOfVals = maxVal - minVal
        binSep = rangeOfVals / nBins

        # Throw a sensible error if the range of values is a delta function
        if rangeOfVals <= 0:
            sys.exit(
                "Error: datastream "
                + str(plot)
                + " contains exactly the same "
                + "number for every point, so pippi cannot bin it further within its range.  Does it make "
                + "sense to plot this quantity at all, if it is constant?"
            )

        # Calculate bin centres
        binCentresOrig = np.array([minVal + (x + 0.5) * rangeOfVals / nBins for x in range(nBins)])
        binCentresInterp = np.array(
            [
                binCentresOrig[0] + x * (binCentresOrig[-1] - binCentresOrig[0]) / (resolution.value - 1)
                for x in range(resolution.value)
            ]
        )

        # Loop over points in chain
        for i in range(dataArray.shape[0] - 1, -1, -1):
            index = min(int((dataArray[i, lk[plot]] - minVal) / rangeOfVals * nBins), nBins - 1)

            # Profile over likelihoods
            if doProfile.value:
                likeGrid[index] = min(dataArray[i, lk[labels.value[refLike]]], likeGrid[index])

            if doPosterior.value:
                # Marginalise by addding to posterior sample count
                postGrid[index] += dataArray[i, lk[labels.value[refMult]]]

        # Convert -log(profile likelihoods) to profile likelihood ratio
        if doProfile.value:
            likeGrid = np.exp(bestFit - likeGrid)
        # Rescale posterior pdf to maximum 1
        if doPosterior.value:
            postGrid = postGrid / postGrid.max()

        # Save raw binned profile likelihood and posterior pdf for outputting in histogram files
        if doProfile.value:
            likeGridHistogram = likeGrid
        if doPosterior.value:
            postGridHistogram = postGrid

        # Interpolate profile likelihoods and posterior pdfs to requested resolution
        if doProfile.value:
            interpolator = oneDspline(binCentresOrig, likeGrid)
            likeGrid = interpolator(binCentresInterp)
            # Fix any points sent NaN by scipy's crappy interpolators
            likeGrid[np.isnan(likeGrid)] = 0.0
            # Kill off any points that have been sent negative due to ringing
            likeGrid[np.isneginf(likeGrid)] = 0.0
            likeGrid[likeGrid < 0] = 0.0
            # Fix any points that have been sent >1 due to ringing
            likeGrid[np.isposinf(likeGrid)] = 1.0
            likeGrid[likeGrid > 1] = 1.0

        if doPosterior.value:
            interpolator = oneDspline(binCentresOrig, postGrid)
            postGrid = interpolator(binCentresInterp)
            # Kill off any points that have been sent negative due to ringing
            postGrid[~np.isfinite(postGrid)] = 0.0
            postGrid[postGrid < 0] = 0.0
            # Rescale posterior pdf  so that it has maximum 1
            postGrid = postGrid / postGrid.max()

        # Find posterior pdf contour levels
        if contours.value is not None and doPosterior.value:
            # Zero posterior contour levels
            postContourLevels = [None for contour in contours.value]
            # Zero posterior integral
            integratedPosterior = 0.0
            # Sort bins in order of posterior mass
            sortedPostGrid = np.ma.sort(postGrid)
            # Work out the new total multiplicity
            totalMult = np.sum(sortedPostGrid)
            # Work through bins backwards until total posterior mass adds up to the requested confidence levels
            for i in range(sortedPostGrid.shape[0] - 1, -1, -1):
                integratedPosterior += sortedPostGrid[i] / totalMult
                for j, contour in enumerate(contours.value):
                    if 100 * integratedPosterior >= contour and postContourLevels[j] is None:
                        postContourLevels[j] = sortedPostGrid[i]
                if all([x is not None for x in postContourLevels]):
                    break

        # Write profile likelihood to file
        if doProfile.value:
            outfile = smart_open(outputBaseFilename + "_" + str(plot) + "_like1D.ct2", "w")
            outfile.write(
                "# This 1D binned profile likelihood ratio file created by pippi "
                + pippiVersion
                + " on "
                + datetime.datetime.now().strftime("%c")
                + "\n"
            )
            outfile.write("\n".join([str(binCentresInterp[i]) + "\t" + str(x) for i, x in enumerate(likeGrid)]))
            outfile.close
            outfile = smart_open(outputBaseFilename + "_" + str(plot) + "_like1Dhist.ct2", "w")
            outfile.write(
                "# This 1D binned profile likelihood ratio file created by pippi "
                + pippiVersion
                + " on "
                + datetime.datetime.now().strftime("%c")
                + "\n"
            )
            outfile.write(
                "\n".join(
                    [
                        str(binCentresOrig[i] - 0.5 * binSep)
                        + "\t"
                        + str(x)
                        + "\n"
                        + str(binCentresOrig[i] + 0.5 * binSep)
                        + "\t"
                        + str(x)
                        for i, x in enumerate(likeGridHistogram)
                    ]
                )
            )
            outfile.close

        # Write posterior pdf and contours to file
        if doPosterior.value:
            outfile = smart_open(outputBaseFilename + "_" + str(plot) + "_post1D.ct2", "w")
            outfile.write(
                "# This 1D binned posterior pdf file created by pippi "
                + pippiVersion
                + " on "
                + datetime.datetime.now().strftime("%c")
                + "\n"
            )
            outfile.write("\n".join([str(binCentresInterp[i]) + "\t" + str(x) for i, x in enumerate(postGrid)]))
            outfile.close
            outfile = smart_open(outputBaseFilename + "_" + str(plot) + "_post1Dhist.ct2", "w")
            outfile.write(
                "# This 1D binned posterior pdf file created by pippi "
                + pippiVersion
                + " on "
                + datetime.datetime.now().strftime("%c")
                + "\n"
            )
            outfile.write(
                "\n".join(
                    [
                        str(binCentresOrig[i] - 0.5 * binSep)
                        + "\t"
                        + str(x)
                        + "\n"
                        + str(binCentresOrig[i] + 0.5 * binSep)
                        + "\t"
                        + str(x)
                        for i, x in enumerate(postGridHistogram)
                    ]
                )
            )
            outfile.close
            if contours.value is not None:
                outfile = smart_open(outputBaseFilename + "_" + str(plot) + "_post1D.contours", "w")
                outfile.write(
                    "# This 1D posterior pdf contours file created by pippi "
                    + pippiVersion
                    + " on "
                    + datetime.datetime.now().strftime("%c")
                    + "\n"
                )
                outfile.write(" ".join([str(x) for x in postContourLevels]) + "\n")
                outfile.close
예제 #5
0
def twoDsampler(dataArray,lk,bestFit,worstFit,outputBaseFilename,dataRanges,nAllBins):
  # Do sample sorting for 2D plots

  if twoDplots.value is None: return

  # Determine profile likelihood contour levels (same for all plots of a given dimensionality)
  if contours2D.value is not None:
    profContourLevels = [np.exp(-deltaLnLike(1.0,0.01*contour)) for contour in contours2D.value]
    outName = outputBaseFilename+'_like2D.contours'
    outfile = smart_open(outName,'w')
    outfile.write('# This 2D profile likelihood ratio contours file created by pippi '\
                  +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
    outfile.write(' '.join([str(x) for x in profContourLevels]))
    outfile.close

  for plot in twoDplots.value:

    print('    Parsing data for 2D plots of quantities ',plot)

    nBins = [nAllBins[plot[j]] for j in range(2)]

    likeGrid = np.empty((nBins[0],nBins[1]), dtype=np.float64)
    likeGrid[:,:] = worstFit + 100.0
    postGrid = np.zeros((nBins[0],nBins[1]), dtype=np.float64)


    num_obs = 0

    if obsPlots.value is not None:
      for column in obsPlots.value:
        if column in lk:
          num_obs = num_obs+1

    obsGrid = np.zeros((num_obs,nBins[0],nBins[1]), dtype=np.float64)
    k = -1
    minimum_obs = np.zeros(num_obs)
    obsMinVal = np.zeros(num_obs)
    obsMaxVal = np.zeros(num_obs)
    obsFloor = np.zeros(num_obs)
    if obsPlots.value is not None:
      for column in obsPlots.value:
        if column in lk:
          k = k+1

          obsMinVal[k] = dataArray[:,lk[column]].min()
          obsMaxVal[k] = dataArray[:,lk[column]].max()

          # temporarily set the whole grid to a very low value
          obsGrid[k,:,:] = obsMinVal[k] - 100

          # set a value just below the actual minimum
          if obsMinVal[k] < 0:
            obsFloor[k] = obsMinVal[k]*1.01
          if obsMinVal[k] > 0:
            obsFloor[k] = obsMinVal[k]*0.99
          if obsMinVal[k] == 0:
            obsFloor[k] = -0.01

    # Work out maximum and minimum values of parameters/derived quantities
    minVal = [dataRanges[plot[j]][0] for j in range(2)]
    maxVal = [dataRanges[plot[j]][1] for j in range(2)]
    rangeOfVals = [maxVal[j] - minVal[j] for j in range(2)]
    # Pad edges of grid
    binSep = [rangeOfVals[j]/(nBins[j]-2) for j in range(2)]
    minVal = [minVal[j] - binSep[j] for j in range(2)]
    maxVal = [maxVal[j] + binSep[j] for j in range(2)]
    rangeOfVals = [rangeOfVals[j] + 2.0 * binSep[j] for j in range(2)]

    # Calculate bin centres
    binCentresOrig = []
    binCentresInterp = []
    for j in range(2): binCentresOrig.append(np.array([minVal[j] + (x+0.5)*rangeOfVals[j]/nBins[j] for x in range(nBins[j])]))
    for j in range(2): binCentresInterp.append(np.array([binCentresOrig[j][0] + x*(binCentresOrig[j][-1]-binCentresOrig[j][0])\
                                 /(resolution.value-1) for x in range(resolution.value)]))

    # Loop over points in chain
    for i in range(dataArray.shape[0]-1,-1,-1):
      [in1,in2] = [min(int((dataArray[i,lk[plot[j]]]-minVal[j])/rangeOfVals[j]*nBins[j]),nBins[j]-2) for j in range(2)]

      # Take observable at maximum likelihood for this bin
      if dataArray[i,lk[labels.value[refLike]]] < likeGrid[in1,in2]:
        if obsPlots.value is not None:
          k = -1
          for column in obsPlots.value:
            if column in lk:
              k = k + 1
              obsGrid[k,in1,in2] = dataArray[i,lk[column]]

      # Profile over likelihoods
      if doProfile.value: likeGrid[in1,in2] = min(dataArray[i,lk[labels.value[refLike]]],likeGrid[in1,in2])

      # Marginalise by addding to posterior sample count
      if doPosterior.value: postGrid[in1,in2] += dataArray[i,lk[labels.value[refMult]]]

    # Convert -log(profile likelihoods) to profile likelihood ratio
    likeGrid = np.exp(bestFit - likeGrid)

    #obsFloor = np.zeros(k+1)
    k = -1
    if obsPlots.value is not None:
        for column in obsPlots.value:
          if column in lk:
            k = k + 1

            obsContourLevels = [obsFloor[k],obsMinVal[k],obsMaxVal[k]]
            outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_obs2D_' + str(column) + '.contours'
            outfile = smart_open(outName,'w')
            outfile.write('# This 2D observable color-map levels file created by pippi '\
                          +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
            outfile.write(' '.join([str(x) for x in obsContourLevels]))
            outfile.close


    # Precompute co-ordinate grids for splines to avoid repetition
    if intMethod.value == 'spline':
      oldCoords = np.array([[binCentresOrig[0][i], binCentresOrig[1][j]] for i in range(nBins[0]) for j in range(nBins[1])])
      newCoords = [[binCentresInterp[0][i], binCentresInterp[1][j]] for i in range(resolution.value) for j in range(resolution.value)]

    # Interpolate posterior pdf, profile likelihood and observable to requested display resolution
    if doProfile.value:
      if intMethod.value == 'spline':
        likeGrid = np.array(likeGrid).reshape(nBins[0]*nBins[1])
        interpolator = twoDspline(oldCoords,likeGrid)
        likeGrid = np.array(interpolator(newCoords)).reshape(resolution.value,resolution.value)
      else:
        interpolator = twoDbilinear(binCentresOrig[0], binCentresOrig[1], likeGrid, ky = 1, kx = 1)
        likeGrid = np.array([interpolator(binCentresInterp[0][j], binCentresInterp[1][i])
                   for j in range(resolution.value) for i in range(resolution.value)]).reshape(resolution.value,resolution.value)

      # Fix any points sent NaN by scipy's crappy interpolators
      likeGrid[np.isnan(likeGrid)] = 0.0
      # Kill off any points that have been sent negative due to ringing
      likeGrid[np.isneginf(likeGrid)] = 0.0
      likeGrid[likeGrid<0] = 0.0
      # Fix any points that have been sent >1 due to ringing
      likeGrid[np.isposinf(likeGrid)] = 1.0
      likeGrid[likeGrid>1] = 1.0
      # Make sure we haven't erased the best-fit point by interpolating over it
      likeGrid[np.unravel_index(likeGrid.argmax(),likeGrid.shape)] = 1.0

    if doPosterior.value:
      if intMethod.value == 'spline':
        postGrid = np.array(postGrid).reshape(nBins[0]*nBins[1])
        interpolator = twoDspline(oldCoords,postGrid)
        postGrid = np.array(interpolator(newCoords)).reshape(resolution.value,resolution.value)
      else:
        interpolator = twoDbilinear(binCentresOrig[0], binCentresOrig[1], postGrid, ky = 1, kx = 1)
        postGrid = np.array([interpolator(binCentresInterp[0][j], binCentresInterp[1][i])
                   for j in range(resolution.value) for i in range(resolution.value)]).reshape(resolution.value,resolution.value)

      # Kill off any points that have been sent negative due to ringing
      postGrid[~np.isfinite(postGrid)] = 0.0
      postGrid[postGrid<0] = 0.0
      # Rescale posterior pdf back into the range [0,1]
      postGrid = postGrid / postGrid.max()

    if obsPlots.value is not None:
        k = -1
        for column in obsPlots.value:
          if column in lk:
            k = k + 1
            obsGrid_temp = obsGrid[k,:,:]

            obsGrid_temp[obsGrid_temp == (obsMinVal[k]-100) ] = obsMinVal[k]

            if intMethod.value == 'spline':
                    obsGrid_temp = np.array(obsGrid_temp).reshape(nBins[0]*nBins[1])
                    interpolator = twoDspline(oldCoords,obsGrid_temp)
                    obsGrid_temp = np.array(interpolator(newCoords)).reshape(resolution.value,resolution.value)
            else:
                    interpolator = twoDbilinear(binCentresOrig[0], binCentresOrig[1], obsGrid_temp, ky = 1, kx = 1)
                    obsGrid_temp = np.array([interpolator(binCentresInterp[0][j], binCentresInterp[1][i])
                               for j in range(resolution.value) for i in range(resolution.value)]).reshape(resolution.value,resolution.value)

            obsGrid_temp[obsGrid_temp < obsMinVal[k] ] = obsMinVal[k]

            # set points outside the contours to the floor value (effectively "no data")
            obsGrid_temp[likeGrid<min(profContourLevels)] = obsFloor[k]

            # Write observable to file

            outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_obs2D_'+str(column)+'.ct2'
            outfile = smart_open(outName,'w')
            outfile.write('# This 2D binned observable file created by pippi '\
                           +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
            outfile.write('\n'.join([str(binCentresInterp[0][i])+'\t'+str(binCentresInterp[1][j])+'\t'+str(obsGrid_temp[i,j]) \
                                     for i in range(obsGrid_temp.shape[0]) for j in range(obsGrid_temp.shape[1])]))
            outfile.close

            # make a dummy grid with maximum and minimum values (of the reduced grid) to use for colorbar
            obsGrid_temp_list = obsGrid_temp.reshape(obsGrid_temp.shape[1] * obsGrid_temp.shape[0] )
            obsGrid_temp_list = obsGrid_temp_list[obsGrid_temp_list != obsFloor[k]]
            obsMinValReduced = obsGrid_temp_list.min()
            obsMaxValReduced = obsGrid_temp_list.max()
            dummyGrid = np.zeros([2, 3])
            dummyGrid[0,0] = binCentresInterp[0][0]
            dummyGrid[0,1] = binCentresInterp[0][0]
            dummyGrid[0,2] = obsMinValReduced
            dummyGrid[1,0] = binCentresInterp[0][1]
            dummyGrid[1,1] = binCentresInterp[0][1]
            dummyGrid[1,2] = obsMaxValReduced
            outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_obs2D_'+str(column)+'_colorbar.ct2'
            outfile = smart_open(outName,'w')
            outfile.write('# This 2D binned observable file created by pippi '\
                           +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
            outfile.write('\n'.join([str(dummyGrid[i,0])+'\t'+str(dummyGrid[i,1])+'\t'+str(dummyGrid[i,2]) \
                                     for i in range(2) ]))
            outfile.close




    # Find posterior pdf contour levels
    if contours2D.value is not None and doPosterior.value:
      # Zero posterior contour levels
      postContourLevels = [None for contour in contours2D.value]
      # Zero posterior integral
      integratedPosterior = 0.0
      # Sort bins in order of posterior mass
      sortedPostGrid = np.ma.sort(postGrid.flatten())
      # Work out the new total multiplicity
      totalMult = np.sum(sortedPostGrid)
      # Work through bins backwards until total posterior mass adds up to the requested confidence levels
      for i in range(sortedPostGrid.shape[0]-1,-1,-1):
        integratedPosterior += sortedPostGrid[i]/totalMult
        for j,contour in enumerate(contours2D.value):
          if 100*integratedPosterior >= contour and postContourLevels[j] is None:
            postContourLevels[j] = sortedPostGrid[i]
        if all([x is not None for x in postContourLevels]): break

    # Write profile likelihood to file
    if doProfile.value:
      outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_like2D.ct2'
      outfile = smart_open(outName,'w')
      outfile.write('# This 2D binned profile likelihood ratio file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
      outfile.write('\n'.join([str(binCentresInterp[0][i])+'\t'+str(binCentresInterp[1][j])+'\t'+str(likeGrid[i,j]) \
                               for i in range(likeGrid.shape[0]) for j in range(likeGrid.shape[1])]))
      outfile.close

    # Write posterior pdf and contours to file
    if doPosterior.value:
      outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_post2D.ct2'
      outfile = smart_open(outName,'w')
      outfile.write('# This 2D binned posterior pdf file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
      outfile.write('\n'.join([str(binCentresInterp[0][i])+'\t'+str(binCentresInterp[1][j])+'\t'+str(postGrid[i,j]) \
                               for i in range(postGrid.shape[0]) for j in range(postGrid.shape[1])]))
      outfile.close
      if contours2D.value is not None:
        outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_post2D.contours'
        outfile = smart_open(outName,'w')
        outfile.write('# This 2D posterior pdf contours file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
        outfile.write(' '.join([str(x) for x in postContourLevels]))
        outfile.close
예제 #6
0
def oneDsampler(dataArray,lk,bestFit,worstFit,outputBaseFilename,dataRanges,nAllBins):
  # Do sample sorting for 1D plots

  if oneDplots.value is None: return

  if contours1D.value is not None:
    # Determine profile likelihood contour levels (same for all plots of a given dimensionality)
    profContourLevels = [np.exp(-deltaLnLike(0.5,0.01*contour)) for contour in contours1D.value]
    outfile = smart_open(outputBaseFilename+'_like1D.contours','w')
    outfile.write('# This 1D profile likelihood ratio contours file created by pippi '\
                  +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
    outfile.write(' '.join([str(x) for x in profContourLevels])+'\n')
    outfile.close

  for plot in oneDplots.value:

    print('    Parsing data for 1D plots of quantity ',plot)

    nBins = nAllBins[plot]

    likeGrid = np.empty((nBins), dtype=np.float64)
    likeGrid[:] = worstFit + 100.0
    postGrid = np.zeros((nBins), dtype=np.float64)

    # Work out maximum and minimum values of parameter/derived quantity
    minVal = dataRanges[plot][0]
    maxVal = dataRanges[plot][1]
    rangeOfVals = maxVal - minVal
    # Fix things if the range of values is a delta function
    if (rangeOfVals <= 0): rangeOfVals = maxVal * 1e-3
    binSep = rangeOfVals / nBins

    # Calculate bin centres
    binCentresOrig = np.array([minVal + (x+0.5)*rangeOfVals/nBins for x in range(nBins)])
    binCentresInterp = np.array([binCentresOrig[0] + x*(binCentresOrig[-1]-binCentresOrig[0])\
                                 /(resolution.value-1) for x in range(resolution.value)])

    # Loop over points in chain
    for i in range(dataArray.shape[0]-1,-1,-1):
      index = min(int((dataArray[i,lk[plot]]-minVal)/rangeOfVals*nBins),nBins-1)

      # Profile over likelihoods
      if doProfile.value: likeGrid[index] = min(dataArray[i,lk[labels.value[refLike]]],likeGrid[index])

      if doPosterior.value:
        # Marginalise by addding to posterior sample count
        postGrid[index] += dataArray[i,lk[labels.value[refMult]]]

    # Convert -log(profile likelihoods) to profile likelihood ratio
    if doProfile.value: likeGrid = np.exp(bestFit - likeGrid)
    # Rescale posterior pdf to maximum 1
    if doPosterior.value: postGrid = postGrid / postGrid.max()

    # Save raw binned profile likelihood and posterior pdf for outputting in histogram files
    if doProfile.value: likeGridHistogram = likeGrid
    if doPosterior.value: postGridHistogram = postGrid

    # Interpolate profile likelihoods and posterior pdfs to requested resolution
    if doProfile.value:
      interpolator = oneDspline(binCentresOrig, likeGrid)
      likeGrid = interpolator(binCentresInterp)
      # Fix any points sent NaN by scipy's crappy interpolators
      likeGrid[np.isnan(likeGrid)] = 0.0
      # Kill off any points that have been sent negative due to ringing
      likeGrid[np.isneginf(likeGrid)] = 0.0
      likeGrid[likeGrid<0] = 0.0
      # Fix any points that have been sent >1 due to ringing
      likeGrid[np.isposinf(likeGrid)] = 1.0
      likeGrid[likeGrid>1] = 1.0

    if doPosterior.value:
      interpolator = oneDspline(binCentresOrig, postGrid)
      postGrid = interpolator(binCentresInterp)
      # Kill off any points that have been sent negative due to ringing
      postGrid[~np.isfinite(postGrid)] = 0.0
      postGrid[postGrid<0] = 0.0
      # Rescale posterior pdf  so that it has maximum 1
      postGrid = postGrid / postGrid.max()

    # Find posterior pdf contour levels
    if contours1D.value is not None and doPosterior.value:
      # Zero posterior contour levels
      postContourLevels = [None for contour in contours1D.value]
      # Zero posterior integral
      integratedPosterior = 0.0
      # Sort bins in order of posterior mass
      sortedPostGrid = np.ma.sort(postGrid)
      # Work out the new total multiplicity
      totalMult = np.sum(sortedPostGrid)
      # Work through bins backwards until total posterior mass adds up to the requested confidence levels
      for i in range(sortedPostGrid.shape[0]-1,-1,-1):
        integratedPosterior += sortedPostGrid[i]/totalMult
        for j,contour in enumerate(contours1D.value):
          if 100*integratedPosterior >= contour and postContourLevels[j] is None:
            postContourLevels[j] = sortedPostGrid[i]
        if all([x is not None for x in postContourLevels]): break

    # Write profile likelihood to file
    if doProfile.value:
      outfile = smart_open(outputBaseFilename+'_'+str(plot)+'_like1D.ct2','w')
      outfile.write('# This 1D binned profile likelihood ratio file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
      outfile.write('\n'.join([str(binCentresInterp[i])+'\t'+str(x) for i,x in enumerate(likeGrid)]))
      outfile.close
      outfile = smart_open(outputBaseFilename+'_'+str(plot)+'_like1Dhist.ct2','w')
      outfile.write('# This 1D binned profile likelihood ratio file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
      outfile.write('\n'.join([str(binCentresOrig[i]-0.5*binSep)+'\t'+str(x)+'\n'+
                               str(binCentresOrig[i]+0.5*binSep)+'\t'+str(x) for i,x in enumerate(likeGridHistogram)]))
      outfile.close

    # Write posterior pdf and contours to file
    if doPosterior.value:
      outfile = smart_open(outputBaseFilename+'_'+str(plot)+'_post1D.ct2','w')
      outfile.write('# This 1D binned posterior pdf file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
      outfile.write('\n'.join([str(binCentresInterp[i])+'\t'+str(x) for i,x in enumerate(postGrid)]))
      outfile.close
      outfile = smart_open(outputBaseFilename+'_'+str(plot)+'_post1Dhist.ct2','w')
      outfile.write('# This 1D binned posterior pdf file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
      outfile.write('\n'.join([str(binCentresOrig[i]-0.5*binSep)+'\t'+str(x)+'\n'+
                               str(binCentresOrig[i]+0.5*binSep)+'\t'+str(x) for i,x in enumerate(postGridHistogram)]))
      outfile.close
      if contours1D.value is not None:
        outfile = smart_open(outputBaseFilename+'_'+str(plot)+'_post1D.contours','w')
        outfile.write('# This 1D posterior pdf contours file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
        outfile.write(' '.join([str(x) for x in postContourLevels])+'\n')
        outfile.close
예제 #7
0
def twoDsampler(dataArray,lk,bestFit,worstFit,outputBaseFilename,dataRanges,nAllBins):
  # Do sample sorting for 2D plots

  if twoDplots.value is None: return

  # Determine profile likelihood contour levels (same for all plots of a given dimensionality)
  if contours2D.value is not None:
    profContourLevels = [np.exp(-deltaLnLike(1.0,0.01*contour)) for contour in contours2D.value]
    outName = outputBaseFilename+'_like2D.contours'
    outfile = smart_open(outName,'w')
    outfile.write('# This 2D profile likelihood ratio contours file created by pippi '\
                  +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
    outfile.write(' '.join([str(x) for x in profContourLevels]))
    outfile.close

  for plot in twoDplots.value:

    print '    Parsing data for 2D plots of quantities ',plot

    nBins = [nAllBins[plot[j]] for j in range(2)]

    likeGrid = np.empty((nBins[0],nBins[1]), dtype=np.float64)
    likeGrid[:,:] = worstFit + 100.0
    postGrid = np.zeros((nBins[0],nBins[1]), dtype=np.float64)


    num_obs = 0

    if obsPlots.value is not None:
      for column in obsPlots.value:
        if column in lk:
          num_obs = num_obs+1

    obsGrid = np.zeros((num_obs,nBins[0],nBins[1]), dtype=np.float64)
    k = -1
    minimum_obs = np.zeros(num_obs)
    obsMinVal = np.zeros(num_obs)
    obsMaxVal = np.zeros(num_obs)
    obsFloor = np.zeros(num_obs)
    if obsPlots.value is not None:
      for column in obsPlots.value:
        if column in lk:
          k = k+1
          
          obsMinVal[k] = dataArray[:,lk[column]].min()
          obsMaxVal[k] = dataArray[:,lk[column]].max()
          
          # temporarily set the whole grid to a very low value
          obsGrid[k,:,:] = obsMinVal[k] - 100
          
          # set a value just below the actual minimum
          if obsMinVal[k] < 0:
            obsFloor[k] = obsMinVal[k]*1.01
          if obsMinVal[k] > 0:
            obsFloor[k] = obsMinVal[k]*0.99
          if obsMinVal[k] == 0:
            obsFloor[k] = -0.01

    # Work out maximum and minimum values of parameters/derived quantities
    minVal = [dataRanges[plot[j]][0] for j in range(2)]
    maxVal = [dataRanges[plot[j]][1] for j in range(2)]
    rangeOfVals = [maxVal[j] - minVal[j] for j in range(2)]
    # Pad edges of grid
    binSep = [rangeOfVals[j]/(nBins[j]-2) for j in range(2)]
    minVal = [minVal[j] - binSep[j] for j in range(2)]
    maxVal = [maxVal[j] + binSep[j] for j in range(2)]
    rangeOfVals = [rangeOfVals[j] + 2.0 * binSep[j] for j in range(2)]

    # Calculate bin centres
    binCentresOrig = []
    binCentresInterp = []
    for j in range(2): binCentresOrig.append(np.array([minVal[j] + (x+0.5)*rangeOfVals[j]/nBins[j] for x in range(nBins[j])]))
    for j in range(2): binCentresInterp.append(np.array([binCentresOrig[j][0] + x*(binCentresOrig[j][-1]-binCentresOrig[j][0])\
                                 /(resolution.value-1) for x in range(resolution.value)]))
                                 
    # Loop over points in chain
    for i in range(dataArray.shape[0]-1,-1,-1):
      [in1,in2] = [min(int((dataArray[i,lk[plot[j]]]-minVal[j])/rangeOfVals[j]*nBins[j]),nBins[j]-2) for j in range(2)]

      # Take observable at maximum likelihood for this bin
      if dataArray[i,lk[labels.value[refLike]]] < likeGrid[in1,in2]:
        if obsPlots.value is not None:
          k = -1
          for column in obsPlots.value:
            if column in lk:
              k = k + 1
              obsGrid[k,in1,in2] = dataArray[i,lk[column]]

      # Profile over likelihoods
      if doProfile.value: likeGrid[in1,in2] = min(dataArray[i,lk[labels.value[refLike]]],likeGrid[in1,in2])

      # Marginalise by addding to posterior sample count
      if doPosterior.value: postGrid[in1,in2] += dataArray[i,lk[labels.value[refMult]]]

    # Convert -log(profile likelihoods) to profile likelihood ratio
    likeGrid = np.exp(bestFit - likeGrid)

    #obsFloor = np.zeros(k+1)
    k = -1
    if obsPlots.value is not None:
        for column in obsPlots.value:
          if column in lk:
            k = k + 1

            obsContourLevels = [obsFloor[k],obsMinVal[k],obsMaxVal[k]]
            outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_obs2D_' + str(column) + '.contours'
            outfile = smart_open(outName,'w')
            outfile.write('# This 2D observable color-map levels file created by pippi '\
                          +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
            outfile.write(' '.join([str(x) for x in obsContourLevels]))
            outfile.close


    # Precompute co-ordinate grids for splines to avoid repetition
    if intMethod.value == 'spline':
      oldCoords = np.array([[binCentresOrig[0][i], binCentresOrig[1][j]] for i in range(nBins[0]) for j in range(nBins[1])])
      newCoords = [[binCentresInterp[0][i], binCentresInterp[1][j]] for i in range(resolution.value) for j in range(resolution.value)]

    # Interpolate posterior pdf, profile likelihood and observable to requested display resolution
    if doProfile.value:
      if intMethod.value == 'spline':
        likeGrid = np.array(likeGrid).reshape(nBins[0]*nBins[1])
        interpolator = twoDspline(oldCoords,likeGrid)
        likeGrid = np.array(interpolator(newCoords)).reshape(resolution.value,resolution.value)
      else:
        interpolator = twoDbilinear(binCentresOrig[0], binCentresOrig[1], likeGrid, ky = 1, kx = 1)
        likeGrid = np.array([interpolator(binCentresInterp[0][j], binCentresInterp[1][i])
                   for j in range(resolution.value) for i in range(resolution.value)]).reshape(resolution.value,resolution.value)

      # Fix any points sent NaN by scipy's crappy interpolators
      likeGrid[np.isnan(likeGrid)] = 0.0
      # Kill off any points that have been sent negative due to ringing
      likeGrid[np.isneginf(likeGrid)] = 0.0
      likeGrid[likeGrid<0] = 0.0
      # Fix any points that have been sent >1 due to ringing
      likeGrid[np.isposinf(likeGrid)] = 1.0
      likeGrid[likeGrid>1] = 1.0
      # Make sure we haven't erased the best-fit point by interpolating over it
      likeGrid[np.unravel_index(likeGrid.argmax(),likeGrid.shape)] = 1.0

    if doPosterior.value:
      if intMethod.value == 'spline':
        postGrid = np.array(postGrid).reshape(nBins[0]*nBins[1])
        interpolator = twoDspline(oldCoords,postGrid)
        postGrid = np.array(interpolator(newCoords)).reshape(resolution.value,resolution.value)
      else:
        interpolator = twoDbilinear(binCentresOrig[0], binCentresOrig[1], postGrid, ky = 1, kx = 1)
        postGrid = np.array([interpolator(binCentresInterp[0][j], binCentresInterp[1][i])
                   for j in range(resolution.value) for i in range(resolution.value)]).reshape(resolution.value,resolution.value)

      # Kill off any points that have been sent negative due to ringing
      postGrid[~np.isfinite(postGrid)] = 0.0
      postGrid[postGrid<0] = 0.0
      # Rescale posterior pdf back into the range [0,1]
      postGrid = postGrid / postGrid.max()

    if obsPlots.value is not None:
        k = -1
        for column in obsPlots.value:
          if column in lk:
            k = k + 1
            obsGrid_temp = obsGrid[k,:,:]
            
            obsGrid_temp[obsGrid_temp == (obsMinVal[k]-100) ] = obsMinVal[k]
            
            if intMethod.value == 'spline':
                    obsGrid_temp = np.array(obsGrid_temp).reshape(nBins[0]*nBins[1])
                    interpolator = twoDspline(oldCoords,obsGrid_temp)
                    obsGrid_temp = np.array(interpolator(newCoords)).reshape(resolution.value,resolution.value)
            else:
                    interpolator = twoDbilinear(binCentresOrig[0], binCentresOrig[1], obsGrid_temp, ky = 1, kx = 1)
                    obsGrid_temp = np.array([interpolator(binCentresInterp[0][j], binCentresInterp[1][i])
                               for j in range(resolution.value) for i in range(resolution.value)]).reshape(resolution.value,resolution.value)

            obsGrid_temp[obsGrid_temp < obsMinVal[k] ] = obsMinVal[k]
            
            # set points outside the contours to the floor value (effectively "no data")
            obsGrid_temp[likeGrid<min(profContourLevels)] = obsFloor[k]

            # Write observable to file
            
            outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_obs2D_'+str(column)+'.ct2'
            outfile = smart_open(outName,'w')
            outfile.write('# This 2D binned observable file created by pippi '\
                           +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
            outfile.write('\n'.join([str(binCentresInterp[0][i])+'\t'+str(binCentresInterp[1][j])+'\t'+str(obsGrid_temp[i,j]) \
                                     for i in range(obsGrid_temp.shape[0]) for j in range(obsGrid_temp.shape[1])]))
            outfile.close

            # make a dummy grid with maximum and minimum values (of the reduced grid) to use for colorbar
            obsGrid_temp_list = obsGrid_temp.reshape(obsGrid_temp.shape[1] * obsGrid_temp.shape[0] )
            obsGrid_temp_list = obsGrid_temp_list[obsGrid_temp_list != obsFloor[k]]
            obsMinValReduced = obsGrid_temp_list.min()
            obsMaxValReduced = obsGrid_temp_list.max()
            dummyGrid = np.zeros([2, 3])
            dummyGrid[0,0] = binCentresInterp[0][0]
            dummyGrid[0,1] = binCentresInterp[0][0]
            dummyGrid[0,2] = obsMinValReduced
            dummyGrid[1,0] = binCentresInterp[0][1]
            dummyGrid[1,1] = binCentresInterp[0][1]
            dummyGrid[1,2] = obsMaxValReduced
            outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_obs2D_'+str(column)+'_colorbar.ct2'
            outfile = smart_open(outName,'w')
            outfile.write('# This 2D binned observable file created by pippi '\
                           +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
            outfile.write('\n'.join([str(dummyGrid[i,0])+'\t'+str(dummyGrid[i,1])+'\t'+str(dummyGrid[i,2]) \
                                     for i in range(2) ]))
            outfile.close
            



    # Find posterior pdf contour levels
    if contours2D.value is not None and doPosterior.value:
      # Zero posterior contour levels
      postContourLevels = [None for contour in contours2D.value]
      # Zero posterior integral
      integratedPosterior = 0.0
      # Sort bins in order of posterior mass
      sortedPostGrid = np.ma.sort(postGrid.flatten())
      # Work out the new total multiplicity
      totalMult = np.sum(sortedPostGrid)
      # Work through bins backwards until total posterior mass adds up to the requested confidence levels
      for i in range(sortedPostGrid.shape[0]-1,-1,-1):
        integratedPosterior += sortedPostGrid[i]/totalMult
        for j,contour in enumerate(contours2D.value):
          if 100*integratedPosterior >= contour and postContourLevels[j] is None:
            postContourLevels[j] = sortedPostGrid[i]
        if all([x is not None for x in postContourLevels]): break

    # Write profile likelihood to file
    if doProfile.value:
      outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_like2D.ct2'
      outfile = smart_open(outName,'w')
      outfile.write('# This 2D binned profile likelihood ratio file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
      outfile.write('\n'.join([str(binCentresInterp[0][i])+'\t'+str(binCentresInterp[1][j])+'\t'+str(likeGrid[i,j]) \
                               for i in range(likeGrid.shape[0]) for j in range(likeGrid.shape[1])]))
      outfile.close

    # Write posterior pdf and contours to file
    if doPosterior.value:
      outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_post2D.ct2'
      outfile = smart_open(outName,'w')
      outfile.write('# This 2D binned posterior pdf file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
      outfile.write('\n'.join([str(binCentresInterp[0][i])+'\t'+str(binCentresInterp[1][j])+'\t'+str(postGrid[i,j]) \
                               for i in range(postGrid.shape[0]) for j in range(postGrid.shape[1])]))
      outfile.close
      if contours2D.value is not None:
        outName = outputBaseFilename+'_'+'_'.join([str(x) for x in plot])+'_post2D.contours'
        outfile = smart_open(outName,'w')
        outfile.write('# This 2D posterior pdf contours file created by pippi '\
                     +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
        outfile.write(' '.join([str(x) for x in postContourLevels]))
        outfile.close
예제 #8
0
def twoDsampler(dataArray, lk, bestFit, worstFit, outputBaseFilename,
                dataRanges, nAllBins):
    # Do sample sorting for 2D plots

    if twoDplots.value is None: return

    # Determine profile likelihood contour levels (same for all plots of a given dimensionality)
    if contours2D.value is not None:
        profContourLevels = [
            np.exp(-deltaLnLike(1.0, 0.01 * contour))
            for contour in contours2D.value
        ]
        outName = outputBaseFilename + '_like2D.contours'
        outfile = smart_open(outName, 'w')
        outfile.write('# This 2D profile likelihood ratio contours file created by pippi '\
                      +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
        outfile.write(' '.join([str(x) for x in profContourLevels]))
        outfile.close

    for plot in twoDplots.value:

        print '    Parsing data for 2D plots of quantities ', plot

        nBins = [nAllBins[plot[j]] for j in range(2)]

        likeGrid = np.empty((nBins[0], nBins[1]), dtype=np.float64)
        likeGrid[:, :] = worstFit + 100.0
        postGrid = np.zeros((nBins[0], nBins[1]), dtype=np.float64)

        # Work out maximum and minimum values of parameters/derived quantities
        minVal = [dataRanges[plot[j]][0] for j in range(2)]
        maxVal = [dataRanges[plot[j]][1] for j in range(2)]
        rangeOfVals = [maxVal[j] - minVal[j] for j in range(2)]
        # Pad edges of grid
        binSep = [rangeOfVals[j] / (nBins[j] - 2) for j in range(2)]
        minVal = [minVal[j] - binSep[j] for j in range(2)]
        maxVal = [maxVal[j] + binSep[j] for j in range(2)]
        rangeOfVals = [rangeOfVals[j] + 2.0 * binSep[j] for j in range(2)]

        # Calculate bin centres
        binCentresOrig = []
        binCentresInterp = []
        for j in range(2):
            binCentresOrig.append(
                np.array([
                    minVal[j] + (x + 0.5) * rangeOfVals[j] / nBins[j]
                    for x in range(nBins[j])
                ]))
        for j in range(2):            binCentresInterp.append(np.array([binCentresOrig[j][0] + x*(binCentresOrig[j][-1]-binCentresOrig[j][0])\
                      /(resolution.value-1) for x in range(resolution.value)]))

        # Loop over points in chain
        for i in range(dataArray.shape[0] - 1, -1, -1):
            [in1, in2] = [
                min(
                    int((dataArray[i, lk[plot[j]]] - minVal[j]) /
                        rangeOfVals[j] * nBins[j]), nBins[j] - 2)
                for j in range(2)
            ]

            # Profile over likelihoods
            if doProfile.value:
                likeGrid[in1,
                         in2] = min(dataArray[i, lk[labels.value[refLike]]],
                                    likeGrid[in1, in2])

            # Marginalise by addding to posterior sample count
            if doPosterior.value:
                postGrid[in1, in2] += dataArray[i, lk[labels.value[refMult]]]

        # Convert -log(profile likelihoods) to profile likelihood ratio
        likeGrid = np.exp(bestFit - likeGrid)

        # Precompute co-ordinate grids for splines to avoid repetition
        if intMethod.value == 'spline':
            oldCoords = np.array([[binCentresOrig[0][i], binCentresOrig[1][j]]
                                  for i in range(nBins[0])
                                  for j in range(nBins[1])])
            newCoords = [[binCentresInterp[0][i], binCentresInterp[1][j]]
                         for i in range(resolution.value)
                         for j in range(resolution.value)]

        # Interpolate posterior pdf and profile likelihood to requested display resolution
        if doProfile.value:
            if intMethod.value == 'spline':
                likeGrid = np.array(likeGrid).reshape(nBins[0] * nBins[1])
                interpolator = twoDspline(oldCoords, likeGrid)
                likeGrid = np.array(interpolator(newCoords)).reshape(
                    resolution.value, resolution.value)
            else:
                interpolator = twoDbilinear(binCentresOrig[0],
                                            binCentresOrig[1],
                                            likeGrid,
                                            ky=1,
                                            kx=1)
                likeGrid = np.array([
                    interpolator(binCentresInterp[0][j],
                                 binCentresInterp[1][i])
                    for j in range(resolution.value)
                    for i in range(resolution.value)
                ]).reshape(resolution.value, resolution.value)

            # Fix any points sent NaN by scipy's crappy interpolators
            likeGrid[np.isnan(likeGrid)] = 0.0
            # Kill off any points that have been sent negative due to ringing
            likeGrid[np.isneginf(likeGrid)] = 0.0
            likeGrid[likeGrid < 0] = 0.0
            # Fix any points that have been sent >1 due to ringing
            likeGrid[np.isposinf(likeGrid)] = 1.0
            likeGrid[likeGrid > 1] = 1.0
            # Make sure we haven't erased the best-fit point by interpolating over it
            likeGrid[np.unravel_index(likeGrid.argmax(), likeGrid.shape)] = 1.0

        if doPosterior.value:
            if intMethod.value == 'spline':
                postGrid = np.array(postGrid).reshape(nBins[0] * nBins[1])
                interpolator = twoDspline(oldCoords, postGrid)
                postGrid = np.array(interpolator(newCoords)).reshape(
                    resolution.value, resolution.value)
            else:
                interpolator = twoDbilinear(binCentresOrig[0],
                                            binCentresOrig[1],
                                            postGrid,
                                            ky=1,
                                            kx=1)
                postGrid = np.array([
                    interpolator(binCentresInterp[0][j],
                                 binCentresInterp[1][i])
                    for j in range(resolution.value)
                    for i in range(resolution.value)
                ]).reshape(resolution.value, resolution.value)

            # Kill off any points that have been sent negative due to ringing
            postGrid[~np.isfinite(postGrid)] = 0.0
            postGrid[postGrid < 0] = 0.0
            # Rescale posterior pdf back into the range [0,1]
            postGrid = postGrid / postGrid.max()

        # Find posterior pdf contour levels
        if contours2D.value is not None and doPosterior.value:
            # Zero posterior contour levels
            postContourLevels = [None for contour in contours2D.value]
            # Zero posterior integral
            integratedPosterior = 0.0
            # Sort bins in order of posterior mass
            sortedPostGrid = np.ma.sort(postGrid.flatten())
            # Work out the new total multiplicity
            totalMult = np.sum(sortedPostGrid)
            # Work through bins backwards until total posterior mass adds up to the requested confidence levels
            for i in range(sortedPostGrid.shape[0] - 1, -1, -1):
                integratedPosterior += sortedPostGrid[i] / totalMult
                for j, contour in enumerate(contours2D.value):
                    if 100 * integratedPosterior >= contour and postContourLevels[
                            j] is None:
                        postContourLevels[j] = sortedPostGrid[i]
                if all([x is not None for x in postContourLevels]): break

        # Write profile likelihood to file
        if doProfile.value:
            outName = outputBaseFilename + '_' + '_'.join(
                [str(x) for x in plot]) + '_like2D.ct2'
            outfile = smart_open(outName, 'w')
            outfile.write('# This 2D binned profile likelihood ratio file created by pippi '\
                           +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
            outfile.write('\n'.join([str(binCentresInterp[0][i])+'\t'+str(binCentresInterp[1][j])+'\t'+str(likeGrid[i,j]) \
                                     for i in range(likeGrid.shape[0]) for j in range(likeGrid.shape[1])]))
            outfile.close

        # Write posterior pdf and contours to file
        if doPosterior.value:
            outName = outputBaseFilename + '_' + '_'.join(
                [str(x) for x in plot]) + '_post2D.ct2'
            outfile = smart_open(outName, 'w')
            outfile.write('# This 2D binned posterior pdf file created by pippi '\
                           +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
            outfile.write('\n'.join([str(binCentresInterp[0][i])+'\t'+str(binCentresInterp[1][j])+'\t'+str(postGrid[i,j]) \
                                     for i in range(postGrid.shape[0]) for j in range(postGrid.shape[1])]))
            outfile.close
            if contours2D.value is not None:
                outName = outputBaseFilename + '_' + '_'.join(
                    [str(x) for x in plot]) + '_post2D.contours'
                outfile = smart_open(outName, 'w')
                outfile.write('# This 2D posterior pdf contours file created by pippi '\
                             +pippiVersion+' on '+datetime.datetime.now().strftime('%c')+'\n')
                outfile.write(' '.join([str(x) for x in postContourLevels]))
                outfile.close