Skip to content

Commit 56f3fe3

Browse files
committed
ecotaxa/ecotaxa_front#843: Reconcile individual_biovolume with individual_volume, use formulas from projects during calculations.
1 parent 767d8e2 commit 56f3fe3

File tree

10 files changed

+44
-18
lines changed

10 files changed

+44
-18
lines changed

QA/py/pg_files/upgrade_prod.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ CREATE TABLE projects_variables (
11521152
project_id INTEGER NOT NULL,
11531153
subsample_coef VARCHAR,
11541154
total_water_volume VARCHAR,
1155-
individual_biovolume VARCHAR,
1155+
individual_volume VARCHAR,
11561156
PRIMARY KEY (project_id),
11571157
FOREIGN KEY(project_id) REFERENCES projects (projid)
11581158
);

QA/py/tests/test_export_sci.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from typing import Dict
23

34
from starlette import status
45

@@ -11,19 +12,33 @@
1112
from tests.test_import import DATA_DIR, do_import
1213
from tests.test_jobs import get_job_and_wait_until_ok
1314
from tests.test_objectset_query import _prj_query
15+
from tests.test_update_prj import PROJECT_UPDATE_URL
1416

1517
formulae = {"subsample_coef": "1/ssm.sub_part",
1618
"total_water_volume": "sam.tot_vol", # Volumes are in m3 already for this data
1719
"individual_volume": "4.0/3.0*math.pi*(math.sqrt(obj.area/math.pi)*ssm.pixel)**3"}
1820

1921

20-
def test_export_sci(config, database, fastapi, caplog):
22+
def set_formulae_in_project(fastapi, prj_id: int, prj_formulae: Dict):
23+
from tests.test_project_vars import BODC_VARS_KEY
24+
read_url = PROJECT_QUERY_URL.format(project_id=prj_id, manage=True)
25+
rsp = fastapi.get(read_url, headers=ADMIN_AUTH)
26+
assert rsp.status_code == status.HTTP_200_OK
27+
prj_json = rsp.json()
28+
prj_json[BODC_VARS_KEY] = prj_formulae
29+
upd_url = PROJECT_UPDATE_URL.format(project_id=prj_id)
30+
rsp = fastapi.put(upd_url, headers=ADMIN_AUTH, json=prj_json)
31+
assert rsp.status_code == status.HTTP_200_OK
32+
33+
34+
def test_export_abundances(config, database, fastapi, caplog):
2135
caplog.set_level(logging.FATAL)
2236

2337
# Admin imports the project, which is an export expected result
2438
from tests.test_import import test_import
2539
path = str(DATA_DIR / "ref_exports" / "bak_all_images")
2640
prj_id = test_import(config, database, caplog, "TSV sci export", path=path)
41+
set_formulae_in_project(fastapi, prj_id, formulae) # Note: This is _not_ needed for abundances
2742

2843
# Validate all, otherwise empty report
2944
obj_ids = _prj_query(fastapi, CREATOR_AUTH, prj_id)
@@ -106,6 +121,8 @@ def test_export_conc_biovol(config, database, fastapi, caplog):
106121
prj_id = test_import(config, database, caplog, "SCISUM project")
107122
# Add a sample spanning 2 days
108123
test_import_a_bit_more_skipping(config, database, caplog, "SCISUM project")
124+
# Store computation variables
125+
set_formulae_in_project(fastapi, prj_id, formulae)
109126
# Add some data for calculations
110127
add_concentration_data(fastapi, prj_id)
111128
# Add a sample with weird data in free columns
@@ -129,8 +146,7 @@ def test_export_conc_biovol(config, database, fastapi, caplog):
129146
req = _req_tmpl.copy()
130147
req.update({"project_id": prj_id,
131148
"exp_type": "CNC",
132-
"sum_subtotal": "S",
133-
"formulae": formulae})
149+
"sum_subtotal": "S"})
134150
req_and_filters = {"filters": filters,
135151
"request": req}
136152
rsp = fastapi.post(OBJECT_SET_EXPORT_URL, headers=ADMIN_AUTH, json=req_and_filters)
@@ -144,8 +160,7 @@ def test_export_conc_biovol(config, database, fastapi, caplog):
144160
req = _req_tmpl.copy()
145161
req.update({"project_id": prj_id,
146162
"exp_type": "BIV",
147-
"sum_subtotal": "S",
148-
"formulae": formulae})
163+
"sum_subtotal": "S"})
149164
req_and_filters = {"filters": filters,
150165
"request": req}
151166
rsp = fastapi.post(OBJECT_SET_EXPORT_URL, headers=ADMIN_AUTH, json=req_and_filters)
@@ -163,7 +178,7 @@ def test_export_conc_biovol(config, database, fastapi, caplog):
163178
# log = get_log_file(fastapi, job_id)
164179

