# Notebook from AfroditiMariaZaki/OxCompBio
Path: tutorials/Python/00_Introduction/Introduction_solutions.ipynb

# 0. Introduction_____no_output_____## Course overview

This tutorial aims to teach the basics of python programming with a focus on its application in computational biochemistry. Assuming no previous knowledge of python, we start by explaining the basic building blocks (e.g. variables, conditionals, and lists) and build upon these to show examples of how python can be used to solve problems related to computational biochemistry (e.g. analysis of Molecular Dynamics simulations).

The tutorial does not aim to completely cover every aspect of python programming, this unfortunately would not be feasible in a half day session. Instead we encourage attendees to use this as a jumping point into learning more about python and its many applications.

We recommend the following useful resources for python:
- [Python Documentation](https://docs.python.org/3.7/) (tutorials, library reference, ...)
- [CodeAcademy Python tutorial](https://www.codecademy.com/learn/learn-python)

### Course structure

The tutorial is thought across a series of jupyter notebooks:

0. Introduction
1. Basic Types
2. Variables
3. Conditionals
4. Loops
5. Lists
6. File Handling
7. Functions
8. Documentation
9. Libraries
10. Numpy
11. Object Orientated Programming (OOP)
12. Protein Analysis

These notebooks are contained within their own labelled/named directories. Within these directories you will also sometimes find `datafiles` sub-directories that contain all the relevant data to run the notebook, in addition to copies of the notebooks with the exercise solutions (whose name ends in `_solutions.ipynb`).

We recommend that each section be followed in order, however those with prior experience with python may wish to jump to the later sections.

### Launching the notebooks

Please see the `setup.md` "Starting the tutorial" instructions.

Briefly, using a terminal (Anaconda prompt in Windows) do the following:

1. You will first need to activate the conda environment: `conda activate OxPython`
2. Then you will need to start the jupyter notebook server: `jupyter notebook`
3. From there navigate to the desired directory and click on the `.ipynb` notebook you wish to open.
4. Solutions for some of the notebooks are provided under `<notebook_name>_solutions.ipynb`, we recommend you only open these once you have finished going through a notebook.
5. To close the notebooks, click on "File" -> "Close and Halt".
6. You may then also want to quit the jupyter notebook server altogether.

### Using the notebooks

Jupyter notebooks are a useful way to demonstrate python code in a clear and organised manner. Each notebook is composed of a series of `cells` which can either contain text (such as this one) or code (which will usually have the words `In []:` next to them). You can type in code `cells` by clicking on them and typing whatever changes you want to make.

Code cells can be used to run any valid python code. To do this, simply click on the cell and press the `Run` button in the toolbar above, or type `Shift+Enter`.

**Important note:** All code executed is retained in the `memory` of the notebook. That means that if you `import` a module or declare a variable, these will be seen and can interact with code executed in `cells` further down the notebook. There are many places in this tutorial where modules are imported early on in the notebook and used in subsequent code `cells`. We therefore recommend that tutorial users do not jump to later parts of the notebook without doing the earlier ones.

Notebooks can be cleared to their original state by navigating to `Kernel > Restart & Clear Output`. A further prompt will ask you if you wish to clear all the outputs, pressing on this will return the notebook to a state where no code `cells` have been run.
_____no_output_____## 0.1 A first command in python:

Let's start things off with executing our first python command. In the cell below we will use `print` to write out "Hello world". Try it out by clicking on the cell and pressing `Run` in the toolbar above._____no_output_____

print('Hello world')_____no_output_____

The `print` function takes an input value (some text, in quotation marks) and prints the text as output (without the quotation marks). One should note that Python is case-sensitive - ie. we can't use `Print` or `PRINT`.

Whilst `print` is a very simple function, it is one of the most useful. It allows us to write out any information relevant to our python code. This can be anything from usage instruction to the output of some calculation.

**Note:** As of python 3, the inputs to the 'print' function must be placed within parantheses. If you use code developed for python 2.7 or lower, you may notice that this requirement is not followed and therefore will cause issues if run using python 3+. There are other key differences between python 3 and previous versions, some of which will be covered in this tutorial. For a more detailed look into them, the following resource may be of use: [Porting Python 2 Code to Python 3](https://docs.python.org/3.6/howto/pyporting.html). As python 2.7 will reach end of life as of January 2020, we strongly recommend that no new code be written in python 2.7._____no_output_____### Exercise 0.1.1

In the cell below, use print to output the phrase "This is the second command"._____no_output_____

# Exercise 0.1.1
print('This is the second command')_____no_output_____

### A note on python comments

You will have noticed that the "Exercise 0.1.1" in the above box does not affect the notebook output. In python, in-line code comments are indicated using the # symbol. Any text that comes after this is considered to be a comment and is ignored by the python interpreter. It is considered good practice to comment your code in order to make it more readable for yourself and future users. Other means of commenting python code, such as docstrings, also exist and will be briefly covered in section 8 of this tutorial._____no_output_____## 0.2 Python scripts_____no_output_____Whilst jupyter notebooks can be useful for demonstrating python code and prototyping new ideas, the main way in which to run python code is to execute a script. To do this, you need to write the python instructions within a file and execute it via the python interpretor.

For example if you were to write the following in a file (let's assume we call it hello.py):

```
print("Hello world")
```

And then type `python hello.py` in a terminal, this should print out `Hello world`.

In the remainder of this tutorial we will, for convenience, focus on executing code within jupyter notebooks. However, it is worth remembering that using written scripts/code is often a much more reproducible and manageable way to use python._____no_output_____## Python: An Interpreted Language_____no_output_____Python is an _interpreted_ programming language. This means that Python code is read and executed line by line by the Python _interpreter_ (the program that transforms Python code you wrote into something that your computer can understand and run). This is different from _compiled_ languages (such as FORTRAN or C/C++), where all the code is first translated by the _compiler_ to something the computer can understand and then run._____no_output_____### Why Python?_____no_output_____As as an interpreted language, Python is usually slower than compiled languages such as FORTRAN and C++. However, Python is extremely flexible, can be made reasonably fast under the hood, and it is relatively easy to run on different operating systems. This is the reason why it popularity exploded in recent years, especially in computational and data sciences: its clean syntax allows to write clear and concise programs, while sacrificing speed to a minimum._____no_output_____In computational sciences there are other commonly used interpreted languages such as Matlab and R. Matlab's interpreter is not free and open source, so you won't be able to run your code unless you keep paying for a licence. R is a fantastic language for statistical computing, but it is very domain-specific. Python, in contrast, is free, open source and has a wide domain of applicability and it is therefore a very powerful language to know, for beginners and experts alike._____no_output_____## Review

In this tutorial section we have:
- Detailed the contents of the tutorial.
- Shown how to execute and use a jupyter notebook session.
- Used a function, `print`.
- Written our first python script.
- Run the script using the `python` interpretor.
- Discussed the advantages and disadvantages of Python_____no_output_____


# Notebook from hrichstein/Stellar_mass_env_Density
Path: Codes/iPython_Notebooks/adding_plots.ipynb

The code for plotting bands and determining the vertical range to plot does not consider the different numbers of mass bins. It won't be able to create the proper matrices to find the min and max at each x value.    The one for the median distances should work... Would fix this bug now, but I have some Schechter functions to wrangle.

neigh_dict and nn_dict are the same thing. Need to combine/change variables at some point_____no_output_____

<code>
from __future__ import division, absolute_import

import astropy.stats
import glob
import math
import matplotlib.pyplot as plt
from matplotlib import ticker
from matplotlib.ticker import FormatStrFormatter
import numpy as np
import os
import pandas as pd
from scipy import integrate,optimize,spatial_____no_output_______author__     =['Victor Calderon']
__copyright__  =["Copyright 2016 Victor Calderon, Index function"]
__email__      =['victor.calderon@vanderbilt.edu']
__maintainer__ =['Victor Calderon']

def Index(directory, datatype):
    """
    Indexes the files in a directory `directory' with a
    specific data type.

    Parameters
    ----------
    directory: str
            Absolute path to the folder that is indexed.

    datatype: str
            Data type of the files to be indexed in the folder.

    Returns
    -------
    file_array: array_like
            np.array of indexed files in the folder 'directory'
            with specific datatype.

    Examples
    --------
    >>> Index('~/data', '.txt')
    >>> array(['A.txt', 'Z'.txt', ...])
    """
    assert(os.path.exists(directory))
    files = np.array(glob.glob('{0}/*{1}'.format(directory, datatype)))

    return files_____no_output_____def myceil(x, base=10):
    """
    Returns the upper-bound integer of 'x' in base 'base'.

    Parameters
    ----------
    x: float
        number to be approximated to closest number to 'base'

    base: float
        base used to calculate the closest 'largest' number

    Returns
    -------
    n_high: float
        Closest float number to 'x', i.e. upper-bound float.

    Example
    -------
    >>>> myceil(12,10)
      20
    >>>>
    >>>> myceil(12.05, 0.1)
     12.10000
    """
    n_high = float(base*math.ceil(float(x)/base))

    return n_high

###############################################################################

def myfloor(x, base=10):
    """
    Returns the lower-bound integer of 'x' in base 'base'

    Parameters
    ----------
    x: float
        number to be approximated to closest number of 'base'

    base: float
        base used to calculate the closest 'smallest' number

    Returns
    -------
    n_low: float
        Closest float number to 'x', i.e. lower-bound float.

    Example
    -------
    >>>> myfloor(12, 5)
    >>>> 10
    """
    n_low = float(base*math.floor(float(x)/base))

    return n_low

###############################################################################

def Bins_array_create(arr, base=10):
    """
    Generates array between [arr.min(), arr.max()] in steps of `base`.

    Parameters
    ----------
    arr: array_like, Shape (N,...), One-dimensional
        Array of numerical elements

    base: float, optional (default=10)
        Interval between bins

    Returns
    -------
    bins_arr: array_like
        Array of bin edges for given arr

    """
    base = float(base)
    arr  = np.array(arr)
    assert(arr.ndim==1)
    arr_min  = myfloor(arr.min(), base=base)
    arr_max  = myceil( arr.max(), base=base)
    bins_arr = np.arange(arr_min, arr_max+0.5*base, base)

    return bins_arr_____no_output_____def sph_to_cart(ra,dec,cz):
    """
    Converts spherical coordinates to Cartesian coordinates.

    Parameters
    ----------
    ra: array-like
        right-ascension of galaxies in degrees
    dec: array-like
        declination of galaxies in degrees
    cz: array-like
        velocity of galaxies in km/s

    Returns
    -------
    coords: array-like, shape = N by 3
        x, y, and z coordinates
    """
    cz_dist = cz/70. #converts velocity into distance
    x_arr   = cz_dist*np.cos(np.radians(ra))*np.cos(np.radians(dec))
    y_arr   = cz_dist*np.sin(np.radians(ra))*np.cos(np.radians(dec))
    z_arr   = cz_dist*np.sin(np.radians(dec))
    coords  = np.column_stack((x_arr,y_arr,z_arr))

    return coords

############################################################################

def calc_dens(n_val,r_val):
    """
    Returns densities of spheres with radius being the distance to the
        nth nearest neighbor.

    Parameters
    ----------
    n_val = integer
        The 'N' from Nth nearest neighbor
    r_val = array-like
        An array with the distances to the Nth nearest neighbor for
        each galaxy

    Returns
    -------
    dens: array-like
        An array with the densities of the spheres created with radii
        to the Nth nearest neighbor.
    """
    dens = np.array([(3.*(n_val+1)/(4.*np.pi*r_val[hh]**3)) \
                     for hh in range(len(r_val))])

    return dens_____no_output_____def plot_calcs(mass,bins,dlogM):
    """
    Returns values for plotting the stellar mass function and
        mass ratios

    Parameters
    ----------
    mass: array-like
        A 1D array with mass values, assumed to be in order
    bins: array=like
        A 1D array with the values which will be used as the bin edges
        by the histogram function
    dlogM: float-like
        The log difference between bin edges

    Returns
    -------
    bin_centers: array-like
        An array with the medians mass values of the mass bins
    mass-freq: array-like
        Contains the number density values of each mass bin
    ratio_dict: dictionary-like
        A dictionary with three keys, corresponding to the divisors
        2,4, and 10 (as the percentile cuts are based on these
        divisions). Each key has the density-cut, mass ratios for
        that specific cut (50/50 for 2; 25/75 for 4; 10/90 for 10).
    """

    mass_counts, edges = np.histogram(mass,bins)
    bin_centers        = 0.5*(edges[:-1]+edges[1:])

    mass_freq  = mass_counts/float(len(mass))/dlogM

#     non_zero   = (mass_freq!=0)

    ratio_dict = {}
    frac_val   = [2,4,10]

    yerr = []
    bin_centers_fin = []

    for ii in frac_val:
        ratio_dict[ii] = {}
        frac_data      = int(len(mass)/ii)

        # Calculations for the lower density cut
        frac_mass      = mass[0:frac_data]
        counts, edges  = np.histogram(frac_mass,bins)

        # Calculations for the higher density cut
        frac_mass_2       = mass[-frac_data:]
        counts_2, edges_2 = np.histogram(frac_mass_2,bins)

        # Ratio determination
        ratio_counts   = (1.*counts_2)/(1.*counts)

        non_zero = np.isfinite(ratio_counts)

        ratio_counts_1 = ratio_counts[non_zero]

#         print 'len ratio_counts: {0}'.format(len(ratio_counts_1))

        ratio_dict[ii] = ratio_counts_1

        temp_yerr = (counts_2*1.)/(counts*1.)*\
            np.sqrt(1./counts + 1./counts_2)

        temp_yerr_1 = temp_yerr[non_zero]

#         print 'len yerr: {0}'.format(len(temp_yerr_1))

        yerr.append(temp_yerr_1)

        bin_centers_1 = bin_centers[non_zero]

#         print 'len bin_cens: {0}'.format(len(bin_centers_1))

        bin_centers_fin.append(bin_centers_1)

    mass_freq_list     = [[] for xx in xrange(2)]
    mass_freq_list[0]  = mass_freq
    mass_freq_list[1]  = np.sqrt(mass_counts)/float(len(mass))/dlogM
    mass_freq          = np.array(mass_freq_list)

    ratio_dict_list    = [[] for xx in range(2)]
    ratio_dict_list[0] = ratio_dict
    ratio_dict_list[1] = yerr
    ratio_dict         = ratio_dict_list

    return bin_centers, mass_freq, ratio_dict, bin_centers_fin_____no_output_____def bin_func(mass_dist,bins,kk,bootstrap=False):
    """
    Returns median distance to Nth nearest neighbor

    Parameters
    ----------
    mass_dist: array-like
        An array with mass values in at index 0 (when transformed) and distance
        to the Nth nearest neighbor in the others
        Example: 6239 by 7
            Has mass values and distances to 6 Nth nearest neighbors
    bins: array=like
        A 1D array with the values which will be used as the bin edges
    kk: integer-like
        The index of mass_dist (transformed) where the appropriate distance
        array may be found

    Optional
    --------
    bootstrap == True
        Calculates the bootstrap errors associated with each median distance
        value. Creates an array housing arrays containing the actual distance
        values associated with every galaxy in a specific bin. Bootstrap error
        is then performed using astropy, and upper and lower one sigma values
        are found for each median value.  These are added to a list with the
        median distances, and then converted to an array and returned in place
        of just 'medians.'

    Returns
    -------
    medians: array-like
        An array with the median distance to the Nth nearest neighbor from
        all the galaxies in each of the bins
    """

    edges        = bins
    bin_centers  = 0.5*(edges[:-1]+edges[1:])

    # print 'length bins:'
    # print len(bins)

    digitized    = np.digitize(mass_dist.T[0],edges)
    digitized   -= int(1)

    bin_nums          = np.unique(digitized)

    bin_nums_list = list(bin_nums)

    if (len(bin_centers)) in bin_nums_list:
        bin_nums_list.remove(len(bin_centers))

    bin_nums = np.array(bin_nums_list)

#     print bin_nums

    non_zero_bins = []
    for ii in bin_nums:
        if (len(mass_dist.T[kk][digitized==ii]) != 0):
            non_zero_bins.append(bin_centers[ii])
#     print len(non_zero_bins)

    for ii in bin_nums:

        if len(mass_dist.T[kk][digitized==ii]) == 0:
#             temp_list = list(mass_dist.T[kk]\
#                                              [digitized==ii])
#             temp_list.append(np.nan)
            mass_dist.T[kk][digitized==ii] = np.nan

    # print bin_nums
    # print len(bin_nums)

    medians  = np.array([np.nanmedian(mass_dist.T[kk][digitized==ii]) \
                for ii in bin_nums])

    # print len(medians)

    if bootstrap == True:
        dist_in_bin    = np.array([(mass_dist.T[kk][digitized==ii]) \
                for ii in bin_nums])
        for vv in range(len(dist_in_bin)):
            if len(dist_in_bin[vv]) == 0:
#                 dist_in_bin_list = list(dist_in_bin[vv])
#                 dist_in_bin[vv] = np.zeros(len(dist_in_bin[0]))
                dist_in_bin[vv] = np.nan
        low_err_test   = np.array([np.percentile(astropy.stats.bootstrap\
                        (dist_in_bin[vv],bootnum=1000,bootfunc=np.median),16) \
                        for vv in range(len(dist_in_bin))])
        high_err_test  = np.array([np.percentile(astropy.stats.bootstrap\
                        (dist_in_bin[vv],bootnum=1000,bootfunc=np.median),84) \
                        for vv in range(len(dist_in_bin))])

        med_list    = [[] for yy in range(3)]
        med_list[0] = medians
        med_list[1] = low_err_test
        med_list[2] = high_err_test
        medians     = np.array(med_list)

#     print len(medians)
#     print len(non_zero_bins)

    return medians, np.array(non_zero_bins)
    _____no_output_____def hist_calcs(mass,bins,dlogM):
    """
    Returns dictionaries with the counts for the upper
        and lower density portions; calculates the
        three different percentile cuts for each mass
        array given

    Parameters
    ----------
    mass: array-like
        A 1D array with log stellar mass values, assumed
        to be an order which corresponds to the ascending
        densities; (necessary, as the index cuts are based
        on this)
    bins: array-like
        A 1D array with the values which will be used as the bin edges
    dlogM: float-like
        The log difference between bin edges

    Returns
    -------
    hist_dict_low: dictionary-like
        A dictionary with three keys (the frac vals), with arrays
        as values. The values for the lower density cut
    hist_dict_high: dictionary like
        A dictionary with three keys (the frac vals), with arrays
        as values. The values for the higher density cut
    """
    hist_dict_low  = {}
    hist_dict_high = {}
    bin_cens_low   = {}
    bin_cens_high  = {}
    frac_val  = np.array([2,4,10])
    frac_dict = {2:0,4:1,10:2}

    edges = bins

    bin_centers = 0.5 * (edges[:-1]+edges[1:])

    low_err   = [[] for xx in xrange(len(frac_val))]
    high_err  = [[] for xx in xrange(len(frac_val))]

    for ii in frac_val:
#         hist_dict_low[ii]  = {}
#         hist_dict_high[ii] = {}

        frac_data     = int(len(mass)/ii)

        frac_mass     = mass[0:frac_data]
        counts, edges = np.histogram(frac_mass,bins)
        low_counts    = (counts/float(len(frac_mass))/dlogM)

        non_zero = (low_counts!=0)
        low_counts_1 = low_counts[non_zero]
        hist_dict_low[ii]  = low_counts_1
        bin_cens_low[ii]   = bin_centers[non_zero]

        ##So... I don't actually know if I need to be calculating error
        ##on the mocks. I thought I didn't, but then, I swear someone
        ##*ahem (Victor)* said to. So I am. Guess I'm not sure they're
        ##useful. But I'll have them if necessary. And ECO at least
        ##needs them.

        low_err = np.sqrt(counts)/len(frac_mass)/dlogM
        low_err_1 = low_err[non_zero]
        err_key = 'err_{0}'.format(ii)
        hist_dict_low[err_key] = low_err_1

        frac_mass_2        = mass[-frac_data:]
        counts_2, edges_2  = np.histogram(frac_mass_2,bins)
        high_counts        = (counts_2/float(len(frac_mass_2))/dlogM)

        non_zero = (high_counts!=0)
        high_counts_1 = high_counts[non_zero]
        hist_dict_high[ii] = high_counts_1
        bin_cens_high[ii]  = bin_centers[non_zero]

        high_err = np.sqrt(counts_2)/len(frac_mass_2)/dlogM
        high_err_1 = high_err[non_zero]
        hist_dict_high[err_key] = high_err_1

    return hist_dict_low, hist_dict_high, bin_cens_low, bin_cens_high_____no_output_____def mean_bin_mass(mass_dist,bins,kk):
    """
    Returns mean mass of galaxies in each bin

    Parameters
    ----------
    mass_dist: array-like
        An array with mass values in at index 0 (when transformed)
    bins: array=like
        A 1D array with the values which will be used as the bin edges

    Returns
    -------

    """
    edges        = bins

    digitized    = np.digitize(mass_dist.T[0],edges)
    digitized   -= int(1)

    bin_nums          = np.unique(digitized)

    for ii in bin_nums:
        if len(mass_dist.T[kk][digitized==ii]) == 0:
            mass_dist.T[kk][digitized==ii] = np.nan

    mean_mass = np.array([np.nanmean(mass_dist.T[0][digitized==ii]) \
                for ii in bin_nums])

    return mean_mass

###note, this should use the same bin_centers as provided by the
#median from bin_func_____no_output_____eco_mass_dist.T[0]_____no_output_____# dirpath  = r"C:\Users\Hannah\Desktop\Vanderbilt_REU\Stellar_mass_env_density"
# dirpath += r"\Catalogs\Resolve_plk_5001_so_mvir_scatter_ECO_Mocks_"
# dirpath += r"scatter_mocks\Resolve_plk_5001_so_mvir_scatter0p1_ECO_Mocks"

dirpath  = r"C:\Users\Hannah\Desktop\Vanderbilt_REU\Stellar_mass_env_Density\Catalogs"
dirpath += r"\Mocks_Scatter_Abundance_Matching\Resolve_plk_5001_so_mvir_scatter0p3_ECO_Mocks"

usecols  = (0,1,4,8,13)
dlogM    = 0.2
neigh_dict = {1:0,2:1,3:2,5:3,10:4,20:5}_____no_output_____ECO_cats = (Index(dirpath,'.dat'))

names    = ['ra','dec','Halo_ID','cz','logMstar']

PD = [[] for ii in range(len(ECO_cats))]

for ii in range(len(ECO_cats)):
    temp_PD = (pd.read_csv(ECO_cats[ii],sep="\s+", usecols= usecols,header=None,\
                   skiprows=2,names=names))
    col_list = list(temp_PD)
    col_list[2], col_list[3], col_list[4] = col_list[3], col_list[4], col_list[2]
    temp_PD.ix[:,col_list]
    PD[ii] = temp_PD

PD_comp_1  = [(PD[ii][PD[ii].logMstar >= 9.1]) for ii in range(len(ECO_cats))]
PD_comp  = [(PD_comp_1[ii][PD_comp_1[ii].logMstar <=11.77]) for ii in range(len(ECO_cats))]

[(PD_comp[ii].reset_index(drop=True,inplace=True)) for ii in range(len(ECO_cats))]_____no_output_____for ii in range(len(ECO_cats)):
    print len(PD_comp[ii][PD_comp[ii].logMstar >=11.5])
# for ii in range(len(ECO_cats)):
#     print PD_comp[ii]
9
9
9
12
24
7
6
10
min_max_mass_arr = []

for ii in range(len(PD_comp)):
    min_max_mass_arr.append(max(PD_comp[ii].logMstar))
    min_max_mass_arr.append(min(PD_comp[ii].logMstar))

min_max_mass_arr = np.array(min_max_mass_arr)

bins = Bins_array_create(min_max_mass_arr,dlogM)
bins+= 0.1
bins_list = list(bins)
for ii in bins:
    if ii > 11.77:
        bins_list.remove(ii)

bins = np.array(bins_list)

num_of_bins = int(len(bins) - 1)

ra_arr  = np.array([(PD_comp[ii].ra) \
    for ii in range(len(PD_comp))])

dec_arr  = np.array([(PD_comp[ii].dec) \
    for ii in range(len(PD_comp))])

cz_arr  = np.array([(PD_comp[ii].cz) \
    for ii in range(len(PD_comp))])

mass_arr  = np.array([(PD_comp[ii].logMstar) \
    for ii in range(len(PD_comp))])

halo_id_arr  = np.array([(PD_comp[ii].Halo_ID) \
    for ii in range(len(PD_comp))])

coords_test = np.array([sph_to_cart(ra_arr[vv],dec_arr[vv],cz_arr[vv]) \
                for vv in range(len(ECO_cats))])

neigh_vals  = np.array([1,2,3,5,10,20])

nn_arr_temp = [[] for uu in xrange(len(coords_test))]
nn_arr      = [[] for xx in xrange(len(coords_test))]
nn_arr_nn   = [[] for yy in xrange(len(neigh_vals))]
nn_idx      = [[] for zz in xrange(len(coords_test))]

for vv in range(len(coords_test)):
    nn_arr_temp[vv] = spatial.cKDTree(coords_test[vv])
    nn_arr[vv] = np.array(nn_arr_temp[vv].query(coords_test[vv],21)[0])
    nn_idx[vv] = np.array(nn_arr_temp[vv].query(coords_test[vv],21)[1])

nn_specs       = [(np.array(nn_arr).T[ii].T[neigh_vals].T) for ii in \
                    range(len(coords_test))]
nn_mass_dist   = np.array([(np.column_stack((mass_arr[qq],nn_specs[qq]))) \
                    for qq in range(len(coords_test))])

nn_neigh_idx      = np.array([(np.array(nn_idx).T[ii].T[neigh_vals].T) for ii in \
                    range(len(coords_test))])_____no_output_____bins_____no_output_____# truth_vals[ii] = {}
# for kk in range(10):
#     truth_list.append(np.unique(halo_id_arr[ii][nn_neigh_idx[ii].T[neigh_dict[jj]]\
#                                   [halo_id_arr[ii][nn_neigh_idx[ii].T[neigh_dict[jj]]].keys()[kk]]])==halo_id_arr[ii][kk])
#     truth_vals[ii][jj] = truth_list

truth_vals = {}
for ii in range(len(halo_id_arr)):
    truth_vals[ii] = {}
    for jj in neigh_vals:
        halo_id_neigh = halo_id_arr[ii][nn_neigh_idx[ii].T[neigh_dict[jj]]].values
        truth_vals[ii][jj] = halo_id_neigh==halo_id_arr[ii].values_____no_output_____halo_frac = {}
for ii in range(len(mass_arr)):
    halo_frac[ii] = {}
    mass_binning = np.digitize(mass_arr[ii],bins)
    bins_to_use = list(np.unique(mass_binning))
    if (len(bins)-1) not in bins_to_use:
        bins_to_use.append(len(bins)-1)
    if len(bins) in bins_to_use:
        bins_to_use.remove(len(bins))
    for jj in neigh_vals:
        one_zero = truth_vals[ii][jj].astype(int)
        frac = []
        for xx in bins_to_use:
            truth_binning = one_zero[mass_binning==xx]
            num_in_bin = len(truth_binning)
            if num_in_bin == 0:
                num_in_bin = np.nan
            num_same_halo = np.count_nonzero(truth_binning==1)
            frac.append(num_same_halo/(1.*num_in_bin))
        halo_frac[ii][jj] = frac_____no_output_____nn_dict   = {1:0,2:1,3:2,5:3,10:4,20:5}

mean_mock_halo_frac = {}

for ii in neigh_vals:
    for jj in range(len(halo_frac)):
        bin_str = '{0}'.format(ii)
        oo_arr = halo_frac[jj][ii]
        n_o_elem = len(oo_arr)
        if jj == 0:
            oo_tot = np.zeros((n_o_elem,1))
        oo_tot = np.insert(oo_tot,len(oo_tot.T),oo_arr,1)
    oo_tot = np.array(np.delete(oo_tot,0,axis=1))
    oo_tot_mean = [np.nanmean(oo_tot[uu]) for uu in xrange(len(oo_tot))]
    oo_tot_std  = [np.nanstd(oo_tot[uu])/np.sqrt(len(halo_frac)) for uu in xrange(len(oo_tot))]
    mean_mock_halo_frac[bin_str] = [oo_tot_mean,oo_tot_std]

_____no_output_____# (mean_mock_halo_frac['1'])_____no_output_____def plot_halo_frac(bin_centers,y_vals,ax,plot_idx):
    titles = [1,2,3,5,10,20]
    ax.set_xlim(9.1,11.9)
    ax.set_xticks(np.arange(9.5,12.,0.5))
    ax.tick_params(axis='x', which='major', labelsize=16)
    title_here = 'n = {0}'.format(titles[plot_idx])
    ax.text(0.05, 0.95, title_here,horizontalalignment='left',\
            verticalalignment='top',transform=ax.transAxes,fontsize=18)
    if plot_idx == 4:
        ax.set_xlabel('$\log\ (M_{*}/M_{\odot})$',fontsize=20)
    ax.plot(bin_centers,y_vals,color='silver')

def plot_mean_halo_frac(bin_centers,mean_vals,ax,std):
    ax.errorbar(bin_centers,mean_vals,yerr=std,color='deeppink')
_____no_output_____mass_bin_test = np.digitize(mass_arr[0],bins)
one_zero_test = truth_vals[0][1].astype(int)

test_arr_ones = one_zero_test[mass_bin_test==1]

print len(test_arr_ones)
print len(mass_bin_test)

print np.count_nonzero(test_arr_ones==1)1052
6438
217
# nn_dist    = {}
nn_dens    = {}
mass_dat   = {}
ratio_info = {}
bin_cens_diff = {}

mass_freq  = [[] for xx in xrange(len(coords_test))]

for ii in range(len(coords_test)):
#     nn_dist[ii]    = {}
    nn_dens[ii]    = {}
    mass_dat[ii]   = {}
    ratio_info[ii] = {}
    bin_cens_diff[ii] = {}

#     nn_dist[ii]['mass'] = nn_mass_dist[ii].T[0]

    for jj in range(len(neigh_vals)):
#         nn_dist[ii][(neigh_vals[jj])]  = np.array(nn_mass_dist[ii].T\
#                                             [range(1,len(neigh_vals)+1)[jj]])
        nn_dens[ii][(neigh_vals[jj])]  = np.column_stack((nn_mass_dist[ii].T\
                                            [0],calc_dens(neigh_vals[jj],\
                                            nn_mass_dist[ii].T[range(1,len\
                                                (neigh_vals)+1)[jj]])))

        idx = np.array([nn_dens[ii][neigh_vals[jj]].T[1].argsort()])
        mass_dat[ii][(neigh_vals[jj])] = (nn_dens[ii][neigh_vals[jj]]\
                                            [idx].T[0])

        bin_centers, mass_freq[ii], ratio_info[ii][neigh_vals[jj]],bin_cens_diff[ii][neigh_vals[jj]] = \
                            plot_calcs(mass_dat[ii][neigh_vals[jj]],bins,dlogM)

all_mock_meds = {}
mock_meds_bins = {}
all_mock_mass_means = {}

for vv in range(len(nn_mass_dist)):
    all_mock_meds[vv] = {}
    mock_meds_bins[vv]= {}
    all_mock_mass_means[vv] = {}
    for jj in range(len(nn_mass_dist[vv].T)-1):
        all_mock_meds[vv][neigh_vals[jj]],mock_meds_bins[vv][neigh_vals[jj]] = (bin_func(nn_mass_dist[vv],bins,(jj+1)))
        all_mock_mass_means[vv][neigh_vals[jj]] = (mean_bin_mass(nn_mass_dist[vv],bins,(jj+1))) _____no_output_____med_plot_arr = {}

for ii in range(len(neigh_vals)):
    med_plot_arr[neigh_vals[ii]] = {}
    for jj in range(len(nn_mass_dist)):
        med_plot_arr[neigh_vals[ii]][jj] = all_mock_meds[jj][neigh_vals[ii]]

# for ii in range(len(neigh_vals)):
#     for jj in range(len(nn_mass_dist)):
#         print len(all_mock_meds[jj][ii])

mass_freq_plot  = (np.array(mass_freq))
max_lim = [[] for xx in range(len(mass_freq_plot.T))]
min_lim = [[] for xx in range(len(mass_freq_plot.T))]
for jj in range(len(mass_freq_plot.T)):
    max_lim[jj] = max(mass_freq_plot.T[jj][0])
    min_lim[jj] = min(mass_freq_plot.T[jj][0])_____no_output_____# haloid_neigh = halo_id_arr[ii][nn_neigh_idx[ii].T[neigh_dict[jj]]].values
# B = haloid_neigh == halo_id_arr[ii].values
# print(B)
# print(haloid_neigh)
# print(halo_id_arr[ii].values)_____no_output_____# for ii in range(len(neigh_vals)):
for jj in range(len(nn_mass_dist)):
    print len(all_mock_meds[jj])13
13
13
13
13
13
13
13
print all_mock_meds[array([ 6.26569471,  6.24965134,  6.07319606,  6.19346353,  6.20446401,
        6.07430155,  5.9270275 ,  6.08499683,  5.72830407,  5.21042752,
        4.83366964,  4.99760239,  3.49344021]), array([ 6.71794719,  6.79618226,  6.41537924,  6.5564611 ,  6.68719785,
        6.48234149,  6.52114849,  6.14095675,  5.41170317,  6.0014924 ,
        5.41193825,  5.52115575,  4.01493564]), array([ 5.9474175 ,  5.9581926 ,  6.21834399,  5.98869011,  6.0872101 ,
        6.19028513,  6.03525196,  5.7168246 ,  5.47383497,  5.22139399,
        4.22517576,  5.1608911 ,  3.72720344]), array([ 5.32603467,  5.29966481,  5.32493191,  5.37213674,  5.33943798,
        5.29309786,  5.09717599,  4.93409825,  4.89723663,  4.60853626,
        4.53946647,  3.96629358,  3.50774445]), array([ 4.47825117,  4.38534494,  4.4632355 ,  4.53947356,  4.35728087,
        4.42425787,  4.50518286,  4.35444041,  4.17402261,  4.02805828,
        3.77372985,  3.30955029,  3.02924792]), array([ 5.48125549,  5.32593161,  5.52563852,  5.48070911,  5.3360458 ,
        5.37182778,  5.2999896 ,  5.22081307,  4.82524237,  4.90870137,
        4.31365323,  3.12532438,  2.95440696]), array([ 5.99234158,  6.15653197,  5.8965705 ,  6.04404129,  5.99150486,
        5.88667322,  5.99959426,  5.51991349,  5.39674391,  5.16270611,
        5.17717181,  4.81404993,  5.57701763]), array([ 6.15058884,  6.47605002,  6.32731385,  6.06979882,  6.14335609,
        6.1184185 ,  5.91862974,  5.86014739,  5.92113073,  4.99791237,
        5.17054022,  4.63201285,  4.28925863])]
bin_cens_diff

bins_curve_fit = bins.copy()
global bins_curve_fit

def abc():
    print bins_curve_fit

abc()[  9.1   9.3   9.5   9.7   9.9  10.1  10.3  10.5  10.7  10.9  11.1  11.3
  11.5  11.7]
eco_path  = r"C:\Users\Hannah\Desktop\Vanderbilt_REU\Stellar_mass_env_density"
eco_path += r"\Catalogs\ECO_true"
eco_cols  = np.array([0,1,2,4])_____no_output_____ECO_true = (Index(eco_path,'.txt'))
names    = ['ra','dec','cz','logMstar']
PD_eco   = pd.read_csv(ECO_true[0],sep="\s+", usecols=(eco_cols),header=None,\
                skiprows=1,names=names)
eco_comp = PD_eco[PD_eco.logMstar >= 9.1]

ra_eco   = (np.array(eco_comp)).T[0]
dec_eco  = (np.array(eco_comp)).T[1]
cz_eco   = (np.array(eco_comp)).T[2]
mass_eco = (np.array(eco_comp)).T[3]

coords_eco        = sph_to_cart(ra_eco,dec_eco,cz_eco)
eco_neighbor_tree = spatial.cKDTree(coords_eco)
eco_tree_dist     = np.array(eco_neighbor_tree.query(coords_eco,\
                    (neigh_vals[-1]+1))[0])

eco_mass_dist = np.column_stack((mass_eco,eco_tree_dist.T[neigh_vals].T))
##range 1,7 because of the six nearest neighbors (and fact that 0 is mass)
##the jj is there to specify which index in the [1,6] array
eco_dens = ([calc_dens(neigh_vals[jj],\
            (eco_mass_dist.T[range(1,7)[jj]])) for jj in range\
            (len(neigh_vals))])

eco_mass_dens = [(np.column_stack((mass_eco,eco_dens[ii]))) for ii in \
                range(len(neigh_vals))]
eco_idx  = [(eco_mass_dens[jj].T[1].argsort()) for jj in \
            range(len(neigh_vals))]
eco_mass_dat  = [(eco_mass_dens[jj][eco_idx[jj]].T[0]) for jj in \
                range(len(neigh_vals))]

eco_ratio_info    = [[] for xx in xrange(len(eco_mass_dat))]
eco_final_bins    = [[] for xx in xrange(len(eco_mass_dat))]

for qq in range(len(eco_mass_dat)):
    bin_centers, eco_freq, eco_ratio_info[qq],eco_final_bins[qq] = plot_calcs(eco_mass_dat[qq],\
                                    bins,dlogM)

eco_medians   = [[] for xx in xrange(len(eco_mass_dat))]
eco_med_bins   = [[] for xx in xrange(len(eco_mass_dat))]
eco_mass_means   = [[] for xx in xrange(len(eco_mass_dat))]

for jj in (range(len(eco_mass_dat))):
    eco_medians[jj],eco_med_bins[jj] = np.array(bin_func(eco_mass_dist,bins,(jj+1),\
        bootstrap=True))
    eco_mass_means[jj] = (mean_bin_mass(eco_mass_dist,bins,(jj+1))) _____no_output_____hist_low_info  = {}
hist_high_info = {}
hist_low_bins  = {}
hist_high_bins = {}

for ii in xrange(len(coords_test)):
    hist_low_info[ii]  = {}
    hist_high_info[ii] = {}
    hist_low_bins[ii]  = {}
    hist_high_bins[ii] = {}

    for jj in range(len(neigh_vals)):
        hist_low_info[ii][neigh_vals[jj]],\
        hist_high_info[ii][neigh_vals[jj]], \
        hist_low_bins[ii][neigh_vals[jj]],\
        hist_high_bins[ii][neigh_vals[jj]] \
        = hist_calcs(mass_dat[ii][neigh_vals[jj]],bins,dlogM)

frac_vals     = [2,4,10]
hist_low_arr  = [[[] for yy in xrange(len(nn_mass_dist))] for xx in \
    xrange(len(neigh_vals))]
hist_high_arr = [[[] for yy in xrange(len(nn_mass_dist))] for xx in \
    xrange(len(neigh_vals))]_____no_output_____hist_low_info[0][1]_____no_output_____for ii in range(len(neigh_vals)):
    for jj in range(len(nn_mass_dist)):
        hist_low_arr[ii][jj]  = (hist_low_info[jj][neigh_vals[ii]])
        hist_high_arr[ii][jj] = (hist_high_info[jj][neigh_vals[ii]])

##I unindented the below two "lines". Because they don't seem to need to be called iteratively

plot_low_hist  = [[[[] for yy in xrange(len(nn_mass_dist))] \
                         for zz in xrange(len(frac_vals))] for xx in \
                         xrange(len(hist_low_arr))]

plot_high_hist = [[[[] for yy in xrange(len(nn_mass_dist))] \
                 for zz in xrange(len(frac_vals))] for xx in \
                 xrange(len(hist_high_arr))]

for jj in range(len(nn_mass_dist)):
    for hh in range(len(frac_vals)):
        for ii in range(len(neigh_vals)):
            plot_low_hist[ii][hh][jj]  = hist_low_arr[ii][jj][frac_vals[hh]]
            plot_high_hist[ii][hh][jj] = hist_high_arr[ii][jj][frac_vals[hh]] _____no_output_____eco_mass_means_____no_output_____eco_low  = {}
eco_high = {}
eco_low_bins = {}
eco_high_bins = {}
for jj in range(len(neigh_vals)):
    eco_low[neigh_vals[jj]]  = {}
    eco_high[neigh_vals[jj]] = {}
    eco_low_bins[neigh_vals[jj]]  = {}
    eco_high_bins[neigh_vals[jj]] = {}
    eco_low[neigh_vals[jj]], eco_high[neigh_vals[jj]], \
    eco_low_bins[neigh_vals[jj]], eco_high_bins[neigh_vals[jj]]= \
    hist_calcs(eco_mass_dat[jj],bins,dlogM)_____no_output_____eco_low[1]_____no_output_____def perc_calcs(mass,bins,dlogM):
    mass_counts, edges = np.histogram(mass,bins)
    mass_freq          = mass_counts/float(len(mass))/dlogM

    bin_centers        = 0.5*(edges[:-1]+edges[1:])

    non_zero = (mass_freq!=0)

    mass_freq_1 = mass_freq[non_zero]

    smf_err            = np.sqrt(mass_counts)/float(len(mass))/dlogM

    smf_err_1   = smf_err[non_zero]

    bin_centers_1 = bin_centers[non_zero]

    return mass_freq_1, smf_err_1, bin_centers_1_____no_output_____def quartiles(mass):
    dec_val     =  int(len(mass)/4)
    res_list      =  [[] for bb in range(4)]

    for aa in range(0,4):
        if aa == 3:
            res_list[aa] = mass[aa*dec_val:]
        else:
            res_list[aa] = mass[aa*dec_val:(aa+1)*dec_val]

    return res_list_____no_output_____def deciles(mass):
    dec_val     =  int(len(mass)/10)
    res_list      =  [[] for bb in range(10)]

    for aa in range(0,10):
        if aa == 9:
            res_list[aa] = mass[aa*dec_val:]
        else:
            res_list[aa] = mass[aa*dec_val:(aa+1)*dec_val]

    return res_list_____no_output_____def mean_perc_mass(mass,bins):
    """
    Returns mean mass of galaxies in each bin

    Parameters
    ----------
    mass_dist: array-like
        An array with mass values in at index 0 (when transformed)
    bins: array=like
        A 1D array with the values which will be used as the bin edges

    Returns
    -------

    """
    edges        = bins

    digitized    = np.digitize(mass,edges)
    digitized   -= int(1)

    bin_nums          = np.unique(digitized)

    for ii in bin_nums:
        if len(mass[digitized==ii]) == 0:
            mass[digitized==ii] = np.nan

    mean_mass = np.array([np.nanmean(mass[digitized==ii]) \
                for ii in bin_nums])

    return mean_mass _____no_output_____eco_one_perc_means = mean_perc_mass(eco_dec[1][0],bins)_____no_output_____eco_mass_dist.T[0][]_____no_output_____eco_dec = {}
for cc in range(len(eco_mass_dat)):
    eco_dec[neigh_vals[cc]] = deciles(eco_mass_dat[cc])

eco_dec_smf = {}
eco_dec_err = {}
eco_dec_bin = {}

for ss in neigh_vals:
    eco_dec_smf[ss] = {}
    eco_dec_err[ss] = {}
    eco_dec_bin[ss] = {}
    for tt in range(len(eco_dec[ss])):
        eco_dec_smf[ss][tt], eco_dec_err[ss][tt], eco_dec_bin[ss][tt] = perc_calcs(eco_dec[ss][tt],bins,dlogM)    _____no_output_____print len(eco_dec_smf[1][0])
print len(all_mock_mass_means[0][:-2])
print len(eco_dec_err[1][0])
print eco_dec_bin[1][0]
print all_mock_mass_means[0]
print bins_curve_fit11
12
11
[  9.2   9.4   9.6   9.8  10.   10.2  10.4  10.6  10.8  11.   11.2]
[  9.19642586   9.39671156   9.59526919   9.79982097   9.99914601
  10.19368263  10.39086466  10.59475703  10.7895302   10.98679389  11.19
  11.35777778  11.56666667  11.77      ]
[  9.1   9.3   9.5   9.7   9.9  10.1  10.3  10.5  10.7  10.9  11.1  11.3
  11.5  11.7]

</code>

# Stellar Mass Function_____no_output_____

<code>
fig,ax  = plt.subplots(figsize=(8,8))
ax.set_title('Mass Distribution',fontsize=18)
ax.set_xlabel('$\log\ (M_{*}/M_{\odot})$',fontsize=18)
ax.set_ylabel(r'$\log\ (\frac{N_{gal}}{N_{total}*dlogM_{*}})$',fontsize=20)
ax.set_yscale('log')
ax.set_xlim(9.1,11.9)
ax.tick_params(axis='both', labelsize=14)

for ii in range(len(mass_freq)):
    ax.plot(bin_centers,mass_freq[ii][0],color='silver')
    ax.fill_between(bin_centers,max_lim,min_lim,color='silver',alpha=0.1)
ax.errorbar(bin_centers,eco_freq[0],yerr=eco_freq[1],color='dodgerblue',\
            linewidth=2,label='ECO')
ax.legend(loc='best')

plt.subplots_adjust(left=0.15, bottom=0.1, right=0.85, top=0.94,\
                    hspace=0.2,wspace=0.2)
plt.show()_____no_output_____
</code>

# The Mess I am unlovingly referring to as Schechter Functions_____no_output_____

<code>
def schechter_real_func(mean_of_mass_bin,phi_star,alpha,Mstar):
    """

    mean_of_mass_bin: array-like
        Unlogged x-values
    phi-star: float-like
        Normalization value
    alpha: float-like
        Low-mass end slope
    Mstar: float-like
        Unlogged value where function switches from power-law to exponential

    """
#     M_over_mstar = (10**mean_of_mass_bin)/Mstar
    M_over_mstar = (mean_of_mass_bin)/Mstar
    res_arr    = (phi_star) * (M_over_mstar**(alpha)) * \
                        np.exp(- M_over_mstar)

    return res_arr_____no_output_____def schechter_log_func(stellar_mass,phi_star,alpha,m_star):
    """
    Returns a plottable Schechter function for the
        stellar mass functions of galaxies

    Parameters
    ----------
    stellar_mass: array-like
        An array of unlogged stellar mass values which
        will eventually be the x-axis values the function
        is plotted against
    phi_star: float-like
        A constant which normalizes (?) the function;
        Moves the graph up and down
    alpha: negative integer-like
        The faint-end, or in this case, low-mass slope;
        Describes the power-law portion of the curve
    m_star: float-like
        Unlogged value of the characteristic (?) stellar
        mass; the "knee" of the function, where the
        power-law gives way to the exponential portion

    Returns
    -------
    res: array-like
        Array of values to be plotted on a log
        scale to display the Schechter function

    """
    constant = np.log(10) * phi_star
    log_M_Mstar = np.log10(stellar_mass/m_star)
    res = constant * 10**(log_M_Mstar * (alpha+1)) * \
        np.exp(-10**log_M_Mstar)

    return res_____no_output_____def schech_integral(edge_1,edge_2,phi_star,alpha,Mstar):
    bin_integral = (integrate.quad(schechter_real_func,edge_1,edge_2,args=(phi_star,alpha,Mstar))[0])
#     tot_integral = (integrate.quad(schechter_real_func,9.1,11.7,args=(phi_star,alpha,Mstar)))[0]
# #
#     result = bin_integral/tot_integral/0.2

    return bin_integral_____no_output_____schech_integral(10**9.1,10**9.3,opt_v[0],opt_v[1],opt_v[2])_____no_output_____bins_curve_fit_____no_output_____def schech_step_3(xdata,phi_star,alpha,Mstar):
    """
    xdata: array-like
        Unlogged x-values
    Mstar:
        unlogged
    """
    test_int = []
    for ii in range(len(xdata)):
        test_int.append((schech_integral(10**bins_curve_fit[ii],10**bins_curve_fit[ii+1],phi_star,alpha,Mstar)))
    return test_int_____no_output_____len(eco_mass_means[0])_____no_output_____schech_vals_graph = schech_step_3(bins_curve_fit[:-1],opt_v[0],opt_v[1],opt_v[2])_____no_output_____print schech_integral(10**9.1,10**9.3,1.5,-1.1,10**10.64)

print integrate.quad(schechter_real_func,10**9.1,10**9.3,args=(1.5,-1.1,10**10.64))0.927898471907
(0.9278984719073082, 1.0301742480259926e-14)
def find_params(bin_int,mean_mass,count_err):
    """
    Parameters
    ----------
    bin_int: array-like
        Integral (number of counts) in each bin of width dlogM
    mean_mass: array-like
        Logged values (?)

    Returns
    -------
    opt_v: array-like
        Array with three values: phi_star, alpha, and M_star
    res_arr: array-like
        Array with two values: alpha and log_M_star

    """
    xdata = 10**mean_mass
#     xdata = mean_mass
    p0    = (1.5,-1.05,10**10.64)
    opt_v,est_cov = optimize.curve_fit(schech_step_3,xdata,\
                            bin_int,p0=p0,sigma=count_err,check_finite=True)
    alpha   = opt_v[1]
    log_m_star    = np.log10(opt_v[2])

    res_arr = np.array([alpha,log_m_star])

    perr = np.sqrt(np.diag(est_cov))

    return opt_v, res_arr, perr, est_cov_____no_output_____opt_v_test, res_arr,perr,est_cov = find_params(eco_dec_smf[1][0],eco_one_perc_means,eco_dec_err[1][0])_____no_output_____schechter_real_func(10**eco_one_perc_means,opt_v_test[0],(opt_v_test[1]+1),opt_v_test[2])_____no_output_____m_over_mstar_test = 10**eco_mass_means[0]/10**10.64
res_arr    = (opt_v[0]) * (m_over_mstar_test**(opt_v[1]+1)) * \
                        np.exp(- m_over_mstar_test)
print res_arr[  2.12317712e+00   1.98678755e+00   1.83298971e+00   1.65717247e+00
   1.45470153e+00   1.22152232e+00   9.49395214e-01   6.51615794e-01
   3.68913264e-01   1.55165690e-01   4.20412475e-02   5.75696323e-03
   2.01055265e-04   3.49417482e-06]
schechter_real_func(10**eco_mass_means[0],opt_v[0],(opt_v[1]),opt_v[2])_____no_output_____print len(eco_dec_smf[1][0])
print len(eco_mass_means[0][:-3])11
11
len(eco_freq[0])_____no_output_____# print len(eco_dec_smf[1][0])
# print len(eco_mass_means[0])
# print len(all_mock_mass_means[0][:-2])
# print len(eco_dec_err[1][0])

opt_v, res_arr, perr, est_cov = find_params(eco_dec_smf[1][0],eco_mass_means[0][:-3],eco_dec_err[1][0])
# opt_v, res_arr, perr, est_cov = find_params(eco_dec_smf[1][0],eco_mass_means[0][:-3],None)_____no_output_____print opt_v
print res_arr
# print perr
# print eco_dec_err[1][0]
# print est_cov[  5.13943492e-11  -1.10044964e+00   3.06923523e+10]
[ -1.10044964  10.48703017]
schech_integral(10**9.1,10**24,opt_v[0],opt_v[1],opt_v[2])_____no_output_____test_x = np.linspace(9.1,17,80)
print test_x[  9.1   9.2   9.3   9.4   9.5   9.6   9.7   9.8   9.9  10.   10.1  10.2
  10.3  10.4  10.5  10.6  10.7  10.8  10.9  11.   11.1  11.2  11.3  11.4
  11.5  11.6  11.7  11.8  11.9  12.   12.1  12.2  12.3  12.4  12.5  12.6
  12.7  12.8  12.9  13.   13.1  13.2  13.3  13.4  13.5  13.6  13.7  13.8
  13.9  14.   14.1  14.2  14.3  14.4  14.5  14.6  14.7  14.8  14.9  15.
  15.1  15.2  15.3  15.4  15.5  15.6  15.7  15.8  15.9  16.   16.1  16.2
  16.3  16.4  16.5  16.6  16.7  16.8  16.9  17. ]
# test = schechter_real_func(10**eco_mass_means[0][:-3],opt_v[0],(opt_v[1]),opt_v[2])
test = schechter_real_func(10**test_x,opt_v[0],(opt_v[1]),opt_v[2])
print test[  1.65751926e-009   1.27292023e-009   9.74876315e-010   7.44036688e-010
   5.65387742e-010   4.27282927e-010   3.20689555e-010   2.38603862e-010
   1.75596412e-010   1.27458343e-010   9.09254689e-011   6.34623848e-011
   4.30927791e-011   2.82655617e-011   1.77493641e-011   1.05506474e-011
   5.85297481e-012   2.97651445e-012   1.35673334e-012   5.38797528e-013
   1.79888418e-013   4.82743448e-014   9.84016408e-015   1.41885598e-015
   1.32310674e-016   7.12791959e-018   1.92461141e-019   2.17801694e-021
   8.24766612e-024   7.87130693e-027   1.32503615e-030   2.51052401e-035
   3.04108603e-041   1.15556200e-048   5.62035463e-058   1.13200311e-069
   2.28063125e-084   7.68496378e-103   4.55769033e-126   2.79452095e-155
   4.99483302e-192   2.91267677e-238   1.93794012e-296   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000]
fig, ax = plt.subplots()
ax.set_yscale('log')
ax.set_xscale('log')
# ax.plot(eco_mass_means[0][:-3],test)
ax.plot(10**bin_centers,schech_vals_graph)
ax.plot(10**eco_mass_means[0][:-3],(eco_dec_smf[1][0]))
plt.show()_____no_output_____# print opt_v

print len(test)
print len(all_mock_mass_means[0])
print len(test)
print len(eco_mass_means[0])
print len(eco_dec_smf[1][0])80
13
80
14
11
idx_edge = len(all_mock_mass_means[0]) - len(eco_dec_smf[1][0])
print len(eco_dec_smf[1][0])
print len(all_mock_mass_means[0][:-idx_edge])
print len(eco_dec_err[1][0])
# opt_v, res_arr, perr, est_cov = find_params(eco_dec_smf[1][0],all_mock_mass_means[0][:-(idx_edge)],eco_dec_err[1][0])11
11
11
print len(eco_mass_means[0])
print len(test)
print len(eco_dec_smf[1][0])
print test
# print test*10**10
print eco_dec_smf[1][0]
# print np.log10(eco_dec_smf[1][0])

# [  1.27691357e-09   7.52289969e-10   4.29532422e-10   2.38074992e-10
#    1.27498704e-10   6.47224003e-11   2.92667401e-11   1.10292764e-11
#    3.16160331e-12   5.95850360e-13   6.06349916e-14]14
80
11
[  1.65751926e-009   1.27292023e-009   9.74876315e-010   7.44036688e-010
   5.65387742e-010   4.27282927e-010   3.20689555e-010   2.38603862e-010
   1.75596412e-010   1.27458343e-010   9.09254689e-011   6.34623848e-011
   4.30927791e-011   2.82655617e-011   1.77493641e-011   1.05506474e-011
   5.85297481e-012   2.97651445e-012   1.35673334e-012   5.38797528e-013
   1.79888418e-013   4.82743448e-014   9.84016408e-015   1.41885598e-015
   1.32310674e-016   7.12791959e-018   1.92461141e-019   2.17801694e-021
   8.24766612e-024   7.87130693e-027   1.32503615e-030   2.51052401e-035
   3.04108603e-041   1.15556200e-048   5.62035463e-058   1.13200311e-069
   2.28063125e-084   7.68496378e-103   4.55769033e-126   2.79452095e-155
   4.99483302e-192   2.91267677e-238   1.93794012e-296   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000
   0.00000000e+000   0.00000000e+000   0.00000000e+000   0.00000000e+000]
[ 0.95302013  0.87919463  0.72483221  0.68456376  0.55704698  0.59060403
  0.29530201  0.18120805  0.10738255  0.02013423  0.00671141]
# len(test_int)

# fig, ax = plt.subplots()
# ax.set_yscale('log')
# ax.plot(all_mock_mass_means[0],test_int)
# plt.show()_____no_output_____nrow = int(2)
ncol = int(3)

fig,axes = plt.subplots(nrows=nrow,ncols=ncol,\
                        figsize=(100,200),sharex=True)
axes_flat = axes.flatten()

zz = int(0)
while zz <=4:
    for jj in neigh_vals:
        for kk in range(len(halo_frac)):
            plot_halo_frac(bin_centers,halo_frac[kk][jj],axes_flat[zz],zz)
        nn_str = '{0}'.format(jj)
        plot_mean_halo_frac(bin_centers,mean_mock_halo_frac[nn_str][0],axes_flat[zz],mean_mock_halo_frac[nn_str][1])
        zz += 1

plt.subplots_adjust(top=0.97,bottom=0.1,left=0.03,right=0.99,hspace=0.10,wspace=0.12)
plt.show()            _____no_output_____
</code>

# Regular Plotting Reintroduced_____no_output_____

<code>
def plot_all_rats(bin_centers,y_vals,neigh_val,ax,col_num,plot_idx):
    """
    Returns a plot showing the density-cut, mass ratio.  Optimally
        used with a well-initiated for-loop

    Parameters
    ----------
    bin_centers: array-like
        An array with the medians mass values of the mass bins
    y_vals: array-like
        An array containing the ratio values for each mass bin
    neigh_val: integer-like
        Value which will be inserted into the text label of each plot
    ax: axis-like
        A value which specifies which axis each subplot is to be
        plotted to
    col_num: integer-like
        Integer which specifies which column is currently being
        plotted. Used for labelling subplots
    plot_idx: integer-like
        Specifies which subplot the figure is plotted to. Used for
        labeling the x-axis

    Returns
    -------
    Figure with three subplots showing appropriate ratios
    """
    if plot_idx     ==16:
        ax.set_xlabel('$\log\ (M_{*}/M_{\odot})$',fontsize=18)
    if col_num      ==0:
        title_label = 'Mass Ratio 50/50, {0} NN'.format(neigh_val)
        frac_val    = 10
        ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                verticalalignment='top',transform=ax.transAxes,fontsize=12)
    elif col_num    ==1:
        title_label = 'Mass Ratio 25/75, {0} NN'.format(neigh_val)
        frac_val    = 4
        ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                verticalalignment='top',transform=ax.transAxes,fontsize=12)
    elif col_num    ==2:
        title_label = 'Mass Ratio 10/90, {0} NN'.format(neigh_val)
        frac_val    = 2
        ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                verticalalignment='top',transform=ax.transAxes,fontsize=12)
    ax.set_xlim(9.1,11.9)
#     ax.set_ylim([0,5])
    ax.set_ylim(0,7)
    ax.set_xticks(np.arange(9.5, 12., 0.5))
    ax.set_yticks([1.,3.])
    ax.tick_params(axis='both', labelsize=12)
    ax.axhline(y=1,c="darkorchid",linewidth=0.5,zorder=0)
    ax.plot(bin_centers,y_vals,color='silver')_____no_output_____def plot_eco_rats(bin_centers,y_vals,neigh_val,ax,col_num,plot_idx,only=False):
    """
    Returns subplots of ECO density-cut,mass ratios

    Parameters
    ----------
    bin_centers: array-like
        An array with the medians mass values of the mass bins
    y_vals: array-like
        An array containing the ratio values for each mass bin
    neigh_val: integer-like
        Value which will be inserted into the text label of each plot
    ax: axis-like
        A value which specifies which axis each subplot is to be
        plotted to
    col_num: integer-like
        Integer which specifies which column is currently being
        plotted. Used for labelling subplots
    plot_idx: integer-like
        Specifies which subplot the figure is plotted to. Used for
        labeling the x-axis

    Optional
    --------
    only == True
        To be used when only plotting the ECO ratios, no mocks.
        Will add in the additional plotting specifications that
        would have been taken care of previously in a for-loop
        which plotted the mocks as well

    Returns
    -------
    ECO ratios plotted to any previously initialized figure
    """
    if only == True:
        if plot_idx     ==16:
            ax.set_xlabel('$\log\ (M_{*}/M_{\odot})$',fontsize=18)
        if col_num      ==0:
            title_label = 'Mass Ratio 50/50, {0} NN'.format(neigh_val)
            frac_val    = 10
            ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                    verticalalignment='top',transform=ax.transAxes,fontsize=12)
        elif col_num    ==1:
            title_label = 'Mass Ratio 25/75, {0} NN'.format(neigh_val)
            frac_val    = 4
            ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                    verticalalignment='top',transform=ax.transAxes,fontsize=12)
        elif col_num    ==2:
            title_label = 'Mass Ratio 10/90, {0} NN'.format(neigh_val)
            frac_val    = 2
            ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                    verticalalignment='top',transform=ax.transAxes,fontsize=12)
        ax.set_xlim(9.1,11.9)
        ax.set_ylim(0,7)
