Final Testing

Here, we train and test LR, RF, and CNN using the output of notebook #104.


In [226]:
import sklearn.linear_model, numpy, matplotlib.pyplot as plt, seaborn, h5py, sklearn.ensemble, keras.models
from collections import defaultdict
from crowdastro.crowd.util import balanced_accuracy
%matplotlib inline

norris_labelled_sets = ['RGZ & Norris & compact', 'RGZ & Norris & resolved', 'RGZ & Norris']
rgz_labelled_sets = ['RGZ & Norris & compact', 'RGZ & Norris & resolved', 'RGZ & Norris',
                     'RGZ & compact', 'RGZ & resolved', 'RGZ']
zid_to_radio_url = {}
zid_to_ir_url = {}
with open('/Users/alger/data/RGZ/zooniverse_id_to_urls.csv') as f:
    for row in f:
        zid, radio, ir = row.strip().split(',')
        zid_to_radio_url[zid] = radio[:20] + radio[20:].replace('radio', 'contours').replace('png', 'json')
        zid_to_ir_url[zid] = ir

Training logistic regression


In [ ]:
def train_lr():
    with h5py.File('/Users/alger/data/Crowdastro/all_training_data_22_05_17.h5', 'r') as f:
        features = f['features'].value
        features[:, -1024:] = numpy.arcsinh(features[:, -1024:] / 0.1) / numpy.arcsinh(1 / 0.1)
        norris_labels = f['norris_labels'].value
        rgz_labels = f['rgz_labels'].value

        lr_norris_predictions = defaultdict(list)  # Maps set -> 4 x n predictions for each quadrant.
        lr_norris_predicted_probs = defaultdict(list)  # Maps set -> 4 x n probabilities for each quadrant.
        lr_norris_accuracies = defaultdict(list)  # Maps set -> 4 x 1 balanced accuracies.
        lr_norris_classifiers = defaultdict(list)  # Maps set -> classifiers.
        for set_name in norris_labelled_sets:
            print('Norris: {}'.format(set_name))
            for train, test in zip(f['/sets/{}/train'.format(set_name)].value,
                                   f['/sets/{}/test'.format(set_name)].value):
                lr = sklearn.linear_model.LogisticRegression(class_weight='balanced', penalty='l1')
                lr.fit(features[train], norris_labels[train])
                predictions = lr.predict(features[test])
                probabilities = lr.predict_proba(features[test])
                accuracy = balanced_accuracy(norris_labels[test], predictions)
                lr_norris_predictions[set_name].append(predictions)
                lr_norris_predicted_probs[set_name].append(probabilities)
                lr_norris_accuracies[set_name].append(accuracy)
                lr_norris_classifiers[set_name].append(lr)

        lr_rgz_predictions = defaultdict(list)  # Maps set -> 4 x n predictions for each quadrant.
        lr_rgz_predicted_probs = defaultdict(list)  # Maps set -> 4 x n probabilities for each quadrant.
        lr_rgz_accuracies = defaultdict(list)  # Maps set -> 4 x 1 balanced accuracies.
        lr_rgz_classifiers = defaultdict(list)  # Maps set -> classifiers.
        set_name_to_norris_set = {
            'RGZ & compact': 'RGZ & Norris & compact',
            'RGZ & resolved': 'RGZ & Norris & resolved',
            'RGZ': 'RGZ & Norris',
            'RGZ & Norris & compact': 'RGZ & Norris & compact',
            'RGZ & Norris & resolved': 'RGZ & Norris & resolved',
            'RGZ & Norris': 'RGZ & Norris',
        }
        for set_name in rgz_labelled_sets:
            print('RGZ: {}'.format(set_name))
            for train, test in zip(f['/sets/{}/train'.format(set_name)].value,
                                   f['/sets/{}/test'.format(set_name_to_norris_set[set_name])].value):
                lr = sklearn.linear_model.LogisticRegression(class_weight='balanced', penalty='l1')
                lr.fit(features[train], rgz_labels[train])
                predictions = lr.predict(features[test])
                probabilities = lr.predict_proba(features[test])
                accuracy = balanced_accuracy(norris_labels[test], predictions)
                lr_rgz_predictions[set_name].append(predictions)
                lr_rgz_predicted_probs[set_name].append(probabilities)
                lr_rgz_accuracies[set_name].append(accuracy)
                lr_rgz_classifiers[set_name].append(lr)
        
        return lr_norris_predictions, lr_norris_predicted_probs, lr_norris_accuracies, lr_norris_classifiers, \
               lr_rgz_predictions, lr_rgz_predicted_probs, lr_rgz_accuracies, lr_rgz_classifiers

In [229]:
lr_norris_predictions, lr_norris_predicted_probs, lr_norris_accuracies, lr_norris_classifiers, \
lr_rgz_predictions, lr_rgz_predicted_probs, lr_rgz_accuracies, lr_rgz_classifiers = train_lr()


Norris: RGZ & Norris & compact
Norris: RGZ & Norris & resolved
Norris: RGZ & Norris
RGZ: RGZ & Norris & compact
RGZ: RGZ & Norris & resolved
RGZ: RGZ & Norris
RGZ: RGZ & compact
RGZ: RGZ & resolved
RGZ: RGZ

Training random forests


In [240]:
def train_rf():
    import scipy.stats
    with h5py.File('/Users/alger/data/Crowdastro/all_training_data_22_05_17.h5', 'r') as f:
        features = f['features'].value
        features[:, -1024:] = numpy.arcsinh(features[:, -1024:] / 0.1) / numpy.arcsinh(1 / 0.1)
        norris_labels = f['norris_labels'].value
        rgz_labels = f['rgz_labels'].value

        rf_norris_predictions = defaultdict(list)  # Maps set -> 4 x n predictions for each quadrant.
        rf_norris_predicted_probs = defaultdict(list)  # Maps set -> 4 x n probabilities for each quadrant.
        rf_norris_accuracies = defaultdict(list)  # Maps set -> 4 x 1 balanced accuracies.
        rf_norris_classifiers = defaultdict(list)  # Maps set -> classifiers.
        for set_name in norris_labelled_sets:
            print('Norris: {}'.format(set_name))
            for train, test in zip(f['/sets/{}/train'.format(set_name)].value,
                                   f['/sets/{}/test'.format(set_name)].value):
                rf = sklearn.ensemble.RandomForestClassifier(
                    class_weight='balanced', criterion='entropy', bootstrap=True, max_depth=8,
                    min_weight_fraction_leaf=0.01)
                rf.fit(features[train], norris_labels[train])
                predictions = rf.predict(features[test])
                probabilities = rf.predict_proba(features[test])
                accuracy = balanced_accuracy(norris_labels[test], predictions)
                rf_norris_predictions[set_name].append(predictions)
                rf_norris_predicted_probs[set_name].append(probabilities)
                rf_norris_accuracies[set_name].append(accuracy)
                rf_norris_classifiers[set_name].append(rf)

        rf_rgz_predictions = defaultdict(list)  # Maps set -> 4 x n predictions for each quadrant.
        rf_rgz_predicted_probs = defaultdict(list)  # Maps set -> 4 x n probabilities for each quadrant.
        rf_rgz_accuracies = defaultdict(list)  # Maps set -> 4 x 1 balanced accuracies.
        rf_rgz_classifiers = defaultdict(list)  # Maps set -> classifiers.
        set_name_to_norris_set = {
            'RGZ & compact': 'RGZ & Norris & compact',
            'RGZ & resolved': 'RGZ & Norris & resolved',
            'RGZ': 'RGZ & Norris',
            'RGZ & Norris & compact': 'RGZ & Norris & compact',
            'RGZ & Norris & resolved': 'RGZ & Norris & resolved',
            'RGZ & Norris': 'RGZ & Norris',
        }
        for set_name in rgz_labelled_sets:
            print('RGZ: {}'.format(set_name))
            for train, test in zip(f['/sets/{}/train'.format(set_name)].value,
                                   f['/sets/{}/test'.format(set_name_to_norris_set[set_name])].value):
                rf = sklearn.ensemble.RandomForestClassifier(
                    class_weight='balanced', criterion='entropy', bootstrap=True, max_depth=8,
                    min_samples_leaf=45)
                rf.fit(features[train], rgz_labels[train])
                predictions = rf.predict(features[test])
                probabilities = rf.predict_proba(features[test])
                accuracy = balanced_accuracy(norris_labels[test], predictions)
                rf_rgz_predictions[set_name].append(predictions)
                rf_rgz_predicted_probs[set_name].append(probabilities)
                rf_rgz_accuracies[set_name].append(accuracy)
                rf_rgz_classifiers[set_name].append(rf)
        
        return rf_norris_predictions, rf_norris_predicted_probs, rf_norris_accuracies, rf_norris_classifiers, \
               rf_rgz_predictions, rf_rgz_predicted_probs, rf_rgz_accuracies, rf_rgz_classifiers

In [241]:
rf_norris_predictions, rf_norris_predicted_probs, rf_norris_accuracies, rf_norris_classifiers, \
rf_rgz_predictions, rf_rgz_predicted_probs, rf_rgz_accuracies, rf_rgz_classifiers = train_rf()


Norris: RGZ & Norris & compact
Norris: RGZ & Norris & resolved
Norris: RGZ & Norris
RGZ: RGZ & Norris & compact
RGZ: RGZ & Norris & resolved
RGZ: RGZ & Norris
RGZ: RGZ & compact
RGZ: RGZ & resolved
RGZ: RGZ

Running a "Perfect" Classifier


In [242]:
def train_gt():
    with h5py.File('/Users/alger/data/Crowdastro/all_training_data_22_05_17.h5', 'r') as f:
        features = f['features'].value
        features[:, -1024:] = numpy.arcsinh(features[:, -1024:] / 0.1) / numpy.arcsinh(1 / 0.1)
        norris_labels = f['norris_labels'].value
        rgz_labels = f['rgz_labels'].value

        gt_norris_predictions = defaultdict(list)  # Maps set -> 4 x n predictions for each quadrant.
        gt_norris_predicted_probs = defaultdict(list)  # Maps set -> 4 x n probabilities for each quadrant.
        gt_norris_accuracies = defaultdict(list)  # Maps set -> 4 x 1 balanced accuracies.
        gt_norris_classifiers = defaultdict(list)  # Maps set -> classifiers.
        for set_name in norris_labelled_sets:
            print('Norris: {}'.format(set_name))
            for train, test in zip(f['/sets/{}/train'.format(set_name)].value,
                                   f['/sets/{}/test'.format(set_name)].value):
                predictions = norris_labels[test]
                probabilities = norris_labels[test].astype(float)
                accuracy = balanced_accuracy(norris_labels[test], predictions)
                gt_norris_predictions[set_name].append(predictions)
                gt_norris_predicted_probs[set_name].append(probabilities)
                gt_norris_accuracies[set_name].append(accuracy)
                gt_norris_classifiers[set_name].append(None)

        gt_rgz_predictions = defaultdict(list)  # Maps set -> 4 x n predictions for each quadrant.
        gt_rgz_predicted_probs = defaultdict(list)  # Maps set -> 4 x n probabilities for each quadrant.
        gt_rgz_accuracies = defaultdict(list)  # Maps set -> 4 x 1 balanced accuracies.
        gt_rgz_classifiers = defaultdict(list)  # Maps set -> classifiers.
        set_name_to_norris_set = {
            'RGZ & compact': 'RGZ & Norris & compact',
            'RGZ & resolved': 'RGZ & Norris & resolved',
            'RGZ': 'RGZ & Norris',
            'RGZ & Norris & compact': 'RGZ & Norris & compact',
            'RGZ & Norris & resolved': 'RGZ & Norris & resolved',
            'RGZ & Norris': 'RGZ & Norris',
        }
        for set_name in rgz_labelled_sets:
            print('RGZ: {}'.format(set_name))
            for train, test in zip(f['/sets/{}/train'.format(set_name)].value,
                                   f['/sets/{}/test'.format(set_name_to_norris_set[set_name])].value):
                predictions = rgz_labels[test]
                probabilities = rgz_labels[test].astype(float)
                accuracy = balanced_accuracy(norris_labels[test], predictions)
                gt_rgz_predictions[set_name].append(predictions)
                gt_rgz_predicted_probs[set_name].append(probabilities)
                gt_rgz_accuracies[set_name].append(accuracy)
                gt_rgz_classifiers[set_name].append(None)
        
        return gt_norris_predictions, gt_norris_predicted_probs, gt_norris_accuracies, gt_norris_classifiers, \
               gt_rgz_predictions, gt_rgz_predicted_probs, gt_rgz_accuracies, gt_rgz_classifiers

