Skip to content

Commit

Permalink
refactor: get bsyncr config from analysis config
Browse files Browse the repository at this point in the history
  • Loading branch information
macintoshpie committed Jan 13, 2021
1 parent 343bd86 commit e8ef8d1
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 13 deletions.
47 changes: 42 additions & 5 deletions seed/analysis_pipelines/bsyncr.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,36 @@

logger = logging.getLogger(__name__)

# map for translating SEED's model names into bsyncr's model names
# used for communicating with bsyncr service
BSYNCR_MODEL_TYPE_MAP = {
'Simple Linear Regression': 'SLR',
'Three Parameter Linear Model Cooling': '3PC',
'Three Parameter Linear Model Heating': '3PH',
'Four Parameter Linear Model': '4P',
}


def _validate_bsyncr_config(analysis):
"""Performs basic validation of the analysis for running bsyncr. Returns any
errors
:param analysis: Analysis
:returns: list[str], list of validation error messages
"""
config = analysis.configuration
if not isinstance(config, dict):
return ['Analysis configuration must be a dictionary/JSON']

if 'model_type' not in config:
return ['Analysis configuration missing required property "model_type"']

model_type = config['model_type']
if model_type not in BSYNCR_MODEL_TYPE_MAP:
return [f'Analysis configuration.model_type "{model_type}" is invalid. '
f'Must be one of the following: {", ".join(BSYNCR_MODEL_TYPE_MAP.keys())}']

return []

class BsyncrPipeline(AnalysisPipeline):
"""
Expand All @@ -58,6 +88,10 @@ def _prepare_analysis(self, analysis_id, property_view_ids):
self.fail(message, logger)
raise AnalysisPipelineException(message)

validation_errors = _validate_bsyncr_config(Analysis.objects.get(id=self._analysis_id))
if validation_errors:
raise AnalysisPipelineException(f'Unexpected error(s) while validating analysis configuration: {"; ".join(validation_errors)}')

progress_data = ProgressData('prepare-analysis-bsyncr', analysis_id)

# Steps:
Expand Down Expand Up @@ -317,10 +351,11 @@ def _start_analysis(self, analysis_id, progress_data_key):
progress_data = ProgressData.from_key(progress_data_key)
progress_data.step('Sending requests to bsyncr service')

bsyncr_model_type = BSYNCR_MODEL_TYPE_MAP[analysis.configuration['model_type']]
output_xml_file_ids = []
for input_file in analysis.input_files.all():
analysis_property_view_id = _parse_analysis_property_view_id(input_file.file.path)
results_dir, errors = _run_bsyncr_analysis(input_file.file)
results_dir, errors = _run_bsyncr_analysis(input_file.file, bsyncr_model_type)

if errors:
for error in errors:
Expand Down Expand Up @@ -435,10 +470,11 @@ def elem2dict(node):
return {'models': parsed_models}


def _bsyncr_service_request(file_):
def _bsyncr_service_request(file_, model_type):
"""Makes request to bsyncr service using the provided file
:param file_: File
:param model_type: str
:returns: requests.Response
"""
files = [
Expand All @@ -449,22 +485,23 @@ def _bsyncr_service_request(file_):
method='POST',
url=f'http://{settings.BSYNCR_SERVER_HOST}:{settings.BSYNCR_SERVER_PORT}/',
files=files,
params={'model_type': 'SLR'},
params={'model_type': model_type},
timeout=60 * 2, # timeout after two minutes
)


def _run_bsyncr_analysis(file_):
def _run_bsyncr_analysis(file_, model_type):
"""Runs the bsyncr analysis by making a request to a bsyncr server with the
provided file. Returns a tuple, an object representing a temporary directory
created with tempfile.TemporaryDirectory which contains the files returned by bsyncr
followed by a list of error messages.
:param file_: File
:param model_type: str
:returns: tuple, (object, list[str])
"""
try:
response = _bsyncr_service_request(file_)
response = _bsyncr_service_request(file_, model_type)
except requests.exceptions.Timeout:
return None, ['Request to bsyncr server timed out.']
except Exception as e:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ angular.module('BE.seed.controller.inventory_detail_analyses_modal', [])
inventory_ids,
) {
$scope.bsyncr_models = [
{model_type:'Simple Linear Regression'},
{model_type:'Three Parameter Linear Model Cooling'},
{model_type:'Three Parameter Linear Model Heating'},
{model_type:'Four Parameter Linear Model'},
{model_type:'Five Parameter Linear Model'}
{model_type: 'Simple Linear Regression'},
{model_type: 'Three Parameter Linear Model Cooling'},
{model_type: 'Three Parameter Linear Model Heating'},
{model_type: 'Four Parameter Linear Model'}
];

function initialize_new_analysis () {
Expand Down
9 changes: 7 additions & 2 deletions seed/tests/test_analysis_pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,8 @@ def setUp(self):
FakeAnalysisFactory(organization=self.org, user=self.user)
.get_analysis(
name='Good Analysis',
service=Analysis.BSYNCR
service=Analysis.BSYNCR,
configuration={'model_type': 'Simple Linear Regression'}
)
)

Expand Down Expand Up @@ -573,8 +574,12 @@ def _build_bsyncr_output(file_):
result.seek(0)
return result

def _mock_request(file_):
def _mock_request(file_, model_type):
# mock the call to _bsyncr_service_request by returning a constructed Response

# ignore model_type
_ = model_type

the_response = Response()
if error_messages is not None:
the_response.status_code = 400
Expand Down
4 changes: 3 additions & 1 deletion seed/tests/test_analysis_property_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ def setUp(self):
cycle_b = FakeCycleFactory(organization=self.org_b, user=self.user).get_cycle(name="Cycle Org B")

self.analysis_a = (
FakeAnalysisFactory(organization=self.org_a, user=self.user).get_analysis(
FakeAnalysisFactory(organization=self.org_a, user=self.user)
.get_analysis(
name='Quite neat',
service=Analysis.BSYNCR,
configuration={'model_type': 'Simple Linear Regression'}
)
)

Expand Down

0 comments on commit e8ef8d1

Please sign in to comment.