#         ax.set_ylim([0,5])
        ax.set_xticks(np.arange(9.5, 12., 0.5))
        ax.set_yticks([1.,3.])
        ax.tick_params(axis='both', labelsize=12)
        ax.axhline(y=1,c="darkorchid",linewidth=0.5,zorder=0)
    frac_vals = np.array([2,4,10])
    y_vals_2 = y_vals[0][frac_vals[hh]]
    ax.errorbar(bin_centers,y_vals_2,yerr=y_vals[1][hh],\
                color='dodgerblue',linewidth=2)_____no_output_____frac_vals   = [2,4,10]
nn_plot_arr = [[[] for yy in xrange(len(nn_mass_dist))] for xx in \
    xrange(len(neigh_vals))]

for ii in range(len(neigh_vals)):
    for jj in range(len(nn_mass_dist)):
        nn_plot_arr[ii][jj] = (ratio_info[jj][neigh_vals[ii]])

plot_frac_arr = [[[[] for yy in xrange(len(nn_mass_dist))] \
                 for zz in xrange(len(frac_vals))] for xx in \
                 xrange(len(nn_plot_arr))]
frac_err_arr = [[[[] for yy in xrange(len(nn_mass_dist))] \
                 for zz in xrange(len(frac_vals))] for xx in \
                 xrange(len(nn_plot_arr))]