165180

166-
def test_export_sci_filtered_by_taxo(config, database, fastapi, caplog):
181+
def test_export_abundances_filtered_by_taxo(config, database, fastapi, caplog):
167182
""" Simulate calls to export with an active filter """
168183
caplog.set_level(logging.FATAL)
169184

@@ -172,6 +187,7 @@ def test_export_sci_filtered_by_taxo(config, database, fastapi, caplog):
172187
from tests.test_import import test_import
173188
path = str(DATA_DIR / "ref_exports" / "bak_all_images")
174189
prj_id = test_import(config, database, caplog, "TSV sci export filtered", path=path)
190+
set_formulae_in_project(fastapi, prj_id, formulae) # Not needed
175191

176192
# Validate all, otherwise empty report
177193
obj_ids = _prj_query(fastapi, CREATOR_AUTH, prj_id)
@@ -198,7 +214,7 @@ def test_export_sci_filtered_by_taxo(config, database, fastapi, caplog):
198214
download_and_check(fastapi, job_id, "abundances_by_sample_filtered_on_cat", only_hdr=True)
199215

200216

201-
def test_export_sci_filtered_by_sample(config, database, fastapi, caplog):
217+
def test_export_abundances_filtered_by_sample(config, database, fastapi, caplog):
202218
""" Simulate calls to export with an active filter """
203219
caplog.set_level(logging.FATAL)
204220

@@ -207,6 +223,7 @@ def test_export_sci_filtered_by_sample(config, database, fastapi, caplog):
207223
from tests.test_import import test_import
208224
path = str(DATA_DIR / "ref_exports" / "bak_all_images")
209225
prj_id = test_import(config, database, caplog, "TSV sci export filtered", path=path)
226+
set_formulae_in_project(fastapi, prj_id, formulae)
210227

211228
# Validate all, otherwise empty report
212229
obj_ids = _prj_query(fastapi, CREATOR_AUTH, prj_id)

QA/py/tests/test_project_vars.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def test_project_vars(config, database, fastapi, caplog):
7171
assert rsp.status_code == status.HTTP_200_OK, rsp.reason + str(rsp.text)
7272
# Good format update with good key but no val
7373
vars["subsample_coef"] = " "
74-
vars["individual_biovolume"] = " "
74+
vars["individual_volume"] = " "
7575
vars["total_water_volume"] = None
7676
rsp = fastapi.put(url, headers=ADMIN_AUTH, json=upd_json)
7777
assert rsp.status_code == status.HTTP_200_OK, rsp.reason + str(rsp.text)

QA/py/tests/test_update_prj.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ def test_update_prj_bodc_vars(config, database, fastapi, caplog):
258258

259259
vars = {"subsample_coef": "1",
260260
"total_water_volume": "2",
261-
"individual_biovolume": "3"}
261+
"individual_volume": "3"}
262262
settings_json[BODC_VARS_KEY] = vars
263263
# Now it should be OK
264264
rsp = fastapi.put(upd_url, headers=ADMIN_AUTH, json=settings_json)

