Пример #1
0
def experiment(light_curves, u0=1.0, events_per_light_curve=100):
    """ Fetch a sample of light curves from the photometric database and compare the vanilla
        variability statistic distributions to those with events added. Here the events **all
        have the same impact parameter**.
        
        Parameters
        ----------
        light_curves : list
            A list of light_curve objects
        u0 : float
            The impact parameter of events to add to the light curves
        events_per_light_curve : int
            Number of events to add to each light curve
    """

    var_indices = []
    var_indices_with_event = []

    for light_curve in light_curves:
        var_indices.append(
            analyze.compute_variability_indices(light_curve,
                                                indices=indices,
                                                return_tuple=True))
        for event_id in range(events_per_light_curve):
            # Reset the simulated light curve back to the original data, e.g. erase any previously
            #   added microlensing events
            light_curve.reset()
            tE = 10**np.random.uniform(0., 3.)
            light_curve.addMicrolensingEvent(tE=tE, u0=u0)

            try:
                lc_var_indices = analyze.compute_variability_indices(
                    light_curve, indices, return_tuple=True)
            except:
                break
            var_indices_with_event.append(lc_var_indices)

    dtype = zip(indices, [float] * len(indices))
    var_indices = np.array(var_indices, dtype=dtype)
    var_indices_with_event = np.array(var_indices_with_event, dtype=dtype)

    return var_indices, var_indices_with_event
Пример #2
0
def experiment(light_curves, u0=1.0, events_per_light_curve=100):
    """ Fetch a sample of light curves from the photometric database and compare the vanilla
        variability statistic distributions to those with events added. Here the events **all
        have the same impact parameter**.
        
        Parameters
        ----------
        light_curves : list
            A list of light_curve objects
        u0 : float
            The impact parameter of events to add to the light curves
        events_per_light_curve : int
            Number of events to add to each light curve
    """
    
    var_indices = []
    var_indices_with_event = []
    
    for light_curve in light_curves:
        var_indices.append(analyze.compute_variability_indices(light_curve, indices=indices, return_tuple=True))
        for event_id in range(events_per_light_curve):
            # Reset the simulated light curve back to the original data, e.g. erase any previously
            #   added microlensing events
            light_curve.reset()
            tE = 10**np.random.uniform(0., 3.)
            light_curve.addMicrolensingEvent(tE=tE, u0=u0)
            
            try:
                lc_var_indices = analyze.compute_variability_indices(light_curve, indices, return_tuple=True)
            except:
                break
            var_indices_with_event.append(lc_var_indices)
        
    dtype = zip(indices, [float]*len(indices))
    var_indices = np.array(var_indices, dtype=dtype)
    var_indices_with_event = np.array(var_indices_with_event, dtype=dtype)
    
    return var_indices, var_indices_with_event