for jj in range(len(nn_mass_dist)):
    for hh in range(len(frac_vals)):
        for ii in range(len(neigh_vals)):
            plot_frac_arr[ii][hh][jj] = nn_plot_arr[ii][jj][0][frac_vals[hh]]
            frac_err_arr[ii][hh][jj] = nn_plot_arr[ii][jj][1][hh]_____no_output_____np.seterr(divide='ignore',invalid='ignore')

nrow_num = int(6)
ncol_num = int(3)
zz       = int(0)

fig, axes = plt.subplots(nrows=nrow_num, ncols=ncol_num, \
            figsize=(100,200), sharex= True,sharey=True)
axes_flat = axes.flatten()

fig.text(0.01, 0.5, 'High Density Counts/Lower Density Counts', ha='center', \
    va='center',rotation='vertical',fontsize=20)
# fig.suptitle("Percentile Trends", fontsize=18)

while zz <= 16:
    for ii in range(len(eco_ratio_info)):
        for hh in range(len(eco_ratio_info[0][1])):
            for jj in range(len(nn_mass_dist)):
                # upper = A['{0}_{1}'.format(neigh_vals[ii],frac_vals[hh])][0]
                # lower  = A['{0}_{1}'.format(neigh_vals[ii],frac_vals[hh])][1]
                # plot_bands(bin_centers,upper,lower,axes_flat[zz] )
                plot_all_rats(bin_cens_diff[jj][neigh_vals[ii]][hh],(plot_frac_arr[ii][hh][jj]),\
                              neigh_vals[ii],axes_flat[zz],hh,zz)
            plot_eco_rats(eco_final_bins[ii][hh],(eco_ratio_info[ii]),neigh_vals[ii],\
                                    axes_flat[zz],hh,zz)
            zz += 1