In [243]:
gt_norris_predictions, gt_norris_predicted_probs, gt_norris_accuracies, gt_norris_classifiers, \
gt_rgz_predictions, gt_rgz_predicted_probs, gt_rgz_accuracies, gt_rgz_classifiers = train_gt()


Norris: RGZ & Norris & compact
Norris: RGZ & Norris & resolved
Norris: RGZ & Norris
RGZ: RGZ & Norris & compact
RGZ: RGZ & Norris & resolved
RGZ: RGZ & Norris
RGZ: RGZ & compact
RGZ: RGZ & resolved
RGZ: RGZ

Running CNNs


In [255]:
def run_cnn():
    with h5py.File('/Users/alger/data/Crowdastro/all_training_data_22_05_17.h5', 'r') as f:
        features = f['features'].value
        features[:, -1024:] = numpy.arcsinh(features[:, -1024:] / 0.1) / numpy.arcsinh(1 / 0.1)
        im_features = features[:, -1024:].reshape((-1, 1, 32, 32))
        as_features = features[:, :-1024]
        norris_labels = f['norris_labels'].value
        rgz_labels = f['rgz_labels'].value

        cnn_norris_predictions = defaultdict(list)  # Maps set -> 4 x n predictions for each quadrant.
        cnn_norris_predicted_probs = defaultdict(list)  # Maps set -> 4 x n probabilities for each quadrant.
        cnn_norris_accuracies = defaultdict(list)  # Maps set -> 4 x 1 balanced accuracies.
        cnn_norris_classifiers = defaultdict(list)  # Maps set -> classifiers.
        set_name_to_cnn_weights = {
            'RGZ & Norris & compact': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_norris_compact.h5',
            'RGZ & Norris & resolved': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_norris_resolved.h5',
            'RGZ & Norris': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_norris.h5',
        }
        for set_name in norris_labelled_sets:
            print('Norris: {}'.format(set_name))
            for i, test in enumerate(f['/sets/{}/test'.format(set_name)].value):
                with open('/Users/alger/data/Crowdastro/model_22_05_17_5conv.json', 'r') as model:
                    cnn = keras.models.model_from_json(model.read())
                try:
                    cnn.load_weights(set_name_to_cnn_weights[set_name].format(i))
                except:
                    print('\tSkipping {}...'.format(i))
                    continue
                predicted_probs = cnn.predict([as_features[test], im_features[test]])
                predictions = predicted_probs > 0.5
                accuracy = balanced_accuracy(norris_labels[test], predictions)
                cnn_norris_predictions[set_name].append(predictions)
                cnn_norris_predicted_probs[set_name].append(predicted_probs)
                cnn_norris_accuracies[set_name].append(accuracy)
                cnn_norris_classifiers[set_name].append(cnn)

        cnn_rgz_predictions = defaultdict(list)  # Maps set -> 4 x n predictions for each quadrant.
        cnn_rgz_predicted_probs = defaultdict(list)  # Maps set -> 4 x n probabilities for each quadrant.
        cnn_rgz_accuracies = defaultdict(list)  # Maps set -> 4 x 1 balanced accuracies.
        cnn_rgz_classifiers = defaultdict(list)  # Maps set -> classifiers.
        set_name_to_cnn_weights = {
            'RGZ & Norris & compact': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_rgz_compact.h5',
            'RGZ & Norris & resolved': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_rgz_resolved.h5',
            'RGZ & Norris': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_rgz.h5',
            'RGZ & compact': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_rgz_full_compact.h5',
            'RGZ & resolved': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_rgz_full_resolved.h5',
            'RGZ': '/Users/alger/data/Crowdastro/weights_22_05_17/weights_{}_rgz_full.h5',
        }
        for set_name in rgz_labelled_sets:
            print('RGZ: {}'.format(set_name))
            for i, test in enumerate(f['/sets/{}/test'.format(set_name)].value):
                with open('/Users/alger/data/Crowdastro/model_22_05_17_5conv.json', 'r') as model:
                    cnn = keras.models.model_from_json(model.read())
                try:
                    cnn.load_weights(set_name_to_cnn_weights[set_name].format(i))
                except:
                    print('\tSkipping {}...'.format(i))
                    continue
                predicted_probs = cnn.predict([as_features[test], im_features[test]])
                predictions = predicted_probs > 0.5
                accuracy = balanced_accuracy(norris_labels[test], predictions)
                cnn_rgz_predictions[set_name].append(predictions)
                cnn_rgz_predicted_probs[set_name].append(predicted_probs)
                cnn_rgz_accuracies[set_name].append(accuracy)
                cnn_rgz_classifiers[set_name].append(cnn)

        return cnn_norris_predictions, cnn_norris_predicted_probs, cnn_norris_accuracies, \
               cnn_rgz_predictions, cnn_rgz_predicted_probs, cnn_rgz_accuracies

In [256]:
cnn_norris_predictions, cnn_norris_predicted_probs, cnn_norris_accuracies, \
cnn_rgz_predictions, cnn_rgz_predicted_probs, cnn_rgz_accuracies = run_cnn()


(42252, 10) (42252, 1, 32, 32)
Norris: RGZ & Norris & compact
Norris: RGZ & Norris & resolved
Norris: RGZ & Norris
RGZ: RGZ & Norris & compact
RGZ: RGZ & Norris & resolved
RGZ: RGZ & Norris
RGZ: RGZ & compact
RGZ: RGZ & resolved
RGZ: RGZ

In [257]:
titlemap = {
    'RGZ & Norris & compact': 'Compact',
    'RGZ & Norris & resolved': 'Resolved',
    'RGZ & Norris': 'All',
}

fullmap = {
    'RGZ & Norris & compact': 'RGZ & compact',
    'RGZ & Norris & resolved': 'RGZ & resolved',
    'RGZ & Norris': 'RGZ',
}

