diff --git a/LCU/Maintenance/DBInterface/monitoringdb/models/rtsm.py b/LCU/Maintenance/DBInterface/monitoringdb/models/rtsm.py index b82a31324371eb25a69b821b219c1f72c83ffdb9..cfcaef773e79bc0de642704af10f495e2121788c 100644 --- a/LCU/Maintenance/DBInterface/monitoringdb/models/rtsm.py +++ b/LCU/Maintenance/DBInterface/monitoringdb/models/rtsm.py @@ -7,7 +7,7 @@ from .station import Station from .fixed_types import STATION_TYPES -MODE_TO_COMPONENT = { +MODE_TO_COMPONENT = { 1: 'LBL', 2: 'LBL', 3: 'LBH', @@ -17,6 +17,11 @@ MODE_TO_COMPONENT = { 7: 'HBA' } +COMPONENT_TO_MODE = { + 'LBL': [1, 2], + 'LBH': [3, 4], + 'HBA': [5, 6, 7] +} class RTSMObservation(models.Model): observation_id = models.PositiveIntegerField(default=0) diff --git a/LCU/Maintenance/DBInterface/monitoringdb/urls.py b/LCU/Maintenance/DBInterface/monitoringdb/urls.py index 31bd3275b091b1eefb3c17a1de49de95a23ee646..51e3c6f0495fbd0889f6e03a2522d927036016dc 100644 --- a/LCU/Maintenance/DBInterface/monitoringdb/urls.py +++ b/LCU/Maintenance/DBInterface/monitoringdb/urls.py @@ -43,6 +43,6 @@ urlpatterns = [ url(r'^api/view/ctrl_stationtest_statistics', ControllerStationTestStatistics.as_view()), url(r'^api/view/ctrl_list_component_error_types', ControllerAllComponentErrorTypes.as_view()), url(r'^api/view/ctrl_station_component_errors', ControllerStationComponentErrors.as_view()), - + url(r'^api/view/ctrl_station_component_element_errors', ControllerStationComponentElementErrors.as_view()), url(r'^api/docs', include_docs_urls(title='Monitoring DB API')) ] diff --git a/LCU/Maintenance/DBInterface/monitoringdb/views/controllers.py b/LCU/Maintenance/DBInterface/monitoringdb/views/controllers.py index dc4b0bd734fac16b8fcf1a00e566c7b1e89fe42a..578282f44c35e2799b95ef184b973337da879f66 100644 --- a/LCU/Maintenance/DBInterface/monitoringdb/views/controllers.py +++ b/LCU/Maintenance/DBInterface/monitoringdb/views/controllers.py @@ -7,7 +7,7 @@ import coreapi import coreschema from django.db.models import Count from lofar.maintenance.monitoringdb.models.component_error import ComponentError -from lofar.maintenance.monitoringdb.models.rtsm import RTSMErrorSummary, MODE_TO_COMPONENT +from lofar.maintenance.monitoringdb.models.rtsm import RTSMErrorSummary, MODE_TO_COMPONENT, COMPONENT_TO_MODE from lofar.maintenance.monitoringdb.models.rtsm import RTSMObservation from lofar.maintenance.monitoringdb.models.station import Station from lofar.maintenance.monitoringdb.models.station_test import StationTest @@ -92,7 +92,7 @@ class ValidableReadOnlyView(APIView): self.__setattr__(field.name, value) errors = field.schema.validate(self.__getattribute__(field.name)) for error in errors: - raise ValueError(error.text) + raise ValueError(" ".join([field.name, error.text])) def get(self, request): try: @@ -881,7 +881,6 @@ class ControllerStationComponentErrors(ValidableReadOnlyView): component_errors_dict[str(component_id)] = list() component_errors_dict[str(component_id)] += [dict(error_type=error_type, details=details)] - #self.decorate_component_errors_with_url(component_errors_dict, rtsm_observation.observation_id, rtsm_observation.start_datetime, MODE_TO_COMPONENT[observing_mode]) return response_payload def compute_response(self): @@ -904,4 +903,196 @@ class ControllerStationComponentErrors(ValidableReadOnlyView): payload[component_type] = sorted(station_test_errors_per_type + rtsm_errors_per_type, key=lambda item: item['start_date'], reverse=True) - return Response(status=status.HTTP_200_OK, data=payload) \ No newline at end of file + return Response(status=status.HTTP_200_OK, data=payload) + + +class ControllerStationComponentElementErrors(ValidableReadOnlyView): + station_name= None # required + from_date= None # required + to_date= None # required + component_type= None # required + antenna_id= None # required + test_type= "A" + + fields = [ + coreapi.Field( + 'station_name', + required=True, + location='query', + schema=coreschema.String(description='name of the station to select') + ), + coreapi.Field( + 'from_date', + required=True, + location='query', + schema=coreschema.String(description='select tests from date (ex. YYYY-MM-DD)') + ), + coreapi.Field( + 'to_date', + required=True, + location='query', + schema=coreschema.String(description='select tests from date (ex. YYYY-MM-DD)') + ), + coreapi.Field( + 'component_type', + required=True, + location='query', + schema=coreschema.Enum( + ['HBA', 'LBH', 'LBL'], + description='select the antenna type. Possible values are (HBA, LBH, LBL)' + ) + ), + coreapi.Field( + 'antenna_id', + required=True, + location='query', + type=int, + schema=coreschema.Integer(description='Select the antenna id') + ), + coreapi.Field( + 'test_type', + required=False, + location='query', + schema=coreschema.Enum( + ['R', 'S', 'A'], + description='select the type of test possible values are (R, RTSM),' + ' (S, Station test), (A, all)[DEFAULT=A]', + ) + ) + ] + + def rcu_from_antenna_type_polarization(self, antenna_id, type, polarization): + """ + Compute the rcu number for a given antenna number, type and polarization + :param antenna_id: id of the antenna + :param type: type of the antenna + :param polarization: polarization either [X, Y] + :return: the rcu id + :rtype: int + """ + if polarization not in ['X', 'Y']: + raise ValueError('Polarization has to be either X or Y: %s not recognized' % polarization) + + if type == 'LBH': + rcu_id = antenna_id * 2 + rcu_id += 1 if polarization == 'X' else 0 + elif type == 'LBL': + rcu_id = (antenna_id - 48) * 2 + rcu_id += 0 if polarization == 'X' else 1 + elif type == 'HBA': + rcu_id = antenna_id + rcu_id += 1 if polarization == 'X' else 0 + else: + rcu_id = -1 + return rcu_id + + def rcus_from_antenna_and_type(self, antenna_id, type): + rcu_x = self.rcu_from_antenna_type_polarization(antenna_id, type, 'X') + rcu_y = self.rcu_from_antenna_type_polarization(antenna_id, type, 'Y') + + rcus={rcu_x:'X', rcu_y:'Y'} + return rcus + + def compute_rtsm_errors_list(self): + errors = dict() + rcus_per_polarization = self.rcus_from_antenna_and_type(self.antenna_id, + self.component_type) + + rtsm_errors = RTSMErrorSummary.objects.values('observation__pk', + 'observation__start_datetime', + 'observation__end_datetime', + 'observation__observation_id', + 'observation__station__name', + 'rcu', + 'mode', + 'error_type', + 'percentage', + 'count', + 'observation__samples').filter( + observation__start_datetime__gt=self.from_date, + observation__end_datetime__lt=self.to_date, + observation__station__name=self.station_name, + mode__in=COMPONENT_TO_MODE[self.component_type], + rcu__in=list(rcus_per_polarization.keys())).order_by('-observation__start_datetime') + for item in rtsm_errors: + observation_pk = item['observation__pk'] + if observation_pk not in errors.keys(): + errors[observation_pk] = dict(test_id=item['observation__observation_id'], + db_id=item['observation__pk'], + start_date=item[ + 'observation__start_datetime'], + end_date=item[ + 'observation__end_datetime'], + test_type='R', + component_errors=dict()) + rcu = item['rcu'] + polarization = rcus_per_polarization[rcu] + if polarization not in errors[observation_pk]: + errors[observation_pk]['component_errors'][polarization] = dict( + rcu=rcu, + errors = dict(), + element_errors = dict() + ) + error_type = item['error_type'] + percentage = item['percentage'] + count = item['count'] + mode = item['mode'] + samples = item['observation__samples'] + errors[observation_pk]['component_errors'][polarization]['errors'][error_type] = dict(samples=samples, + percentage=percentage, + count=count, + mode=mode, + url='empty') + return list(errors.values()) + + def compute_station_tests_error_list(self): + errors = dict() + rcus_per_polarization = self.rcus_from_antenna_and_type(self.antenna_id, + self.component_type) + component_errors = ComponentError.objects.filter( + station_test__start_datetime__gt=self.from_date, + station_test__end_datetime__lt=self.to_date, + station_test__station__name=self.station_name, + component__type=self.component_type, + component__component_id__in=list(rcus_per_polarization.keys())).order_by('-station_test__start_datetime') + for component_error in component_errors: + station_test_pk = component_error.station_test.pk + if station_test_pk not in errors.keys(): + errors[station_test_pk] = dict(test_id=station_test_pk, + db_id=station_test_pk, + start_date=component_error.station_test.start_datetime, + end_date=component_error.station_test.end_datetime, + test_type='S', + component_errors=dict()) + component_id = component_error.component.component_id + polarization = rcus_per_polarization[component_id] + if polarization not in errors[station_test_pk]: + errors[station_test_pk]['component_errors'][polarization] = dict( + rcu=component_id, + errors=dict()) + error_type = component_error.type + details = component_error.details + errors_per_error_polarization = errors[station_test_pk]['component_errors'][polarization]['errors'] + errors_per_error_polarization[error_type] = dict(details=details, element_errors=dict()) + + + for element in component_error.failing_elements.values('element__element_id', 'details'): + element_id = element['element__element_id'] + errors_per_error_polarization[error_type]['element_errors'][element_id] = element['details'] + + return list(errors.values()) + + def compute_response(self): + self.from_date = parse_date(self.from_date) + self.to_date = parse_date(self.to_date) + rtsm_errors_list = [] + station_test_list = [] + + if self.test_type == 'R' or self.test_type == 'A': + rtsm_errors_list = self.compute_rtsm_errors_list() + if self.test_type == 'S' or self.test_type == 'A': + station_test_list = self.compute_station_tests_error_list() + + combined = rtsm_errors_list + station_test_list + combined_and_sorted = sorted(combined, key=lambda test: test['start_date'], reverse=True) + return Response(status=status.HTTP_200_OK, data=dict(errors=combined_and_sorted)) \ No newline at end of file