plt.subplots_adjust(left=0.04, bottom=0.09, right=0.98, top=0.98,\
                    hspace=0,wspace=0)

plt.show()_____no_output_____def plot_hists(bins_high,bins_low,high_counts,low_counts,\
               neigh_val,ax,col_num,plot_idx,text=False):
    """
    Returns a plot showing the density-cut, mass counts.

    Parameters
    ----------
    mass: array-like
        A 1D array with log stellar mass values
    neigh_val: integer-like
        Value which will be inserted into the text label of each plot
    bins: array-like
        A 1D array with the values which will be used as the bin edges
    dlogM: float-like
        The log difference between bin edges
    ax: axis-like
        A value which specifies which axis each subplot is to be
        plotted to
    col_num: integer-like
        Integer which specifies which column is currently being
        plotted. Used for labelling subplots
    plot_idx: integer-like
        Specifies which subplot the figure is plotted to. Used for
        labeling the x-axis

    Returns
    -------
    Figure with two curves, optionally (if uncommented) plotted in step

    """
    ax.set_yscale('log')
    if text == True:
        if col_num==0:
            title_label = 'Mass 50/50, {0} NN'.format(neigh_val)
            ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                    verticalalignment='top',transform=ax.transAxes,fontsize=12)
        elif col_num==1:
            title_label = 'Mass 25/75, {0} NN'.format(neigh_val)
            ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                    verticalalignment='top',transform=ax.transAxes,fontsize=12)
        elif col_num==2:
            title_label = 'Mass 10/90, {0} NN'.format(neigh_val)
            ax.text(0.05, 0.95, title_label,horizontalalignment='left',\
                    verticalalignment='top',transform=ax.transAxes,fontsize=12)

    if plot_idx == 16:
        ax.set_xlabel('$\log\ (M_{*}/M_{\odot})$',fontsize=18)
    ax.set_xlim(9.1,11.9)
    ax.set_ylim([10**-3,10**1])
    ax.set_xticks(np.arange(9.5, 12., 0.5))
    ax.set_yticks([10**-2,10**0])

    ax.plot(bins_high,high_counts,color = 'lightslategrey',alpha=0.2)
    ax.plot(bins_low,low_counts,color = 'lightslategray',alpha=0.2)_____no_output_____print eco_high_bins[1]{2: array([  9.2,   9.4,   9.6,   9.8,  10. ,  10.2,  10.4,  10.6,  10.8,
        11. ,  11.2,  11.4,  11.6]), 4: array([  9.2,   9.4,   9.6,   9.8,  10. ,  10.2,  10.4,  10.6,  10.8,
        11. ,  11.2,  11.4,  11.6]), 10: array([  9.2,   9.4,   9.6,   9.8,  10. ,  10.2,  10.4,  10.6,  10.8,
        11. ,  11.2,  11.4,  11.6])}
