def monitor_fem_progress(self): """Check fem hardware progress. Busy either: -Initialising from cold (2 fudge frames) -Normal initialisation -Waiting for data collection to complete, either single/multi run """ if (self.fem.hardware_busy): # Still sending data IOLoop.instance().call_later(0.5, self.monitor_fem_progress) return else: # Current collection completed; Do we have all the requested frames? if self.extended_acquisition: if (self.frames_already_acquired < self.number_frames): # Need further bias window(s) IOLoop.instance().add_callback(self.acquisition) return # Issue reset to summed_image command = "config/summed_image/reset_image" request = ApiAdapterRequest(self.file_dir, content_type="application/json") request.body = "{}".format(1) self.adapters["fp"].put(command, request) rc = self.daq.prepare_odin() if not rc: message = "Prepare Odin failed!" self.fem._set_status_error(message) self.status_error = message self.reset_state_variables()
def set_file_writing(self, writing): self.file_writing = writing # send command to Odin Data command = "config/hdf/file/path" request = ApiAdapterRequest(self.file_dir, content_type="application/json") self.adapters["fp"].put(command, request) command = "config/hdf/file/name" request.body = self.file_name self.adapters["fp"].put(command, request) command = "config/hdf/write" request.body = "{}".format(writing) self.adapters["fp"].put(command, request)
def check_fr_status(self): valid_check = True reason = '' # We should have a valid connection to the FR adapter if self._fr_adapter is not None: # Create an inter adapter request req = ApiAdapterRequest(None, accept='application/json') status_dict = self._fr_adapter.get(path='status', request=req).data if 'value' in status_dict: frs = status_dict['value'] for fr in frs: try: frames_dropped = fr['frames']['dropped'] empty_buffers = fr['buffers']['empty'] total_buffers = fr['buffers']['total'] if frames_dropped > 0: valid_check = False reason = "Frames dropped [{}] on at least one FR".format(frames_dropped) pct_free = 0.0 if total_buffers > 0: pct_free = float(empty_buffers) / float(total_buffers) * 100.0 if pct_free < self._fr_pct_buffer_threshold: valid_check = False reason = "There are only {}% free buffers left on at least one FR".format(pct_free) except Exception as ex: valid_check = False reason = "Could not complete FR validity check, exception was thrown: {}".format(str(ex)) else: valid_check = False reason = "No status returned from the FR adapter" else: valid_check = False reason = "No FR adapter has been registered with the FP adapter" return valid_check, reason
def test_iac_adapter_get(self): path = "" request = ApiAdapterRequest(None) response = self.adapter.get(path, request) assert_equal( response.data, {"fake_adapter": "GET method not implemented by FakeAdapter"})
def set_backplane_register(self, register, value): """Sets the value of a resistor on the backplane """ data = {register: {"register": value}} request = ApiAdapterRequest(data) response = self.proxy_adapter.put("backplane", request) if response.status_code != 200: logging.error("BACKPLANE REGISTER SET FAILED: %s", response.data)
def config_odin_data(self, adapter): config = path.join(self.config_dir, self.config_files[adapter]) config = path.expanduser(config) if not config.startswith('/'): config = '/' + config logging.debug(config) request = ApiAdapterRequest(config, content_type="application/json") command = "config/config_file" _ = self.adapters[adapter].put(command, request)
def test_iac_adapter_put(self): path = "" data = {"test": "value"} request = ApiAdapterRequest(data, content_type="application/json") response = self.adapter.put(path, request) assert_equal(response.data, { "fake_adapter": "PUT received by FakeAdapter, data: {}".format(data) })
def test_request_with_types(self): data = '{\'some_json_value\' : 1.234}' content_type = 'application/json' request_type = "application/vnd.odin-native" request = ApiAdapterRequest(data, content_type=content_type, accept=request_type) assert_equal(request.body, data) assert_equal(request.content_type, content_type) assert_equal(request.response_type, request_type) assert_equal(request.headers, { "Content-Type": content_type, "Accept": request_type})
def test_simple_request(self): data = "This is some simple request data" request = ApiAdapterRequest(data) assert_equal(request.body, data) assert_equal(request.content_type, 'application/vnd.odin-native') assert_equal(request.response_type, "application/json") expected_headers = { "Content-Type": 'application/vnd.odin-native', "Accept": "application/json" } assert_equal(request.headers, expected_headers)
def get_od_status(self, adapter): try: request = ApiAdapterRequest(None, content_type="application/json") response = self.adapters[adapter].get("status", request) response = response.data["value"][0] except KeyError: logging.warning("Odin Data Adapter Not Found") response = {"Error": "Adapter {} not found".format(adapter)} finally: return response
def _get_od_status(self, adapter): """Get status from adapter.""" try: request = ApiAdapterRequest(None, content_type="application/json") response = self.adapters[adapter].get("status", request) response = response.data["value"] except KeyError: logging.warning("%s Adapter Not Found" % adapter) response = [{"Error": "Adapter {} not found".format(adapter)}] finally: return response
def test_iac_adapter_get(self, test_iac_dummy_adapter): """ Test that the GET method of the IAC dummy adapter returns the output of the fake adapter's GET method. """ path = "" request = ApiAdapterRequest(None) response = test_iac_dummy_adapter.iac_adapter.get(path, request) assert response.data == { "fake_adapter": "GET method not implemented by FakeAdapter" }
def test_simple_request(self): """Test that a simple request is populated with the correct fields.""" data = "This is some simple request data" request = ApiAdapterRequest(data) assert request.body == data assert request.content_type == 'application/vnd.odin-native' assert request.response_type == "application/json" expected_headers = { "Content-Type": 'application/vnd.odin-native', "Accept": "application/json" } assert request.headers == expected_headers
def cancel_acquisition(self, put_data=None): """Cancel ongoing acquisition in Software. Not yet possible to stop FEM, mid-acquisition """ self.fem.stop_acquisition = True # Inject End of Acquisition Frame command = "config/inject_eoa" request = ApiAdapterRequest("", content_type="application/json") self.adapters["fp"].put(command, request) self.shutdown_processing() self.software_state = "Idle"
def test_iac_adapter_put(self, test_iac_dummy_adapter): """ Test that the PUT method of the IAC dummy adapter returns the output of the fake adapter's PUT method. """ path = "" data = {"test": "value"} request = ApiAdapterRequest(data, content_type="application/json") response = test_iac_dummy_adapter.iac_adapter.put(path, request) assert response.data == { "fake_adapter": "PUT received by FakeAdapter, data: {}".format(data) }
def test_request_with_types(self): """Test that a request with the correct types is correctly populated.""" data = '{\'some_json_value\' : 1.234}' content_type = 'application/json' request_type = "application/vnd.odin-native" request = ApiAdapterRequest(data, content_type=content_type, accept=request_type) assert request.body == data assert request.content_type == content_type assert request.response_type == request_type assert request.headers == { "Content-Type": content_type, "Accept": request_type }
def test_set_content(self): data = '{\'some_json_value\' : 1.234}' content_type = 'application/json' request_type = "application/vnd.odin-native" remote_ip = "127.0.0.1" request = ApiAdapterRequest(data) request.set_content_type(content_type) request.set_response_type(request_type) request.set_remote_ip(remote_ip) assert_equal(request.body, data) assert_equal(request.content_type, content_type) assert_equal(request.response_type, request_type) assert_equal(request.remote_ip, remote_ip) assert_equal(request.headers, { "Content-Type": content_type, "Accept": request_type})
def test_set_content(self): """Test that explicitly setting fields on the request works correctly.""" data = '{\'some_json_value\' : 1.234}' content_type = 'application/json' request_type = "application/vnd.odin-native" remote_ip = "127.0.0.1" request = ApiAdapterRequest(data) request.set_content_type(content_type) request.set_response_type(request_type) request.set_remote_ip(remote_ip) assert request.body == data assert request.content_type == content_type assert request.response_type == request_type assert request.remote_ip == remote_ip assert request.headers == { "Content-Type": content_type, "Accept": request_type }
def get(self, path, request): """Handle a HTTP GET Request Call the get method of each other adapter that is loaded and return the responses in a dictionary. """ logging.debug("IAC Dummy Get") response = {} request = ApiAdapterRequest(None, accept="application/json") for key, value in self.adapters.items(): logging.debug("Calling Get of %s", key) response[key] = value.get(path=path, request=request).data logging.debug("Full response: %s", response) content_type = "application/json" status_code = 200 return ApiAdapterResponse(response, content_type=content_type, status_code=status_code)
def get_fp_config_file(self): try: return_val = None request = ApiAdapterRequest(None) response = self.adapters["file_interface"].get("", request).data self.config_dir = response["config_dir"] for config_file in response["fp_config_files"]: if "qem" in config_file.lower(): return_val = config_file break else: return_val = response["fp_config_files"][0] except KeyError: logging.warning("File Interface Adapter Not Found") finally: self.config_files["fp"] = return_val return return_val
def get(self, path, request): """ Handle an HTTP GET request. This method handles an HTTP GET request, returning a JSON response. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object with the appropriate response """ content_type = "application/json" status_code = 200 response = {} request = ApiAdapterRequest(None, accept="application/json") # Check adapters if path isn't empty # e.g. If asking for /api/0.1/hexitec/fr/status/frames, # path = "fr/status/frames" # Compare: /api/0.1/hexitec/, path = "" checkAdapters = True if len(path) > 0 else False try: if checkAdapters: for name, adapter in self.adapters.items(): if path.startswith(name): tokens = path.split("/") path = "/".join(tokens[1:]) response = adapter.get(path=path, request=request).data logging.debug(response) return ApiAdapterResponse(response, content_type=content_type, status_code=status_code) # No matching adapter found, try Hexitec member: response = self.hexitec.get(path) except ParameterTreeError as e: response = {'error': str(e)} status_code = 400 return ApiAdapterResponse(response, content_type=content_type, status_code=status_code)
def put(self, path, request): """Handle a HTTP PUT request. Calls the put method of each other adapter that has been loaded, and returns the responses in a dictionary. """ logging.debug("IAC DUMMY PUT") body = decode_request_body(request) response = {} request = ApiAdapterRequest(body) for key, value in self.adapters.items(): logging.debug("Calling Put of %s", key) response[key] = value.put(path="", request=request).data content_type = "application/json" status_code = 200 logging.debug(response) return ApiAdapterResponse(response, content_type=content_type, status_code=status_code)
def acquisition(self, put_data=None): """Instruct DAQ and FEM to acquire data.""" # Synchronise first_initialisation status (i.e. collect 2 fudge frames) with FEM if self.first_initialisation: self.first_initialisation = self.fem.first_initialisation else: # Clear (any previous) daq error self.daq.in_error = False if self.extended_acquisition is False: if self.daq.in_progress: logging.warning("Cannot Start Acquistion: Already in progress") self.fem._set_status_error( "Cannot Start Acquistion: Already in progress") return self.total_delay = 0 self.number_frames_to_request = self.number_frames if self.fem.bias_voltage_refresh: # Did the acquisition coincide with bias dead time? if self.bias_blocking_acquisition: IOLoop.instance().call_later(0.1, self.acquisition) return # Work out how many frames can be acquired before next bias refresh time_into_window = time.time() - self.bias_init_time time_available = self.fem.bias_refresh_interval - time_into_window if time_available < 0: IOLoop.instance().call_later(0.09, self.acquisition) return frames_before_bias = self.fem.frame_rate * time_available number_frames_before_bias = int(round(frames_before_bias)) self.number_frames_to_request = self.number_frames - self.frames_already_acquired # Can we obtain all required frames within current bias window? if (number_frames_before_bias < self.number_frames_to_request): # Need >1 bias window to fulfil acquisition self.extended_acquisition = True self.number_frames_to_request = number_frames_before_bias self.total_delay = time_available + self.fem.bias_voltage_settle_time + \ self.fem.time_refresh_voltage_held # # TODO: Remove once Firmware made to reset on each new acquisition # # TODO: WILL BE NON 0 VALUE IN THE FUTURE - TO SUPPORT BIAS REFRESH INTV # # BUT, if nonzero then won't FP's Acquisition time out before processing done????? # # # Reset Reorder plugin's frame_number (to current frame number, for multi-window acquire) command = "config/reorder/frame_number" request = ApiAdapterRequest(self.file_dir, content_type="application/json") request.body = "{}".format(self.frames_already_acquired) self.adapters["fp"].put(command, request) # TODO: To be removed once firmware updated? FP may be slow to process frame_number reset time.sleep(0.5) # Reset histograms, call DAQ's prepare_daq() once per acquisition if self.initial_acquisition: # Issue reset to histogram command = "config/histogram/reset_histograms" request = ApiAdapterRequest(self.file_dir, content_type="application/json") request.body = "{}".format(1) self.adapters["fp"].put(command, request) self.daq_target = time.time() self.daq.prepare_daq(self.number_frames) self.initial_acquisition = False # Acquisition (whether single/multi-run) starts here self.acquisition_in_progress = True # Wait for DAQ (i.e. file writer) to be enabled before FEM told to collect data # IOLoop.instance().call_later(0.1, self.await_daq_ready) IOLoop.instance().add_callback(self.await_daq_ready)