py/API_operations/exports/ForProject.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,12 @@ def create_sci_summary(self, src_project: Project) -> int:
659659
# The specialized SQL builder operates from the object set
660660
aug_qry = ObjectSetQueryPlus(object_set)
661661
aug_qry.remap_categories(req.pre_mapping)
662-
aug_qry.set_formulae(req.formulae)
662+
# Formulae default from the project but are overriden by the query
663+
formulae: Dict[str, str] = {}
664+
if src_project.variables is not None:
665+
formulae.update(src_project.variables.to_dict())
666+
formulae.update(req.formulae)
667+
aug_qry.set_formulae(formulae)
663668
# Set common aliases, not all of them is always used
664669
aug_qry.set_aliases({"sam.orig_id": "sampleid",
665670
"acq.orig_id": "acquisid",

py/BO/Project.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def __init__(self, project: Project):
8989
self.viewers: List[User] = []
9090
self.annotators: List[User] = []
9191
self.managers: List[User] = []
92-
# Formulas AKA variables
92+
# Formulas AKA variables, used to compute BODC quantities
9393
self.bodc_variables: Dict[str, str] = {}
9494

9595
def get_preset(self) -> ClassifIDListT:

py/BO/ProjectVars.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
TYPES_PER_VAR = {
1616
"subsample_coef": (Vocabulary.subsampling_coefficient, Units.dimensionless),
1717
"total_water_volume": (Vocabulary.volume_sampled, Units.cubic_metres),
18-
"individual_biovolume": (Vocabulary.biovolume, Units.cubic_millimetres_per_cubic_metre)
18+
"individual_volume": (Vocabulary.volume_mm3, Units.cubic_millimetres)
1919
}
2020
# ...but below should prevent any de-sync
2121
assert KNOWN_PROJECT_VARS == set(TYPES_PER_VAR.keys())

py/BO/Vocabulary.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class Vocabulary(object):
2929
"http://vocab.nerc.ac.uk/collection/P01/current/CVOLUKNB/")
3030
concentrations: Final = Term("Abundance of biological entity specified elsewhere per unit volume of the water body",
3131
"http://vocab.nerc.ac.uk/collection/P01/current/SDBIOL01/")
32+
volume_mm3: Final = Term("Volume in mm³",
33+
"http://vocab.nerc.ac.uk/collection/P01/current/SDBIOL01/")
3234

3335

3436
class Units(Vocabulary):
@@ -41,3 +43,5 @@ class Units(Vocabulary):
4143
"http://vocab.nerc.ac.uk/collection/P06/current/CMCM/")
4244
number_per_cubic_metre: Final = Term("Number per cubic metre",
4345
"http://vocab.nerc.ac.uk/collection/P06/current/UPMM/")
46+
cubic_millimetres: Final = Term("Cubic millimetres",
47+
"http://vocab.nerc.ac.uk/collection/P06/current/?/")

py/DB/ProjectVariables.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from .helpers.ORM import relationship
1212
from .helpers.Postgres import VARCHAR, INTEGER
1313

14-
KNOWN_PROJECT_VARS = {"subsample_coef", "total_water_volume", "individual_biovolume"}
14+
KNOWN_PROJECT_VARS = {"subsample_coef", "total_water_volume", "individual_volume"}
1515

1616

1717
class ProjectVariables(Model):
@@ -25,15 +25,15 @@ class ProjectVariables(Model):
2525
subsample_coef = Column(VARCHAR)
2626
# Python expression, the calculation result complies to http://vocab.nerc.ac.uk/collection/P01/current/VOLWBSMP/
2727
total_water_volume = Column(VARCHAR)
28-
# Python expression, the calculation result complies to http://vocab.nerc.ac.uk/collection/P01/current/CVOLUKNB/
29-
individual_biovolume = Column(VARCHAR)
28+
# Python expression, the implied unit is mm3
29+
individual_volume = Column(VARCHAR)
3030

3131
# The relationship(s) are created in Relations.py but the typing here helps IDE
3232
project: relationship
3333

3434
def __str__(self):
3535
return "{0}:{1}{2}{3}".format(self.project_id, self.subsample_coef, self.total_water_volume,
36-
self.individual_biovolume)
36+
self.individual_volume)
3737

3838
def load_from_dict(self, vars_dict: Dict[str, Optional[str]]) -> 'ProjectVariables':
3939
""" Load self from a dict with proper keys """

py/cmds/db_upg/versions/521c25353fa0_new_report_tables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def upgrade():
1919
sa.Column('project_id', sa.INTEGER(), nullable=False),
2020
sa.Column('subsample_coef', sa.VARCHAR(), nullable=True),
2121
sa.Column('total_water_volume', sa.VARCHAR(), nullable=True),
22-
sa.Column('individual_biovolume', sa.VARCHAR(), nullable=True),
22+
sa.Column('individual_volume', sa.VARCHAR(), nullable=True),
2323
sa.ForeignKeyConstraint(['project_id'], ['projects.projid'], ),
2424
sa.PrimaryKeyConstraint('project_id')
2525
)

0 commit comments

Comments
 (0)