diff --git a/jwql/tests/test_data_containers.py b/jwql/tests/test_data_containers.py index ee4ef5454..6cb278c5e 100644 --- a/jwql/tests/test_data_containers.py +++ b/jwql/tests/test_data_containers.py @@ -216,7 +216,7 @@ def test_get_anomaly_form_post(mocker): MockSessionFileAnomaly()) # post a different selection: others are deselected - request.POST['anomaly_choices'] = ['optical_short'] + request.POST['anomaly_choices'] = ['new_short'] # mock form validity and update functions mocker.patch.object(data_containers.InstrumentAnomalySubmitForm, @@ -260,7 +260,7 @@ def test_get_anomaly_form_post_group(mocker): # post a different selection: others are deselected, # unless they belong only to the file, not to the group # as a whole - request.POST['anomaly_choices'] = ['optical_short'] + request.POST['anomaly_choices'] = ['new_short'] # mock form validity and update functions mocker.patch.object(data_containers.InstrumentAnomalySubmitForm, diff --git a/jwql/utils/constants.py b/jwql/utils/constants.py index 0cc2197a3..631ed8f5a 100644 --- a/jwql/utils/constants.py +++ b/jwql/utils/constants.py @@ -70,39 +70,45 @@ # Dictionary describing instruments to which anomalies apply ANOMALIES_PER_INSTRUMENT = { # anomalies affecting all instruments: - "cosmic_ray_shower": ["fgs", "miri", "nircam", "niriss", "nirspec"], "diffraction_spike": ["fgs", "miri", "nircam", "niriss", "nirspec"], "excessive_saturation": ["fgs", "miri", "nircam", "niriss", "nirspec"], - "guidestar_failure": ["fgs", "miri", "nircam", "niriss", "nirspec"], "persistence": ["fgs", "miri", "nircam", "niriss", "nirspec"], # anomalies affecting multiple instruments: - "crosstalk": ["fgs", "nircam", "niriss", "nirspec"], - "data_transfer_error": ["fgs", "nircam", "niriss", "nirspec"], - "ghost": ["fgs", "nircam", "niriss", "nirspec"], - "snowball": ["fgs", "nircam", "niriss", "nirspec"], + "crosstalk": ["fgs", "nircam", "niriss"], + "data_transfer_error": ["fgs", "nircam", "niriss"], + "ghost": ["fgs", "nircam", "niriss"], + "guidestar_failure": ["fgs", "miri", "nircam", "niriss"], + "unusual_cosmic_rays": ["fgs", "nircam", "niriss", "nirspec"], + "unusual_snowballs": ["fgs", "nircam", "niriss", "nirspec"], # instrument-specific anomalies: + "cosmic_ray_shower": ["miri"], "column_pull_up": ["miri"], "column_pull_down": ["miri"], - "Dominant_MSA_Leakage": ["nirspec"], + "Noticeable_MSA_Leakage": ["nirspec"], "dragons_breath": ["nircam"], "MRS_Glow": ["miri"], "MRS_Zipper": ["miri"], "internal_reflection": ["miri"], - "optical_short": ["nirspec"], # Only for MOS observations + "new_short": ["nirspec"], # Only for MOS observations "row_pull_up": ["miri"], "row_pull_down": ["miri"], "LRS_Contamination": ["miri"], "tree_rings": ["miri"], - "scattered_light": ["niriss", "nircam"], + "scattered_light": ["niriss", "nircam", "nirspec"], "claws": ["nircam"], "wisps": ["nircam"], "tilt_event": ["nircam"], "light_saber": ["niriss"], + "transient_short": ["nirspec"], + "subsequently_masked_short": ["nirspec"], + "monitored_short": ["nirspec"], + "bright_object_not_a_short": ["nirspec"], # additional anomalies: "other": ["fgs", "miri", "nircam", "niriss", "nirspec"], + "needs_discussion": ["fgs", "miri", "nircam", "niriss", "nirspec"], } # anomalies that shouldn't be 'titleized' -special_cases = ["Dominant_MSA_Leakage", "MRS_Glow", "MRS_Zipper", "LRS_Contamination"] +special_cases = ["Noticeable_MSA_Leakage", "MRS_Glow", "MRS_Zipper", "LRS_Contamination"] # Defines the possible anomalies to flag through the web app ANOMALY_CHOICES = [ diff --git a/jwql/website/apps/jwql/admin.py b/jwql/website/apps/jwql/admin.py index f9525cef7..9d20fff5e 100644 --- a/jwql/website/apps/jwql/admin.py +++ b/jwql/website/apps/jwql/admin.py @@ -47,9 +47,15 @@ class RootFileInfoAdmin(admin.ModelAdmin): @admin.register(Anomalies) class AnomaliesAdmin(admin.ModelAdmin): - list_display = ('root_file_info', 'flag_date', 'user', 'cosmic_ray_shower', 'diffraction_spike', 'excessive_saturation', 'guidestar_failure', 'persistence', 'crosstalk', 'data_transfer_error', - 'ghost', 'snowball', 'column_pull_up', 'column_pull_down', 'dominant_msa_leakage', 'dragons_breath', 'mrs_glow', 'mrs_zipper', 'internal_reflection', 'optical_short', 'row_pull_up', - 'row_pull_down', 'lrs_contamination', 'tree_rings', 'scattered_light', 'claws', 'wisps', 'tilt_event', 'light_saber', 'other') - list_filter = ('flag_date', 'user', 'cosmic_ray_shower', 'diffraction_spike', 'excessive_saturation', 'guidestar_failure', 'persistence', 'crosstalk', 'data_transfer_error', - 'ghost', 'snowball', 'column_pull_up', 'column_pull_down', 'dominant_msa_leakage', 'dragons_breath', 'mrs_glow', 'mrs_zipper', 'internal_reflection', 'optical_short', 'row_pull_up', - 'row_pull_down', 'lrs_contamination', 'tree_rings', 'scattered_light', 'claws', 'wisps', 'tilt_event', 'light_saber', 'other', 'root_file_info') + list_display = ('root_file_info', 'flag_date', 'user', 'cosmic_ray_shower', 'unusual_cosmic_rays', 'diffraction_spike', 'excessive_saturation', + 'guidestar_failure', 'persistence', 'crosstalk', 'data_transfer_error', 'ghost', 'unusual_snowballs', 'column_pull_up', + 'column_pull_down', 'noticeable_msa_leakage', 'dragons_breath', 'mrs_glow', 'mrs_zipper', 'internal_reflection', 'new_short', + 'row_pull_up', 'row_pull_down', 'lrs_contamination', 'tree_rings', 'scattered_light', 'claws', 'wisps', 'tilt_event', + 'light_saber', 'other', 'needs_discussion', 'transient_short', 'subsequently_masked_short', 'monitored_short', + 'bright_object_not_a_short') + list_filter = ('flag_date', 'user', 'cosmic_ray_shower', 'unusual_cosmic_rays', 'diffraction_spike', 'excessive_saturation', 'guidestar_failure', + 'persistence', 'crosstalk', 'data_transfer_error', 'ghost', 'unusual_snowballs', 'column_pull_up', 'column_pull_down', + 'noticeable_msa_leakage', 'dragons_breath', 'mrs_glow', 'mrs_zipper', 'internal_reflection', 'new_short', 'row_pull_up', + 'row_pull_down', 'lrs_contamination', 'tree_rings', 'scattered_light', 'claws', 'wisps', 'tilt_event', 'light_saber', 'other', + 'needs_discussion', 'transient_short', 'subsequently_masked_short', 'monitored_short', 'bright_object_not_a_short', + 'root_file_info') diff --git a/jwql/website/apps/jwql/forms.py b/jwql/website/apps/jwql/forms.py index 5b7d7ac49..f9ce45b7b 100644 --- a/jwql/website/apps/jwql/forms.py +++ b/jwql/website/apps/jwql/forms.py @@ -250,6 +250,7 @@ def update_anomaly_table(self, rootfileinfo, user, anomaly_choices): A list of anomalies that are to be flagged (e.g. ``['snowball', 'crosstalk']``) """ + anomaly_choices = list(map(str.lower, anomaly_choices)) default_dict = {'flag_date': datetime.datetime.now(), 'user': user} for anomaly in Anomalies.get_all_anomalies(): diff --git a/jwql/website/apps/jwql/migrations/0011_rename_snowball_anomalies_unusual_snowballs.py b/jwql/website/apps/jwql/migrations/0011_rename_snowball_anomalies_unusual_snowballs.py new file mode 100644 index 000000000..8132ad61f --- /dev/null +++ b/jwql/website/apps/jwql/migrations/0011_rename_snowball_anomalies_unusual_snowballs.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2024-01-12 20:48 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwql', '0010_auto_20230313_1053'), + ] + + operations = [ + migrations.RenameField( + model_name='anomalies', + old_name='snowball', + new_name='unusual_snowballs', + ), + ] diff --git a/jwql/website/apps/jwql/migrations/0012_rename_dominant_msa_leakage_anomalies_noticeable_msa_leakage.py b/jwql/website/apps/jwql/migrations/0012_rename_dominant_msa_leakage_anomalies_noticeable_msa_leakage.py new file mode 100644 index 000000000..f5e22c44e --- /dev/null +++ b/jwql/website/apps/jwql/migrations/0012_rename_dominant_msa_leakage_anomalies_noticeable_msa_leakage.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2024-01-12 20:52 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwql', '0011_rename_snowball_anomalies_unusual_snowballs'), + ] + + operations = [ + migrations.RenameField( + model_name='anomalies', + old_name='dominant_msa_leakage', + new_name='noticeable_msa_leakage', + ), + ] diff --git a/jwql/website/apps/jwql/migrations/0013_rename_optical_short_anomalies_new_short.py b/jwql/website/apps/jwql/migrations/0013_rename_optical_short_anomalies_new_short.py new file mode 100644 index 000000000..ebdb1bdde --- /dev/null +++ b/jwql/website/apps/jwql/migrations/0013_rename_optical_short_anomalies_new_short.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2024-01-12 20:55 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwql', '0012_rename_dominant_msa_leakage_anomalies_noticeable_msa_leakage'), + ] + + operations = [ + migrations.RenameField( + model_name='anomalies', + old_name='optical_short', + new_name='new_short', + ), + ] diff --git a/jwql/website/apps/jwql/migrations/0014_anomalies_unusual_cosmic_rays.py b/jwql/website/apps/jwql/migrations/0014_anomalies_unusual_cosmic_rays.py new file mode 100644 index 000000000..f04e45f70 --- /dev/null +++ b/jwql/website/apps/jwql/migrations/0014_anomalies_unusual_cosmic_rays.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2024-01-12 21:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwql', '0013_rename_optical_short_anomalies_new_short'), + ] + + operations = [ + migrations.AddField( + model_name='anomalies', + name='unusual_cosmic_rays', + field=models.BooleanField(default=False), + ), + ] diff --git a/jwql/website/apps/jwql/migrations/0015_anomalies_needs_discussion.py b/jwql/website/apps/jwql/migrations/0015_anomalies_needs_discussion.py new file mode 100644 index 000000000..57b9dba5b --- /dev/null +++ b/jwql/website/apps/jwql/migrations/0015_anomalies_needs_discussion.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2024-01-17 20:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwql', '0014_anomalies_unusual_cosmic_rays'), + ] + + operations = [ + migrations.AddField( + model_name='anomalies', + name='needs_discussion', + field=models.BooleanField(default=False), + ), + ] diff --git a/jwql/website/apps/jwql/migrations/0016_anomalies_bright_object_not_a_short_and_more.py b/jwql/website/apps/jwql/migrations/0016_anomalies_bright_object_not_a_short_and_more.py new file mode 100644 index 000000000..ec240aaa4 --- /dev/null +++ b/jwql/website/apps/jwql/migrations/0016_anomalies_bright_object_not_a_short_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.1.7 on 2024-01-17 22:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwql', '0015_anomalies_needs_discussion'), + ] + + operations = [ + migrations.AddField( + model_name='anomalies', + name='bright_object_not_a_short', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='anomalies', + name='monitored_short', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='anomalies', + name='subsequently_masked_short', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='anomalies', + name='transient_short', + field=models.BooleanField(default=False), + ), + ] diff --git a/jwql/website/apps/jwql/models.py b/jwql/website/apps/jwql/models.py index 2d39bd340..715b1bb5b 100644 --- a/jwql/website/apps/jwql/models.py +++ b/jwql/website/apps/jwql/models.py @@ -143,15 +143,15 @@ class Anomalies(models.Model): crosstalk = models.BooleanField(default=False) data_transfer_error = models.BooleanField(default=False) ghost = models.BooleanField(default=False) - snowball = models.BooleanField(default=False) + unusual_snowballs = models.BooleanField(default=False) column_pull_up = models.BooleanField(default=False) column_pull_down = models.BooleanField(default=False) - dominant_msa_leakage = models.BooleanField(default=False) + noticeable_msa_leakage = models.BooleanField(default=False) dragons_breath = models.BooleanField(default=False) mrs_glow = models.BooleanField(default=False) mrs_zipper = models.BooleanField(default=False) internal_reflection = models.BooleanField(default=False) - optical_short = models.BooleanField(default=False) + new_short = models.BooleanField(default=False) row_pull_up = models.BooleanField(default=False) row_pull_down = models.BooleanField(default=False) lrs_contamination = models.BooleanField(default=False) @@ -162,6 +162,12 @@ class Anomalies(models.Model): tilt_event = models.BooleanField(default=False) light_saber = models.BooleanField(default=False) other = models.BooleanField(default=False) + unusual_cosmic_rays = models.BooleanField(default=False) + needs_discussion = models.BooleanField(default=False) + transient_short = models.BooleanField(default=False) + subsequently_masked_short = models.BooleanField(default=False) + monitored_short = models.BooleanField(default=False) + bright_object_not_a_short = models.BooleanField(default=False) def get_marked_anomalies(self): """Return all boolean field names (anomalies) currently set""" @@ -170,7 +176,7 @@ def get_marked_anomalies(self): if isinstance(value, bool) and value: true_anomalies.append(field) return true_anomalies - + @classmethod def get_all_anomalies(cls): """Return list of all anomalies (assumed as any field with default of False)"""