def variable_index_gridsearch_magbin(simbasedir,<EOL>stetson_stdev_range=(<NUM_LIT:1.0>,<NUM_LIT>),<EOL>inveta_stdev_range=(<NUM_LIT:1.0>,<NUM_LIT>),<EOL>iqr_stdev_range=(<NUM_LIT:1.0>,<NUM_LIT>),<EOL>ngridpoints=<NUM_LIT:32>,<EOL>ngridworkers=None):
<EOL>outdir = os.path.join(simbasedir,'<STR_LIT>')<EOL>if not os.path.exists(outdir):<EOL><INDENT>os.mkdir(outdir)<EOL><DEDENT>with open(os.path.join(simbasedir, '<STR_LIT>'),'<STR_LIT:rb>') as infd:<EOL><INDENT>siminfo = pickle.load(infd)<EOL><DEDENT>timecols = siminfo['<STR_LIT>']<EOL>magcols = siminfo['<STR_LIT>']<EOL>errcols = siminfo['<STR_LIT>']<EOL>magbinmedians = siminfo['<STR_LIT>'][magcols[<NUM_LIT:0>]]['<STR_LIT>']<EOL>stetson_grid = np.linspace(stetson_stdev_range[<NUM_LIT:0>],<EOL>stetson_stdev_range[<NUM_LIT:1>],<EOL>num=ngridpoints)<EOL>inveta_grid = np.linspace(inveta_stdev_range[<NUM_LIT:0>],<EOL>inveta_stdev_range[<NUM_LIT:1>],<EOL>num=ngridpoints)<EOL>iqr_grid = np.linspace(iqr_stdev_range[<NUM_LIT:0>],<EOL>iqr_stdev_range[<NUM_LIT:1>],<EOL>num=ngridpoints)<EOL>stet_inveta_iqr_grid = []<EOL>for stet in stetson_grid:<EOL><INDENT>for inveta in inveta_grid:<EOL><INDENT>for iqr in iqr_grid:<EOL><INDENT>grid_point = [stet, inveta, iqr]<EOL>stet_inveta_iqr_grid.append(grid_point)<EOL><DEDENT><DEDENT><DEDENT>grid_results = {'<STR_LIT>':stetson_grid,<EOL>'<STR_LIT>':inveta_grid,<EOL>'<STR_LIT>':iqr_grid,<EOL>'<STR_LIT>':stet_inveta_iqr_grid,<EOL>'<STR_LIT>':magbinmedians,<EOL>'<STR_LIT>':timecols,<EOL>'<STR_LIT>':magcols,<EOL>'<STR_LIT>':errcols,<EOL>'<STR_LIT>':os.path.abspath(simbasedir),<EOL>'<STR_LIT>':[]}<EOL>pool = mp.Pool(ngridworkers)<EOL>for magbinmedian in magbinmedians:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>' % magbinmedian)<EOL>tasks = [(simbasedir, gp, magbinmedian) for gp in stet_inveta_iqr_grid]<EOL>thisbin_results = pool.map(magbin_varind_gridsearch_worker, tasks)<EOL>grid_results['<STR_LIT>'].append(thisbin_results)<EOL><DEDENT>pool.close()<EOL>pool.join()<EOL>LOGINFO('<STR_LIT>')<EOL>with open(os.path.join(simbasedir,<EOL>'<STR_LIT>'),'<STR_LIT:wb>') as outfd:<EOL><INDENT>pickle.dump(grid_results,outfd,pickle.HIGHEST_PROTOCOL)<EOL><DEDENT>return grid_results<EOL>
This runs a variable index grid search per magbin.

    For each magbin, this does a grid search using the stetson and inveta ranges
    provided and tries to optimize the Matthews Correlation Coefficient (best
    value is +1.0), indicating the best possible separation of variables
    vs. nonvariables. The thresholds on these two variable indexes that produce
    the largest coeff for the collection of fake LCs will probably be the ones
    that work best for actual variable classification on the real LCs.

    https://en.wikipedia.org/wiki/Matthews_correlation_coefficient

    For each grid-point, calculates the true positives, false positives, true
    negatives, false negatives. Then gets the precision and recall, confusion
    matrix, and the ROC curve for variable vs. nonvariable.

    Once we've identified the best thresholds to use, we can then calculate
    variable object numbers:

    - as a function of magnitude
    - as a function of period
    - as a function of number of detections
    - as a function of amplitude of variability


    Writes everything back to `simbasedir/fakevar-recovery.pkl`. Use the
    plotting function below to make plots for the results.

    Parameters
    ----------

    simbasedir : str
        The directory where the fake LCs are located.

    stetson_stdev_range : sequence of 2 floats
        The min and max values of the Stetson J variability index to generate a
        grid over these to test for the values of this index that produce the
        'best' recovery rate for the injected variable stars.

    inveta_stdev_range : sequence of 2 floats
        The min and max values of the 1/eta variability index to generate a
        grid over these to test for the values of this index that produce the
        'best' recovery rate for the injected variable stars.

    iqr_stdev_range : sequence of 2 floats
        The min and max values of the IQR variability index to generate a
        grid over these to test for the values of this index that produce the
        'best' recovery rate for the injected variable stars.

    ngridpoints : int
        The number of grid points for each variability index grid. Remember that
        this function will be searching in 3D and will require lots of time to
        run if ngridpoints is too large.

        For the default number of grid points and 25000 simulated light curves,
        this takes about 3 days to run on a 40 (effective) core machine with 2 x
        Xeon E5-2650v3 CPUs.

    ngridworkers : int or None
        The number of parallel grid search workers that will be launched.

    Returns
    -------

    dict
        The returned dict contains a list of recovery stats for each magbin and
        each grid point in the variability index grids that were used. This dict
        can be passed to the plotting function below to plot the results.