##when doing loop, include frac vals for bins_high and low, not on counts

def plot_eco_hists(bins_high,bins_low,high_counts,low_counts,\
               frac_val,ax,plot_idx):
        err_key = 'err_{0}'.format(frac_val)

        ax.errorbar(bins_high[frac_val],high_counts[frac_val],\
                    yerr=high_counts[err_key],drawstyle='steps-mid',\
                    color='royalblue',label='Higher Density')
        ax.errorbar(bins_low[frac_val],low_counts[frac_val],\
                    yerr=low_counts[err_key],drawstyle='steps-mid',\
                    color='crimson',label='Lower Density')

        if plot_idx == 0:
            ax.legend(loc='best')_____no_output_____nrow_num  = int(6)
ncol_num  = int(3)

frac_dict = {2:0,4:1,10:2}

fig, axes = plt.subplots(nrows=nrow_num, ncols=ncol_num, \
            figsize=(150,200), sharex= True,sharey=True)
axes_flat = axes.flatten()

fig.text(0.02, 0.5,r'$\log\ (\frac{N_{gal}}{N_{total}*dlogM_{*}})$', ha='center',
    va='center',rotation='vertical',fontsize=20)

for ii in range(len(mass_dat)):
    zz = 0
    for jj in range(len(neigh_vals)):
        for hh in frac_vals:
            # upper    = C['{0}_{1}'.format(neigh_vals[jj],frac_vals[hh])][0]
            # lower    = C['{0}_{1}'.format(neigh_vals[jj],frac_vals[hh])][1]
            # upper_2  = D['{0}_{1}'.format(neigh_vals[jj],frac_vals[hh])][0]
            # lower_2  = D['{0}_{1}'.format(neigh_vals[jj],frac_vals[hh])][1]
            # plot_bands(bin_centers,upper,lower,axes_flat[zz])
            # plot_bands(bin_centers,upper_2,lower_2,axes_flat[zz])
            if ii == 0:
                value = True
            else:
                value = False
            plot_hists(hist_high_bins[ii][neigh_vals[jj]][hh],\
                hist_low_bins[ii][neigh_vals[jj]][hh],\
                hist_high_info[ii][neigh_vals[jj]][hh],\
                hist_low_info[ii][neigh_vals[jj]][hh],\
                neigh_vals[jj],axes_flat[zz],frac_dict[hh],zz,text=value)
            if ii == 0:
                plot_eco_hists(eco_high_bins[neigh_vals[jj]],\
                   eco_low_bins[neigh_vals[jj]],eco_high[neigh_vals[jj]],\
                   eco_low[neigh_vals[jj]],\
                   hh,axes_flat[zz],zz)
            zz += int(1)