Пример #3
0
def compare_detection_efficiencies_on_field(
        field,
        light_curves_per_ccd,
        events_per_light_curve,
        overwrite=False,
        indices=["j", "k", "eta", "sigma_mu", "delta_chi_squared"],
        u0s=[],
        limiting_mags=[]):
    """ TODO: document """

    if u0s == None or len(u0s) == 0:
        u0s = [None]

    if limiting_mags == None or len(limiting_mags) == 0:
        limiting_mags = [14.3, 21]

    file_base = "field{:06d}_Nperccd{}_Nevents{}_u0_{}_m{}".format(
        field.id, light_curves_per_ccd, events_per_light_curve, "-".join(
            map(str, u0s)), "-".join(map(str, limiting_mags))) + ".{ext}"
    pickle_filename = os.path.join("data", "detectionefficiency",
                                   file_base.format(ext="pickle"))
    plot_filename = os.path.join("plots", "detectionefficiency",
                                 file_base.format(ext="png"))
    fpr_plot_filename = os.path.join(
        "plots", "detectionefficiency",
        "fpr_{}".format(file_base.format(ext="png")))

    if not os.path.exists(os.path.dirname(pickle_filename)):
        os.mkdir(os.path.dirname(pickle_filename))

    if not os.path.exists(os.path.dirname(plot_filename)):
        os.mkdir(os.path.dirname(plot_filename))

    if os.path.exists(pickle_filename) and overwrite:
        logger.debug("Data file exists, but you want to overwrite it!")
        os.remove(pickle_filename)
        logger.debug("Data file deleted...")

    # If the cache pickle file doesn't exist, generate the data
    if not os.path.exists(pickle_filename):
        logger.info("Data file {} not found. Generating data...".format(
            pickle_filename))

        # Conditions for reading from the 'sources' table
        #   - Only select sources with enough good observations (>25)
        #   - Omit sources with large amplitude variability so they don't mess with our simulation
        wheres = [
            "(ngoodobs > 25)", "(stetsonJ < 100)", "(vonNeumannRatio > 1.0)",
            "(stetsonJ > 0)"
        ]

        # Keep track of calculated var indices for each CCD
        var_indices = dict()
        var_indices_with_events = dict()

        for ccd in field.ccds.values():
            logger.info(greenText("Starting with CCD {}".format(ccd.id)))

            # Get the chip object for this CCD
            chip = ccd.read()

            for ii, limiting_mag in enumerate(limiting_mags[:-1]):
                # Define bin edges for selection on reference magnitude
                limiting_mag1 = limiting_mag
                limiting_mag2 = limiting_mags[ii + 1]
                mag_key = (limiting_mag1, limiting_mag2)
                logger.info("\tMagnitude range: {:.2f} - {:.2f}".format(
                    limiting_mag1, limiting_mag2))

                if not var_indices_with_events.has_key(mag_key):
                    var_indices_with_events[mag_key] = dict()

                read_wheres = wheres + [
                    "(referenceMag >= {:.3f})".format(limiting_mag1)
                ]
                read_wheres += [
                    "(referenceMag < {:.3f})".format(limiting_mag2)
                ]

                # Read information from the 'sources' table
                source_ids = chip.sources.readWhere(
                    " & ".join(read_wheres))["matchedSourceID"]

                # Randomly shuffle the sources
                np.random.shuffle(source_ids)
                logger.info("\t\tSelected {} source ids".format(
                    len(source_ids)))

                dtype = zip(indices, [float] * len(indices))
                count = 0
                good_source_ids = []
                for source_id in source_ids:
                    logger.debug("\t\t\tSource ID: {}".format(source_id))
                    light_curve = ccd.light_curve(source_id,
                                                  clean=True,
                                                  barebones=True)

                    # After my quality cut, if light curve has less than 25 observations, skip it!
                    if len(light_curve.mjd) < 25:
                        continue

                    # Run simulation to compute false positive variability indices
                    logger.debug("Starting false positive simulation")
                    these_indices = simulate_light_curves_compute_indices(
                        light_curve,
                        num_simulated=events_per_light_curve,
                        indices=indices)
                    try:
                        var_indices_simulated = np.hstack(
                            (var_indices_simulated, these_indices))
                    except NameError:
                        var_indices_simulated = these_indices

                    these_var_indices = np.array([
                        analyze.compute_variability_indices(
                            light_curve, indices, return_tuple=True)
                    ],
                                                 dtype=dtype)
                    try:
                        var_indices[mag_key] = np.hstack(
                            (var_indices[mag_key], these_var_indices))
                    except KeyError:
                        var_indices[mag_key] = these_var_indices

                    for u0 in u0s:
                        logger.debug(
                            "Starting detection efficiency computation for u0={}"
                            .format(u0))
                        these_indices = simulate_events_compute_indices(
                            light_curve,
                            events_per_light_curve=events_per_light_curve,
                            indices=indices,
                            u0=u0)
                        try:
                            var_indices_with_events[mag_key][u0] = np.hstack(
                                (var_indices_with_events[mag_key][u0],
                                 these_indices))
                        except KeyError:
                            var_indices_with_events[mag_key][
                                u0] = these_indices

                    good_source_ids.append(source_id)
                    count += 1
                    if count >= light_curves_per_ccd: break

                if len(good_source_ids) == 0:
                    logger.error(
                        "No good sources selected from this CCD for mag range {:.2f}-{:.2f}!"
                        .format(limiting_mag1, limiting_mag2))
                    continue

                logger.info("\t\t{} good light curves selected".format(count))

                # HACK: This is super hacky...
                # ----------------------------------------------
                while count < light_curves_per_ccd:
                    idx = np.random.randint(len(good_source_ids))
                    source_id = good_source_ids[idx]

                    logger.debug("\t\t\tSource ID: {}".format(source_id))
                    light_curve = ccd.light_curve(source_id,
                                                  clean=True,
                                                  barebones=True)
                    #light_curve.shuffle()

                    these_var_indices = np.array([
                        analyze.compute_variability_indices(
                            light_curve, indices, return_tuple=True)
                    ],
                                                 dtype=dtype)
                    try:
                        var_indices[mag_key] = np.hstack(
                            (var_indices[mag_key], these_var_indices))
                    except KeyError:
                        var_indices[mag_key] = these_var_indices

                    for u0 in u0s:
                        these_indices = simulate_events_compute_indices(
                            light_curve,
                            events_per_light_curve=events_per_light_curve,
                            indices=indices,
                            u0=u0)
                        try:
                            var_indices_with_events[mag_key][u0] = np.hstack(
                                (var_indices_with_events[mag_key][u0],
                                 these_indices))
                        except KeyError:
                            var_indices_with_events[mag_key][
                                u0] = these_indices

                    count += 1
                # ----------------------------------------------

            ccd.close()

        f = open(pickle_filename, "w")
        pickle.dump(
            (var_indices, var_indices_with_events, var_indices_simulated), f)
        f.close()
    else:
        logger.info("Data file {} already exists".format(pickle_filename))

    logger.info(
        greenText("Starting plot routine!") +
        "\n  Data source: {}\n  Plotting and saving to: {}".format(
            pickle_filename, plot_filename))
    logger.debug("\t\tReading in data file...")
    f = open(pickle_filename, "r")
    var_indices, var_indices_with_events, var_indices_simulated = pickle.load(
        f)
    f.close()
    logger.debug("\t\tData loaded!")

    # Styling for lines: J, K, eta, sigma_mu, delta_chi_squared
    line_styles = { "j" : {"lw" : 1, "ls" : "-", "color" : "r", "alpha" : 0.5}, \
                   "k" : {"lw" : 1, "ls" : "-", "color" : "g", "alpha" : 0.5}, \
                   "eta" : {"lw" : 3, "ls" : "-", "color" : "k"}, \
                   "sigma_mu" : {"lw" : 1, "ls" : "-", "color" : "b", "alpha" : 0.5}, \
                   "delta_chi_squared" : {"lw" : 3, "ls" : "--", "color" : "k"},
                   "con" : {"lw" : 3, "ls" : ":", "color" : "k"},
                   "corr" : {"lw" : 3, "ls" : ":", "color" : "r"}}

    num_u0_bins = len(u0s)
    num_mag_bins = len(limiting_mags) - 1

    # Detection efficiency figure, axes
    eff_fig, eff_axes = plt.subplots(num_u0_bins,
                                     num_mag_bins,
                                     sharex=True,
                                     sharey=True,
                                     figsize=(25, 25))

    for ii, limiting_mag_pair in enumerate(sorted(var_indices.keys())):
        selection_indices = var_indices[limiting_mag_pair]
        for jj, u0 in enumerate(
                sorted(var_indices_with_events[limiting_mag_pair].keys())):

            Nsigmas = determine_Nsigma(selection_indices,
                                       var_indices_simulated, indices)

            # Log the values of N x sigma
            for index, Nsigma in Nsigmas.items():
                logger.info("{} = {}sigma".format(index, Nsigma))

            data = compute_detection_efficiency(
                selection_indices,
                var_indices_with_events[limiting_mag_pair][u0],
                indices,
                Nsigmas=Nsigmas)

            try:
                eff_ax = eff_axes[ii, jj]
            except:
                # If only one axis
                eff_ax = eff_axes

            for index_name in indices:
                eff_ax.semilogx((data["bin_edges"][1:]+data["bin_edges"][:-1])/2, \
                             data[index_name]["detections_per_bin"] / data["total_counts_per_bin"], \
                             label=r"{}".format(index_to_label[index_name]), \
                             **line_styles[index_name])
                #label=r"{}: $\varepsilon$={:.3f}, $F$={:.1f}%".format(index_to_label[index_name], data[index_name]["total_efficiency"], data[index_name]["num_false_positives"]/(11.*events_per_light_curve*light_curves_per_ccd)*100), \

            # Fix the y range and modify the tick lines
            eff_ax.set_ylim(0., 1.0)
            eff_ax.tick_params(which='major', length=10, width=2)
            eff_ax.tick_params(which='minor', length=5, width=1)

            if ii == 0:
                try:
                    eff_ax.set_title("$u_0$={:.2f}".format(u0), size=36, y=1.1)
                except:
                    pass

            if jj == (num_mag_bins - 1):
                eff_ax.set_ylabel("{:.1f}<R<{:.1f}".format(*limiting_mag_pair),
                                  size=32,
                                  rotation="horizontal")
                eff_ax.yaxis.set_label_position("right")

            plt.setp(eff_ax.get_xticklabels(), visible=False)
            plt.setp(eff_ax.get_yticklabels(), visible=False)

            if jj == 0:
                plt.setp(eff_ax.get_yticklabels(), visible=True, size=24)
                eff_ax.set_ylabel(r"$\varepsilon$", size=38)
            if ii == (num_u0_bins - 1):
                eff_ax.set_xlabel(r"$t_E$ [days]", size=34)
                plt.setp(eff_ax.get_xticklabels(), visible=True, size=24)

            if jj == (num_mag_bins - 1) and ii == (num_u0_bins - 1):
                legend = eff_ax.legend(loc="upper right")
                legend_text = legend.get_texts()
                plt.setp(legend_text, fontsize=36)

    eff_fig.subplots_adjust(hspace=0.1, wspace=0.1, right=0.88)
    logger.debug("Saving figure and cleaning up!")
    eff_fig.savefig(plot_filename)
    #fpr_fig.savefig(fpr_plot_filename)

    vifigure = VIFigure(indices=indices, figsize=(22, 22))
    vifigure.scatter(var_indices_simulated, alpha=0.1)
    #vifigure.contour(var_indices, nbins=50)
    vifigure.beautify()
    plot_path = os.path.join("plots", "var_indices")
    vifigure.save(
        os.path.join(
            plot_path,
            "field{}_Nperccd{}_Nevents{}.png".format(field.id,
                                                     light_curves_per_ccd,
                                                     events_per_light_curve)))