markers = ['>', '.', 'x', '+']
handles = []
plt.figure(figsize=(15, 5))
for i, set_name in enumerate(norris_labelled_sets):
    ax = plt.subplot(1, 3, i + 1)
    ax.set_title(titlemap[set_name])
    for i in range(4):
        handles.append(
            ax.scatter([0], lr_norris_accuracies[set_name][i] * 100, marker=markers[i], color='k'))
        ax.scatter([1], lr_rgz_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        ax.scatter([2], lr_rgz_accuracies[fullmap[set_name]][i] * 100, marker=markers[i], color='k')
        ax.scatter([3], rf_norris_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        ax.scatter([4], rf_rgz_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        ax.scatter([5], rf_rgz_accuracies[fullmap[set_name]][i] * 100, marker=markers[i], color='k')

        try:
            ax.scatter([6], cnn_norris_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        except IndexError: pass
        try:
            ax.scatter([7], cnn_rgz_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        except IndexError: pass
        try:
            ax.scatter([8], cnn_rgz_accuracies[fullmap[set_name]][i] * 100, marker=markers[i], color='k')
        except IndexError: pass
        
        ax.scatter([9],  gt_rgz_accuracies[set_name][i] * 100, marker=markers[i], color='k')

    ax.set_ylim((85, 100))
    ax.set_xlim((-0.5, 9.5))
    ax.set_xticks([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    ax.set_xticklabels(['LR(Norris)', 'LR(RGZ N)', 'LR(RGZ)',
                        'RF(Norris)', 'RF(RGZ N)', 'RF(RGZ)',
                        'CNN(Norris)', 'CNN(RGZ N)', 'CNN(RGZ)',
                        'RGZ'
                       ], rotation='vertical')
    plt.xlabel('Classifier(Labels)')
    plt.ylabel('Balanced accuracy (%)')
plt.figlegend(handles, map(str, range(4)), 'lower center', ncol=4)
plt.subplots_adjust(wspace=0.3, bottom=0.3)
plt.savefig('/User/alger/repos/crowdastro-projects/ATLAS-CDFS/atlas-ml-ba.pdf')
plt.show()


---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-257-5d6f186606a3> in <module>()
     50 plt.figlegend(handles, map(str, range(4)), 'lower center', ncol=4)
     51 plt.subplots_adjust(wspace=0.3, bottom=0.3)
---> 52 plt.savefig('/User/alger/repos/crowdastro-projects/ATLAS-CDFS/atlas-ml-ba.pdf')
     53 plt.show()

/usr/local/lib/python3.6/site-packages/matplotlib/pyplot.py in savefig(*args, **kwargs)
    695 def savefig(*args, **kwargs):
    696     fig = gcf()
--> 697     res = fig.savefig(*args, **kwargs)
    698     fig.canvas.draw_idle()   # need this if 'transparent=True' to reset colors
    699     return res

/usr/local/lib/python3.6/site-packages/matplotlib/figure.py in savefig(self, *args, **kwargs)
   1570             self.set_frameon(frameon)
   1571 
-> 1572         self.canvas.print_figure(*args, **kwargs)
   1573 
   1574         if frameon:

/usr/local/lib/python3.6/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs)
   2242                 orientation=orientation,
   2243                 bbox_inches_restore=_bbox_inches_restore,
-> 2244                 **kwargs)
   2245         finally:
   2246             if bbox_inches and restore_bbox:

/usr/local/lib/python3.6/site-packages/matplotlib/backends/backend_pdf.py in print_pdf(self, filename, **kwargs)
   2515             file = filename._file
   2516         else:
-> 2517             file = PdfFile(filename)
   2518         try:
   2519             file.newPage(width, height)

/usr/local/lib/python3.6/site-packages/matplotlib/backends/backend_pdf.py in __init__(self, filename)
    420         self.tell_base = 0
    421         if is_string_like(filename):
--> 422             fh = open(filename, 'wb')
    423         elif is_writable_file_like(filename):
    424             try:

FileNotFoundError: [Errno 2] No such file or directory: '/User/alger/repos/crowdastro-projects/ATLAS-CDFS/atlas-ml-ba.pdf'

In [231]:
# Plot Norris vs RGZ vs RGZ N.
def plot_labelsets():
    xs = ['Norris', 'RGZ N', 'RGZ']
    ys = []
    y_norris = []
    for accs in [lr_norris_accuracies, rf_norris_accuracies, cnn_norris_accuracies]:
        y_norris.extend(accs['RGZ & Norris'])
    ys.append(y_norris)
    y_rgz = []
    y_rgz_n = []
    for accs in [lr_rgz_accuracies, rf_rgz_accuracies, cnn_rgz_accuracies]:
        y_rgz_n.extend(accs['RGZ & Norris'])
        y_rgz.extend(accs['RGZ'])
    ys.append(y_rgz_n)
    ys.append(y_rgz)
    
    import pandas
    dicts = []
    for x, y in zip(xs, ys):
        for y_ in y:
            dicts.append({'Label': x, 'Accuracy': y_})
    df = pandas.DataFrame(dicts, columns=('Label', 'Accuracy'))
    seaborn.violinplot(data=df, x='Label', y='Accuracy', inner='point')

plot_labelsets()



In [258]:
def plot_classifiers():
    xs = ['LR', 'RF', 'CNN']
    ys = []
    
    y_lr = []
    y_lr.extend(lr_norris_accuracies['RGZ & Norris'])
    y_lr.extend(lr_rgz_accuracies['RGZ & Norris'])
    y_lr.extend(lr_rgz_accuracies['RGZ'])
    ys.append(y_lr)
    
    y_rf = []
    y_rf.extend(rf_norris_accuracies['RGZ & Norris'])
    y_rf.extend(rf_rgz_accuracies['RGZ & Norris'])
    y_rf.extend(rf_rgz_accuracies['RGZ'])
    ys.append(y_rf)
    
    y_cnn = []
    y_cnn.extend(cnn_norris_accuracies['RGZ & Norris'])
    y_cnn.extend(cnn_rgz_accuracies['RGZ & Norris'])
    y_cnn.extend(cnn_rgz_accuracies['RGZ'])
    ys.append(y_cnn)
    
    import pandas
    dicts = []
    for x, y in zip(xs, ys):
        for y_ in y:
            dicts.append({'Classifier': x, 'Accuracy': y_})
    df = pandas.DataFrame(dicts, columns=('Classifier', 'Accuracy'))
    seaborn.violinplot(data=df, x='Classifier', y='Accuracy', inner='point')

plot_classifiers()



In [259]:
-
#         plt.show()
plot_grid()



In [260]:
def ba_table():
    # Get a table of balanced accuracies.
    titlemap = {
        'RGZ & Norris & compact': 'Compact',
        'RGZ & Norris & resolved': 'Resolved',
        'RGZ & Norris': 'All',
    }
    classifiers = []
    label_sets = []
    data_sets = []
    means = []
    for j, (classifier_name, classifier_set) in enumerate([
            ('LR', [lr_norris_accuracies, lr_rgz_accuracies]),
            ('RF', [rf_norris_accuracies, rf_rgz_accuracies]),
            ('CNN', [cnn_norris_accuracies, cnn_rgz_accuracies]),
    ]):
        for i, set_name in enumerate(norris_labelled_sets):
            for k in range(2):
                mean = numpy.mean(classifier_set[0][set_name]) * 100
                std = numpy.std(classifier_set[0][set_name]) * 100
                classifiers.append(classifier_name)
                label_sets.append(['Norris', 'RGZ'][k])
                data_sets.append(titlemap[set_name])
                means.append('{:.02f} +- {:.02f}'.format(mean, std))
    
    import astropy.table
    table = astropy.table.Table(data=[data_sets, label_sets, classifiers, means],
                                names=['Data set', 'Labeller', 'Classifier', 'Mean Balanced Accuracy (%)'])
    table.sort(keys=['Data set', 'Labeller', 'Classifier'])
    return table

ba_table_ = ba_table()
ba_table_.write('/Users/alger/repos/crowdastro-projects/ATLAS-CDFS/atlas-ml-ba.tex', format='latex')


WARNING: AstropyDeprecationWarning: /Users/alger/repos/crowdastro-projects/ATLAS-CDFS/atlas-ml-ba.tex already exists. Automatically overwriting ASCII files is deprecated. Use the argument 'overwrite=True' in the future. [astropy.io.ascii.ui]

In [235]:
def plot_sets():
    xs = ['Compact', 'Resolved', 'All']
    ys = []
    
    y_compact = []
    y_compact.extend(lr_norris_accuracies['RGZ & Norris & compact'])
    y_compact.extend(lr_rgz_accuracies['RGZ & Norris & compact'])
    y_compact.extend(lr_rgz_accuracies['RGZ & compact'])
    y_compact.extend(cnn_norris_accuracies['RGZ & Norris & compact'])
    y_compact.extend(cnn_rgz_accuracies['RGZ & Norris & compact'])
    y_compact.extend(cnn_rgz_accuracies['RGZ & compact'])
    y_compact.extend(rf_norris_accuracies['RGZ & Norris & compact'])
    y_compact.extend(rf_rgz_accuracies['RGZ & Norris & compact'])
    y_compact.extend(rf_rgz_accuracies['RGZ & compact'])
    ys.append(y_compact)
    
    y_resolved = []
    y_resolved.extend(lr_norris_accuracies['RGZ & Norris & resolved'])
    y_resolved.extend(lr_rgz_accuracies['RGZ & Norris & resolved'])
    y_resolved.extend(lr_rgz_accuracies['RGZ & resolved'])
    y_resolved.extend(cnn_norris_accuracies['RGZ & Norris & resolved'])
    y_resolved.extend(cnn_rgz_accuracies['RGZ & Norris & resolved'])
    y_resolved.extend(cnn_rgz_accuracies['RGZ & resolved'])
    y_resolved.extend(rf_norris_accuracies['RGZ & Norris & resolved'])
    y_resolved.extend(rf_rgz_accuracies['RGZ & Norris & resolved'])
    y_resolved.extend(rf_rgz_accuracies['RGZ & resolved'])
    ys.append(y_resolved)
    
    y_all = []
    y_all.extend(lr_norris_accuracies['RGZ & Norris'])
    y_all.extend(lr_rgz_accuracies['RGZ & Norris'])
    y_all.extend(lr_rgz_accuracies['RGZ'])
    y_all.extend(cnn_norris_accuracies['RGZ & Norris'])
    y_all.extend(cnn_rgz_accuracies['RGZ & Norris'])
    y_all.extend(cnn_rgz_accuracies['RGZ'])
    y_all.extend(rf_norris_accuracies['RGZ & Norris'])
    y_all.extend(rf_rgz_accuracies['RGZ & Norris'])
    y_all.extend(rf_rgz_accuracies['RGZ'])
    ys.append(y_all)
    
    import pandas
    dicts = []
    for x, y in zip(xs, ys):
        for y_ in y:
            dicts.append({'Set': x, 'Accuracy': y_})
    df = pandas.DataFrame(dicts, columns=('Set', 'Accuracy'))
    seaborn.violinplot(data=df, x='Set', y='Accuracy', inner='point')

plot_sets()


LR Weights Analysis

LR does remarkably well with raw pixels. What weighting does it assign to each pixel?


In [247]:
plt.figure(figsize=(15, 5))
for k, (label_str, labellers) in enumerate(zip(
        ['Norris', 'RGZ'],
        [lr_norris_classifiers, lr_rgz_classifiers])):
    for i, subset_str in enumerate(labellers):
        im = numpy.mean(
            [c.coef_[0, -1024:].reshape((32, 32))
             for c in labellers[subset_str]], axis=0)
        plt.subplot(2, 6, 1 + i + k * 6)
        plt.imshow(im, cmap='viridis')
        plt.title(subset_str + '\n' + 'LR({})'.format(label_str))
        plt.axis('off')
plt.show()


Cross-identification

We will now use these results to generate full cross-identifications for objects in RGZ.


In [248]:
# We first have to convert the returned probabilities into an array of probabilities for each SWIRE object.
with h5py.File('/Users/alger/data/Crowdastro/crowdastro-swire.h5', 'r') as f:
    n_swire = f['/swire/cdfs/numeric'].shape[0]

def output_probs_to_swire_probs(output_probs, test_sets_name):
    # output_probs is a list of arrays of predictions corresponding to the test sets.
    with h5py.File('/Users/alger/data/Crowdastro/all_training_data_01_05_17.h5', 'r') as f:
        test_sets = f['/sets/{}/test'.format(test_sets_name)].value
        swire_probs = numpy.zeros((n_swire,))
        swire_counts = numpy.zeros((n_swire,))
        for output_probs_, test_set in zip(output_probs, test_sets):
            for prob, index in zip(output_probs_, test_set.nonzero()[0]):
                if prob.shape == (2,):
                    prob = prob[1]  # Output is (p(0), p(1)).
                # Running average.
                swire_probs[index] = (swire_probs[index] * swire_counts[index] + prob) / (
                    swire_counts[index] + 1)
                swire_counts[index] += 1
        swire_probs = numpy.ma.MaskedArray(swire_probs, mask=swire_counts == 0)
        return swire_probs

# We'll ignore objects not in Norris.
swire_probs = {}
probs_sets = {
    ('lr', 'norris'): lr_norris_predicted_probs,
    ('rf', 'norris'): rf_norris_predicted_probs,
    ('cnn', 'norris'): cnn_norris_predicted_probs,
    ('lr', 'rgz'): lr_rgz_predicted_probs,
    ('rf', 'rgz'): rf_rgz_predicted_probs,
    ('cnn', 'rgz'): cnn_rgz_predicted_probs,
    ('gt', 'norris'): gt_norris_predicted_probs,
    ('gt', 'rgz'): gt_rgz_predicted_probs,
}
for classifier in ['lr', 'rf', 'cnn', 'gt']:
    for labeller in ['norris', 'rgz']:
        for subset_str in norris_labelled_sets:
            probs = output_probs_to_swire_probs(probs_sets[classifier, labeller][subset_str], subset_str)
            swire_probs[classifier, labeller, subset_str] = probs

swire_probs.keys()


Out[248]:
dict_keys([('lr', 'norris', 'RGZ & Norris & compact'), ('lr', 'norris', 'RGZ & Norris & resolved'), ('lr', 'norris', 'RGZ & Norris'), ('lr', 'rgz', 'RGZ & Norris & compact'), ('lr', 'rgz', 'RGZ & Norris & resolved'), ('lr', 'rgz', 'RGZ & Norris'), ('rf', 'norris', 'RGZ & Norris & compact'), ('rf', 'norris', 'RGZ & Norris & resolved'), ('rf', 'norris', 'RGZ & Norris'), ('rf', 'rgz', 'RGZ & Norris & compact'), ('rf', 'rgz', 'RGZ & Norris & resolved'), ('rf', 'rgz', 'RGZ & Norris'), ('cnn', 'norris', 'RGZ & Norris & compact'), ('cnn', 'norris', 'RGZ & Norris & resolved'), ('cnn', 'norris', 'RGZ & Norris'), ('cnn', 'rgz', 'RGZ & Norris & compact'), ('cnn', 'rgz', 'RGZ & Norris & resolved'), ('cnn', 'rgz', 'RGZ & Norris'), ('gt', 'norris', 'RGZ & Norris & compact'), ('gt', 'norris', 'RGZ & Norris & resolved'), ('gt', 'norris', 'RGZ & Norris'), ('gt', 'rgz', 'RGZ & Norris & compact'), ('gt', 'rgz', 'RGZ & Norris & resolved'), ('gt', 'rgz', 'RGZ & Norris')])

In [77]:
# Compute a SWIRE KD-Tree for quickly looking up candidate hosts.
import scipy.spatial
with h5py.File('/Users/alger/data/Crowdastro/crowdastro-swire.h5', 'r') as f:
    swire_coords = f['/swire/cdfs/numeric'][:, :2]
    swire_names = numpy.array([i.decode('ascii') for i in f['/swire/cdfs/string'].value])
swire_tree = scipy.spatial.KDTree(swire_coords)

In [78]:
def cross_identify(zid, probabilities, radius: 'degrees'=1 / 60):
    # Where is this object?
    import astropy.io.ascii as asc
    table = asc.read('/Users/alger/data/Crowdastro/one-table-to-rule-them-all.tbl')
    row = table[table['Component Zooniverse ID (RGZ)'] == zid][0]
    ra, dec = row['Component RA (Franzen)'], row['Component DEC (Franzen)']
    # What SWIRE objects are nearby?
    nearby = swire_tree.query_ball_point([ra, dec], radius)
    # Corresponding probabilities.
    nearby_probabilities = probabilities[nearby]
    # Return the probabilities and SWIRE names/coords.
    import astropy.table
    return astropy.table.Table(
        data=[swire_names[nearby], swire_coords[nearby, 0], swire_coords[nearby, 1],
              nearby_probabilities],
        names=['name', 'ra', 'dec', 'prob'])

In [91]:
import astropy.io.ascii as asc
import astropy.io.fits as fits, astropy.wcs
import astropy.modeling.functional_models, astropy.modeling.fitting
def compact_cross_identify(zid, radius: 'degrees'=1 / 60):
    atlas = fits.open('/Users/alger/data/ATLAS/CDFSmosaic_allch_8March2015.fits')[0]
    wcs = astropy.wcs.WCS(atlas.header).dropaxis(3).dropaxis(2)
    table = asc.read('/Users/alger/data/Crowdastro/one-table-to-rule-them-all.tbl')
    # Where is this object?
    row = table[table['Component Zooniverse ID (RGZ)'] == zid][0]
    ra, dec = row['Component RA (Franzen)'], row['Component DEC (Franzen)']
    # What's the closest SWIRE object?
    distance, nearest = swire_tree.query([ra, dec])
    if distance > 5 / 60 / 60:  # 5 arcsec
        return None
    return swire_names[nearest]
#     # What SWIRE objects are nearby?
#     nearby = swire_tree.query_ball_point([ra, dec], radius)
#     # Find the Gaussian peak.
#     py, px = [int(i) for j in wcs.all_world2pix([[ra, dec]], 1) for i in j]
#     w = int(radius * 60 * 25)  # px
#     im = atlas.data[0, 0, px - w:px + w, py - w:py + w]
#     x, y = numpy.meshgrid(range(im.shape[0]), range(im.shape[1]))
#     im_flat = numpy.vstack([x.ravel(), y.ravel(), im.ravel()]).T
#     g = astropy.modeling.functional_models.Gaussian2D(x_mean=25, y_mean=25)
#     fitter = astropy.modeling.fitting.LevMarLSQFitter()
#     g = fitter(g, *im_flat.T)
#     sx, sy = (g.x_mean.value, g.y_mean.value)
#     # Convert back to RA/Dec.
#     (ra, dec), = wcs.all_pix2world([[sy - w + py, sx - w + px]], 1)
#     dist, index = swire_tree.query((ra, dec))
#     return swire_names[index]

In [80]:
# A quick test.
cross_identify('ARG0003sky', swire_probs['lr', 'norris', 'RGZ & Norris'])


Out[80]:
<Table masked=True length=30>
nameradecprob
str26float32float32float64
SWIRE3_J032635.37-280806.151.6474-28.1356.8216399143e-06
SWIRE3_J032635.58-280817.951.6483-28.13836.49668893942e-06
SWIRE3_J032635.62-280757.551.6484-28.13260.024769799538
SWIRE3_J032635.88-280827.951.6495-28.14110.0176781414949
SWIRE3_J032635.97-280822.451.6499-28.13960.000656579568332
SWIRE3_J032637.05-280813.851.6544-28.13725.32693696922e-07
SWIRE3_J032636.25-280723.151.6511-28.12313.57473912532e-08
SWIRE3_J032636.84-280745.851.6535-28.12940.988347773322
SWIRE3_J032636.90-280750.751.6538-28.13080.997025093426
SWIRE3_J032636.99-280729.351.6542-28.12481.60675193835e-06
............
SWIRE3_J032642.16-280824.351.6757-28.14018.24732824787e-07
SWIRE3_J032637.52-280710.051.6564-28.11943.06120841217e-05
SWIRE3_J032637.90-280736.251.6579-28.12670.0537324844028
SWIRE3_J032638.24-280732.451.6594-28.12570.058640593541
SWIRE3_J032638.76-280738.751.6615-28.12740.00491640360145
SWIRE3_J032639.24-280716.451.6635-28.12120.000195882791944
SWIRE3_J032640.46-280725.251.6686-28.12374.67541308619e-06
SWIRE3_J032640.55-280730.751.669-28.12520.000467711911013
SWIRE3_J032640.98-280712.851.6708-28.12020.000116298776524
SWIRE3_J032642.72-280750.451.678-28.13070.651525503317

Accuracy


In [92]:
_compact_xids = {}
def test_cross_identifications(classifier, labeller, subset, filter_compact=True):
    import astropy.io.ascii as asc, collections
    table = asc.read('/Users/alger/data/Crowdastro/one-table-to-rule-them-all.tbl')

    zids = set()
    zid_to_norris = collections.defaultdict(set)
    zid_to_compact = {}
    for row in table:
        if row['Source SWIRE (Norris)'] and row['Source SWIRE (Norris)'].startswith('SWIRE') and \
                row['Primary Component ID (RGZ)']:
            zid = row['Component Zooniverse ID (RGZ)']
            zids.add(zid)
            zid_to_norris[zid].add(row['Source SWIRE (Norris)'])
            if zid in zid_to_compact:
                zid_to_compact[zid] = False
            S = row['Component S (Franzen)']
            S_ERR = row['Component S_ERR (Franzen)']
            Sp = row['Component Sp (Franzen)']
            Sp_ERR = row['Component Sp_ERR (Franzen)']
            R_ERR2 = 2 * numpy.sqrt((S_ERR / S) ** 2 + (Sp_ERR / Sp) ** 2)
            R = numpy.log(S / Sp)
            if R > R_ERR2:
                zid_to_compact[zid] = False
            else:
                zid_to_compact[zid] = True
    print('Found {:.02%} compact.'.format(sum(zid_to_compact.values()) / len(zid_to_compact)))
    
    n_correct = 0
    n_total = len(zids)
    zid_to_classifier = {}
    for zid in zids:
        xid = None

        if zid_to_compact[zid]:
            # Classify using the compact method.
            if zid in _compact_xids:
                xid = _compact_xids[zid]
            else:
                xid = compact_cross_identify(zid)
                _compact_xids[zid] = xid

        if not zid_to_compact[zid] or xid is None:
            # Classify using the ML method.
            xids = cross_identify(zid, swire_probs[classifier, labeller, subset])
            if len(xids['prob']) == 0:
                continue
            xid = xids['name'][xids['prob'].argmax()]
#         print(zid, xid, zid_to_norris[zid])
        n_correct += xid in zid_to_norris[zid]
        zid_to_classifier[zid] = xid
    return n_correct / n_total, zid_to_classifier

In [93]:
# for classifier in ['lr', 'rf', 'cnn']:swire_probs.keys()
test_cross_identifications('lr', 'norris', 'RGZ & Norris')


Found 78.89% compact.
WARNING: VerifyWarning: Invalid 'BLANK' keyword in header.  The 'BLANK' keyword is only applicable to integer data, and will be ignored in this HDU. [astropy.io.fits.hdu.image]
WARNING: FITSFixedWarning: 'celfix' made the change 'Success'. [astropy.wcs.wcs]
WARNING: FITSFixedWarning: 'spcfix' made the change 'Changed CTYPE3 from 'FREQ-LSR' to 'FREQ''. [astropy.wcs.wcs]
Out[93]:
(0.8872950819672131,
 {'ARG0003r17': 'SWIRE3_J032733.99-284621.2',
  'ARG0003r18': 'SWIRE3_J033409.03-282412.3',
  'ARG0003r1a': 'SWIRE3_J033126.14-281838.1',
  'ARG0003r1b': 'SWIRE3_J032845.74-282709.3',
  'ARG0003r1c': 'SWIRE3_J033553.33-272740.4',
  'ARG0003r1d': 'SWIRE3_J033527.50-271950.8',
  'ARG0003r1e': 'SWIRE3_J032916.14-272347.8',
  'ARG0003r1f': 'SWIRE3_J033131.63-283135.7',
  'ARG0003r1g': 'SWIRE3_J033204.88-274647.6',
  'ARG0003r1h': 'SWIRE3_J033242.24-273814.9',
  'ARG0003r1i': 'SWIRE3_J033431.07-282525.8',
  'ARG0003r1j': 'SWIRE3_J033051.41-273013.7',
  'ARG0003r1k': 'SWIRE3_J032941.22-280811.6',
  'ARG0003r1l': 'SWIRE3_J033048.51-283857.7',
  'ARG0003r1m': 'SWIRE3_J033310.18-274842.4',
  'ARG0003r1n': 'SWIRE3_J033522.58-275548.6',
  'ARG0003r1o': 'SWIRE3_J033034.56-282707.7',
  'ARG0003r1p': 'SWIRE3_J033021.89-280206.1',
  'ARG0003r1q': 'SWIRE3_J033323.78-272407.0',
  'ARG0003r1r': 'SWIRE3_J032949.13-273149.1',
  'ARG0003r1s': 'SWIRE3_J033429.74-271745.2',
  'ARG0003r1t': 'SWIRE3_J033423.82-272527.1',
  'ARG0003r1u': 'SWIRE3_J033229.33-280328.9',
  'ARG0003r1w': 'SWIRE3_J033236.12-283707.3',
  'ARG0003r1x': 'SWIRE3_J033225.98-274150.6',
  'ARG0003r1y': 'SWIRE3_J033523.01-273329.8',
  'ARG0003r1z': 'SWIRE3_J032933.80-284140.0',
  'ARG0003r21': 'SWIRE3_J033001.17-274621.1',
  'ARG0003r22': 'SWIRE3_J032751.96-275255.8',
  'ARG0003r23': 'SWIRE3_J033256.68-280204.4',
  'ARG0003r24': 'SWIRE3_J032719.77-280237.1',
  'ARG0003r25': 'SWIRE3_J032641.86-280807.8',
  'ARG0003r26': 'SWIRE3_J033111.48-284430.3',
  'ARG0003r27': 'SWIRE3_J032945.52-273217.5',
  'ARG0003r29': 'SWIRE3_J032648.69-284735.7',
  'ARG0003r2a': 'SWIRE3_J032732.16-282624.8',
  'ARG0003r2b': 'SWIRE3_J033055.63-284852.5',
  'ARG0003r2c': 'SWIRE3_J033438.25-272703.7',
  'ARG0003r2d': 'SWIRE3_J032827.20-271705.0',
  'ARG0003r2e': 'SWIRE3_J033406.72-284141.5',
  'ARG0003r2f': 'SWIRE3_J032746.84-271743.1',
  'ARG0003r2h': 'SWIRE3_J032832.78-285536.1',
  'ARG0003r2i': 'SWIRE3_J032710.49-272906.5',
  'ARG0003r2j': 'SWIRE3_J032616.86-280715.8',
  'ARG0003r2k': 'SWIRE3_J033310.93-281853.3',
  'ARG0003r2m': 'SWIRE3_J033210.74-272635.5',
  'ARG0003r2n': 'SWIRE3_J032931.23-282009.0',
  'ARG0003r2o': 'SWIRE3_J033330.51-285427.8',
  'ARG0003r2p': 'SWIRE3_J033409.24-283144.9',
  'ARG0003r2r': 'SWIRE3_J032636.90-280750.7',
  'ARG0003r2s': 'SWIRE3_J033125.02-281333.5',
  'ARG0003r2t': 'SWIRE3_J033430.53-275754.3',
  'ARG0003r2u': 'SWIRE3_J033215.07-284610.0',
  'ARG0003r2v': 'SWIRE3_J033402.83-282405.5',
  'ARG0003r2x': 'SWIRE3_J032847.72-280550.3',
  'ARG0003r2y': 'SWIRE3_J033026.17-281711.1',
  'ARG0003r2z': 'SWIRE3_J032826.52-273304.1',
  'ARG0003r30': 'SWIRE3_J033249.19-274050.7',
  'ARG0003r31': 'SWIRE3_J033036.04-283922.2',
  'ARG0003r32': 'SWIRE3_J033435.44-271757.2',
  'ARG0003r33': 'SWIRE3_J033158.61-281317.4',
  'ARG0003r34': 'SWIRE3_J033441.14-284940.9',
  'ARG0003r35': 'SWIRE3_J033318.85-284508.3',
  'ARG0003r36': 'SWIRE3_J033113.93-275518.8',
  'ARG0003r38': 'SWIRE3_J032648.47-274938.0',
  'ARG0003r39': 'SWIRE3_J033508.75-275136.3',
  'ARG0003r3a': 'SWIRE3_J032702.07-275729.8',
  'ARG0003r3b': 'SWIRE3_J033205.37-283730.2',
  'ARG0003r3d': 'SWIRE3_J033359.56-272449.2',
  'ARG0003r3e': 'SWIRE3_J033023.22-275356.6',
  'ARG0003r3f': 'SWIRE3_J032847.21-271513.1',
  'ARG0003r3g': 'SWIRE3_J033333.63-281404.0',
  'ARG0003r3h': 'SWIRE3_J033211.64-273726.1',
  'ARG0003r3i': 'SWIRE3_J032739.36-285351.0',
  'ARG0003r3j': 'SWIRE3_J032835.53-273514.2',
  'ARG0003r3k': 'SWIRE3_J032643.10-274727.6',
  'ARG0003r3l': 'SWIRE3_J033219.25-275406.2',
  'ARG0003r3m': 'SWIRE3_J033106.35-285217.0',
  'ARG0003r3n': 'SWIRE3_J033249.41-274235.4',
  'ARG0003r3o': 'SWIRE3_J033009.33-281850.8',
  'ARG0003r3p': 'SWIRE3_J033337.94-283046.7',
  'ARG0003r3q': 'SWIRE3_J032741.08-282320.3',
  'ARG0003r3r': 'SWIRE3_J033129.76-273218.5',
  'ARG0003r3s': 'SWIRE3_J032821.93-280001.9',
  'ARG0003r3t': 'SWIRE3_J033405.53-274636.5',
  'ARG0003r3u': 'SWIRE3_J033417.13-282502.7',
  'ARG0003r3v': 'SWIRE3_J033149.86-280809.5',
  'ARG0003r3w': 'SWIRE3_J032629.81-284754.4',
  'ARG0003r3x': 'SWIRE3_J033157.74-282610.5',
  'ARG0003r3z': 'SWIRE3_J033517.71-275050.2',
  'ARG0003r40': 'SWIRE3_J033245.30-280450.3',
  'ARG0003r41': 'SWIRE3_J033156.04-285026.4',
  'ARG0003r42': 'SWIRE3_J032726.61-272327.9',
  'ARG0003r43': 'SWIRE3_J033156.32-284814.7',
  'ARG0003r44': 'SWIRE3_J033409.97-275212.4',
  'ARG0003r45': 'SWIRE3_J032904.42-285137.6',
  'ARG0003r46': 'SWIRE3_J033113.93-275518.8',
  'ARG0003r47': 'SWIRE3_J033316.31-274725.0',
  'ARG0003r48': 'SWIRE3_J033323.69-281139.2',
  'ARG0003r49': 'SWIRE3_J032922.66-274136.1',
  'ARG0003r4a': 'SWIRE3_J032914.02-273502.1',
  'ARG0003r4b': 'SWIRE3_J033412.23-281630.5',
  'ARG0003r4c': 'SWIRE3_J032922.96-280729.4',
  'ARG0003r4d': 'SWIRE3_J033246.87-285400.5',
  'ARG0003r4e': 'SWIRE3_J033210.93-274415.3',
  'ARG0003r4f': 'SWIRE3_J032910.90-272717.7',
  'ARG0003r4g': 'SWIRE3_J032702.71-284753.6',
  'ARG0003r4h': 'SWIRE3_J033332.32-282238.1',
  'ARG0003r4j': 'SWIRE3_J033057.22-283520.1',
  'ARG0003r4l': 'SWIRE3_J033500.83-285519.6',
  'ARG0003r4m': 'SWIRE3_J032801.90-272044.9',
  'ARG0003r4n': 'SWIRE3_J032741.44-271933.4',
  'ARG0003r4o': 'SWIRE3_J033014.16-275049.7',
  'ARG0003r4p': 'SWIRE3_J033030.43-281605.3',
  'ARG0003r4q': 'SWIRE3_J033410.85-282723.7',
  'ARG0003r4r': 'SWIRE3_J032818.03-274308.0',
  'ARG0003r4s': 'SWIRE3_J032829.30-280150.5',
  'ARG0003r4t': 'SWIRE3_J033147.44-282605.2',
  'ARG0003r4u': 'SWIRE3_J033210.99-284001.6',
  'ARG0003r4v': 'SWIRE3_J033501.32-282203.1',
  'ARG0003r4w': 'SWIRE3_J032718.94-284641.1',
  'ARG0003r4x': 'SWIRE3_J033149.91-274837.9',
  'ARG0003r4y': 'SWIRE3_J033430.64-281808.6',
  'ARG0003r4z': 'SWIRE3_J032731.61-275245.5',
  'ARG0003r50': 'SWIRE3_J033522.85-275959.1',
  'ARG0003r51': 'SWIRE3_J033111.69-273144.2',
  'ARG0003r52': 'SWIRE3_J032805.81-272335.0',
  'ARG0003r53': 'SWIRE3_J033448.98-281145.1',
  'ARG0003r54': 'SWIRE3_J032806.11-272628.6',
  'ARG0003r55': 'SWIRE3_J032630.64-283658.0',
  'ARG0003r56': 'SWIRE3_J033111.70-283721.7',
  'ARG0003r57': 'SWIRE3_J033238.79-282749.9',
  'ARG0003r59': 'SWIRE3_J033533.90-273310.9',
  'ARG0003r5b': 'SWIRE3_J033038.36-283401.8',
  'ARG0003r5c': 'SWIRE3_J033029.42-274328.7',
  'ARG0003r5d': 'SWIRE3_J033208.67-274734.6',
  'ARG0003r5e': 'SWIRE3_J033454.31-284633.4',
  'ARG0003r5f': 'SWIRE3_J033521.96-275414.5',
  'ARG0003r5g': 'SWIRE3_J032934.24-273431.8',
  'ARG0003r5h': 'SWIRE3_J033355.42-273708.9',
  'ARG0003r5j': 'SWIRE3_J032747.04-282608.3',
  'ARG0003r5k': 'SWIRE3_J033225.08-274403.4',
  'ARG0003r5l': 'SWIRE3_J033358.95-283504.0',
  'ARG0003r5m': 'SWIRE3_J033237.80-283620.4',
  'ARG0003r5o': 'SWIRE3_J032706.97-275814.6',
  'ARG0003r5p': 'SWIRE3_J032715.90-275332.7',
  'ARG0003r5q': 'SWIRE3_J033127.18-274246.6',
  'ARG0003r5r': 'SWIRE3_J032804.56-274047.3',
  'ARG0003r5s': 'SWIRE3_J033200.83-273556.6',
  'ARG0003r5t': 'SWIRE3_J033106.52-274514.7',
  'ARG0003r5u': 'SWIRE3_J032826.51-281920.7',
  'ARG0003r5v': 'SWIRE3_J033023.39-273634.8',
  'ARG0003r5w': 'SWIRE3_J033221.29-284817.7',
  'ARG0003r5x': 'SWIRE3_J032811.20-272553.3',
  'ARG0003r5y': 'SWIRE3_J033023.22-275356.6',
  'ARG0003r5z': 'SWIRE3_J033517.75-285407.1',
  'ARG0003r62': 'SWIRE3_J032921.68-283012.9',
  'ARG0003r64': 'SWIRE3_J032822.69-283157.9',
  'ARG0003r65': 'SWIRE3_J032843.33-282157.2',
  'ARG0003r67': 'SWIRE3_J033448.62-282205.8',
  'ARG0003r68': 'SWIRE3_J032845.52-283604.6',
  'ARG0003r69': 'SWIRE3_J033338.32-280030.6',
  'ARG0003r6a': 'SWIRE3_J032946.77-273640.4',
  'ARG0003r6b': 'SWIRE3_J033256.43-275848.2',
  'ARG0003r6c': 'SWIRE3_J032753.03-285140.5',
  'ARG0003r6d': 'SWIRE3_J033358.29-274848.8',
  'ARG0003r6e': 'SWIRE3_J033059.50-281001.0',
  'ARG0003r6f': 'SWIRE3_J033537.03-273432.9',
  'ARG0003r6g': 'SWIRE3_J032824.71-274149.3',
  'ARG0003r6h': 'SWIRE3_J032825.35-274445.0',
  'ARG0003r6i': 'SWIRE3_J032638.08-280336.2',
  'ARG0003r6j': 'SWIRE3_J033052.80-275458.7',
  'ARG0003r6k': 'SWIRE3_J033338.86-281804.7',
  'ARG0003r6l': 'SWIRE3_J033206.24-281645.2',
  'ARG0003r6m': 'SWIRE3_J032927.56-284015.5',
  'ARG0003r6n': 'SWIRE3_J033008.19-280108.5',
  'ARG0003r6o': 'SWIRE3_J032844.22-282323.5',
  'ARG0003r6p': 'SWIRE3_J033316.70-275630.4',
  'ARG0003r6q': 'SWIRE3_J032940.94-281830.4',
  'ARG0003r6s': 'SWIRE3_J032931.23-282009.0',
  'ARG0003r6t': 'SWIRE3_J033123.28-274906.1',
  'ARG0003r6u': 'SWIRE3_J033308.15-275033.5',
  'ARG0003r6v': 'SWIRE3_J032821.51-280811.8',
  'ARG0003r6w': 'SWIRE3_J032938.99-280658.8',
  'ARG0003r6x': 'SWIRE3_J033131.33-272846.8',
  'ARG0003r6y': 'SWIRE3_J033348.98-281944.9',
  'ARG0003r71': 'SWIRE3_J033206.09-283941.5',
  'ARG0003r72': 'SWIRE3_J032853.99-273835.4',
  'ARG0003r73': 'SWIRE3_J033111.09-281725.5',
  'ARG0003r74': 'SWIRE3_J033113.95-273910.6',
  'ARG0003r75': 'SWIRE3_J032907.63-284117.6',
  'ARG0003r76': 'SWIRE3_J032909.12-284825.4',
  'ARG0003r77': 'SWIRE3_J033145.54-281955.0',
  'ARG0003r78': 'SWIRE3_J033447.96-283009.8',
  'ARG0003r79': 'SWIRE3_J033445.16-272718.6',
  'ARG0003r7a': 'SWIRE3_J032909.46-281833.3',
  'ARG0003r7c': 'SWIRE3_J032704.94-283859.7',
  'ARG0003r7e': 'SWIRE3_J032924.68-273917.5',
  'ARG0003r7f': 'SWIRE3_J033208.37-283357.7',
  'ARG0003r7h': 'SWIRE3_J033429.74-271745.2',
  'ARG0003r7i': 'SWIRE3_J032841.23-283646.6',
  'ARG0003r7j': 'SWIRE3_J032814.92-273650.9',
  'ARG0003r7l': 'SWIRE3_J033400.19-281010.8',
  'ARG0003r7m': 'SWIRE3_J033249.65-281815.6',
  'ARG0003r7n': 'SWIRE3_J032722.24-271615.7',
  'ARG0003r7p': 'SWIRE3_J032719.53-284144.3',
  'ARG0003r7q': 'SWIRE3_J033023.57-285340.9',
  'ARG0003r7r': 'SWIRE3_J033145.28-281956.1',
  'ARG0003r7s': 'SWIRE3_J032953.02-275341.2',
  'ARG0003r7v': 'SWIRE3_J033246.01-282232.3',
  'ARG0003r7w': 'SWIRE3_J032731.60-273355.1',
  'ARG0003r7x': 'SWIRE3_J033430.66-271914.7',
  'ARG0003r7z': 'SWIRE3_J033128.66-272244.4',
  'ARG0003r80': 'SWIRE3_J033348.74-280232.0',
  'ARG0003r81': 'SWIRE3_J033105.57-280042.3',
  'ARG0003r83': 'SWIRE3_J033245.81-283114.8',
  'ARG0003r84': 'SWIRE3_J033115.99-274442.9',
  'ARG0003r85': 'SWIRE3_J033442.40-281528.4',
  'ARG0003r87': 'SWIRE3_J032758.57-285339.8',
  'ARG0003r88': 'SWIRE3_J032648.21-275746.9',
  'ARG0003r89': 'SWIRE3_J033457.87-272637.6',
  'ARG0003r8a': 'SWIRE3_J033256.68-280204.4',
  'ARG0003r8b': 'SWIRE3_J032759.16-272827.0',
  'ARG0003r8c': 'SWIRE3_J032949.49-285057.3',
  'ARG0003r8d': 'SWIRE3_J033439.16-272346.7',
  'ARG0003r8e': 'SWIRE3_J032629.54-284051.9',
  'ARG0003r8g': 'SWIRE3_J033152.10-273926.4',
  'ARG0003r8h': 'SWIRE3_J033310.93-281853.3',
  'ARG0003r8i': 'SWIRE3_J033316.10-272746.1',
  'ARG0003r8j': 'SWIRE3_J033313.64-284306.6',
  'ARG0003r8k': 'SWIRE3_J032924.66-273209.9',
  'ARG0003r8l': 'SWIRE3_J032921.00-281054.5',
  'ARG0003r8m': 'SWIRE3_J032923.52-274018.2',
  'ARG0003r8n': 'SWIRE3_J032820.30-273011.3',
  'ARG0003r8o': 'SWIRE3_J032837.04-275435.0',
  'ARG0003r8p': 'SWIRE3_J032914.73-281000.2',
  'ARG0003r8q': 'SWIRE3_J033052.80-275458.7',
  'ARG0003r8r': 'SWIRE3_J032636.14-283936.1',
  'ARG0003r8s': 'SWIRE3_J032615.52-280559.8',
  'ARG0003r8t': 'SWIRE3_J033422.76-284910.6',
  'ARG0003r8u': 'SWIRE3_J032657.10-272701.0',
  'ARG0003r8v': 'SWIRE3_J033316.28-285008.0',
  'ARG0003r8w': 'SWIRE3_J032926.55-284225.8',
  'ARG0003r8x': 'SWIRE3_J033327.50-275725.8',
  'ARG0003r8y': 'SWIRE3_J033044.16-282107.4',
  'ARG0003r8z': 'SWIRE3_J032823.95-281520.0',
  'ARG0003r90': 'SWIRE3_J033417.71-273932.4',
  'ARG0003r92': 'SWIRE3_J032717.52-275946.5',
  'ARG0003r93': 'SWIRE3_J032649.37-274832.8',
  'ARG0003r94': 'SWIRE3_J033052.80-275458.7',
  'ARG0003r95': 'SWIRE3_J033219.51-284028.5',
  'ARG0003r96': 'SWIRE3_J033012.07-274613.9',
  'ARG0003r97': 'SWIRE3_J032840.34-280539.2',
  'ARG0003r98': 'SWIRE3_J033114.02-284708.5',
  'ARG0003r9a': 'SWIRE3_J032958.95-280624.8',
  'ARG0003r9b': 'SWIRE3_J032732.16-275456.7',
  'ARG0003r9c': 'SWIRE3_J033054.78-273811.0',
  'ARG0003r9d': 'SWIRE3_J033525.21-285446.2',
  'ARG0003r9f': 'SWIRE3_J033341.31-273808.9',
  'ARG0003r9h': 'SWIRE3_J032653.39-281815.3',
  'ARG0003r9i': 'SWIRE3_J033341.75-280737.0',
  'ARG0003r9k': 'SWIRE3_J033432.61-281730.5',
  'ARG0003r9n': 'SWIRE3_J033023.57-282531.2',
  'ARG0003r9o': 'SWIRE3_J033209.83-282705.3',
  'ARG0003r9p': 'SWIRE3_J033102.45-282027.1',
  'ARG0003r9q': 'SWIRE3_J033130.05-275602.5',
  'ARG0003r9r': 'SWIRE3_J033038.50-274535.1',
  'ARG0003r9u': 'SWIRE3_J033405.91-284327.9',
  'ARG0003r9v': 'SWIRE3_J033153.42-280221.5',
  'ARG0003r9w': 'SWIRE3_J033325.15-281319.4',
  'ARG0003r9y': 'SWIRE3_J033035.11-280337.0',
  'ARG0003r9z': 'SWIRE3_J033059.00-284416.7',
  'ARG0003ra0': 'SWIRE3_J033229.12-273035.4',
  'ARG0003ra1': 'SWIRE3_J032749.55-274445.2',
  'ARG0003ra3': 'SWIRE3_J033456.51-274720.5',
  'ARG0003ra4': 'SWIRE3_J033149.96-284234.9',
  'ARG0003ra5': 'SWIRE3_J032708.43-271504.6',
  'ARG0003ra6': 'SWIRE3_J032951.87-274906.7',
  'ARG0003ra7': 'SWIRE3_J033532.19-284801.1',
  'ARG0003ra9': 'SWIRE3_J033529.46-285154.5',
  'ARG0003rab': 'SWIRE3_J033418.69-272522.1',
  'ARG0003rac': 'SWIRE3_J033125.06-285228.8',
  'ARG0003rae': 'SWIRE3_J033138.08-284249.8',
  'ARG0003raf': 'SWIRE3_J032724.44-284723.1',
  'ARG0003rah': 'SWIRE3_J033405.57-272637.8',
  'ARG0003rai': 'SWIRE3_J033431.73-273210.0',
  'ARG0003raj': 'SWIRE3_J033343.61-282214.3',
  'ARG0003rak': 'SWIRE3_J032956.26-271931.2',
  'ARG0003ral': 'SWIRE3_J033256.63-283045.3',
  'ARG0003ran': 'SWIRE3_J033334.56-274751.4',
  'ARG0003rap': 'SWIRE3_J033102.32-280119.1',
  'ARG0003raq': 'SWIRE3_J032904.38-284753.0',
  'ARG0003rar': 'SWIRE3_J033016.99-273646.0',
  'ARG0003ras': 'SWIRE3_J032728.78-282110.2',
  'ARG0003raw': 'SWIRE3_J032832.78-273540.2',
  'ARG0003rax': 'SWIRE3_J033043.64-283754.3',
  'ARG0003raz': 'SWIRE3_J032625.19-280910.1',
  'ARG0003rb1': 'SWIRE3_J033325.15-281319.4',
  'ARG0003rb2': 'SWIRE3_J032604.58-284650.9',
  'ARG0003rb4': 'SWIRE3_J032957.18-272641.9',
  'ARG0003rb6': 'SWIRE3_J033244.26-275141.3',
  'ARG0003rb7': 'SWIRE3_J032731.31-281258.1',
  'ARG0003rb8': 'SWIRE3_J033238.09-281358.9',
  'ARG0003rb9': 'SWIRE3_J033114.13-281651.8',
  'ARG0003rba': 'SWIRE3_J033315.01-275150.8',
  'ARG0003rbb': 'SWIRE3_J033429.43-273234.7',
  'ARG0003rbc': 'SWIRE3_J033156.60-284925.7',
  'ARG0003rbd': 'SWIRE3_J033049.18-281930.6',
  'ARG0003rbe': 'SWIRE3_J032709.34-284246.2',
  'ARG0003rbi': 'SWIRE3_J033004.46-283944.9',
  'ARG0003rbj': 'SWIRE3_J033128.57-274935.1',
  'ARG0003rbk': 'SWIRE3_J032658.39-272658.0',
  'ARG0003rbl': 'SWIRE3_J032639.96-281814.1',
  'ARG0003rbn': 'SWIRE3_J033126.70-285632.1',
  'ARG0003rbo': 'SWIRE3_J033158.16-281457.1',
  'ARG0003rbp': 'SWIRE3_J033217.16-282406.7',
  'ARG0003rbq': 'SWIRE3_J033219.51-284431.8',
  'ARG0003rbr': 'SWIRE3_J033529.19-283848.1',
  'ARG0003rbs': 'SWIRE3_J033152.10-273926.4',
  'ARG0003rbt': 'SWIRE3_J033008.69-274137.8',
  'ARG0003rbv': 'SWIRE3_J032652.40-275238.6',
  'ARG0003rbw': 'SWIRE3_J032801.61-273214.2',
  'ARG0003rbx': 'SWIRE3_J033530.19-281108.5',
  'ARG0003rby': 'SWIRE3_J033150.77-274703.7',
  'ARG0003rc0': 'SWIRE3_J032919.57-274227.7',
  'ARG0003rc6': 'SWIRE3_J033457.33-282158.6',
  'ARG0003rc7': 'SWIRE3_J033401.63-272524.5',
  'ARG0003rc8': 'SWIRE3_J033514.28-283843.7',
  'ARG0003rc9': 'SWIRE3_J033553.56-280952.4',
  'ARG0003rcb': 'SWIRE3_J032833.78-280153.5',
  'ARG0003rcd': 'SWIRE3_J033326.68-283409.9',
  'ARG0003rce': 'SWIRE3_J032824.52-281839.8',
  'ARG0003rcf': 'SWIRE3_J032753.19-280631.7',
  'ARG0003rcg': 'SWIRE3_J032922.03-280420.7',
  'ARG0003rci': 'SWIRE3_J032929.57-274331.3',
  'ARG0003rcn': 'SWIRE3_J033157.45-284041.9',
  'ARG0003rco': 'SWIRE3_J033439.68-282257.9',
  'ARG0003rcp': 'SWIRE3_J033305.43-281849.1',
  'ARG0003rcq': 'SWIRE3_J033443.65-280017.4',
  'ARG0003rcr': 'SWIRE3_J033218.00-274719.1',
  'ARG0003rcv': 'SWIRE3_J032723.48-284751.1',
  'ARG0003rcx': 'SWIRE3_J033405.40-283535.6',
  'ARG0003rcy': 'SWIRE3_J033321.28-274138.5',
  'ARG0003rcz': 'SWIRE3_J033335.66-281353.1',
  'ARG0003rd0': 'SWIRE3_J033038.97-274814.1',
  'ARG0003rd1': 'SWIRE3_J033241.69-284409.9',
  'ARG0003rd2': 'SWIRE3_J033331.69-280624.0',
  'ARG0003rd3': 'SWIRE3_J033033.05-273255.2',
  'ARG0003rd4': 'SWIRE3_J033241.60-280127.9',
  'ARG0003rd9': 'SWIRE3_J033520.51-274654.9',
  'ARG0003rdd': 'SWIRE3_J032716.98-284103.7',
  'ARG0003rdf': 'SWIRE3_J032853.28-275401.0',
  'ARG0003rdg': 'SWIRE3_J032816.68-272702.1',
  'ARG0003rdh': 'SWIRE3_J033408.79-272119.8',
  'ARG0003rdi': 'SWIRE3_J033216.20-283257.1',
  'ARG0003rdl': 'SWIRE3_J033204.99-282815.6',
  'ARG0003rdm': 'SWIRE3_J033005.85-272651.6',
  'ARG0003rdt': 'SWIRE3_J032922.16-273748.2',
  'ARG0003rdu': 'SWIRE3_J033046.27-275518.8',
  'ARG0003rdv': 'SWIRE3_J032914.98-273103.9',
  'ARG0003rdx': 'SWIRE3_J033538.73-283012.9',
  'ARG0003re1': 'SWIRE3_J033117.33-280147.3',
  'ARG0003re8': 'SWIRE3_J033344.31-283325.2',
  'ARG0003re9': 'SWIRE3_J032745.14-274052.4',
  'ARG0003rea': 'SWIRE3_J032738.22-275704.0',
  'ARG0003reb': 'SWIRE3_J033448.19-281041.1',
  'ARG0003rec': 'SWIRE3_J032855.08-272834.9',
  'ARG0003red': 'SWIRE3_J033138.46-275942.2',
  'ARG0003ref': 'SWIRE3_J032639.36-284132.1',
  'ARG0003rel': 'SWIRE3_J033342.33-274736.9',
  'ARG0003ren': 'SWIRE3_J033440.88-275630.3',
  'ARG0003reo': 'SWIRE3_J033010.72-272712.8',
  'ARG0003req': 'SWIRE3_J033043.45-272323.3',
  'ARG0003reu': 'SWIRE3_J033107.55-271918.5',
  'ARG0003rex': 'SWIRE3_J033025.72-275017.4',
  'ARG0003rey': 'SWIRE3_J033427.84-284235.6',
  'ARG0003rf1': 'SWIRE3_J033359.93-273739.2',
  'ARG0003rf3': 'SWIRE3_J033249.95-273433.0',
  'ARG0003rf9': 'SWIRE3_J033307.41-281410.6',
  'ARG0003rfa': 'SWIRE3_J032812.10-274010.4',
  'ARG0003rfc': 'SWIRE3_J033032.82-273542.5',
  'ARG0003rfd': 'SWIRE3_J032700.98-272804.0',
  'ARG0003rfe': 'SWIRE3_J033319.00-281432.8',
  'ARG0003rfh': 'SWIRE3_J033041.65-280606.0',
  'ARG0003rfi': 'SWIRE3_J032758.05-280359.6',
  'ARG0003rfo': 'SWIRE3_J033146.57-275735.2',
  'ARG0003rfq': 'SWIRE3_J033309.72-274801.9',
  'ARG0003rfr': 'SWIRE3_J032615.41-284630.7',
  'ARG0003rfw': 'SWIRE3_J033453.92-272921.3',
  'ARG0003rfx': 'SWIRE3_J033339.11-281705.9',
  'ARG0003rg0': 'SWIRE3_J032842.41-274446.5',
  'ARG0003rg2': 'SWIRE3_J033329.09-284333.9',
  'ARG0003rg7': 'SWIRE3_J033456.70-283425.2',
  'ARG0003rgb': 'SWIRE3_J033512.20-281438.0',
  'ARG0003rgg': 'SWIRE3_J033510.39-285428.2',
  'ARG0003rgh': 'SWIRE3_J033332.16-272917.5',
  'ARG0003rgi': 'SWIRE3_J033337.97-284706.9',
  'ARG0003rgq': 'SWIRE3_J032654.55-273751.2',
  'ARG0003rgw': 'SWIRE3_J033244.48-285124.5',
  'ARG0003rgz': 'SWIRE3_J033311.77-274138.8',
  'ARG0003rh3': 'SWIRE3_J033124.61-280455.2',
  'ARG0003rhk': 'SWIRE3_J033403.25-272151.7',
  'ARG0003rho': 'SWIRE3_J033117.33-280147.3',
  'ARG0003rhq': 'SWIRE3_J033130.73-275734.0',
  'ARG0003rhx': 'SWIRE3_J033158.02-284234.9',
  'ARG0003ri1': 'SWIRE3_J032836.19-271650.3',
  'ARG0003rie': 'SWIRE3_J032702.71-284753.6',
  'ARG0003rif': 'SWIRE3_J033006.24-272821.5',
  'ARG0003rii': 'SWIRE3_J033337.14-272906.6',
  'ARG0003rik': 'SWIRE3_J033109.56-274040.3',
  'ARG0003riw': 'SWIRE3_J033248.86-283052.3',
  'ARG0003riy': 'SWIRE3_J033148.03-281007.7',
  'ARG0003riz': 'SWIRE3_J033313.10-274930.4',
  'ARG0003rj2': 'SWIRE3_J032634.58-282022.8',
  'ARG0003rj5': 'SWIRE3_J033147.70-280856.2',
  'ARG0003rj6': 'SWIRE3_J032635.10-281229.2',
  'ARG0003rjd': 'SWIRE3_J033316.93-274121.9',
  'ARG0003rjk': 'SWIRE3_J033316.52-275039.7',
  'ARG0003rjm': 'SWIRE3_J033231.40-281420.3',
  'ARG0003rjn': 'SWIRE3_J033149.58-281614.8',
  'ARG0003rjo': 'SWIRE3_J033340.55-280833.6',
  'ARG0003rju': 'SWIRE3_J033203.87-275805.2',
  'ARG0003rk0': 'SWIRE3_J033004.69-273208.5',
  'ARG0003rk2': 'SWIRE3_J033211.07-274055.7',
  'ARG0003rk5': 'SWIRE3_J033306.15-273040.2',
  'ARG0003rk8': 'SWIRE3_J033505.58-272148.9',
  'ARG0003rki': 'SWIRE3_J033130.59-280423.7',
  'ARG0003rko': 'SWIRE3_J033228.72-274620.5',
  'ARG0003rkt': 'SWIRE3_J033336.41-274355.4',
  'ARG0003rkz': 'SWIRE3_J033221.07-273530.2',
  'ARG0003rl0': 'SWIRE3_J033305.69-272407.2',
  'ARG0003rl8': 'SWIRE3_J033218.74-281321.2',
  'ARG0003rlf': 'SWIRE3_J033125.29-275959.0',
  'ARG0003rlp': 'SWIRE3_J033202.82-275613.3',
  'ARG0003rlt': 'SWIRE3_J033109.80-275225.3',
  'ARG0003rm0': 'SWIRE3_J033146.07-280026.7',
  'ARG0003rm1': 'SWIRE3_J033138.27-280810.7',
  'ARG0003rm8': 'SWIRE3_J033332.56-273538.6',
  'ARG0003rmc': 'SWIRE3_J033022.42-272119.0',
  'ARG0003rme': 'SWIRE3_J033353.93-275548.7',
  'ARG0003rmi': 'SWIRE3_J033337.99-275932.5',
  'ARG0003rmn': 'SWIRE3_J033438.38-282955.5',
  'ARG0003rmo': 'SWIRE3_J033325.83-274342.8',
  'ARG0003rn4': 'SWIRE3_J033209.71-274248.5',
  'ARG0003rng': 'SWIRE3_J033409.51-271441.1',
  'ARG0003ro4': 'SWIRE3_J032629.13-280650.7',
  'ARG0003rot': 'SWIRE3_J033307.30-274432.9',
  'ARG0003roz': 'SWIRE3_J033100.42-272114.1',
  'ARG0003rpe': 'SWIRE3_J033245.99-280848.5',
  'ARG0003rq0': 'SWIRE3_J033245.97-275745.7',
  'ARG0003rq1': 'SWIRE3_J033024.96-273420.5',
  'ARG0003rqj': 'SWIRE3_J033335.21-274550.1',
  'ARG0003rqp': 'SWIRE3_J033317.40-274949.1',
  'ARG0003rqy': 'SWIRE3_J033226.82-280453.8',
  'ARG0003rrk': 'SWIRE3_J033352.81-274346.7',
  'ARG0003rro': 'SWIRE3_J033137.68-272551.0',
  'ARG0003rs0': 'SWIRE3_J033155.74-284004.0',
  'ARG0003rs2': 'SWIRE3_J033219.49-275217.7',
  'ARG0003rs8': 'SWIRE3_J033140.63-272939.0',
  'ARG0003rsi': 'SWIRE3_J033208.53-274648.6',
  'ARG0003rsm': 'SWIRE3_J033249.32-275845.1',
  'ARG0003rsz': 'SWIRE3_J033241.79-280551.2',
  'ARG0003rtj': 'SWIRE3_J033237.72-275000.7',
  'ARG0003rtt': 'SWIRE3_J033318.68-274940.2',
  'ARG0003rtx': 'SWIRE3_J033425.21-272953.1',
  'ARG0003rul': 'SWIRE3_J032700.05-272126.3',
  'ARG0003rus': 'SWIRE3_J033312.51-272731.4',
  'ARG0003rve': 'SWIRE3_J033221.26-274435.8',
  'ARG0003rvu': 'SWIRE3_J033136.55-273126.7',
  'ARG0003rvy': 'SWIRE3_J032850.93-273827.1',
  'ARG0003rw0': 'SWIRE3_J033403.57-273923.9',
  'ARG0003rwe': 'SWIRE3_J033101.23-273938.7',
  'ARG0003rwy': 'SWIRE3_J033132.82-280116.3',
  'ARG0003ryh': 'SWIRE3_J033153.15-272638.0',
  'ARG0003s0y': 'SWIRE3_J033102.87-284230.2',
  'ARG0003s1f': 'SWIRE3_J033328.01-273027.2',
  'ARG0003s24': 'SWIRE3_J033210.77-274627.9',
  'ARG0003s3k': 'SWIRE3_J033223.68-273648.7',
  'ARG0003s8d': 'SWIRE3_J033238.92-275700.8',
  'ARG0003sc0': 'SWIRE3_J033259.19-274325.3',
  'ARG0003se7': 'SWIRE3_J033239.71-280311.4',
  'ARG0003sgb': 'SWIRE3_J033222.59-274426.0',
  'ARG0003sky': 'SWIRE3_J032639.11-280801.5',
  'ARG0003sms': 'SWIRE3_J033304.46-273802.1',
  'ARG0003sw7': 'SWIRE3_J033333.11-274602.1',
  'ARG0003sw9': 'SWIRE3_J033213.24-274241.1'})

In [ ]:
# Compute all the cross-identification accuracies.
cross_id_results = {}
for key in swire_probs.keys():
    print(key)
    cross_id_results[key] = test_cross_identifications(*key)

In [94]:
# Plot cross-identification accuracy.
markers = ['>', '.', 'x', '+']
plt.figure(figsize=(15, 4))
for i, set_name in enumerate(norris_labelled_sets):
    ax = plt.subplot(1, 3, i + 1)
    ax.set_title(titlemap[set_name])
    for i in range(4):
        ax.scatter([0], lr_norris_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        ax.scatter([1], lr_rgz_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        ax.scatter([2], lr_rgz_accuracies[fullmap[set_name]][i] * 100, marker=markers[i], color='k')
        ax.scatter([3], rf_norris_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        ax.scatter([4], rf_rgz_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        ax.scatter([5], rf_rgz_accuracies[fullmap[set_name]][i] * 100, marker=markers[i], color='k')
        ax.scatter([6], cnn_norris_accuracies[set_name][i] * 100, marker=markers[i], color='k')

        ax.scatter([7], cnn_rgz_accuracies[set_name][i] * 100, marker=markers[i], color='k')
        ax.scatter([8], cnn_rgz_accuracies[fullmap[set_name]][i] * 100, marker=markers[i], color='k')
        
        ax.scatter([9],  gt_rgz_accuracies[set_name][i] * 100, marker=markers[i], color='k')

    ax.set_ylim((85, 100))
    ax.set_xlim((-0.5, 9.5))
    ax.set_xticks([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    ax.set_xticklabels(['LR(Norris)', 'LR(RGZ N)', 'LR(RGZ)',
                        'RF(Norris)', 'RF(RGZ N)', 'RF(RGZ)',
                        'CNN(Norris)', 'CNN(RGZ N)', 'CNN(RGZ)',
                        'RGZ'
                       ], rotation='vertical')
    plt.xlabel('Classifier(Labels)')
    plt.ylabel('Balanced accuracy (%)')
plt.subplots_adjust(wspace=0.3)
plt.savefig('/Users/alger/repos/crowdastro-projects/ATLAS-CDFS/atlas-ml-ba.pdf')
plt.show()



In [95]:
# What we really want is a plot of this for visualisation.
def plot_cross_identification(zid, swire_probs, plot_scatter=True, ax=None):
    import astropy.io.fits, astropy.wcs, astropy.io.ascii, requests, skimage.io, skimage.transform
    import matplotlib.patches as patches
    probs_table = cross_identify(zid, swire_probs)
    # Where is the ATLAS object?
    table = astropy.io.ascii.read('/Users/alger/data/Crowdastro/one-table-to-rule-them-all.tbl')
    row = table[table['Component Zooniverse ID (RGZ)'] == zid][0]
    ra, dec = row['Component RA (Franzen)'], row['Component DEC (Franzen)']
    # Load the RGZ images.
    ir = skimage.io.imread(zid_to_ir_url[zid])
    radio = requests.get(zid_to_radio_url[zid]).json()['contours']
    # Convert SWIRE objects into pixel locations.
    ras = probs_table['ra']
    decs = probs_table['dec']
    ras -= ra
    decs -= dec
    ras *= 60 * 250 * 0.9
    decs *= 60 * 250
    ras += 250
    decs += 250
    ras = 500 - ras
    decs = 500 - decs
    if not ax:
        fig = plt.figure(figsize=(15, 7.5))
        ax = fig.add_subplot(1, 2 if plot_scatter else 1, 1)
    ax.imshow(ir, origin='upper', alpha=0.5)
    for contour in radio:
        for contour_ in contour:
            xs = []
            ys = []
            for point in contour_['arr']:
                xs.append(point['x'] * 500 / 201)
                ys.append(point['y'] * 500 / 201)
            plt.plot(xs, ys, c='white', zorder=1)
    sizes = [max(i, 10) for i in probs_table['prob']**2 * 200]
    probs = [i for i in probs_table['prob']]
    plt.scatter(ras, decs, s=sizes, zorder=2,
         color='black', facecolor='white',
         linewidth=1)
    plt.grid('off')
    w = 32 * 500 / 140
    plt.axis('off')
    top_n = [i for i in numpy.argsort(probs_table['prob'])[-5:] if probs_table['prob'][i] > 0.2]
    indices = {i:j + 1 for j, i in enumerate(numpy.argsort(probs_table['prob'])[::-1])}
    for i, (ra, dec) in enumerate(zip(ras, decs)):
        if plot_scatter:
            plt.text(ra + 12, dec + 12, str(indices[i]), color="black", fontsize=12)

        if i not in top_n:
            continue

        ax.add_patch(
            patches.Rectangle(
                (ra - w / 2, dec - w / 2),   # (x, y)
                w,          # width
                w,          # height
                facecolor='None',
                linestyle='--',
                edgecolor='white',
                linewidth=2,
            )
        )
    if plot_scatter and not ax:
        ax = fig.add_subplot(1, 2, 2)
        ax.scatter(range(1, len(probs_table) + 1), sorted(probs, reverse=True), s=sorted(sizes, reverse=True))
        ax.invert_xaxis()

In [261]:
plot_cross_identification(
    'ARG0003sky', swire_probs['cnn', 'norris', 'RGZ & Norris'],
    plot_scatter=False)


Let's plot some of these against their resolved-ness, which is $S/S_p$. For now we'll just set both axes to that; we would like to add a disagreement axis (but that will require some way of disagreeing — a committee might work.)


In [319]:
def resolvedness(r):
    aa = 10.0
    bb = 1.3
    s = r['Component S (Franzen)'] if r['Component S (Franzen)'] != 0.0 else r['Component Sp (Franzen)']
    ssp = s / r['Component Sp (Franzen)']
    aasnrbb = aa / (r['Component SNR (Franzen)'] ** bb)
    return ssp / aasnrbb

def plot_by_resolved():
    import astropy.io.ascii
    table = astropy.io.ascii.read('/Users/alger/data/Crowdastro/one-table-to-rule-them-all.tbl')
    zid_to_resolvedness = {}
    for row in table:
        if row['Source SWIRE (Norris)'] and row['Source SWIRE (Norris)'].startswith('SWIRE') and \
                row['Primary Component ID (RGZ)']:
            zid = row['Component Zooniverse ID (RGZ)']
            res = resolvedness(row)
            zid_to_resolvedness[zid] = res
    
    zids = sorted(zid_to_resolvedness, key=zid_to_resolvedness.get)
    resolvednesses = numpy.array([zid_to_resolvedness[zid] for zid in zids])
    resolvednesses_original = resolvednesses.copy()
#     print(resolvednesses)
    seaborn.distplot(resolvednesses)
    plt.yscale('log')
#     print((resolvednesses == 1).sum())
    
#     for i, (zid, res) in enumerate(zip(zids, resolvednesses * 100)):
#         print(zid, i, res)
#         fig = plt.figure(figsize=(10, 10))
#         ax = fig.add_subplot(1, 1, 1)
#         plot_cross_identification(zid, swire_probs['lr', 'norris', 'RGZ & Norris'], ax=ax, plot_scatter=False)
#         # Hacks: http://stackoverflow.com/a/27227718/1105803
#         ax.set_axis_off()
#         plt.subplots_adjust(top=1, bottom=0, right=1, left=0,
#                             hspace=0, wspace=0)
#         plt.margins(0, 0)
#         ax.xaxis.set_major_locator(plt.NullLocator())
#         ax.yaxis.set_major_locator(plt.NullLocator())
#         plt.savefig('/Users/alger/data/Crowdastro/cross_id_plots/{}.pdf'.format(zid),
#                     bbox_inches='tight', pad_inches=0)
#         plt.close()

In [320]:
plot_by_resolved()
# table = astropy.io.ascii.read('/Users/alger/data/Crowdastro/one-table-to-rule-them-all.tbl')
# for i in table:
#     print(i['Component S (Franzen)'], i['Component Zooniverse ID (RGZ)'], i['Component ID (Franzen)'])


Export

Export the CNN predictions.


In [ ]:
def export():
    cnn_norris_output_predictions = numpy.zeros((len(swire_names),))
    lr_norris_output_predictions = numpy.zeros((len(swire_names),))
    rf_norris_output_predictions = numpy.zeros((len(swire_names),))
    cnn_rgz_output_predictions = numpy.zeros((len(swire_names),))
    lr_rgz_output_predictions = numpy.zeros((len(swire_names),))
    rf_rgz_output_predictions = numpy.zeros((len(swire_names),))
    with h5py.File('/Users/alger/data/Crowdastro/all_training_data_11_05_17.h5', 'r') as f:
        test_sets = f['/sets/{}/test'.format('RGZ & Norris')].value
    for test_set, probs in zip(test_sets, cnn_norris_predicted_probs['RGZ & Norris']):
        cnn_norris_output_predictions[test_set] = probs.ravel()
    for test_set, probs in zip(test_sets, lr_norris_predicted_probs['RGZ & Norris']):
        lr_norris_output_predictions[test_set] = probs[:, 1]
    for test_set, probs in zip(test_sets, rf_norris_predicted_probs['RGZ & Norris']):
        rf_norris_output_predictions[test_set] = probs[:, 1]
    for test_set, probs in zip(test_sets, cnn_rgz_predicted_probs['RGZ & Norris']):
        cnn_rgz_output_predictions[test_set] = probs.ravel()
    for test_set, probs in zip(test_sets, lr_rgz_predicted_probs['RGZ & Norris']):
        lr_rgz_output_predictions[test_set] = probs[:, 1]
    for test_set, probs in zip(test_sets, rf_rgz_predicted_probs['RGZ & Norris']):
        rf_rgz_output_predictions[test_set] = probs[:, 1]
    with h5py.File('/Users/alger/data/Crowdastro/predictions_swire_11_05_17.h5', 'w') as f:
        f.create_dataset('cnn_norris', data=cnn_norris_output_predictions)
        f.create_dataset('lr_norris', data=lr_norris_output_predictions)
        f.create_dataset('cnn_rgz', data=cnn_rgz_output_predictions)
        f.create_dataset('lr_rgz', data=lr_rgz_output_predictions)
        f.create_dataset('rf_rgz', data=rf_rgz_output_predictions)
        f.create_dataset('rf_norris', data=rf_norris_output_predictions)
export()

Feature ablation


In [ ]:

Quadrants map


In [170]:
def plot_quadrants():
#     middle = (52.8, -28.1)
#     (q == 0 and coords[0] >= middle[0] and coords[1] >= middle[1]) or
#     (q == 1 and coords[0] < middle[0] and coords[1] >= middle[1]) or
#     (q == 2 and coords[0] < middle[0] and coords[1] < middle[1]) or
#     (q == 3 and coords[0] >= middle[0] and coords[1] < middle[1]))
    import astropy.io.fits, astropy.wcs, astropy.visualization, matplotlib.patches
    import astropy.visualization.wcsaxes
    atlas = astropy.io.fits.open('/Users/alger/data/ATLAS/CDFSmosaic_allch_8March2015.fits')[0]
    wcs = astropy.wcs.WCS(atlas.header).dropaxis(3).dropaxis(2)
    fig = plt.figure(figsize=(15, 15))
    ax = astropy.visualization.wcsaxes.WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], wcs=wcs)
    fig.add_axes(ax)
    stretch = astropy.visualization.ManualInterval(-100e-6, 300e-6)
    ax.imshow(stretch(atlas.data[0, 0]), cmap='Greys')
    ax.set_xlim((1500, 8500))
    ax.set_ylim((1700, 7300))
    middle, = wcs.all_world2pix([(52.8, -28.1)], 1)
    ax.scatter([middle[0]], [middle[1]], s=150, c='black', marker='o')
    ax.axvline(middle[0], color='black')
    ax.axhline(middle[1], color='black')
    plt.text((1500 + middle[0]) / 2,
             (7300 + middle[1]) / 2,
             '0', {'fontsize': 50, 'horizontalalignment': 'center', 'verticalalignment': 'center'})
    plt.text((8500 + middle[0]) / 2,
             (7300 + middle[1]) / 2,
             '1', {'fontsize': 50, 'horizontalalignment': 'center', 'verticalalignment': 'center'})
    plt.text((8500 + middle[0]) / 2,
             (1700 + middle[1]) / 2,
             '2', {'fontsize': 50, 'horizontalalignment': 'center', 'verticalalignment': 'center'})
    plt.text((1500 + middle[0]) / 2,
             (1700 + middle[1]) / 2,
             '3', {'fontsize': 50, 'horizontalalignment': 'center', 'verticalalignment': 'center'})
    lon, lat = ax.coords
    lon.set_ticklabel(size=20)
    lat.set_ticklabel(size=20)
    lon.set_major_formatter('hh:mm')
    lon.set_axislabel('Right Ascension', size=20)
    lat.set_axislabel('Declination', size=20)
    plt.savefig('/Users/alger/repos/crowdastro-projects/ATLAS-CDFS/quadrants.pdf')

plot_quadrants()


WARNING: VerifyWarning: Invalid 'BLANK' keyword in header.  The 'BLANK' keyword is only applicable to integer data, and will be ignored in this HDU. [astropy.io.fits.hdu.image]
WARNING: FITSFixedWarning: 'celfix' made the change 'Success'. [astropy.wcs.wcs]
WARNING: FITSFixedWarning: 'spcfix' made the change 'Changed CTYPE3 from 'FREQ-LSR' to 'FREQ''. [astropy.wcs.wcs]

In [ ]: