Skip to content

Commit

Permalink
Fixed encoding and launch page issues
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphaelRobidas committed Nov 11, 2023
1 parent 40fa05c commit be85d90
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Cloud_dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ENV CALCUS_CLOUD True

ADD ./cloud_requirements.txt /calcus/cloud_requirements.txt
RUN pip install -r /calcus/cloud_requirements.txt
RUN apt update && apt install openbabel postgresql-client dos2unix nwchem libxm4 libgl1 -y
RUN apt update && apt install openbabel postgresql-client dos2unix nwchem libxm4 libgl1 libmagic1 -y

COPY calcus /calcus/calcus
COPY frontend /calcus/frontend
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"/binaries/orca"
ENV PATH=$PATH:$XTB4STDAHOME/xtb/bin:$XTB4STDAHOME:$EBROOTORCA:$GAUSS_EXEDIR
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/binaries/orca:/usr/lib/openmpi/

RUN apt update && apt install openbabel sshpass postgresql-client dos2unix python3-dev gfortran mpi-default-bin mpi-default-dev libxm4 libgl1 -y
RUN apt update && apt install openbabel sshpass postgresql-client dos2unix python3-dev gfortran mpi-default-bin mpi-default-dev libxm4 libgl1 libmagic1 -y
RUN curl -LJO https://github.com/nwchemgit/nwchem/releases/download/v7.2.0-release/nwchem-data_7.2.0-2_all.debian_bullseye.deb
RUN curl -LJO https://github.com/nwchemgit/nwchem/releases/download/v7.2.0-release/nwchem_7.2.0-2_amd64.debian_bullseye.deb
RUN dpkg -i nwchem*7.2.0*.deb
Expand Down
1 change: 1 addition & 0 deletions cloud_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ periodictable
psutil==5.7.2
psycopg2
pysisyphus
python-magic
rdkit
requests
scipy
Expand Down
39 changes: 19 additions & 20 deletions frontend/management/commands/init_static_obj.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,25 +211,24 @@ def handle(self, *args, **options):
title=title, page_path="nmr_prediction_quick.html"
)

if not settings.IS_TEST:
if self.is_absent_property("mo"):
molden = get_showcase("mo_molden")
mo_diagram = get_showcase("mo_diagram")
prop = ShowcaseProperty.objects.create(
name="mo", molden=molden, mo_diagram=mo_diagram
)
if self.is_absent_property("mo"):
molden = get_showcase("mo_molden")
mo_diagram = get_showcase("mo_diagram")
prop = ShowcaseProperty.objects.create(
name="mo", molden=molden, mo_diagram=mo_diagram
)

if self.is_absent_ensemble("acetylsalicylic_acid"):
e = ShowcaseEnsemble.objects.create(label="acetylsalicylic_acid")
params = Parameters.objects.create(charge=0, multiplicity=1)
multixyz, E = parse_multixyz_from_file(
os.path.join(showcase_dir, "Acetylsalicylic_Acid.xyz")
if self.is_absent_ensemble("acetylsalicylic_acid"):
e = ShowcaseEnsemble.objects.create(label="acetylsalicylic_acid")
params = Parameters.objects.create(charge=0, multiplicity=1)
multixyz, E = parse_multixyz_from_file(
os.path.join(showcase_dir, "Acetylsalicylic_Acid.xyz")
)
for ind, (xyz, ener) in enumerate(zip(multixyz, E)):
_xyz = format_xyz(xyz)
s = Structure.objects.create(
parent_ensemble=e, xyz_structure=_xyz, number=ind + 1
)
prop = ShowcaseProperty.objects.create(
energy=ener, parent_structure=s, parameters=params
)
for ind, (xyz, ener) in enumerate(zip(multixyz, E)):
_xyz = format_xyz(xyz)
s = Structure.objects.create(
parent_ensemble=e, xyz_structure=_xyz, number=ind + 1
)
prop = ShowcaseProperty.objects.create(
energy=ener, parent_structure=s, parameters=params
)
112 changes: 110 additions & 2 deletions frontend/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,8 @@ def setUp(self):
self.client.force_login(self.user)

def test_single_file(self):
with open(os.path.join(tests_dir, "Cl.xyz")) as f:
xyz = bytes(f.read(), "UTF-8")
with open(os.path.join(tests_dir, "Cl.xyz"), "rb") as f:
xyz = f.read()

f = SimpleUploadedFile("Cl.xyz", xyz, content_type="chemical/x-xyz")

Expand All @@ -645,6 +645,48 @@ def test_single_file(self):
self.assertEqual(Molecule.objects.count(), 1)
self.assertEqual(Ensemble.objects.count(), 1)

def test_iso_8859_1(self):
with open(os.path.join(tests_dir, "ethanol_iso-8859-1.xyz"), "rb") as f:
xyz = f.read()

f = SimpleUploadedFile("ethanol.xyz", xyz, content_type="chemical/x-xyz")

params = basic_params.copy()
params["structure"] = ""
params["calc_charge"] = "0"
params["file_structure"] = [f]
params["calc_combine_files"] = ("",)
params["calc_parse_filenames"] = ""

response = self.client.post("/submit_calculation/", data=params, follow=True)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, "Error while submitting your calculation")

self.assertEqual(CalculationOrder.objects.count(), 1)
self.assertEqual(Molecule.objects.count(), 1)
self.assertEqual(Ensemble.objects.count(), 1)

def test_utf_16(self):
with open(os.path.join(tests_dir, "ethanol_utf-16.xyz"), "rb") as f:
xyz = f.read()

f = SimpleUploadedFile("ethanol.xyz", xyz, content_type="chemical/x-xyz")

params = basic_params.copy()
params["structure"] = ""
params["calc_charge"] = "0"
params["file_structure"] = [f]
params["calc_combine_files"] = ("",)
params["calc_parse_filenames"] = ""

response = self.client.post("/submit_calculation/", data=params, follow=True)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, "Error while submitting your calculation")

self.assertEqual(CalculationOrder.objects.count(), 1)
self.assertEqual(Molecule.objects.count(), 1)
self.assertEqual(Ensemble.objects.count(), 1)

def test_parse_charge_no_filename(self):
with open(os.path.join(tests_dir, "Cl.xyz")) as f:
xyz = bytes(f.read(), "UTF-8")
Expand Down Expand Up @@ -2008,3 +2050,69 @@ def test_refill_busted(self):
self.assertEqual(
self.user.allocated_seconds, settings.FREE_DEFAULT_COMP_SECONDS + 100
)


class LaunchPageTests(TestCase):
def setUp(self):
call_command("init_static_obj")
self.email = "Tester@test.com"
self.password = "test1234"

self.user = User.objects.create_superuser(
email=self.email,
password=self.password,
)
self.proj = Project.objects.create(author=self.user)
self.group = ResearchGroup.objects.create(name="Test group", PI=self.user)
self.client = Client()
self.client.force_login(self.user)

def test_basic(self):
response = self.client.get("/launch/")
self.assertEqual(response.status_code, 200)

def test_ensemble_does_not_exist(self):
response = self.client.post("/launch/", data={"ensemble": 2})
self.assertEqual(response.status_code, 302)

def test_ensemble_no_structure(self):
mol = Molecule.objects.create(project=self.proj)
e = Ensemble.objects.create(parent_molecule=mol)
response = self.client.post("/launch/", data={"ensemble": e.id})
self.assertEqual(response.status_code, 200)

def test_ensemble_no_prop(self):
mol = Molecule.objects.create(project=self.proj)
e = Ensemble.objects.create(parent_molecule=mol)
struct = Structure.objects.create(parent_ensemble=e, number=1)
response = self.client.post("/launch/", data={"ensemble": e.id})
self.assertEqual(response.status_code, 200)

def test_ensemble_prop(self):
mol = Molecule.objects.create(project=self.proj)
e = Ensemble.objects.create(parent_molecule=mol)
struct = Structure.objects.create(parent_ensemble=e, number=1)
prop = Property.objects.create(parent_structure=struct)
response = self.client.post("/launch/", data={"ensemble": e.id})
self.assertEqual(response.status_code, 200)

def test_ensemble_structure_with_prop(self):
mol = Molecule.objects.create(project=self.proj)
e = Ensemble.objects.create(parent_molecule=mol)
struct = Structure.objects.create(parent_ensemble=e, number=1)
prop = Property.objects.create(parent_structure=struct)

response = self.client.post(
"/launch/", data={"ensemble": e.id, "structures": [1]}
)
self.assertEqual(response.status_code, 200)

def test_ensemble_structure_without_prop(self):
mol = Molecule.objects.create(project=self.proj)
e = Ensemble.objects.create(parent_molecule=mol)
struct = Structure.objects.create(parent_ensemble=e, number=1)

response = self.client.post(
"/launch/", data={"ensemble": e.id, "structures": [1]}
)
self.assertEqual(response.status_code, 200)
11 changes: 11 additions & 0 deletions frontend/tests/ethanol_iso-8859-1.xyz
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
9
Title
C -1.31970 -0.64380 0.00000
H -0.96310 -1.65260 0.00000
H -0.96310 -0.13940 -0.87370
H -2.38970 -0.64380 0.00000
C -0.80640 0.08220 1.25740
H -1.16150 1.09160 1.25640
H -1.16470 -0.42110 2.13110
O 0.62360 0.07990 1.25870
H 0.94410 0.53240 2.04240
Binary file added frontend/tests/ethanol_utf-16.xyz
Binary file not shown.
29 changes: 21 additions & 8 deletions frontend/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import base64, gzip
import copy
import itertools
import magic

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
Expand Down Expand Up @@ -1620,7 +1621,13 @@ def set_project_default(request):


def handle_file_upload(ff, is_local, verify=False):
in_file = clean(ff.read().decode("utf-8"))
blob = ff.read()

m = magic.open(magic.MAGIC_MIME_ENCODING)
m.load()
encoding = m.buffer(blob)

in_file = clean(blob.decode(encoding))
fname = clean(ff.name)
filename = ".".join(fname.split(".")[:-1])
ext = fname.split(".")[-1]
Expand Down Expand Up @@ -4549,9 +4556,11 @@ def launch(request):
params["interface"] = "simple"

if "ensemble" in request.POST.keys():
e_id = clean(request.POST["ensemble"])
try:
e = Ensemble.objects.get(pk=clean(request.POST["ensemble"]))
e = Ensemble.objects.get(pk=e_id)
except Ensemble.DoesNotExist:
logger.info(f"Ensemble with id {e_id} requested, but not found")
return redirect("/")

if not can_view_ensemble(e, request.user):
Expand Down Expand Up @@ -4585,16 +4594,20 @@ def launch(request):
if s_num not in avail_nums:
return HttpResponse(status=404)

# TODO: catch possible edge cases
init_params = struct.properties.all()[0].parameters
if struct.properties.count() > 0:
init_params = struct.properties.first().parameters
if init_params is not None:
params["init_params_id"] = init_params.id

params["structures"] = s_str
params["structure"] = struct
params["init_params_id"] = init_params.id
else:
init_params = e.structure_set.all()[0].properties.all()[0].parameters

params["init_params_id"] = init_params.id
if e.structure_set.count() > 0:
example_struct = e.structure_set.first()
if example_struct.properties.count() > 0:
init_params = example_struct.properties.first().parameters
if init_params is not None:
params["init_params_id"] = init_params.id
elif "calc_id" in request.POST.keys():
calc_id = clean(request.POST["calc_id"])

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pre-commit
psutil==5.7.2
psycopg2
pysisyphus
python-magic
rdkit
requests
scipy
Expand Down

0 comments on commit be85d90

Please sign in to comment.