diff --git a/benchmarks/forms.py b/benchmarks/forms.py index d6836bcf..7644db76 100644 --- a/benchmarks/forms.py +++ b/benchmarks/forms.py @@ -46,6 +46,15 @@ class Meta: fields = ('zip_file', 'public', 'competition') +class UploadNWBMetadataForm(forms.Form): + json_file = forms.FileField(label="JSON", help_text='Required') + dandiset_file = forms.FileField(label="Optionally, you can also upload your DANDIset directly", required=False) + + class Meta: + model = UploadPlaceHolder + fields = ('json_file', 'dandiset_file') + + class ChangePasswordForm(PasswordChangeForm): def __init__(self, *args, **kwargs): super(ChangePasswordForm, self).__init__(*args, **kwargs) diff --git a/benchmarks/templates/benchmarks/central_profile.html b/benchmarks/templates/benchmarks/central_profile.html index 0e32438d..6bffc55a 100644 --- a/benchmarks/templates/benchmarks/central_profile.html +++ b/benchmarks/templates/benchmarks/central_profile.html @@ -40,6 +40,11 @@

Welcome, {{ user.email }}

{% endfor %} +
+

+ Convert NWB data to a BrainScore data plugin here. +

+
{% else %} diff --git a/benchmarks/templates/benchmarks/convert_nwb.html b/benchmarks/templates/benchmarks/convert_nwb.html new file mode 100644 index 00000000..4f984242 --- /dev/null +++ b/benchmarks/templates/benchmarks/convert_nwb.html @@ -0,0 +1,56 @@ +{% extends "benchmarks/components/app-view.html" %} +{% load static %} + +{% block banner %} +

Convert NWB Data

+

Here you can convert your NWB data to a BrainScore Benchmark!

+{% endblock %} + +{% block info_section %} + {% include "benchmarks/tutorials/tutorial-info-section.html" %} +{% endblock %} + + +{% block content %} + +{% if user %} +
+

To convert, upload a JSON file containing the required NWB metadata.

+
+ +

Feel free to download a reference template JSON file here, + and fill in the required values.

+
+ +
+ {% csrf_token %} + + {% for field in form %} +

+
+ {{ field.label_tag }} +
+ {{ field }} +
+ {% if field.help_text %} + {{ field.help_text }} + {% endif %} + {% for error in field.errors %} +

{{ error }}

+ {% endfor %} +

+ {% endfor %} +

+
+ +
+
+
+ +
+{% else %} +{% endif %} + +{% endblock %} + + diff --git a/benchmarks/urls.py b/benchmarks/urls.py index 6c50f393..a969ed85 100644 --- a/benchmarks/urls.py +++ b/benchmarks/urls.py @@ -43,6 +43,7 @@ path('profile/submit/', user.Upload.as_view(domain="vision"), name=f'vision-submit'), path('profile/resubmit/', partial(user.resubmit, domain="vision"), name='vision-resubmit'), path('profile/logout/', user.Logout.as_view(domain="vision"), name='vision-logout'), + path('profile/nwb/', user.ConvertNWB.as_view(domain="vision"), name=f'convert-nwb'), # central tutorial page, constant across all Brain-Score domains path('tutorials/', user.Tutorials.as_view(tutorial_type="tutorial"), name='tutorial'), diff --git a/benchmarks/views/user.py b/benchmarks/views/user.py index 4e5c5fb1..f318335d 100644 --- a/benchmarks/views/user.py +++ b/benchmarks/views/user.py @@ -17,7 +17,7 @@ from django.utils.encoding import force_bytes, force_str from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.views import View -from benchmarks.forms import SignupForm, LoginForm, UploadFileForm +from benchmarks.forms import SignupForm, LoginForm, UploadFileForm, UploadNWBMetadataForm from benchmarks.models import Model, BenchmarkInstance, BenchmarkType from benchmarks.tokens import account_activation_token from benchmarks.views.index import get_context @@ -234,6 +234,58 @@ def post(self, request): _logger.debug("Job triggered successfully") return render(request, 'benchmarks/success.html', {"domain": self.domain}) +class ConvertNWB(View): + domain = None + + def get(self, request): + assert self.domain is not None + if request.user.is_anonymous: + return HttpResponseRedirect(f'../profile/{self.domain}') + form = UploadNWBMetadataForm() + return render(request, 'benchmarks/convert_nwb.html', + {'form': form, 'domain': self.domain, 'formatted': self.domain.capitalize()}) + + def post(self, request): + assert self.domain is not None + form = UploadNWBMetadataForm(request.POST, request.FILES) + + metadata_json = form.files.get('json_file') + json_data = json.load(metadata_json) + with open('submission.json', 'w') as fp: + json.dump(json_data, fp) + + user_instance = User.objects.get_by_natural_key(request.user.email) + json_info = { + "model_type": request.POST['model_type'] if "model_type" in form.base_fields else "BrainModel", + "user_id": user_instance.id, + "public": str('public' in request.POST), + "domain": self.domain + } + + with open('result.json', 'w') as fp: + json.dump(json_info, fp) + + _logger.debug(request.user.get_full_name()) + _logger.debug(f"request user: {request.user.get_full_name()}") + + # submit to jenkins + jenkins_url = "http://www.brain-score-jenkins.com:8080" + auth = get_secret("brainscore-website_jenkins_access_aws") + auth = (auth['user'], auth['password']) + request_url = f"{jenkins_url}/job/brainscore_nwb_converter/buildWithParameters" \ + f"?TOKEN=trigger2convertNWB" \ + f"&email={request.user.email}" + _logger.debug(f"request_url: {request_url}") + params = {'metadata.json': open('submission.json', 'rb'), 'submission.config': open('result.json', 'rb')} + if 'dandiset_file' in request.FILES: + params['dandiset.zip'] = request.FILES['dandiset_file'] + response = requests.post(request_url, files=params, auth=auth) + _logger.debug(f"response: {response}") + + # update frontend + response.raise_for_status() + _logger.debug("Job triggered successfully") + return render(request, 'benchmarks/success.html', {"domain": self.domain}) def is_submission_original_and_under_plugin_limit(file, submitter: User) -> Tuple[bool, Union[None, List[str]]]: """ diff --git a/static/benchmarks/example_json.json b/static/benchmarks/example_json.json new file mode 100644 index 00000000..dfd5cfa7 --- /dev/null +++ b/static/benchmarks/example_json.json @@ -0,0 +1,16 @@ +{ + "dandiset_id": "Dandiset id, i.e. 000788", + "nwb_file_path": "path to the NWB file within the overall Dandiset, i.e. for a Dandiset structure of 000788/sub-pico/sub-pico_ecephys.nwb, this value should be sub-pico/sub-pico_ecephys.nwb", + "identifier": "identifier for your data, i.e. DataGenerationTrial_emogan", + "assembly": { + "region": ["IT"], + "presentation": 8500, + "neuroid": 18, + "start_time_ms": 0, + "stop_time_ms": 300, + "tb_ms": 10 + }, + "stimulus_set": { + "length": 170 + } +} \ No newline at end of file