Пример #4
0
def get_var_indices(field,
                    light_curves_per_ccd,
                    events_per_light_curve,
                    indices,
                    overwrite=True):
    """ This function will create a len(indices) x len(indices) plot grid and plot
        distributions of all of the variability indices
    """

    limiting_mags = [14.3, 21]

    file_base = "field{:06d}_Nperccd{}_Nevents{}".format(
        field.id, light_curves_per_ccd, events_per_light_curve) + ".{ext}"
    pickle_filename = os.path.join("data", "var_indices",
                                   file_base.format(ext="pickle"))
    plot_filename = os.path.join("plots", "var_indices",
                                 file_base.format(ext="png"))

    if not os.path.exists(os.path.dirname(pickle_filename)):
        os.mkdir(os.path.dirname(pickle_filename))

    if not os.path.exists(os.path.dirname(plot_filename)):
        os.mkdir(os.path.dirname(plot_filename))

    if os.path.exists(pickle_filename) and overwrite:
        logger.debug("Data file exists, but you want to overwrite it!")
        os.remove(pickle_filename)
        logger.debug("Data file deleted...")

    # If the cache pickle file doesn't exist, generate the data
    if not os.path.exists(pickle_filename):
        logger.info("Data file {} not found. Generating data...".format(
            pickle_filename))

        # Conditions for reading from the 'sources' table
        #   - Only select sources with enough good observations (>25)
        wheres = [
            "(ngoodobs > 25)", "(vonNeumannRatio > 1)", "(stetsonJ > 0)",
            "(stetsonJ < 100)"
        ]

        for ccd in field.ccds.values():
            logger.info(greenText("Starting with CCD {}".format(ccd.id)))

            # Get the chip object for this CCD
            chip = ccd.read()

            for ii, limiting_mag in enumerate(limiting_mags[:-1]):
                # Define bin edges for selection on reference magnitude
                limiting_mag1 = limiting_mag
                limiting_mag2 = limiting_mags[ii + 1]
                mag_key = (limiting_mag1, limiting_mag2)
                logger.info("\tMagnitude range: {:.2f} - {:.2f}".format(
                    limiting_mag1, limiting_mag2))

                read_wheres = wheres + [
                    "(referenceMag >= {:.3f})".format(limiting_mag1)
                ]
                read_wheres += [
                    "(referenceMag < {:.3f})".format(limiting_mag2)
                ]

                # Read information from the 'sources' table
                sources = chip.sources.readWhere(" & ".join(read_wheres))
                #source_ids = sources["matchedSourceID"]
                source_idxs = range(len(sources))

                # Randomly shuffle the sources
                np.random.shuffle(source_idxs)
                logger.info("\t\tSelected {} source ids".format(len(sources)))

                dtype = zip(indices + ["tE", "u0", "m", "event_added"],
                            [float] * len(indices) +
                            [float, float, float, bool])
                count = 0
                good_source_ids = []
                for source_idx in source_idxs:
                    source = sources[source_idx]
                    source_id = source["matchedSourceID"]

                    logger.debug("\t\t\tSource ID: {}".format(source_id))
                    light_curve = ccd.light_curve(source_id,
                                                  clean=True,
                                                  barebones=True)

                    # After quality cut, if light curve has less than 25 observations, skip it!
                    if len(light_curve.mjd) < 25:
                        continue

                    these_var_indices = np.array([
                        analyze.compute_variability_indices(
                            light_curve, indices, return_tuple=True) +
                        (None, None, np.median(light_curve.mag), False)
                    ],
                                                 dtype=dtype)
                    try:
                        var_indices = np.hstack(
                            (var_indices, these_var_indices))
                    except NameError:
                        var_indices = these_var_indices

                    these_indices = de.simulate_events_compute_indices(
                        light_curve,
                        events_per_light_curve=events_per_light_curve,
                        indices=indices)
                    try:
                        var_indices_with_events = np.hstack(
                            (var_indices_with_events, these_indices))
                    except NameError:
                        var_indices_with_events = these_indices

                    good_source_ids.append(source_id)
                    count += 1
                    if count >= light_curves_per_ccd and light_curves_per_ccd != 0:
                        break

                if len(good_source_ids) == 0:
                    logger.error(
                        "No good sources selected from this CCD for mag range {:.2f}-{:.2f}!"
                        .format(limiting_mag1, limiting_mag2))
                    continue

                logger.info("\t\t{} good light curves selected".format(count))

            ccd.close()

        with open(pickle_filename, "w") as f:
            pickle.dump((var_indices, var_indices_with_events), f)

    else:
        logger.info("Data file {} already exists".format(pickle_filename))

    logger.debug("\t\tReading in data file...")
    f = open(pickle_filename, "r")
    var_indices, var_indices_with_events = pickle.load(f)
    f.close()

    return var_indices, var_indices_with_events