plt.subplots_adjust(left=0.07, bottom=0.09, right=0.98, top=0.98,\
                    hspace=0, wspace=0)

plt.show()_____no_output_____def plot_all_meds(bin_centers,y_vals,ax,plot_idx,text=False):
    """
    Returns six subplots showing the median distance to
        the Nth nearest neighbor for each mass bin.  Assumes a
        previously defined figure.  Best used in a for-loop

    Parameters
    ----------
    bin_centers: array-like
        An array with the medians mass values of the mass bins
    y_vals: array-like
        An array containing the median distance values for each mass bin
    ax: axis-like
        A value which specifies which axis each subplot is to be
        plotted to
    plot_idx: integer-like
        Specifies which subplot the figure is plotted to. Used for
        the text label in each subplot

    Returns
    -------
    Subplots displaying the median distance to Nth nearest neighbor
    trends for each mass bin

    """
    titles = [1,2,3,5,10,20]
    ax.set_ylim(0,10**1.5)
    ax.set_xlim(9.1,11.9)
    ax.set_yscale('symlog')
    ax.set_xticks(np.arange(9.5,12.,0.5))
    ax.set_yticks(np.arange(0,12,1))
    ax.set_yticklabels(np.arange(1,11,2))
    ax.tick_params(axis='x', which='major', labelsize=16)
    if text == True:
        title_here = 'n = {0}'.format(titles[plot_idx])
        ax.text(0.05, 0.95, title_here,horizontalalignment='left',\
                verticalalignment='top',transform=ax.transAxes,fontsize=18)
    if plot_idx == 4:
        ax.set_xlabel('$\log\ (M_{*}/M_{\odot})$',fontsize=20)
    ax.plot(bin_centers,y_vals,color='silver')_____no_output_____def plot_eco_meds(bin_centers,y_vals,low_lim,up_lim,ax,plot_idx,only=False):
    """
    Returns six subplots showing the median Nth nearest neighbor distance for
        ECO galaxies in each mass bin

    Parameters
    ----------
    bin_centers: array-like
        An array with the medians mass values of the mass bins
    y_vals: array-like
        An array containing the median distance values for each mass bin
    low_lim: array-like
        An array with the lower cut-off of the bootstrap errors for each median
    up_lim: array-like
        An array with the upper cut-off of the bootstrap errors for each median
    ax: axis-like
        A value which specifies which axis each subplot is to be
        plotted to
    plot_idx: integer-like
        Specifies which subplot the figure is plotted to. Used for
        the text label in each subplot

    Optional
    --------
    only == False
        To be used when only plotting the ECO median trends,
        no mocks.  Will add in the additional plotting
        specifications that would have been taken care of
        previously in a for-loop which plotted the mocks as well

    Returns
    -------
    Subplots displaying the median distance to Nth nearest neighbor
    trends for each mass bin, with the bootstrap errors

    """
    if only == True:
        titles = [1,2,3,5,10,20]
        ax.set_ylim(0,10**1.5)
        ax.set_xlim(9.1,11.9)
        ax.set_yscale('symlog')
        ax.set_xticks(np.arange(9.5,12.,0.5))
        ax.tick_params(axis='both', which='major', labelsize=16)
        title_here = 'n = {0}'.format(titles[plot_idx])
        ax.text(0.05, 0.95, title_here,horizontalalignment='left',\
                verticalalignment='top',transform=ax.transAxes,fontsize=18)
        if plot_idx == 4:
            ax.set_xlabel('$\log\ (M_{*}/M_{\odot})$',fontsize=18)
    ax.errorbar(bin_centers,y_vals,yerr=0.1,lolims=low_lim,\
        uplims=up_lim,color='dodgerblue',label='ECO')
    # if plot_idx == 5:
    #     ax.legend(loc='best')_____no_output_____nrow_num_mass = int(2)
