diff --git a/src/InSillyCloWeb/assemblies/admin.py b/src/InSillyCloWeb/assemblies/admin.py index 00babc05bdf75ee4b6a5514a31ce817c8e08277d..8faea5da85085b18408a80aefec6871fb9d76567 100644 --- a/src/InSillyCloWeb/assemblies/admin.py +++ b/src/InSillyCloWeb/assemblies/admin.py @@ -38,6 +38,12 @@ class InputPartAdmin(ViewOnSiteModelAdmin, admin.ModelAdmin): ) +@admin.register(models.SimulatorJob) +class SimulatorJobAdmin(ViewOnSiteModelAdmin, admin.ModelAdmin): + date_hierarchy = 'created_at' + search_fields = ('uuid',) + + @admin.register(models.User) class UserAdmin(auth_admin.UserAdmin): ordering = ("email",) diff --git a/src/InSillyCloWeb/assemblies/models.py b/src/InSillyCloWeb/assemblies/models.py index 46546f89bab49ba8bb483e04c00740245ff7fbd7..ab336f3247bd5a1039e22e61bb9724da83672a40 100644 --- a/src/InSillyCloWeb/assemblies/models.py +++ b/src/InSillyCloWeb/assemblies/models.py @@ -17,11 +17,14 @@ from django.db.models.functions import Upper from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django.conf import settings +from .insillyclo_impl import InSillyCloDjangoMessageObserver import insillyclo.data_source import insillyclo.models import insillyclo.template_generator +import insillyclo +import insillyclo.simulator class UserManager(auth_models.UserManager): @@ -292,11 +295,11 @@ class SimulatorJob(models.Model): # Function and methods ######################################################################### def save(self, *args, **kwargs): - if not self.uuid: - super().save(*args, **kwargs) - if not os.path.isdir(self.job_dir): os.mkdir(self.job_dir) + os.mkdir(self.results_dir) + + super().save(*args, **kwargs) def add_design_to_dir(self, design_file): file_name = os.path.join(self.job_dir, 'design_file.xlsx') @@ -311,7 +314,7 @@ class SimulatorJob(models.Model): with zipfile.ZipFile(gb_file, 'r') as zip: for member in zip.namelist(): - if Path(member).suffix == '.gb': + if Path(member).suffix == '.gb' and not Path(member).stem.startswith('.'): source = zip.open(member) new_filename = os.path.join(self.genbank_dir, Path(member).stem + '.gb') with open(new_filename, 'wb') as dest: @@ -323,10 +326,33 @@ class SimulatorJob(models.Model): with zipfile.ZipFile(db_ip_file, 'r') as zip: for member in zip.namelist(): - source = zip.open(member) - new_filename = os.path.join(self.dbip_dir, Path(member).stem + Path(member).suffix) - with open(new_filename, 'wb') as dest: - shutil.copyfileobj(source, dest) + if not Path(member).stem.startswith('.'): + source = zip.open(member) + new_filename = os.path.join(self.dbip_dir, Path(member).stem + Path(member).suffix) + with open(new_filename, 'wb') as dest: + shutil.copyfileobj(source, dest) + + def run_insillyclo(self, request): + return insillyclo.simulator.compute_all( + observer=InSillyCloDjangoMessageObserver( + request=request, + debug=False, + fail_on_error=False, + ), + input_template_filled=os.path.join(self.job_dir, 'design_file.xlsx'), + input_parts_files=self.db_ip_files, + gb_plasmids=self.genbank_files, + output_dir=Path(self.results_dir), + data_source=insillyclo.data_source.DataSourceHardCodedImplementation(), + ) + + @property + def db_ip_files(self): + return [os.path.join(self.dbip_dir, file) for file in os.listdir(self.dbip_dir)] + + @property + def genbank_files(self): + return [Path(os.path.join(self.genbank_dir, file)) for file in os.listdir(self.genbank_dir)] @property def job_dir(self) -> pathlib.Path: @@ -344,8 +370,9 @@ class SimulatorJob(models.Model): def dbip_dir(self): return os.path.join(self.job_dir, 'db_ip') - def run_simulator(self): - pass + @property + def results_dir(self): + return os.path.join(self.job_dir, 'results') def delete(self, *args, **kwargs): try: diff --git a/src/InSillyCloWeb/assemblies/templates/assemblies/simulator_results.html b/src/InSillyCloWeb/assemblies/templates/assemblies/simulator_results.html new file mode 100644 index 0000000000000000000000000000000000000000..424f371cd0f8b4d1013b1429b15ca3f761941860 --- /dev/null +++ b/src/InSillyCloWeb/assemblies/templates/assemblies/simulator_results.html @@ -0,0 +1,35 @@ +{% extends "base.html" %} +{% load crispy_forms_tags %} +{% load sstatic %} +{% load i18n %} + +{% block extra_js %} +{{block.super}} +{% if extra_js_file %} +<script src="{% sstatic extra_js_file %}"></script> +{% endif%} +{% for extra_js_file in extra_js_files %} +<script src="{% sstatic extra_js_file %}"></script> +{% endfor%} +{% endblock %} + +{% block extra_css %} +{{block.super}} +{% if extra_css_file %} +<link rel="stylesheet" href="{% sstatic extra_css_file %}"/> +{% endif%} +{% for extra_css_file in extra_css_files %} +<link rel="stylesheet" href="{% sstatic extra_css_file %}"/> +{% endfor%} +{% endblock %} + +{% block container_class %}{{block.super}} {{ custom_container_class }}{% endblock %} + +{% block title %}Results{% endblock %} +{% block page_title %}Results{% endblock %} + +{% block content %} +<div class="formset-container col-12 col-xs-12 {%if custom_css_width %}{{custom_css_width}}{%else%}{%if not medium_width%}col-sm-10 col-sm-offset-1 offset-sm-1 col-md-8 col-md-offset-2 offset-md-2 col-lg-6 col-lg-offset-3 offset-lg-3 col-xl-4 col-xl-offset-4 offset-xl-4 col-xxl-2 col-xxl-offset-5{%endif%}{%if medium_width%}col-md-10 col-md-offset-1 offset-md-1 col-lg-8 col-lg-offset-2 offset-lg-2 col-xl-6 col-xl-offset-3 offset-xl-3 col-xxl-4 col-xxl-offset-4 col-xxxl-2 col-xxxl-offset-5{%endif%}{%endif%}"> + {{ simulation.uuid }} +</div> +{% endblock content %} \ No newline at end of file diff --git a/src/InSillyCloWeb/assemblies/views.py b/src/InSillyCloWeb/assemblies/views.py index 641be61ee6032a6ad908c28f75be67a50a09a6a6..7c6ed1998fa60fda94101638a03ee7795cb76962 100644 --- a/src/InSillyCloWeb/assemblies/views.py +++ b/src/InSillyCloWeb/assemblies/views.py @@ -6,7 +6,7 @@ from typing import Tuple import crispy_forms.helper from django.contrib import messages from django.http import HttpResponse -from django.shortcuts import render, redirect +from django.shortcuts import render, redirect, get_object_or_404 from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from django.views.generic import ListView, DetailView, View, DeleteView, UpdateView diff --git a/src/InSillyCloWeb/assemblies/wizard_views.py b/src/InSillyCloWeb/assemblies/wizard_views.py index f0c7d1b3681667495d57e4500dc08cc79ef9e6e7..88ef0daa38d5af1a36851c331c221726ec28ae34 100644 --- a/src/InSillyCloWeb/assemblies/wizard_views.py +++ b/src/InSillyCloWeb/assemblies/wizard_views.py @@ -20,8 +20,8 @@ import os from assemblies import forms, models, mixins from .models import SimulatorJob -from .insillyclo_impl import InSillyCloDjangoMessageObserver from .utils import get_files +from .insillyclo_impl import InSillyCloDjangoMessageObserver class AssemblySimulatorNotProtected(wizard_views.NamedUrlSessionWizardView): @@ -103,38 +103,17 @@ class AssemblySimulatorNotProtected(wizard_views.NamedUrlSessionWizardView): sjob = SimulatorJob.objects.create() sjob.save() - print(sjob.uuid) - - sjob.add_design_to_dir(self.get_cleaned_data_for_step("InputFile")["input_file"]) - - sjob.add_gb_to_dir(self.get_cleaned_data_for_step("Data")["sequence_file"]) - - sjob.add_db_ip_to_dir(self.get_cleaned_data_for_step("Data")["db_ip_files"]) - - """ - results = insillyclo.simulator.compute_all( - observer = InSillyCloDjangoMessageObserver( - request=self.request, - debug=False, - fail_on_error=False, - ), - input_template_filled = input_template, - input_parts_files = db_ip_files, - gb_plasmids = gb_files, - output_dir = pathlib.Path(output_directory), - data_source = insillyclo.data_source.DataSourceHardCodedImplementation(), + sjob.add_design_to_dir( + self.get_cleaned_data_for_step("InputFile")["input_file"], ) - - print(results) - """ - - return render( - self.request, - 'simple_message_page.html', - context=dict( - sub_message="test results", - ), + sjob.add_gb_to_dir( + self.get_cleaned_data_for_step("Data")["sequence_file"], ) + sjob.add_db_ip_to_dir( + self.get_cleaned_data_for_step("Data")["db_ip_files"], + ) + + return redirect('assemblies:simulator-results', uuid=sjob.uuid) class AssemblyDesignerNotProtected(wizard_views.NamedUrlSessionWizardView):