Пример #5
0
def get_var_indices(field, light_curves_per_ccd, events_per_light_curve, indices, overwrite=True):
    """ This function will create a len(indices) x len(indices) plot grid and plot
        distributions of all of the variability indices
    """

    limiting_mags = [14.3, 21]
    
    file_base = "field{:06d}_Nperccd{}_Nevents{}".format(field.id, light_curves_per_ccd, events_per_light_curve) + ".{ext}"
    pickle_filename = os.path.join("data", "var_indices", file_base.format(ext="pickle"))
    plot_filename = os.path.join("plots", "var_indices", file_base.format(ext="png"))
    
    if not os.path.exists(os.path.dirname(pickle_filename)):
        os.mkdir(os.path.dirname(pickle_filename))
    
    if not os.path.exists(os.path.dirname(plot_filename)):
        os.mkdir(os.path.dirname(plot_filename))

    if os.path.exists(pickle_filename) and overwrite:
        logger.debug("Data file exists, but you want to overwrite it!")
        os.remove(pickle_filename)
        logger.debug("Data file deleted...")

    # If the cache pickle file doesn't exist, generate the data
    if not os.path.exists(pickle_filename):
        logger.info("Data file {} not found. Generating data...".format(pickle_filename))
        
        # Conditions for reading from the 'sources' table
        #   - Only select sources with enough good observations (>25)
        wheres = ["(ngoodobs > 25)", "(vonNeumannRatio > 1)", "(stetsonJ > 0)", "(stetsonJ < 100)"]
        
        for ccd in field.ccds.values():
            logger.info(greenText("Starting with CCD {}".format(ccd.id)))
            
            # Get the chip object for this CCD
            chip = ccd.read()
            
            for ii, limiting_mag in enumerate(limiting_mags[:-1]):
                # Define bin edges for selection on reference magnitude
                limiting_mag1 = limiting_mag
                limiting_mag2 = limiting_mags[ii+1]
                mag_key = (limiting_mag1,limiting_mag2)
                logger.info("\tMagnitude range: {:.2f} - {:.2f}".format(limiting_mag1, limiting_mag2))
                    
                read_wheres = wheres + ["(referenceMag >= {:.3f})".format(limiting_mag1)]
                read_wheres += ["(referenceMag < {:.3f})".format(limiting_mag2)]
                
                # Read information from the 'sources' table
                sources = chip.sources.readWhere(" & ".join(read_wheres))
                #source_ids = sources["matchedSourceID"]
                source_idxs = range(len(sources))
                
                # Randomly shuffle the sources
                np.random.shuffle(source_idxs)
                logger.info("\t\tSelected {} source ids".format(len(sources)))
                
                dtype = zip(indices + ["tE", "u0", "m", "event_added"], [float]*len(indices) + [float, float, float, bool])
                count = 0
                good_source_ids = []
                for source_idx in source_idxs:
                    source = sources[source_idx]
                    source_id = source["matchedSourceID"]
                    
                    logger.debug("\t\t\tSource ID: {}".format(source_id))
                    light_curve = ccd.light_curve(source_id, clean=True, barebones=True)
                    
                    # After quality cut, if light curve has less than 25 observations, skip it!
                    if len(light_curve.mjd) < 25:
                        continue
                    
                    these_var_indices = np.array([analyze.compute_variability_indices(light_curve, indices, return_tuple=True) + (None, None, np.median(light_curve.mag), False)], dtype=dtype)
                    try:
                        var_indices = np.hstack((var_indices, these_var_indices))
                    except NameError:
                        var_indices = these_var_indices
                    
                    these_indices = de.simulate_events_compute_indices(light_curve, events_per_light_curve=events_per_light_curve, indices=indices)
                    try:
                        var_indices_with_events = np.hstack((var_indices_with_events, these_indices))
                    except NameError:
                        var_indices_with_events = these_indices
                    
                    good_source_ids.append(source_id)
                    count += 1
                    if count >= light_curves_per_ccd and light_curves_per_ccd != 0: break
                
                if len(good_source_ids) == 0:
                    logger.error("No good sources selected from this CCD for mag range {:.2f}-{:.2f}!".format(limiting_mag1, limiting_mag2))
                    continue
                
                logger.info("\t\t{} good light curves selected".format(count))
                
            ccd.close()
        
        with open(pickle_filename, "w") as f:
            pickle.dump((var_indices, var_indices_with_events), f)
            
    else:
        logger.info("Data file {} already exists".format(pickle_filename))
    
    logger.debug("\t\tReading in data file...")
    f = open(pickle_filename, "r")
    var_indices, var_indices_with_events = pickle.load(f)
    f.close()
    
    return var_indices, var_indices_with_events