ncol_num_mass = int(3)

fig, axes = plt.subplots(nrows=nrow_num_mass, ncols=ncol_num_mass, \
        figsize=(100,200), sharex= True, sharey = True)
axes_flat = axes.flatten()
fig.text(0.01, 0.5, 'Distance to Nth Neighbor (Mpc)', ha='center', \
    va='center',rotation='vertical',fontsize=20)

zz = int(0)
while zz <=4:
    for ii in range(len(med_plot_arr)):
        for vv in range(len(nn_mass_dist)):
            if vv == 0:
                value = True
            else:
                value = False
            plot_all_meds(mock_meds_bins[vv][neigh_vals[ii]],med_plot_arr[neigh_vals[ii]][vv],axes_flat[zz],\
                zz,text=value)
            plot_eco_meds(eco_med_bins[ii],eco_medians[ii][0],\
                          eco_medians[ii][1],eco_medians[ii][2],\
                                            axes_flat[zz],zz)
        zz   += 1

plt.subplots_adjust(left=0.05, bottom=0.09, right=0.98, top=0.98,\
            hspace=0,wspace=0)
plt.show()

###Portion of loop to be used if plotting bands...

# lower_m  = B['{0}'.format(ii)][0]
# upper_m  = B['{0}'.format(ii)][1]
# plot_med_range(bin_centers,top_95[ii][vv],low_95[ii][vv],\
    # axes_flat[zz],0.05,color='lightsteelblue')
