def main(): arguments = docopt.docopt(__doc__) logger.info(arguments) context = zmq.Context() metadata = json.loads(arguments['--metadata']) url = arguments['<url>'] if arguments['--request'] == 'SUB': sub = context.socket(zmq.SUB) sub.connect(url) sub.setsockopt(zmq.SUBSCRIBE, '') while True: arr, metadata = recv_array(sub) logger.info("metadata: %s\n array: %s", metadata, arr) elif arguments['--request'] == 'REQ': req = context.socket(zmq.REQ) req.connect(url) value = None send_array(req, value, metadata=metadata) # wait for reply arr, metadata = recv_array(req) logger.info("metadata: %s\n array: %s", metadata, arr) elif arguments['--request'] == 'PUSH': req = context.socket(zmq.PUSH) req.connect(url) value = None send_array(req, value, metadata=metadata) logger.info("metadata: %s", metadata)
def process_incoming(subgrid, poller, rep, pull, data): """ process incoming messages data is a dict with several arrays """ # Check for new messages items = poller.poll(100) for sock, n in items: for i in range(n): A, metadata = recv_array(sock) logger.info("got metadata: %s", metadata) if metadata.get("action") == "send grid": logger.info("sending grid") # temporary implementation sock.send_pyobj(data) elif "action" in metadata: logger.info("found action applying update") # TODO: support same operators as MPI_ops here...., # TODO: reduce before apply action = metadata['action'] arr = subgrid.get_nd(metadata['name'], sliced=True) S = tuple(slice(*x) for x in action['slice']) print(repr(arr[S])) if action['operator'] == 'setitem': arr[S] = data elif action['operator'] == 'add': arr[S] += data else: logger.warn("got message from unknown socket {}".format(sock)) else: logger.info("No incoming data")
def test_missing_scalar(arr, req, rep): """send an array with missing data as a scalar""" arr_masked = np.ma.masked_less(arr, 2) # test if it works if we use a numpy scalar arr_masked.fill_value = np.int32(9999) mmi.send_array(req, arr_masked) received, metadata = mmi.recv_array(rep) numpy.testing.assert_array_equal(arr_masked, received)
def test_metadata_only(self): """send a message with only metadata""" req = ctx.socket(zmq.REQ) req.connect('tcp://localhost:9002') rep = ctx.socket(zmq.REP) rep.bind('tcp://*:9002') mmi.send_array(req, A=None) _, metadata = mmi.recv_array(rep) self.assertTrue('timestamp' in metadata)
def test_sndrcv(self): A = np.array([1,2,3]) req = ctx.socket(zmq.REQ) req.connect('tcp://localhost:9002') rep = ctx.socket(zmq.REP) rep.bind('tcp://*:9002') mmi.send_array(req, A) B, metadata = mmi.recv_array(rep) numpy.testing.assert_array_equal(A, B)
def test_missing(self): """send an array with missing data""" A = np.array([1, 2, 3, 4]) A = np.ma.masked_less(A, 2) req = ctx.socket(zmq.REQ) req.connect('tcp://localhost:9002') rep = ctx.socket(zmq.REP) rep.bind('tcp://*:9002') mmi.send_array(req, A) B, metadata = mmi.recv_array(rep) numpy.testing.assert_array_equal(A, B)
def update_data(poller, data): """update a shared array""" while True: for sock, n in poller.poll(1000): for i in range(n): message = mmi.recv_array(sock) arr, meta = message if meta['name'] == 's1': # just pick a value data['counter'] += 1 data['s1'] = arr[data['id']]
def initialize(self, configfile=None): """ Initialize the module """ method = "initialize" A = None metadata = {method : configfile} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket)
def update(self, dt): """ Advance the module with timestep dt """ method = "update" A = None metadata = {method : dt} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket)
def finalize(self): """ Finalize the module """ method = "finalize" A = None metadata = {method : -1} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket)
def set_var(self, name, var): """ Set the variable name with the values of var """ method = "set_var" A = var metadata = {method : name} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket)
def test_missing_scalar(self): """send an array with missing data as a scalar""" A = np.array([1, 2, 3, 4]) A = np.ma.masked_less(A, 2) # test if it works if we use a numpy scalar A.fill_value = np.int32(9999) req = ctx.socket(zmq.REQ) req.connect('tcp://localhost:9002') rep = ctx.socket(zmq.REP) rep.bind('tcp://*:9002') mmi.send_array(req, A) B, metadata = mmi.recv_array(rep) numpy.testing.assert_array_equal(A, B)
def get_start_time(self): """ Return start time """ method = "get_start_time" A = None metadata = {method : -1} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket) return metadata[method]
def get_current_time(self): """ Return current time of simulation """ method = "get_current_time" A = None metadata = {method : -1} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket) return metadata[method]
def get_var_rank(self, name): """ Return variable rank """ method = "get_var_rank" A = None metadata = {method : name} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket) return metadata[method]
def set_var_slice(self, name, start, count, var): """ Set the variable name with the values of var """ method = "set_var_slice" A = var metadata = {method: name, "start": start, "count": count} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def get_var(self, name): """ Return an nd array from model library """ method = "get_var" A = None metadata = {method : name} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket) return A
def set_var(self, name, var): """ Set the variable name with the values of var """ method = "set_var" A = var metadata = {method: name} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def get_var_name(self, i): """ Return variable name """ method = "get_var_name" A = None metadata = {method : i} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket) return metadata[method]
def update(self, dt): """ Advance the module with timestep dt """ method = "update" A = None metadata = {method: dt} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def initialize(self, configfile=None): """ Initialize the module """ method = "initialize" A = None metadata = {method: configfile} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def finalize(self): """ Finalize the module """ method = "finalize" A = None metadata = {method: -1} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def get_var_shape(self, name): """ Return variable shape """ method = "get_var_shape" A = None metadata = {method : rank} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket) return metadata[method]
def get_var_count(self): """ Return number of variables """ method = "get_var_count" A = None metadata = {method : -1} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket) return metadata[method]
def update(self, dt): """ Advance the module with timestep dt """ method = "update" A = None metadata = {method: dt} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def set_var(self, name, var): """ Set the variable name with the values of var """ method = "set_var" A = var metadata = {method: name} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def set_current_time(self, t): """ Set current time of simulation """ method = "set_current_time" A = None metadata = {method: t} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def initialize(self, configfile=None): """ Initialize the module """ method = "initialize" A = None metadata = {method: configfile} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def finalize(self): """ Finalize the module """ method = "finalize" A = None metadata = {method: -1} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags)
def get_var_type(self, name): """ Return variable name """ method = "get_var_type" A = None metadata = {method: name} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def remote(self, action): """ Function specific for MMI, not BMI. action is one of: "play", "stop", "pause", "rewind", "quit" """ method = "remote" A = None metadata = {method: action} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def get_var_count(self): """ Return number of variables """ method = "get_var_count" A = None metadata = {method: -1} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def get_current_time(self): """ Return current time of simulation """ method = "get_current_time" A = None metadata = {method: -1} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def get_start_time(self): """ Return start time """ method = "get_start_time" A = None metadata = {method: -1} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def get_var(self, name): """ Return an nd array from model library """ method = "get_var" A = None metadata = {method: name} send_array(self.socket, A, metadata) A, metadata = recv_array( self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return A
def get_var(self, name): """ Return an nd array from model library """ method = "get_var" A = None metadata = {method: name} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return A
def get_start_time(self): """ Return start time """ method = "get_start_time" A = None metadata = {method: -1} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def get_time_step(self): """ Return time step of simulation """ method = "get_time_step" A = None metadata = {method: -1} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def get_var_count(self): """ Return number of variables """ method = "get_var_count" A = None metadata = {method: -1} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def remote(self, action): """ Function specific for MMI, not BMI. action is one of: "play", "stop", "pause", "rewind", "quit" """ method = "remote" A = None metadata = {method: action} send_array(self.socket, A, metadata) A, metadata = recv_array(self.socket, poll=self.poll, poll_timeout=self.poll_timeout, flags=self.zmq_flags) return metadata[method]
def process_incoming(model, sockets, data): """ process incoming messages data is a dict with several arrays """ # Check for new messages if not sockets: return # unpack sockets poller = sockets['poller'] rep = sockets['rep'] # pull = sockets['pull'] pub = sockets['pub'] items = poller.poll(10) for sock, n in items: for i in range(n): A, metadata = recv_array(sock) logger.debug("got metadata: %s", metadata) var = None # bmi actions if "update" in metadata: dt = float(metadata["update"]) logger.debug("updating with dt %s", dt) model.update(dt) metadata["dt"] = dt elif "get_var" in metadata: name = metadata["get_var"] # temporary implementation if metadata.get("copy", False): var = model.get_var(name).copy() else: var = model.get_var(name) logger.debug("sending variable %s with shape %s", name, var.shape) metadata['name'] = name # assert socket is req socket elif "get_var_count" in metadata: # temporary implementation n = model.get_var_count() metadata['get_var_count'] = n # assert socket is req socket elif "get_var_rank" in metadata: # temporary implementation var_name = metadata['get_var_rank'] n = model.get_var_rank(var_name) metadata['get_var_rank'] = n # assert socket is req socket elif "get_var_shape" in metadata: # temporary implementation var_name = metadata['get_var_shape'] n = model.get_var_shape(var_name) metadata['get_var_shape'] = tuple([int(item) for item in n]) # assert socket is req socket elif "get_var_type" in metadata: # temporary implementation var_name = metadata['get_var_type'] n = model.get_var_type(var_name) metadata['get_var_type'] = n # assert socket is req socket elif "get_var_name" in metadata: i = int(metadata["get_var_name"]) name = model.get_var_name(i) metadata['get_var_name'] = name # assert socket is req socket elif "set_var" in metadata: name = metadata["set_var"] logger.debug("setting variable %s", name) model.set_var(name, A) metadata["name"] = name # !? elif "set_var_slice" in metadata: name = metadata["set_var_slice"] logger.debug("setting variable %s", name) start = metadata["start"] count = metadata["count"] model.set_var_slice(name, start, count, A) metadata["name"] = name # !? elif "set_var_index" in metadata: name = metadata["set_var_index"] logger.debug("setting variable %s using index index", name) index = metadata["index"] # TODO: test if this is fast enough. # Otherwise move to BMI ++ but that is # a bit of a burden on implementers var = model.get_var(name).copy() var.flat[index] = A model.set_var(name, var) metadata["name"] = name # !? elif "get_current_time" in metadata: metadata["get_current_time"] t = model.get_current_time() metadata['get_current_time'] = t elif "get_time_step" in metadata: metadata["get_time_step"] dt = model.get_time_step() metadata['get_time_step'] = dt elif "get_end_time" in metadata: metadata["get_end_time"] t = model.get_end_time() metadata['get_end_time'] = t elif "get_start_time" in metadata: metadata["get_start_time"] t = model.get_start_time() metadata['get_start_time'] = t # assert socket is req socket # custom actions elif "remote" in metadata: assert metadata["remote"] in {"play", "stop", "pause", "rewind"} model.state = metadata["remote"] elif "operator" in metadata: # TODO: support same operators as MPI_ops here...., # TODO: reduce before apply # TODO: assert pull socket pass # S = tuple(slice(*x) for x in action['slice']) # print(repr(arr[S])) # if action['operator'] == 'setitem': # arr[S] = data # elif action['operator'] == 'add': # arr[S] += data elif "initialize" in metadata: config_file = metadata["initialize"] model.initialize(config_file) elif "finalize" in metadata: model.finalize() else: logger.warn("got unknown message {} from socket {}".format(str(metadata), sock)) if sock.socket_type == zmq.REP: # reply send_array(rep, var, metadata=metadata) # any getter requested through the pull socket? elif any(x.startswith("get_") for x in metadata) and sock.socket_type == zmq.PULL: # return through the pub socket send_array(pub, var, metadata=metadata)
def _run(self): """run the thread""" message_data = self.message_data socket = self.socket while not self.kill_received: logger.debug( '(a) number of busy workers: %s' % self.reporter.get_busy_workers(), extra={'subgrid_id': self.reporter.redis_key}) arr, metadata = recv_array(socket) # now it is busy self.reporter.set_busy() # N.B.: to simulate the wms_busy state uncomment the following # line, but do not commit it, never! # time.sleep(random.uniform(0.0, 0.5)) logger.debug( '(b) number of busy workers: %s' % self.reporter.get_busy_workers(), extra={'subgrid_id': self.reporter.redis_key}) logger.debug( 'time in seconds wms is considered busy: %s' % str(self.reporter.busy_duration), extra={'subgrid_id': self.reporter.redis_key}) if metadata['action'] == 'reset': self.reset_grid_data() elif metadata['action'] == 'update': self.reporter.set_timestep(metadata['sim_time_seconds']) logger.debug( 'Updating grid data [%s]' % metadata['name'], extra={'subgrid_id': self.reporter.redis_key}) if 'model' in metadata: restarted = metadata['name'] == 't1' and \ metadata['sim_time_seconds'] < 0.1 if metadata['model'] != message_data.loaded_model or \ restarted: # Since working with 'reset', this part probably never # occur anymore. # New model detected logger.info( 'New model detected: %r (old=%r)' % ( metadata['model'], message_data.loaded_model), extra={'subgrid_id': self.reporter.redis_key}) # Double reset algorithm. message_data.grid = {} message_data.interpolation_ready = False message_data.loaded_model = metadata['model'] # Update new grid if arr.dtype.kind == 'S': # String, for wkt message_data.grid[metadata['name']] = ''.join(arr) else: if 'bbox' in metadata: logger.debug("BBOXED update") x0, x1, y0, y1 = metadata['bbox'] message_data.grid[metadata['name']][y0:y1, x0:x1] = arr else: # normal case message_data.grid[metadata['name']] = arr.copy() # Receive one of the DEPTH_VARS and all DEPTH_VARS are complete if (all([v in message_data.grid for v in DEPTH_VARS]) and metadata['name'] in DEPTH_VARS): if 'bbox' in metadata: logger.debug( 'Update grids using bbox after receiving ' 'dps or quad_grid...', extra={'subgrid_id': self.reporter.redis_key}) message_data.update_grids_bbox(metadata['bbox']) else: logger.debug( 'Update grids after receiving dps or quad_grid...', extra={'subgrid_id': self.reporter.redis_key}) message_data.update_grids() logger.debug( 'Update grids finished.', extra={'subgrid_id': self.reporter.redis_key}) # check update indices if (all([v in message_data.grid for v in UPDATE_INDICES_VARS]) and metadata['name'] in UPDATE_INDICES_VARS): logger.debug( 'Update indices...', extra={'subgrid_id': self.reporter.redis_key}) message_data.X, message_data.Y, message_data.L = \ message_data.calc_indices() logger.debug( 'Update indices finished.', extra={'subgrid_id': self.reporter.redis_key}) elif metadata['action'] == 'update-pandas': logger.debug( 'Update pandas data [%s]...', metadata['name'], extra={'subgrid_id': self.reporter.redis_key}) # TODO: in case of weir, delete unused variables. message_data.pandas[metadata['name']] = json.loads( metadata['pandas_json']) elif metadata['action'] == 'dump': output_filename = metadata['output_filename'] logger.debug( 'Dump: checking other threads...', extra={'subgrid_id': self.reporter.redis_key}) filename_failed = output_filename + '.failed' if os.path.exists(filename_failed): os.remove(filename_failed) if i_am_the_boss(output_filename): # TODO: with statement nc_dump = NCDump(output_filename, message_data) nc_dump.dump_nc('wkt', 'S1', ('i', ), '-', list(message_data.grid['wkt'])) nc_dump.dump_nc('x0p', 'f8', (), '-') nc_dump.dump_nc('y0p', 'f8', (), '-') nc_dump.dump_nc('x1p', 'f8', (), '-') nc_dump.dump_nc('y1p', 'f8', (), '-') nc_dump.dump_nc('dxp', 'f8', (), '-') nc_dump.dump_nc('dyp', 'f8', (), '-') nc_dump.dump_nc('imax', 'i4', (), '-') nc_dump.dump_nc('jmax', 'i4', (), '-') nc_dump.dump_nc('imaxk', 'i4', ('k', ), '-') # nc_dump.dump_nc('jmaxk', 'i4', ('k', ), '-') nc_dump.dump_nc('nodm', 'i4', ('nFlowElem2', ), '-') nc_dump.dump_nc('nodn', 'i4', ('nFlowElem2', ), '-') nc_dump.dump_nc('nodk', 'i4', ('nFlowElem2', ), '-') nc_dump.dump_nc('nod_type', 'i4', ('nFlowElem2', ), '-') nc_dump.dump_nc('dsnop', 'f4', (), '-') nc_dump.dump_nc('dps', 'f4', ('x', 'y', ), '-') try: nc_dump.close() except: # I don't know when nc_dump will fail, but if it fails, # it is probably here. with file(filename_failed, 'w') as f: f.write('I failed...') # So others can see we are finished. os.remove(output_filename + '.busy') else: logger.debug( 'Got an unknown message: %r' % metadata, extra={'subgrid_id': self.reporter.redis_key}) # set this worker to not busy self.reporter.set_not_busy() self.reporter.handle_busy_flag()