Пример #6
0
def compare_detection_efficiencies_on_field(field, light_curves_per_ccd, events_per_light_curve, overwrite=False, indices=["j","k","eta","sigma_mu","delta_chi_squared"], u0s=[], limiting_mags=[]):
    """ TODO: document """   
    
    if u0s == None or len(u0s) == 0:
        u0s = [None]
    
    if limiting_mags == None or len(limiting_mags) == 0:
        limiting_mags = [14.3, 21]
    
    file_base = "field{:06d}_Nperccd{}_Nevents{}_u0_{}_m{}".format(field.id, light_curves_per_ccd, events_per_light_curve, "-".join(map(str,u0s)), "-".join(map(str,limiting_mags))) + ".{ext}"
    pickle_filename = os.path.join("data", "detectionefficiency", file_base.format(ext="pickle"))
    plot_filename = os.path.join("plots", "detectionefficiency", file_base.format(ext="png"))
    fpr_plot_filename = os.path.join("plots", "detectionefficiency", "fpr_{}".format(file_base.format(ext="png")))
    
    if not os.path.exists(os.path.dirname(pickle_filename)):
        os.mkdir(os.path.dirname(pickle_filename))
    
    if not os.path.exists(os.path.dirname(plot_filename)):
        os.mkdir(os.path.dirname(plot_filename))
    
    if os.path.exists(pickle_filename) and overwrite:
        logger.debug("Data file exists, but you want to overwrite it!")
        os.remove(pickle_filename)
        logger.debug("Data file deleted...")
    
    # If the cache pickle file doesn't exist, generate the data
    if not os.path.exists(pickle_filename):
        logger.info("Data file {} not found. Generating data...".format(pickle_filename))
        
        # Conditions for reading from the 'sources' table
        #   - Only select sources with enough good observations (>25)
        #   - Omit sources with large amplitude variability so they don't mess with our simulation
        wheres = ["(ngoodobs > 25)", "(stetsonJ < 100)", "(vonNeumannRatio > 1.0)", "(stetsonJ > 0)"]
        
        # Keep track of calculated var indices for each CCD
        var_indices = dict()
        var_indices_with_events = dict()
        
        for ccd in field.ccds.values():
            logger.info(greenText("Starting with CCD {}".format(ccd.id)))
            
            # Get the chip object for this CCD
            chip = ccd.read()
            
            for ii, limiting_mag in enumerate(limiting_mags[:-1]):
                # Define bin edges for selection on reference magnitude
                limiting_mag1 = limiting_mag
                limiting_mag2 = limiting_mags[ii+1]
                mag_key = (limiting_mag1,limiting_mag2)
                logger.info("\tMagnitude range: {:.2f} - {:.2f}".format(limiting_mag1, limiting_mag2))
                
                if not var_indices_with_events.has_key(mag_key):
                    var_indices_with_events[mag_key] = dict()
                    
                read_wheres = wheres + ["(referenceMag >= {:.3f})".format(limiting_mag1)]
                read_wheres += ["(referenceMag < {:.3f})".format(limiting_mag2)]
                
                # Read information from the 'sources' table
                source_ids = chip.sources.readWhere(" & ".join(read_wheres))["matchedSourceID"]
                
                # Randomly shuffle the sources
                np.random.shuffle(source_ids)
                logger.info("\t\tSelected {} source ids".format(len(source_ids)))
                
                dtype = zip(indices, [float]*len(indices))
                count = 0
                good_source_ids = []
                for source_id in source_ids:
                    logger.debug("\t\t\tSource ID: {}".format(source_id))
                    light_curve = ccd.light_curve(source_id, clean=True, barebones=True)
                    
                    # After my quality cut, if light curve has less than 25 observations, skip it!
                    if len(light_curve.mjd) < 25:
                        continue
                    
                    # Run simulation to compute false positive variability indices
                    logger.debug("Starting false positive simulation")
                    these_indices = simulate_light_curves_compute_indices(light_curve, num_simulated=events_per_light_curve, indices=indices)
                    try:
                        var_indices_simulated = np.hstack((var_indices_simulated, these_indices))
                    except NameError:
                        var_indices_simulated = these_indices
                    
                    these_var_indices = np.array([analyze.compute_variability_indices(light_curve, indices, return_tuple=True)], dtype=dtype)
                    try:
                        var_indices[mag_key] = np.hstack((var_indices[mag_key], these_var_indices))
                    except KeyError:
                        var_indices[mag_key] = these_var_indices
                    
                    for u0 in u0s:
                        logger.debug("Starting detection efficiency computation for u0={}".format(u0))
                        these_indices = simulate_events_compute_indices(light_curve, events_per_light_curve=events_per_light_curve, indices=indices, u0=u0)
                        try:
                            var_indices_with_events[mag_key][u0] = np.hstack((var_indices_with_events[mag_key][u0], these_indices))
                        except KeyError:
                            var_indices_with_events[mag_key][u0] = these_indices
                    
                    good_source_ids.append(source_id)
                    count += 1
                    if count >= light_curves_per_ccd: break
                
                if len(good_source_ids) == 0:
                    logger.error("No good sources selected from this CCD for mag range {:.2f}-{:.2f}!".format(limiting_mag1, limiting_mag2))
                    continue
                
                logger.info("\t\t{} good light curves selected".format(count))
                
                # HACK: This is super hacky...
                # ----------------------------------------------
                while count < light_curves_per_ccd:
                    idx = np.random.randint(len(good_source_ids))
                    source_id = good_source_ids[idx]
                    
                    logger.debug("\t\t\tSource ID: {}".format(source_id))
                    light_curve = ccd.light_curve(source_id, clean=True, barebones=True)
                    #light_curve.shuffle()
                    
                    these_var_indices = np.array([analyze.compute_variability_indices(light_curve, indices, return_tuple=True)], dtype=dtype)
                    try:
                        var_indices[mag_key] = np.hstack((var_indices[mag_key], these_var_indices))
                    except KeyError:
                        var_indices[mag_key] = these_var_indices
                    
                    for u0 in u0s:
                        these_indices = simulate_events_compute_indices(light_curve, events_per_light_curve=events_per_light_curve, indices=indices, u0=u0)
                        try:
                            var_indices_with_events[mag_key][u0] = np.hstack((var_indices_with_events[mag_key][u0], these_indices))
                        except KeyError:
                            var_indices_with_events[mag_key][u0] = these_indices
                    
                    count += 1
                # ----------------------------------------------   
                    
            ccd.close()
        
        f = open(pickle_filename, "w")
        pickle.dump((var_indices, var_indices_with_events, var_indices_simulated), f)
        f.close()
    else:
        logger.info("Data file {} already exists".format(pickle_filename))
    
    logger.info(greenText("Starting plot routine!") + "\n  Data source: {}\n  Plotting and saving to: {}".format(pickle_filename, plot_filename))
    logger.debug("\t\tReading in data file...")
    f = open(pickle_filename, "r")
    var_indices, var_indices_with_events, var_indices_simulated = pickle.load(f)
    f.close()
    logger.debug("\t\tData loaded!")
    
    # Styling for lines: J, K, eta, sigma_mu, delta_chi_squared
    line_styles = { "j" : {"lw" : 1, "ls" : "-", "color" : "r", "alpha" : 0.5}, \
                   "k" : {"lw" : 1, "ls" : "-", "color" : "g", "alpha" : 0.5}, \
                   "eta" : {"lw" : 3, "ls" : "-", "color" : "k"}, \
                   "sigma_mu" : {"lw" : 1, "ls" : "-", "color" : "b", "alpha" : 0.5}, \
                   "delta_chi_squared" : {"lw" : 3, "ls" : "--", "color" : "k"}, 
                   "con" : {"lw" : 3, "ls" : ":", "color" : "k"},
                   "corr" : {"lw" : 3, "ls" : ":", "color" : "r"}}
    
    num_u0_bins = len(u0s)
    num_mag_bins = len(limiting_mags)-1
    
    # Detection efficiency figure, axes
    eff_fig, eff_axes = plt.subplots(num_u0_bins, num_mag_bins, sharex=True, sharey=True, figsize=(25,25))
    
    for ii, limiting_mag_pair in enumerate(sorted(var_indices.keys())):
        selection_indices = var_indices[limiting_mag_pair]
        for jj, u0 in enumerate(sorted(var_indices_with_events[limiting_mag_pair].keys())):

            Nsigmas = determine_Nsigma(selection_indices, var_indices_simulated, indices)

            # Log the values of N x sigma
            for index,Nsigma in Nsigmas.items():
                logger.info("{} = {}sigma".format(index, Nsigma))
                
            data = compute_detection_efficiency(selection_indices, var_indices_with_events[limiting_mag_pair][u0], indices, Nsigmas=Nsigmas)
            
            try:
                eff_ax = eff_axes[ii, jj]
            except:
                # If only one axis
                eff_ax = eff_axes

            for index_name in indices:
                eff_ax.semilogx((data["bin_edges"][1:]+data["bin_edges"][:-1])/2, \
                             data[index_name]["detections_per_bin"] / data["total_counts_per_bin"], \
                             label=r"{}".format(index_to_label[index_name]), \
                             **line_styles[index_name])
                #label=r"{}: $\varepsilon$={:.3f}, $F$={:.1f}%".format(index_to_label[index_name], data[index_name]["total_efficiency"], data[index_name]["num_false_positives"]/(11.*events_per_light_curve*light_curves_per_ccd)*100), \
            
            # Fix the y range and modify the tick lines
            eff_ax.set_ylim(0., 1.0)
            eff_ax.tick_params(which='major', length=10, width=2)
            eff_ax.tick_params(which='minor', length=5, width=1)
            
            if ii == 0:
                try: eff_ax.set_title("$u_0$={:.2f}".format(u0), size=36, y=1.1)
                except: pass
                
            if jj == (num_mag_bins-1):
                eff_ax.set_ylabel("{:.1f}<R<{:.1f}".format(*limiting_mag_pair), size=32, rotation="horizontal")
                eff_ax.yaxis.set_label_position("right")
            
            plt.setp(eff_ax.get_xticklabels(), visible=False)
            plt.setp(eff_ax.get_yticklabels(), visible=False)
            
            if jj == 0:
                plt.setp(eff_ax.get_yticklabels(), visible=True, size=24)
                eff_ax.set_ylabel(r"$\varepsilon$", size=38)
            if ii == (num_u0_bins-1):
                eff_ax.set_xlabel(r"$t_E$ [days]", size=34)
                plt.setp(eff_ax.get_xticklabels(), visible=True, size=24)
            
            if jj == (num_mag_bins-1) and ii == (num_u0_bins-1):
                legend = eff_ax.legend(loc="upper right")
                legend_text  = legend.get_texts()
                plt.setp(legend_text, fontsize=36)
    
    eff_fig.subplots_adjust(hspace=0.1, wspace=0.1, right=0.88)
    logger.debug("Saving figure and cleaning up!")
    eff_fig.savefig(plot_filename) 
    #fpr_fig.savefig(fpr_plot_filename)
    
    vifigure = VIFigure(indices=indices, figsize=(22,22))
    vifigure.scatter(var_indices_simulated, alpha=0.1)
    #vifigure.contour(var_indices, nbins=50)
    vifigure.beautify()
    plot_path = os.path.join("plots", "var_indices")
    vifigure.save(os.path.join(plot_path, "field{}_Nperccd{}_Nevents{}.png".format(field.id, light_curves_per_ccd, events_per_light_curve)))