# plot_med_range(bin_centers,top_68[ii][vv],low_68[ii][vv],\
    # axes_flat[zz],0.15,color='gainsboro')
# plot_bands(bin_centers,upper_m,lower_m,axes_flat[zz])_____no_output_____
</code>

# Extra Code for Plotting Bands_____no_output_____

<code>
# def plot_bands(bin_centers,upper,lower,ax):
#     """
#     Returns an overlayed, fill-between plot, creating a band
#         between the different mock catalog values plotted

#     Parameters
#     ----------
#     bin_centers: array-like
#         An array with the medians mass values of the mass bins
#     upper: array-like
#         Array with the max y-values among all the mocks
#         for each mass bin
#     lower: array-like
#         Array with the min y-values among all the mocks
#         for each mass bin
#     ax: axis-like
#         A value which specifies which axis each subplot is to be
#         plotted to

#     Returns
#     -------
#     A semi-transparent band overlaying the area of the plot
#     bordedodgerblue by the mocks
#     """
#     ax.fill_between(bin_centers,upper,lower,color='silver',alpha=0.1)_____no_output_____# def plot_med_range(bin_centers,low_lim,up_lim,ax,alpha,color='gray'):
#     """
#     Returns a plot with a transparent band highlighting a range of
#         values.

#     Parameters
#     ----------
#     bin_centers: array-like
#         An array with the medians mass values of the mass bins
#     low_lim: array-like
#         Array with the min y-values among all the mocks
#         for each mass bin
#     up_lim: array-like
#         Array with the max y-values among all the mocks
#         for each mass bin
#     ax: axis-like
#         A value which specifies which axis each subplot is to be
#         plotted to
#     alpha: float-like
#         A value which will determine the tranparency of the band
#     color: str
#         Any color which Python recognizes; sets the color of the band

#     Returns
#     -------
#     A band spanning from the max y-values to the minimum.

#     """
#     ax.fill_between(bin_centers,low_lim,up_lim,color=color,alpha=alpha)    _____no_output_____# ##For the distance ranges (68 and 95%) to the nth nearest neighbor (examined because medians were suspiciously close)

# ordered_mass = nn_mass_dist[0].T[0][(nn_mass_dist[0].T[0].argsort())]
# dist_cont = [[[[] for zz in xrange(len(bins)-1)] for yy in \
#               xrange(len(nn_mass_dist))] for xx in \
#               xrange(1,len(nn_mass_dist[0].T))]

# for ii in xrange(len(nn_mass_dist)):
#     sorting_test  = np.digitize(nn_mass_dist[ii].T[0],bins)
#     bin_nums      = np.unique(sorting_test)
#     bin_nums_list = list(bin_nums)
#     if len(bins) in bin_nums_list:
#         bin_nums_list.remove(len(bins))
#     bin_nums  = np.array(bin_nums_list)
#     for jj in xrange(1,len(nn_mass_dist[ii].T)):
#         for hh in bin_nums:
#             dist_cont[jj-1][ii][hh-1] = (nn_mass_dist[ii].T[jj]\
#                 [sorting_test==hh])
#             if len(dist_cont[jj-1][ii][hh-1]) == 0:
#                 (dist_cont[jj-1][ii][hh-1]) = list(dist_cont[jj-1][ii][hh-1])
#                 (dist_cont[jj-1][ii][hh-1]).append(np.zeros\
#                     (len(dist_cont[1][0][0])))
#                 (dist_cont[jj-1][ii][hh-1]) = np.array((dist_cont[jj-1][ii]\
#                     [hh-1]))

# for ii in xrange(len(nn_mass_dist)):
#     for jj in xrange(1,len(nn_mass_dist[ii].T)):
#         for hh in bin_nums:
#             print len(dist_cont[jj-1][ii][hh-1])

# top_68 = [[[[]for ll in xrange(len(bin_nums))]for yy in \
#             xrange(len(nn_mass_dist))] for xx in xrange(len(neigh_vals))]
# low_68 = [[[[]for ll in xrange(len(bin_nums))]for yy in \
#             xrange(len(nn_mass_dist))] for xx in xrange(len(neigh_vals))]
# top_95 = [[[[]for ll in xrange(len(bin_nums))]for yy in \
#             xrange(len(nn_mass_dist))] for xx in xrange(len(neigh_vals))]
# low_95 = [[[[]for ll in xrange(len(bin_nums))]for yy in \
#             xrange(len(nn_mass_dist))] for xx in xrange(len(neigh_vals))]
# med_50 = [[[[]for ll in xrange(len(bin_nums))]for yy in \
#             xrange(len(nn_mass_dist))] for xx in xrange(len(neigh_vals))]

# for aa in xrange(len(neigh_vals)):
#     for bb in xrange(len(nn_mass_dist)):
#         for cc in xrange(len(dist_cont[aa][bb])):
#             top_68[aa][bb][cc] = np.percentile(dist_cont[aa][bb][cc],84)
#             low_68[aa][bb][cc] = np.percentile(dist_cont[aa][bb][cc],16)
#             top_95[aa][bb][cc] = np.percentile(dist_cont[aa][bb][cc],97.5)
#             low_95[aa][bb][cc] = np.percentile(dist_cont[aa][bb][cc],2.5)
#             med_50[aa][bb][cc] = np.median((dist_cont[aa][bb][cc]))

# top_68 = np.array(top_68)
# low_68 = np.array(low_68)
# top_95 = np.array(top_95)
# low_95 = np.array(low_95)
# med_50 = np.array(med_50)            _____no_output_____# ###For the ratios (18 subplots)

# A = {}
# nn_dict   = {1:0,2:1,3:2,5:3,10:4,20:5}
# coln_dict = {2:0,4:1,10:2}

# nn_keys  = np.sort(nn_dict.keys())
# col_keys = np.sort(coln_dict.keys())
# zz_num   = len(plot_frac_arr[nn_dict[1]][coln_dict[2]])

# for nn in nn_keys:
#     for coln in col_keys:
#         bin_str    = '{0}_{1}'.format(nn,coln)
#         for cc in range(zz_num):
#             zz_arr = np.array(plot_frac_arr[nn_dict[nn]][coln_dict[coln]][cc])
#             n_elem = len(zz_arr)
#             if cc == 0:
#                 zz_tot = np.zeros((n_elem,1))
#             zz_tot = np.insert(zz_tot,len(zz_tot.T),zz_arr,1)
#         zz_tot = np.array(np.delete(zz_tot,0,axis=1))
#         for kk in xrange(len(zz_tot)):
#             zz_tot[kk][zz_tot[kk] == np.inf] = np.nan
#         zz_tot_max = [np.nanmax(zz_tot[kk]) for kk in xrange(len(zz_tot))]
#         zz_tot_min = [np.nanmin(zz_tot[kk]) for kk in xrange(len(zz_tot))]
#         A[bin_str] = [zz_tot_max,zz_tot_min]_____no_output_____# ##For the median distance to nth nearest neighbor

# B = {}
# yy_num = len(med_plot_arr[0])

# for nn in range(len(med_plot_arr)):
#     for ii in range(yy_num):
#         med_str  = '{0}'.format(nn)
#         yy_arr   = med_plot_arr[nn][ii]
#         n_y_elem = len(yy_arr)
#         if ii == 0:
#             yy_tot = np.zeros((n_y_elem,1))
#         yy_tot = np.insert(yy_tot,len(yy_tot.T),yy_arr,1)
#     yy_tot = np.array(np.delete(yy_tot,0,axis=1))
#     yy_tot_max = [np.nanmax(yy_tot[kk]) for kk in xrange(len(yy_tot))]
#     yy_tot_min = [np.nanmin(yy_tot[kk]) for kk in xrange(len(yy_tot))]
#     B[med_str] = [yy_tot_max,yy_tot_min]_____no_output_____# ###For the histogram 18-subplot figure

# C = {}
# D = {}
# nn_dict   = {1:0,2:1,3:2,5:3,10:4,20:5}
# coln_dict = {2:0,4:1,10:2}

# nn_keys   = np.sort(nn_dict.keys())
# col_keys  = np.sort(coln_dict.keys())

# vv_num    = len(plot_low_hist[nn_dict[1]][coln_dict[2]])

# for nn in nn_keys:
#     for coln in col_keys:
#         bin_str    = '{0}_{1}'.format(nn,coln)
#         for cc in range(vv_num):
#             vv_arr = np.array(plot_low_hist[nn_dict[nn]][coln_dict[coln]][cc])
#             n_elem = len(vv_arr)
#             if cc == 0:
#                 vv_tot = np.zeros((n_elem,1))
#             vv_tot = np.insert(vv_tot,len(vv_tot.T),vv_arr,1)
#         vv_tot = np.array(np.delete(vv_tot,0,axis=1))
#         for kk in xrange(len(vv_tot)):
#             vv_tot[kk][vv_tot[kk] == np.inf] = np.nan
#         vv_tot_max = [np.nanmax(vv_tot[kk]) for kk in xrange(len(vv_tot))]
#         vv_tot_min = [np.nanmin(vv_tot[kk]) for kk in xrange(len(vv_tot))]
#         C[bin_str] = [vv_tot_max,vv_tot_min]

# hh_num   = len(plot_high_hist[nn_dict[1]][coln_dict[2]])

# for nn in nn_keys:
#     for coln in col_keys:
#         bin_str    = '{0}_{1}'.format(nn,coln)
#         for cc in range(hh_num):
#             hh_arr = np.array(plot_high_hist[nn_dict[nn]][coln_dict[coln]][cc])
#             n_elem = len(hh_arr)
#             if cc == 0:
#                 hh_tot = np.zeros((n_elem,1))
#             hh_tot = np.insert(hh_tot,len(hh_tot.T),hh_arr,1)
#         hh_tot     = np.array(np.delete(hh_tot,0,axis=1))
#         for kk in xrange(len(hh_tot)):
#             hh_tot[kk][hh_tot[kk] == np.inf] = np.nan
#         hh_tot_max = [np.nanmax(hh_tot[kk]) for kk in xrange(len(hh_tot))]
#         hh_tot_min = [np.nanmin(hh_tot[kk]) for kk in xrange(len(hh_tot))]
#         D[bin_str] = [hh_tot_max,hh_tot_min]
_____no_output_____
</code>