class Budget(object): """Device budget (for lack of a better term) Details ------- Keeps a semaphore for the total number of resources available, and a device-specific atomic counter of available slots. """ def __init__(self, devices, n_per_device): self.devices, self.n_per_device = devices, n_per_device self.total = Semaphore(len(devices) * n_per_device) self.alloc = Array("i", len(devices) * [n_per_device]) def acquire(self): self.total.acquire() with self.alloc.get_lock(): # get the largest counter index = max(range(len(self.alloc)), key=self.alloc.__getitem__) # assert self.alloc[index] > 0 # acquire the index and decrease the counter self.alloc[index] -= 1 return index def release(self, index): with self.alloc.get_lock(): self.alloc[index] += 1 self.total.release() def __getitem__(self, index): return self.devices[index]
class MpSafeSharedArray: """Multiprocessing-safe shared array.""" DTYPE_TO_CTYPE = { np.int: ctypes.c_long, np.bool: ctypes.c_bool, np.float: ctypes.c_double } def __init__(self, shape, dtype=np.float): warnings.warn( 'MpSafeSharedArray is experimental. Use at your own risk.') if dtype not in MpSafeSharedArray.DTYPE_TO_CTYPE: raise ValueError('Unsupported dtype') self._shape = shape self._dtype = dtype ctype = MpSafeSharedArray.DTYPE_TO_CTYPE[dtype] num_elements = reduce(lambda x, y: x * y, shape) self._mp_arr = Array(ctype, num_elements) def get_lock(self): return self._mp_arr.get_lock() def get_array(self): buffer = self._mp_arr.get_obj() arr = np.ndarray(shape=self._shape, dtype=self._dtype, buffer=buffer) return arr
def bestMoveConcurrent(self): start = time.time() corners = [ 0, self.board.size - 1, (self.board.size * self.board.size) - self.board.size, (self.board.size * self.board.size) - 1 ] if self.board.getMoveCount() == 1 and self.board.board[ self.board.size // 2][self.board.size // 2] != str( (self.board.size * self.board.size) // 2): # print("Total number of comparisons " + str(self.totalComp)) # print("Total time taken: " + str(time.time() - start)) return random.choice(corners) bestValueSingle = Value(ctypes.c_long, 1000000 if self.playerIsFirst else -1000000) counter = Value(ctypes.c_int, 0) bestMovesArray = Array( ctypes.c_int, range(self.board.getSize() * self.board.getSize())) threads = [] totalComp = Value(ctypes.c_int, 0) stop = [False] row = 0 while (not stop[0] and row < self.board.size): col = 0 while (not stop[0] and col < self.board.size): if (self.board.isCellEmpty(row, col)): threads.append( Process(target=self.callMinimaxConcurrent, args=(row, col, self.board.clone(), 0, self.maxDepth, self.playerIsFirst, -1000000, 1000000, counter, bestMovesArray, bestValueSingle, totalComp, stop))) col += 1 row += 1 # print("Total number of threads " + str(len(threads))) for thread in threads: thread.start() for thread in threads: if stop[0]: for thread in threads: thread.terminate() else: thread.join() with counter.get_lock(): with bestMovesArray.get_lock(): # print("This is the best move " + str(bestMovesArray[0])) # print("Total number of comparisons " + str(totalComp.value)) # print("Total time taken: " + str(time.time() - start)) if (counter.value > 0): return random.choice(bestMovesArray[:counter.value]) return bestMovesArray[0]
class pos(): def __init__(self): xpos = np.zeros(MEMORYDEPTH * NUMBOTS, dtype=np.int16, order="C") ypos = np.zeros(MEMORYDEPTH * NUMBOTS, dtype=np.int16, order="C") self.ids = np.zeros(NUMBOTS, dtype=np.int16, order="C") self.xpos = Array('I', xpos) self.ypos = Array('I', ypos) self.latest = Value('I', 0, lock=True) self.cap = cv2.VideoCapture(0) self.iter = 0 def updatepos(self): while True: ret, frame = self.cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) with self.latest.get_lock(): self.latest.value = 5 with self.xpos.get_lock(): self.xpos[self.iter % NUMBOTS] = self.iter with self.ypos.get_lock(): self.ypos[self.iter % NUMBOTS] = self.iter self.iter += 1
def display_image(array_a: mp.Array, event_start: mp.Event, event_quit: mp.Event, event_next_img: mp.Event, width: mp.Value, height: mp.Value): """ Continually reads from array_a & displays image w/ OpenCV.imshow() Waits for <q> key press to close window or <ENTER> to display next image - array_a: shared memory that contains single image to display - event_start: event signal to indicate when array_a has an image - event_quit: event signal to stop upon shutdown - event_next_img: event signal to display next image - width: image width (in pixels) - height: image height (in pixels) Return values: None """ # TODO: get rid of this, I feel like I could make due with fewer event signals... event_start.wait() # waits/blocks until array_a has an image while not event_quit.is_set(): with array_a.get_lock(): # reads image from array_a as np.ndarray with C type unsigned int image = np.frombuffer(array_a.get_obj(), dtype="I").reshape(height.value, width.value, 3) color_text = RGB_COLORS[tuple(image[0][0])] # converts RGB image to BGR for OpenCV and displays image in new window cv2.imshow(f"Random Color Image Viewer", cv2.cvtColor(image.astype(np.uint8), cv2.COLOR_BGR2RGB)) print(f"Image viewer showing: {color_text}") print(f"Press <Enter> to view next image or 'q' to quit...") key = cv2.waitKey(0) if key == ord('q'): # if 'q' is pressed, quit event_quit.set() event_next_img.set() break elif key == 13: # if <ENTER> key is pressed, go to next image event_next_img.set() print("\n*********\n <Enter> key pressed \n*********\n") # TODO: eliminate this sleep function! time.sleep( 0.01 ) # Atm, necessary to block to synchronize with other process.
def run(frame: Array, target_in_sight: Condition): archive_path = Path("/mnt/nas/data/birdthings") archive_path.mkdir(exist_ok=True, parents=True) while True: with target_in_sight: target_in_sight.wait() with frame.get_lock(): now = datetime.now() if not (7 < now.hour < 18): continue datepart, timepart = str(now).split(" ") dest = ( archive_path / datepart / timepart.split(":")[0] / (timepart + ".jpeg") ) dest.parent.mkdir(exist_ok=True, parents=True) Image.frombytes("RGB", camera.RESOLUTION, frame.get_obj()).save( dest, format="jpeg" ) logging.info(f'archived image {dest}')
def run(frame: Array, new_frame: Condition): with picamera.PiCamera( resolution=RESOLUTION) as camera, picamera.array.PiRGBArray( camera, size=RESOLUTION) as data_container: stream = camera.capture_continuous(data_container, format="rgb", use_video_port=True) f: picamera.array.PiArrayOutput for f in stream: with frame.get_lock(): image = numpy.frombuffer(frame.get_obj(), dtype=numpy.uint8).reshape( (RESOLUTION[1], RESOLUTION[0], 3)) numpy.copyto(image, f.array) with new_frame: new_frame.notify_all() data_container.seek(0) data_container.truncate()
class GridMapper(Process): def __init__(self, params: GridMapperParams) -> None: super().__init__() self.__params = self.__params_type_checked(params) self.__stop = Stop() self.__output = Array('d', self.__params.grid.size) self.__kde = KernelDensity(bandwidth=self.__params.kernel.bandwidth, kernel=self.__params.kernel.name, **KDE_PARAMETERS) self.__grid = self.__grid_from_params() @property def stop(self): return self.__stop @property def output(self) -> ARRAY: return self.__output def run(self) -> None: while not self.__stop.is_set(): if self.__params.data: n_points = len(self.__params.data) self.__kde.fit(self.__params.data.values()) density_on_grid = exp(self.__kde.score_samples(self.__grid)) with self.__output.get_lock(): self.__output.get_obj()[:] = n_points * density_on_grid def __grid_from_params(self) -> ndarray: x_line = linspace(*self.__params.bounds.x_range, self.__params.grid.x) y_line = linspace(*self.__params.bounds.y_range, self.__params.grid.y) x_grid, y_grid = meshgrid(x_line, y_line) return column_stack((x_grid.ravel(), y_grid.ravel())) @staticmethod def __params_type_checked(value: GridMapperParams) -> GridMapperParams: if type(value) is not GridMapperParams: raise TypeError('Parameters must be of type <GridMapperParams>!') return value
class AstractProcessCamera: ''' polling the camera in separate process ''' def __init__(self, width, height, framerate): self.width = width self.height = height self.framerate = framerate self.is_running = Event() self.is_running.set() self._shared_array = Array(ctypes.c_uint8, [0] * (width * height * 3)) self._image = self.get_numpy_array(self._shared_array, self.width, self.height) # fill with zeros self._image[:] = np.zeros((self.height, self.width, 3), dtype=np.uint8) self._process = Process(target=self.update, args=(self.is_running, self._shared_array, self.width, self.height, self.framerate)) self._process.start() @classmethod def get_numpy_array(cls, shared_array, width, height): shared_numpy_array = np.frombuffer(shared_array.get_obj(), dtype=np.uint8) return shared_numpy_array.reshape((height, width, 3)) @classmethod def update(cls, is_running, shared_array, width, height, framerate): raise NotImplementedError def read(self): with self._shared_array.get_lock(): return self._image.copy() def release(self): self.is_running.clear() self._process.join()
class FFMpegVideoSource(): def __init__(self): image_size = (IMAGE_WIDTH, IMAGE_HEIGHT, COLOR_CHANNELS) arr_size = IMAGE_WIDTH * IMAGE_HEIGHT * COLOR_CHANNELS self._shared_arr = Array(ctypes.c_uint8, arr_size) self._image_outside_thread = np.frombuffer(self._shared_arr.get_obj(), dtype=np.uint8) self._image_outside_thread = np.reshape(self._image_outside_thread, image_size) self._p = Process(target=self._run, args=(self._shared_arr, image_size, URL)) self._p.daemon = True self._p.start() def _crop_center(self, image, cropped_width, cropped_height): height, width, _ = image.shape startx = int((width - cropped_width) / 2) starty = int((height - cropped_height) / 2) stopx = startx + cropped_width stopy = starty + cropped_height image = image[starty:stopy, startx:stopx, :] return image def _resize(self, image, width, height): return cv2.resize(image, (width, height)) def frame(self): """ Get Frame Returns : numpy.array(int8) Image as a numpy array """ with self._shared_arr.get_lock(): return np.copy(self._image_outside_thread) def frame_available(self): """ Check if frame is available Returns : boolean true if frame is available otherwise false """ with self._shared_arr.get_lock(): available = not isinstance(self._image_outside_thread, type(None)) return available def stop(self): self._p.terminate() def _run(self, shared_array, image_size, url): """ Get frame to update _frame """ try: image_inside_thread = np.frombuffer(shared_array.get_obj(), dtype=np.uint8) image_inside_thread = np.reshape(image_inside_thread, image_size) cap = cv2.VideoCapture(url) while True: ret, frame = cap.read() if not ret: break if frame is None: print(f'No image from {url}') continue with shared_array.get_lock(): image_inside_thread[:] = frame except Exception as error: print(f'Got unexpected exception in "main" Message: {error}')
class PointRelaxer(): def __init__(self): self.n_relaxation_workers = 8 # self.points_array = None # self.work_array = None self.cancellation = Value('i', 0, lock=True) self.relax_var = Value('i', 0, lock=True) self.relax_completed_var = Value('i', 0, lock=True) self.n_points = Value('i', 0, lock=False) self.points_io_var = Value('i', 0, lock=False) self._buffer_size = None self.neighors_array_buffer_multiplier = 4 self.points = None self.points_relaxed = None self.points_io = None self.neighbor_divs = None self.neighbors = None self.delaunay_process = None self.relax_processes = [] self.alpha = Value('f', 0.1, lock=True) self.beta = Value('f', 0.04, lock=True) def init_processes(self, buffer_size): self._buffer_size = buffer_size if self.points: del self.points if self.points_relaxed: del self.points_relaxed if self.points_io: del self.points_io if self.neighbor_divs: del self.neighbor_divs if self.neighbors: del self.neighbors n_neighbors = self.neighors_array_buffer_multiplier * buffer_size self.points = Array(Vector2, buffer_size, lock=False) self.points_relaxed = Array(Vector2, buffer_size, lock=False) self.points_io = Array(Vector2, buffer_size, lock=True) self.neighbor_divs = Array(c_long, buffer_size + 1, lock=False) self.neighbors = Array(c_long, n_neighbors, lock=False) args_common = (self.cancellation, self.relax_var, self.relax_completed_var, self.n_points, self.points, self.points_relaxed, self.neighbor_divs, self.neighbors) d_args = (self.n_relaxation_workers, self.points_io, self.points_io_var) + args_common r_args_suffix = (self.n_relaxation_workers, self.alpha, self.beta) + \ args_common self.delaunay_process = Process(target=delaunay_loop, args=d_args) self.relax_processes = [ Process(target=relax_points_loop, args=(i, ) + r_args_suffix) for i in range(self.n_relaxation_workers) ] def set_points(self, points): with self.points_io.get_lock(): n_points = len(points) for idx in range(n_points): p = points[idx] # Dithering prevents issues with Delaunay calculation r = 0.00001 * np.random.rand(2) p = (p[0] + r[0], p[1] + r[1]) self.points_io[idx] = tuple(p) self.n_points.value = n_points self.points_io_var.value = 1 def get_points(self): with self.points_io.get_lock(): return [tuple(self.points[i]) for i in range(self.n_points.value)] def start_all(self): self.delaunay_process.start() for r in self.relax_processes: r.start() def stop_all(self): with self.cancellation.get_lock(): self.cancellation.value = 1 if self.delaunay_process: self.delaunay_process.join() for r in self.relax_processes: r.join() with self.cancellation.get_lock(): self.cancellation.value = 0
def _biderectional_dijkstra_branch(adj_list: list, sink: int, to_visit: PriorityQueue, visited_costs: Array, visited_prev_nodes: Array, prospect: Array, priorityq_top: Array, kill: Event, failed: Hashable = None, sync: tuple = None): """The target function for either the forward or the reverse search process. Args: adj_list (list) : the adjacency list sink (int) : the source or the spur-node, if it is the reverse search to_visit (PriorityQueue) : the PriorityQueue visited_costs (Array) : column major packed costs of both searches visited_prev_nodes (Array) : column major packed prev nodes of the searches prospect (Array) : see bidirectional Dijkstra termination priorityq_top (Array) : the top values of both PriorityQueue's kill (Event) : flag to notify the other process to finish failed (hashable) : the failed node sync (tuple) : 2 Event's to synchronize the two searches """ # visited_costs and visited_prev_nodes are a single vector shared by both # searches; thus, each search has to work with the proper slice. n = len(adj_list) - 1 is_forward, visited_offset, opposite_visited_offset = _visited_offsets(n) # Force the synchronization of the processes. sync[int(not is_forward)].set() sync[int(is_forward)].wait() while to_visit: u_path_cost, u_prev, u = to_visit.pop_low() if u == failed: continue # -1 denotes an unconnected node and, in that case, node and previous node # are the same by initialization. with visited_costs.get_lock(): if u_path_cost == math.inf: visited_costs[u + visited_offset] = -1 continue visited_costs[u + visited_offset] = u_path_cost with visited_prev_nodes.get_lock(): visited_prev_nodes[u + visited_offset] = u_prev if (kill.is_set()) or (u == sink): kill.set() return for v, uv_weight in adj_list[u]: if v == failed: continue if v in to_visit: # Check if v is visited by the other process and, if yes, construct the # prospect path. with visited_prev_nodes.get_lock(): if ((visited_prev_nodes[v + opposite_visited_offset] != v) and (visited_costs[v + opposite_visited_offset] != 0)): # print(f"{current_process().name}: u: {u} v: {v}" # f" v visted from:" # f" {visited_prev_nodes[v + opposite_visited_offset]}") uv_prospect_cost = ( u_path_cost + uv_weight + visited_costs[v + opposite_visited_offset]) with prospect.get_lock(): if (uv_prospect_cost < prospect[0]) or (sum(prospect) == 0): # then this is the shortest prospect yet or the 1st one. prospect[0] = uv_prospect_cost prospect[3] = uv_weight if is_forward: prospect[1] = u prospect[2] = v else: prospect[1] = v prospect[2] = u # print(f"{current_process().name}: {prospect[0]}" # f" {prospect[1]} {prospect[2]}\n") to_visit.relax_priority([u_path_cost + uv_weight, u, v]) # Termination condition pq_top = to_visit.peek()[0] if pq_top == math.inf: pq_top = 0 # print(f"{current_process().name}: prospect[0]: {prospect[0]}" # f" topf+topr: {priorityq_top[0]} + {priorityq_top[1]}") with prospect.get_lock(): with priorityq_top.get_lock(): priorityq_top[int(not is_forward)] = pq_top if (sum(priorityq_top) >= prospect[0] != 0) or (kill.is_set()): kill.set() return
def acquire_parallel(self, worker_cls, worker_args, result_shape, plot=False): """ :param worker: Function which the subordinate threads execute as their target :param proc_fun: Function used by the subordinate threads to process their buffers :param result_shape: Shape of the buffer which is the result of the entire acquisition. """ from multiprocessing import Array, Value, Event from slab.plotting import ScriptPlotter import time acquire_buffer_time = self.samples_per_buffer / (self.samples_per_second) print('Acquire buffer time %.2e' % acquire_buffer_time) print('Inter-buffer time %.2e' % self.seconds_per_buffer) print('Duty Cycle', acquire_buffer_time / self.seconds_per_buffer) try: # I don't know why this needs to happen again? channel = 0 if self.ch1_enabled: channel |= 1 if self.ch2_enabled: channel |= 2 pretriggers = C.c_long(0) flags = U32(513) ret = self.Az.AlazarBeforeAsyncRead(self.handle,U32(channel),pretriggers, U32(self.config.samplesPerRecord), U32(self.config.recordsPerBuffer), U32(self.config.recordsPerAcquisition), flags) # Initialize buffers buffers = [Array(U8, self.bytes_per_buffer) for _ in range(self.buffer_count)] for b in buffers: ret = self.Az.AlazarPostAsyncBuffer(self.handle, b.get_obj(), U32(self.bytes_per_buffer)) self.assert_az(ret, 0, 'Initial Post Buffer') res_buffer = Array(C.c_longdouble, result_shape) # Initialize threads bufs_merged = Value(U32, 1) buf_ready_events = [Event() for _ in range(self.buffer_count)] buf_post_events = [Event() for _ in range(self.buffer_count)] workers = [worker_cls(*(worker_args + (self.config, b, bre, bpe, res_buffer, bufs_merged))) for b, bre, bpe in zip(buffers, buf_ready_events, buf_post_events)] for w in workers: w.start() time.sleep(1) import atexit atexit.register(lambda: [w.terminate() for w in workers]) # Initialize things used during capture if plot: plotter = ScriptPlotter() plotter.init_plot('Data', rank=1, accum=False) buffers_acquired, buffers_completed, plot_count = 0, 0, 0 start_time = time.time() # Begin capture ret = self.Az.AlazarStartCapture(self.handle) self.assert_az(ret, 0, "Start Capture") unready_count = 0 while buffers_completed < self.buffers_per_acquisition: # Post all completed buffers while buf_post_events[buffers_completed % self.buffer_count].is_set(): buf_post_events[buffers_completed % self.buffer_count].clear() buf = buffers[buffers_completed % self.buffer_count] with buf.get_lock(): ret = self.Az.AlazarPostAsyncBuffer(self.handle, buf.get_obj(), U32(self.bytes_per_buffer)) self.assert_az(ret, buffers_acquired, 'Post Buffer') buffers_completed += 1 # Current buffer rotates in a ring buf_idx = buffers_acquired % self.buffer_count buf = buffers[buf_idx] # Pull data to buffer with buf.get_lock(): ret = self.Az.AlazarWaitAsyncBufferComplete(self.handle, buf.get_obj(), U32(self.timeout)) if ret == 573: unready_count += 1 continue # BufferNotReady, go back and try to post some buffers. else: self.assert_az(ret, buffers_acquired, 'Wait Buffer Complete') buffers_acquired += 1 # Tell worker thread to begin processing buf_ready_events[buf_idx].set() # If a second has elapsed, replot the avg_buffer if (time.time() - start_time) / self.seconds_per_plot > plot_count: if plot: with res_buffer.get_lock(): plotter.msg(buffers_acquired, buffers_completed, bufs_merged.value) plotter.plot(np.frombuffer(res_buffer.get_obj()), 'Data') plot_count += 1 else: print(buffers_acquired, buffers_completed) plot_count += 1 finally: pass # self.Az.AlazarAbortAsyncRead(self.handle) # if buffers_completed: # final_time = time.time() # print 'Unready Count', unready_count # total_time = final_time - start_time # print 'Total time', total_time # actual_time_per_buffer = total_time / buffers_completed # print 'Time per buffer %.2e' % actual_time_per_buffer # errf = lambda a, b: abs(a - b) / min(a, b) # print 'Perceived overhead %.1f%%' % (errf(actual_time_per_buffer, seconds_per_buffer) * 100) # else: # print 'No buffers completed' res = np.frombuffer(res_buffer.get_obj()) return res
c2 = pipecl2.recv() #Blocking update_c(c1.ravel(),c2.ravel()) ######### print "Running main loop..." while runflag: #print uflag1.value #print uflag2.value dat1 = uflag1.value dat2 = uflag2.value frame = vs.read() #for testing #datrecv1 = pipeul1.recv() #Blocking #datrecv2 = pipeul2.recv() #Blocking #if datrecv1[0] and datrecv2[0]: if (dat1 == 2) and (dat2 ==2): #pos3d = calc3d(datrecv2[2].ravel(),datrecv1[2].ravel()) ######## with uarray1.get_lock(): arr1 = np.frombuffer(uarray1.get_obj()) with uarray2.get_lock(): arr2 = np.frombuffer(uarray2.get_obj()) pos3d = calc3d(arr1,arr2) #print np.asarray(pos3d) imgpts, jac = cv2.projectPoints(np.float32([np.asarray(pos3d)]).reshape(-1,3), rvecs, tvecs, mtx, dist) cv2.rectangle(frame,(int(imgpts[0,0,0]) - 2,int(imgpts[0,0,1]) - 2),(int(imgpts[0,0,0]) + 2 ,int(imgpts[0,0,1]) + 2),(255,0,0),1) #elif not datrecv1[1] or not datrecv2[1]: elif (dat1 == 0) or (dat2 ==0): runflag = False cv2.imshow('frame',frame) if cv2.waitKey(1) & 0xFF == ord('q'): break print "Waiting for both processes to stop..."
def main(): with open("day23.txt", "r") as fp: memory = dict() for i, s in enumerate(fp.read().split(",")): memory[i] = int(s) # Part 1 receive_queues = [Queue() for i in range(50)] done_queue = Queue() def receive(index): yield index while True: try: (x, y) = receive_queues[index].get_nowait() yield x yield y except Empty: yield -1 yield -1 def send(index, program): while True: dest = next(program) x = next(program) y = next(program) if dest == 255: done_queue.put_nowait(y) break receive_queues[dest].put_nowait((x, y)) senders = [ Process(target=send, args=(i, run_program(defaultdict(lambda: 0, memory), receive(i)))) for i in range(50) ] for sender in senders: sender.start() result = done_queue.get() for sender in senders: sender.terminate() print(result) # Part 2 receive_queues = [Queue() for i in range(50)] nat_value = Array(ctypes.c_long, 2) waiting = Array(ctypes.c_bool, len(receive_queues)) def receive(index): yield index while True: try: (x, y) = receive_queues[index].get_nowait() with waiting.get_lock(): waiting[index] = False yield x yield y except Empty: with waiting.get_lock(): waiting[index] = True yield -1 yield -1 def send(index, program): while True: dest = next(program) x = next(program) y = next(program) if dest == 255: with nat_value.get_lock(): nat_value[0] = x nat_value[1] = y else: receive_queues[dest].put_nowait((x, y)) senders = [ Process(target=send, args=(i, run_program(defaultdict(lambda: 0, memory), receive(i)))) for i in range(50) ] for sender in senders: sender.start() last_nat_y = None while True: sleep(0.25) with waiting.get_lock(): all_waiting = True for w in waiting: all_waiting = all_waiting and waiting if all_waiting: with nat_value.get_lock(): receive_queues[0].put_nowait((nat_value[0], nat_value[1])) if last_nat_y == nat_value[1]: break else: last_nat_y = nat_value[1] for sender in senders: sender.terminate() print(last_nat_y)
def run( detect_input: Array, new_detect_input: Condition, frame: Array, preview: Array, new_preview: Condition, target_offset_x: Value, target_offset_y: Value, track: Sequence[str], target_in_sight: Condition, ): interp = interpreter.Interpreter( model_path=path.abspath( path.join( DATA_DIR, "model_postprocessed_quantized_128_uint8_edgetpu.tflite")), experimental_delegates=[ tensorflow.lite.experimental.load_delegate("libedgetpu.so.1") ], ) interp.allocate_tensors() input_details = interp.get_input_details() output_details = interp.get_output_details() label_idxs = label_to_category_index(track) while True: with new_detect_input: new_detect_input.wait() with detect_input.get_lock(): input = numpy.asarray(detect_input.get_obj()).reshape( (RESOLUTION[1], RESOLUTION[0], 3)) input_tensor = tensorflow.convert_to_tensor(input, dtype=tensorflow.uint8) input_tensor = input_tensor[tensorflow.newaxis, ...] interp.set_tensor(input_details[0]["index"], input_tensor) interp.invoke() box_data = tensorflow.convert_to_tensor( interp.get_tensor(output_details[0]["index"])) class_data = tensorflow.convert_to_tensor( interp.get_tensor(output_details[1]["index"])) score_data = tensorflow.convert_to_tensor( interp.get_tensor(output_details[2]["index"])) # num_detections = tensorflow.convert_to_tensor( # interp.get_tensor(output_details[3]["index"]) # ) class_data = (tensorflow.squeeze(class_data, axis=[0]).numpy().astype( numpy.int64) + 1) box_data = tensorflow.squeeze(box_data, axis=[0]).numpy() score_data = tensorflow.squeeze(score_data, axis=[0]).numpy() if any(item in label_idxs for item in class_data): tracked = ((i, x) for i, x in enumerate(class_data) if x in label_idxs) tracked_idxs, tracked_classes = zip(*tracked) if any(score_data[i] > 0.6 for i in tracked_idxs): with target_in_sight: target_in_sight.notify_all() idx = max( tracked_idxs, key=lambda i: numpy.amax(box_data[i]) - numpy.amin(box_data[i] ), ) keypoint_x = numpy.take(box_data[idx], [1, 3]).mean() keypoint_y = numpy.take(box_data[idx], [0, 2]).mean() target_offset_x.value = (keypoint_x - 0.5) * FOV_ANGLE target_offset_y.value = (keypoint_y - 0.5) * FOV_ANGLE else: keypoint_x = None keypoint_y = None target_offset_x.value = float("nan") target_offset_y.value = float("nan") with preview.get_lock(): preview_image = numpy.frombuffer(preview.get_obj(), dtype=numpy.uint8).reshape( (camera.RESOLUTION[1], camera.RESOLUTION[0], 3)) with frame.get_lock(): frame_image = numpy.frombuffer(frame.get_obj(), dtype=numpy.uint8).reshape( (camera.RESOLUTION[1], camera.RESOLUTION[0], 3)) numpy.copyto(preview_image, frame_image) if keypoint_x is not None and keypoint_y is not None: draw_keypoints_on_image_array( preview_image, numpy.array([[keypoint_y, keypoint_x]]), use_normalized_coordinates=True, ) visualize_boxes_and_labels_on_image_array( preview_image, box_data, class_data, score_data, LABEL_MAP, use_normalized_coordinates=True, line_thickness=4, min_score_thresh=0.5, max_boxes_to_draw=3, ) with new_preview: new_preview.notify_all()
width = Value("i", int(width)) if num_images.value < 1 or height.value < 1 or width.value < 1: raise Exception input_is_int = True except: print("Please input integers greater than zero for these values") print("Press the 'q' key to quit") array_a_size = height.value * width.value * 3 array_a = Array(ctypes.c_double, array_a_size) quit_event = Event() p1 = Process(target=process_one, args=(queue_a, )) p2 = Process(target=process_two, args=(queue_a, queue_b, quit_event)) p3 = Process(target=process_three, args=(array_a, quit_event)) p1.start() p2.start() p3.start() while not quit_event.is_set(): im = queue_b.get() if im is None: break with array_a.get_lock(): window = np.frombuffer(array_a.get_obj()).reshape( width.value, height.value, 3) window[:] = im cv2.destroyAllWindows() p1.join() p2.join() p3.join()
class RenderProcess: """ Wraps a multiprocessing.Process for rendering. Assumes there is one MjSim per process. """ def __init__(self, device_id, setup_sim, update_sim, output_var_shape): """ Args: - device_id (int): GPU device to use for rendering (0-indexed) - setup_sim (callback): callback that is given a device_id and returns a MjSim. It is responsible for making MjSim render to given device. - update_sim (callback): callback given a sim and device_id, and should return a numpy array of shape `output_var_shape`. - output_var_shape (tuple): shape of the synchronized output array from `update_sim`. """ self.device_id = device_id self.setup_sim = setup_sim self.update_sim = update_sim # Create a synchronized output variable (numpy array) self._shared_output_var = Array(ctypes.c_double, int(np.prod(output_var_shape))) self._output_var = np.frombuffer(self._shared_output_var.get_obj()) # Number of variables used to communicate with process self._cv = Condition() self._ready = Value('b', 0) self._start = Value('b', 0) self._terminate = Value('b', 0) # Start the actual process self._process = Process(target=self._run) self._process.start() def wait(self): """ Wait for process to be ready for another update call. """ with self._cv: if self._start.value: self._cv.wait() if self._ready.value: return self._cv.wait() def read(self, copy=False): """ Reads the output variable. Returns a copy if copy=True. """ if copy: with self._shared_output_var.get_lock(): return np.copy(self._output_var) else: return self._output_var def update(self): """ Calls update_sim asynchronously. """ with self._cv: self._start.value = 1 self._cv.notify() def stop(self): """ Tells process to stop and waits for it to terminate. """ with self._cv: self._terminate.value = 1 self._cv.notify() self._process.join() def _run(self): sim = self.setup_sim(self.device_id) while True: with self._cv: self._ready.value = 1 self._cv.notify_all() with self._cv: if not self._start.value and not self._terminate.value: self._cv.wait() if self._terminate.value: break assert self._start.value self._start.value = 0 # Run the update and assign output variable with self._shared_output_var.get_lock(): self._output_var[:] = self.update_sim(sim, self.device_id).ravel()
def __init__(self, config_file: str): with open(config_file) as file: # Load the json configuration file json_config = json.load(file) # Create the different IPC message queues we will be using self.client_mq = self.get_ipc_queue( json_config["server"]["ipc_key_client"]) self.house_mq = self.get_ipc_queue( json_config["server"]["ipc_key_house"]) # Create a barrier for synchronization # 4 processes need to be synchronized : Weather, City, Market and Server Sync # If the server_utils if configured as "auto", it runs on regular interval. # If it's not, run when requested by the client compute_barrier = Barrier(parties=4) # This other barrier is used to update shared memory used for the next iteration # of the simulation write_barrier = Barrier(parties=4) # Shared memory for the weather weather_shared = Array("i", 2) with weather_shared.get_lock(): weather_shared[0] = json_config["weather"]["temperature"] weather_shared[1] = json_config["weather"]["cloud_coverage"] # Shared memory for the energy price price_shared = Value("d") with price_shared.get_lock(): price_shared.value = json_config["market"]["initial_price"] self.shared_variables = SharedVariables( compute_barrier=compute_barrier, write_barrier=write_barrier, price_shared=price_shared, weather_shared=weather_shared, ) # Declaring the simulation processes self.city = City( shared_variables=self.shared_variables, ipc_key_houses=json_config["server"]["ipc_key_house"], nb_houses=json_config["cities"]["nb_houses"], average_conso=json_config["cities"]["average_conso"], max_prod=json_config["cities"]["max_prod"], ) self.market = Market( shared_variables=self.shared_variables, politics=json_config["market"]["political_score"], economy=json_config["market"]["economy_score"], nb_houses=json_config["cities"]["nb_houses"], ipc_house=json_config["server"]["ipc_key_house"], time_interval=json_config["server"]["time_interval"], ) self.weather = Weather(shared_variables=self.shared_variables, ) self.sync = ServerSync( shared_variables=self.shared_variables, time_interval=json_config["server"]["time_interval"], ) # Starting all processes self.city.start() self.weather.start() self.market.start() self.sync.start() signal.signal(signal.SIGINT, self.signal_handler) print(f"{Fore.GREEN}Initialization complete{Style.RESET_ALL}")
class MainProgram: """ Main Class of the program, initiates everything and implements OpenGL environment""" def __init__(self): self.init_opengl() self.animation_clock = None self.lost_leak = False self.p_liquid = None # Memory shared variables self.q_activate, self.rst, self.lost = SimpleQueue(), SimpleQueue(), SimpleQueue() self.liquid_grid = Array(ctypes.c_double, (Conf.dim_grille[0] + 1) * Conf.dim_grille[1]) self.liquid_im = Array(ctypes.c_double, 10 * (Conf.dim_grille[0] + 1) * 10 * Conf.dim_grille[1] * 4) self.run_liquid_process() # Main utility class self.augmented_reality = AugmentedReality(Conf.width, Conf.height, self.q_activate, self.liquid_im, self.liquid_grid) # execute OpenGL loop forever self.loop() def init_opengl(self): # OpenGL setup glutInit(sys.argv) glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) glutInitWindowSize(Conf.width, Conf.height) glutInitWindowPosition(screen_number * 1366, 0) # main window dim + 1 glutCreateWindow("Poche AR") glutFullScreen() glClearColor(0.0, 0.0, 0.0, 1.0) glutDisplayFunc(self.display) glutReshapeFunc(self.reshape) glutKeyboardFunc(self.keyboard) glutIdleFunc(self.idle) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) def run_liquid_process(self): # Liquid control Process self.p_liquid = Liquid(self.liquid_im, self.q_activate, self.rst, self.lost, self.liquid_grid) self.p_liquid.daemon = True self.p_liquid.start() def idle(self): """ Opengl routine function, called each loop iteration""" Glob.delta_t = clock() - Glob.t_ref Glob.t_ref = clock() if Glob.mode !=2: # update frame from webcam self.augmented_reality.cam.take_frame() if Glob.mode == 0: # build mode, update bricks self.augmented_reality.detect_brick() self.augmented_reality.check_buttons() if Glob.mode == 1: # Testing structure mode if Conf.cooling: Conf.t_chamber = Conf.temperature if (self.augmented_reality.buttonStart.is_triggered and self.augmented_reality.number) > 0 \ else max(Conf.t_chamber - Conf.cooling_factor * Glob.delta_t, 293) Glob.brick_array.update(not self.augmented_reality.buttonStart.is_ready() and self.augmented_reality.number >= 0) else: Glob.brick_array.update(not self.augmented_reality.buttonStart.is_ready() and self.augmented_reality.number >= 0) lost_struct = False # Glob.brick_array.test_loose() if not self.lost.empty(): self.lost_leak = self.lost.get() if (self.lost_leak or lost_struct) or self.augmented_reality.buttonReset.is_triggered: print("reset") if self.augmented_reality.buttonReset.is_triggered: print("(from rst button)") elif self.lost_leak: print("(from liquid)") elif lost_struct: print("(from struct)") self.rst.put(True) self.augmented_reality.buttonStart.is_triggered = False Glob.t_ref, Glob.delta_t = clock(), 0 Glob.hand_text = None Glob.updating = False Glob.update_timer = 0 self.augmented_reality.buttonReset.is_triggered = False self.augmented_reality.reset() Glob.mode = 2 self.animation_clock = clock() self.augmented_reality.buttonStart.is_waiting = True self.lost_leak = False # update brick grid in liquid simulation if Glob.brick_array is not None: with self.liquid_grid.get_lock(): # synchronize access arr = np.frombuffer(self.liquid_grid.get_obj()) # no data copying arr[:Conf.dim_grille[0] * Conf.dim_grille[1]] = Glob.brick_array.get_grid().flatten() # tell OpenGL to redraw as soon as possible glutPostRedisplay() def display(self): """ Opengl drawing function, called when an update is needed""" # Set Projection Matrix glMatrixMode(GL_PROJECTION) glLoadIdentity() gluOrtho2D(0, Conf.width, 0, Conf.height) # Switch to Model View Matrix glMatrixMode(GL_MODELVIEW) glLoadIdentity() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.augmented_reality.render() if Glob.mode == 2: # reset mode self.augmented_reality.buttonStart.pause() self.augmented_reality.lost_screen() if clock() - self.animation_clock > 5: Glob.mode = 0 else: self.augmented_reality.buttonStart.unpause() glutSwapBuffers() @staticmethod def reshape(w, h): """ OpenGl function, change windows property when window's size changes""" if h == 0: h = 1 glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() if w <= h: glOrtho(-Glob.nRange, Glob.nRange, -Glob.nRange * h / w, Glob.nRange * h / w, -Glob.nRange, Glob.nRange) else: glOrtho(-Glob.nRange * w / h, Glob.nRange * w / h, -Glob.nRange, Glob.nRange, -Glob.nRange, Glob.nRange) glMatrixMode(GL_MODELVIEW) glLoadIdentity() def keyboard(self, key, x, y): """ Opengl function, add action to keyboard input""" print("key_code =%s" % key) if key == b'\x1b': # kill program when escape is pressed self.p_liquid.terminate() self.p_liquid.join() glutLeaveMainLoop() if key == b'd': # change debug mode with d key Glob.debug = not Glob.debug def loop(self): """ in case we handle the loop differently """ glutMainLoop() # OpenGL loop, handle idle/display/reshape/keyboard calls
ir_values = Array('i', 6) laser_values = Array('i', 520) num_laser_values = Value('i', 0) num_hall_reads = Value('i', 0) gyro_value = Value('d', 0) has_new_ir = Value('i', 0) mode = Value('i', 0) # Manual, Atonomous = 0, 1 pid_cons = Array('d', 2) pid_cons[0] = -1 # Make sure to not read pid values from array on boot grid = Array('i', MAP_SIZE**2) shared_pos = Array('i',2) move_cmd = Array('c', 50) steering_cmd_man = SimpleQueue() # Init ir array to avoid errors in the beginning with ir_values.get_lock(): ir_values[0] = EMPTY_TILE # Setup and start processes # sensor_process: Handles communication with the sensor module # slam_process: Decision logic. Uses data recieved from both the sensor and bluetooth processes. # The slam process also takes care of communication with the steering module. # bluetooth_process: Handles communication with the bluetooth connected laptop sensor_process = Process(target=sensor.sensor_serial, args=(ir_values, laser_values, gyro_value, num_laser_values, num_hall_reads, has_new_ir)) slam_process = Process(target=slam, args=(ir_values, laser_values, mode, steering_cmd_man, pid_cons, gyro_value, num_laser_values, num_hall_reads, grid, shared_pos, move_cmd, has_new_ir)) bluetooth_process = Process(target=blueztooth.bluetooth_loop, args=(ir_values, laser_values, steering_cmd_man, mode, pid_cons, num_laser_values, grid, shared_pos, move_cmd)) sensor_process.start() slam_process.start() bluetooth_process.start() print("-- INIT COMPLETE --")
def main(): global top_left_icon, scale args = get_argument() # read all pattern images target_dict = {} for i in animals: target_dict[i] = cv2.cvtColor( cv2.imread("icons/animals/{}.png".format(animals[i])), cv2.COLOR_BGR2GRAY) home_screen = cv2.imread("icons/home.png") round_start = cv2.cvtColor(cv2.imread("icons/round.png"), cv2.COLOR_BGR2GRAY) win = cv2.cvtColor(cv2.imread("icons/win.png"), cv2.COLOR_BGR2GRAY) battle = cv2.cvtColor(cv2.imread("icons/battle.png"), cv2.COLOR_BGR2GRAY) home_icons = cv2.cvtColor(cv2.imread("icons/home_icons.png"), cv2.COLOR_BGR2GRAY) game_mode = 0 battle_start_time = None if args.mp: top_left_flag = True with mss.mss() as sct: min_h = min_w = 300000 max_h = max_w = 0 scale = 0 print("Scan for home screen") while True: # Get raw pixels from the screen, save it to a Numpy array img = np.array(sct.grab(sct.monitors[1])) min_h, max_h, min_w, max_w, shape = locate_home_screen( img[:, :, :3], home_screen) if max_h != 0: scale = img.shape[0] / shape[0] break try: if scale != 0: print("Screen detected, standing by") game_mode = 1 min_h = int(round(min_h * scale)) - 5 max_h = int(round(max_h * scale)) + 5 min_w = int(round(min_w * scale)) - 5 max_w = int(round(max_w * scale)) + 5 coord_base = np.array([min_h, min_w]) monitor = { "top": min_h, "left": min_w, "width": max_w - min_w, "height": max_h - min_h } # get the correct size patterns # round_start = cv2.resize(round_start, (0, 0), fx=scale, fy=scale) # win = cv2.resize(win, (0, 0), fx=scale, fy=scale) # battle = cv2.resize(battle, (0, 0), fx=scale, fy=scale) # for i in target_dict: # target_dict[i] = cv2.resize(target_dict[i], (0, 0), fx=scale, fy=scale) icon_shape = np.array( cv2.resize(target_dict[2], (0, 0), fx=scale, fy=scale).shape) # start second process if specified if args.mp: print("Start moving process...") q = Queue(5) shared_arr = Array(ctypes.c_double, 64) np_arr = np.frombuffer(shared_arr.get_obj()) process_move = Process(target=move_icon, args=( shared_arr, q, icon_shape, coord_base, )) process_move.start() while True: img = np.array(sct.grab(monitor))[:, :, :3] img = cv2.resize(img, (0, 0), fx=1 / scale, fy=1 / scale) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) if (game_mode == 1 or game_mode == 3) and is_pattern_found( img_gray, round_start): game_mode = 2 battle_start_time = time.time() print("Start battle!!!") if args.mp: q.put("battle") elif game_mode == 3 and is_pattern_found(img_gray, win): game_mode = 1 print("End battle, standing by") if args.mp: q.put("pause") elif game_mode == 2: # detect, parse, and command board arr = get_arr(img_gray, target_dict) if args.mp: if top_left_icon is not None and top_left_flag: top_left_flag = False q.put(top_left_icon) with shared_arr.get_lock(): np_arr[:] = arr.reshape(-1) else: moves = get_move(arr) if len(moves) != 0: for idx in range(len(moves)): start, dd = moves[idx] coord_start = (start * icon_shape + (icon_shape * 2 / 3) + top_left_icon + coord_base).astype(np.int32) coord_dest = ( coord_start + dirs[dd] * icon_shape).astype(np.int32) pyautogui.moveTo(coord_start[1], coord_start[0]) pyautogui.dragTo(coord_dest[1], coord_dest[0], button='left') # detect if cur round is over if time.time() - battle_start_time > 29: if is_pattern_found(img_gray, battle): game_mode = 3 if args.mp: q.put('pause') print("Pause battle") elif is_pattern_found(img_gray, home_icons): game_mode = 1 print("Home icons detected, standing by") elif game_mode != 1 and is_pattern_found( img_gray, home_icons): game_mode = 1 time.sleep(0.005) except KeyboardInterrupt: if args.mp: q.put(None) process_move.join()
class RingBuffer(object): """ A RingBuffer containing complex values. """ def __init__(self, size: int): self.__data = Array("f", 2*size) self.size = size self.__left_index = Value("L", 0) self.__right_index = Value("L", 0) self.__length = Value("L", 0) def __len__(self): return self.__length.value @property def left_index(self): return self.__left_index.value @left_index.setter def left_index(self, value): self.__left_index.value = value % self.size @property def right_index(self): return self.__right_index.value @right_index.setter def right_index(self, value): self.__right_index.value = value % self.size @property def is_empty(self) -> bool: return len(self) == 0 @property def space_left(self): return self.size - len(self) @property def data(self): return np.frombuffer(self.__data.get_obj(), dtype=np.complex64) @property def view_data(self): """ Get a representation of the ring buffer for plotting. This is expensive, so it should only be used in frontend :return: """ left, right = self.left_index, self.left_index + len(self) if left > right: left, right = right, left data = np.frombuffer(self.__data.get_obj(), dtype=np.complex64) return np.concatenate((data[left:right], data[right:], data[:left])) def clear(self): self.left_index = 0 self.right_index = 0 def will_fit(self, number_values: int) -> bool: return number_values <= self.space_left def push(self, values: np.ndarray): """ Push values to buffer. If buffer can't store all values a ValueError is raised """ n = len(values) if len(self) + n > self.size: raise ValueError("Too much data to push to RingBuffer") slide_1 = np.s_[self.right_index:min(self.right_index + n, self.size)] slide_2 = np.s_[:max(self.right_index + n - self.size, 0)] with self.__data.get_lock(): data = np.frombuffer(self.__data.get_obj(), dtype=np.complex64) data[slide_1] = values[:slide_1.stop - slide_1.start] data[slide_2] = values[slide_1.stop - slide_1.start:] self.right_index += n self.__length.value += n def pop(self, number: int, ensure_even_length=False): """ Pop number of elements. If there are not enough elements, all remaining elements are returned and the buffer is cleared afterwards. If buffer is empty, an empty numpy array is returned. If number is -1 (or any other value below zero) than complete buffer is returned """ if ensure_even_length: number -= number % 2 if len(self) == 0 or number == 0: return np.array([], dtype=np.complex64) if number < 0: # take everything number = len(self) else: number = min(number, len(self)) with self.__data.get_lock(): data = np.frombuffer(self.__data.get_obj(), dtype=np.complex64) result = np.empty(number, dtype=np.complex64) if self.left_index + number > len(data): end = len(data) - self.left_index else: end = number result[:end] = data[self.left_index:self.left_index + end] if end < number: result[end:] = data[:number-end] self.left_index += number self.__length.value -= number return result
class RingBuffer(object): """ A RingBuffer containing complex values. """ def __init__(self, size: int): self.__data = Array("f", 2 * size) self.size = size self.__left_index = Value("L", 0) self.__right_index = Value("L", 0) self.__length = Value("L", 0) def __len__(self): return self.__length.value @property def left_index(self): return self.__left_index.value @left_index.setter def left_index(self, value): self.__left_index.value = value % self.size @property def right_index(self): return self.__right_index.value @right_index.setter def right_index(self, value): self.__right_index.value = value % self.size @property def is_empty(self) -> bool: return len(self) == 0 @property def space_left(self): return self.size - len(self) @property def data(self): return np.frombuffer(self.__data.get_obj(), dtype=np.complex64) @property def view_data(self): """ Get a representation of the ring buffer for plotting. This is expensive, so it should only be used in frontend :return: """ left, right = self.left_index, self.left_index + len(self) if left > right: left, right = right, left data = np.frombuffer(self.__data.get_obj(), dtype=np.complex64) return np.concatenate((data[left:right], data[right:], data[:left])) def clear(self): self.left_index = 0 self.right_index = 0 def will_fit(self, number_values: int) -> bool: return number_values <= self.space_left def push(self, values: np.ndarray): """ Push values to buffer. If buffer can't store all values a ValueError is raised """ n = len(values) if len(self) + n > self.size: raise ValueError("Too much data to push to RingBuffer") slide_1 = np.s_[self.right_index:min(self.right_index + n, self.size)] slide_2 = np.s_[:max(self.right_index + n - self.size, 0)] with self.__data.get_lock(): data = np.frombuffer(self.__data.get_obj(), dtype=np.complex64) data[slide_1] = values[:slide_1.stop - slide_1.start] data[slide_2] = values[slide_1.stop - slide_1.start:] self.right_index += n self.__length.value += n def pop(self, number: int, ensure_even_length=False): """ Pop number of elements. If there are not enough elements, all remaining elements are returned and the buffer is cleared afterwards. If buffer is empty, an empty numpy array is returned. If number is -1 (or any other value below zero) than complete buffer is returned """ if ensure_even_length: number -= number % 2 if len(self) == 0 or number == 0: return np.array([], dtype=np.complex64) if number < 0: # take everything number = len(self) else: number = min(number, len(self)) with self.__data.get_lock(): data = np.frombuffer(self.__data.get_obj(), dtype=np.complex64) result = np.empty(number, dtype=np.complex64) if self.left_index + number > len(data): end = len(data) - self.left_index else: end = number result[:end] = data[self.left_index:self.left_index + end] if end < number: result[end:] = data[:number - end] self.left_index += number self.__length.value -= number return result
class VideoStream: """ This class returns constant framerate frames from the input stream. """ def __init__(self, input_source, trg_fps, batch_size): """Constructor""" try: self._input_source = int(input_source) except ValueError: self._input_source = input_source self._trg_fps = trg_fps assert self._trg_fps > 0 self._batch_size = batch_size assert self._batch_size > 0 cap = cv2.VideoCapture(self._input_source) assert cap.isOpened(), "Can't open " + str(self._input_source) source_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) source_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) cap.release() self._image_shape = [source_height, source_width, 3] self._batch_shape = [batch_size] + self._image_shape self._image_buffer_size = int(np.prod(self._image_shape)) self._batch_buffer_size = int(np.prod(self._batch_shape)) self._source_finished = Value('i', False, lock=False) self._raw_frame = Array('B', self._image_buffer_size, lock=True) self._slow_frame = Array('B', self._image_buffer_size, lock=True) self._slow_batch = Array('B', self._batch_buffer_size, lock=True) self._frame_generator_process = None self._producer_process = None def get_live_frame(self): """Returns last live frame from the input stream""" if self._source_finished.value: return None with self._raw_frame.get_lock(): buffer = np.frombuffer(self._raw_frame.get_obj(), dtype=np.uint8) frame = np.copy(buffer.reshape(self._image_shape)) return frame def get_batch(self): """Returns last batch of frames with constant framerate from the input stream""" if self._source_finished.value: return None with self._slow_batch.get_lock(): buffer = np.frombuffer(self._slow_batch.get_obj(), dtype=np.uint8) batch = np.copy(buffer.reshape(self._batch_shape)) return batch def start(self): """Starts internal threads""" self._frame_generator_process = \ Process(target=self._frame_generator, args=(self._input_source, self._raw_frame, self._image_shape, self._source_finished)) self._frame_generator_process.daemon = True self._frame_generator_process.start() self._producer_process = \ Process(target=self._producer, args=(self._raw_frame, self._slow_frame, self._slow_batch, self._trg_fps, self._batch_size, self._image_shape, self._source_finished)) self._producer_process.daemon = True self._producer_process.start() def release(self): """Release internal threads""" if self._frame_generator_process is not None: self._frame_generator_process.terminate() self._frame_generator_process.join() if self._producer_process is not None: self._producer_process.terminate() self._producer_process.join() @staticmethod def _frame_generator(input_source, out_frame, frame_shape, finish_flag): """Produces live frames from the input stream""" cap = cv2.VideoCapture(input_source) cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) source_fps = cap.get(cv2.CAP_PROP_FPS) if source_fps > 0: trg_time_step = 1.0 / source_fps else: log.warning( 'Got a non-positive value as FPS of the input. Interpret it as 30 FPS' ) trg_time_step = 1.0 / 30.0 while True: start_time = time.perf_counter() _, frame = cap.read() if frame is None: break with out_frame.get_lock(): buffer = np.frombuffer(out_frame.get_obj(), dtype=np.uint8) np.copyto(buffer.reshape(frame_shape), frame) end_time = time.perf_counter() elapsed_time = end_time - start_time rest_time = trg_time_step - elapsed_time if rest_time > 0.0: time.sleep(rest_time) finish_flag.value = True cap.release() @staticmethod def _producer(input_frame, out_frame, out_batch, trg_fps, batch_size, image_shape, finish_flag): """Produces frames and batch of frames with constant framerate from the internal stream of frames""" trg_time_step = 1.0 / float(trg_fps) batch_shape = [batch_size] + image_shape frame_buffer = [] while not finish_flag.value: start_time = time.perf_counter() with input_frame.get_lock(): in_frame_buffer = np.frombuffer(input_frame.get_obj(), dtype=np.uint8) frame = np.copy(in_frame_buffer.reshape(image_shape)) with out_frame.get_lock(): out_frame_buffer = np.frombuffer(out_frame.get_obj(), dtype=np.uint8) np.copyto(out_frame_buffer.reshape(image_shape), frame) frame_buffer.append(frame) if len(frame_buffer) > batch_size: frame_buffer = frame_buffer[-batch_size:] if len(frame_buffer) == batch_size: with out_batch.get_lock(): out_batch_buffer = np.frombuffer(out_batch.get_obj(), dtype=np.uint8) np.copyto(out_batch_buffer.reshape(batch_shape), frame_buffer) end_time = time.perf_counter() elapsed_time = end_time - start_time rest_time = trg_time_step - elapsed_time if rest_time > 0.0: time.sleep(rest_time)
def acquire_parallel(self, worker_cls, worker_args, result_shape, plot=False): """ :param worker: Function which the subordinate threads execute as their target :param proc_fun: Function used by the subordinate threads to process their buffers :param result_shape: Shape of the buffer which is the result of the entire acquisition. """ from multiprocessing import Array, Value, Event from slab.plotting import ScriptPlotter import time acquire_buffer_time = self.samples_per_buffer / ( self.samples_per_second) print('Acquire buffer time %.2e' % acquire_buffer_time) print('Inter-buffer time %.2e' % self.seconds_per_buffer) print('Duty Cycle', acquire_buffer_time / self.seconds_per_buffer) try: # I don't know why this needs to happen again? channel = 0 if self.ch1_enabled: channel |= 1 if self.ch2_enabled: channel |= 2 pretriggers = C.c_long(0) flags = U32(513) ret = self.Az.AlazarBeforeAsyncRead( self.handle, U32(channel), pretriggers, U32(self.config.samplesPerRecord), U32(self.config.recordsPerBuffer), U32(self.config.recordsPerAcquisition), flags) # Initialize buffers buffers = [ Array(U8, self.bytes_per_buffer) for _ in range(self.buffer_count) ] for b in buffers: ret = self.Az.AlazarPostAsyncBuffer(self.handle, b.get_obj(), U32(self.bytes_per_buffer)) self.assert_az(ret, 0, 'Initial Post Buffer') res_buffer = Array(C.c_longdouble, result_shape) # Initialize threads bufs_merged = Value(U32, 1) buf_ready_events = [Event() for _ in range(self.buffer_count)] buf_post_events = [Event() for _ in range(self.buffer_count)] workers = [ worker_cls( *(worker_args + (self.config, b, bre, bpe, res_buffer, bufs_merged))) for b, bre, bpe in zip(buffers, buf_ready_events, buf_post_events) ] for w in workers: w.start() time.sleep(1) import atexit atexit.register(lambda: [w.terminate() for w in workers]) # Initialize things used during capture if plot: plotter = ScriptPlotter() plotter.init_plot('Data', rank=1, accum=False) buffers_acquired, buffers_completed, plot_count = 0, 0, 0 start_time = time.time() # Begin capture ret = self.Az.AlazarStartCapture(self.handle) self.assert_az(ret, 0, "Start Capture") unready_count = 0 while buffers_completed < self.buffers_per_acquisition: # Post all completed buffers while buf_post_events[buffers_completed % self.buffer_count].is_set(): buf_post_events[buffers_completed % self.buffer_count].clear() buf = buffers[buffers_completed % self.buffer_count] with buf.get_lock(): ret = self.Az.AlazarPostAsyncBuffer( self.handle, buf.get_obj(), U32(self.bytes_per_buffer)) self.assert_az(ret, buffers_acquired, 'Post Buffer') buffers_completed += 1 # Current buffer rotates in a ring buf_idx = buffers_acquired % self.buffer_count buf = buffers[buf_idx] # Pull data to buffer with buf.get_lock(): ret = self.Az.AlazarWaitAsyncBufferComplete( self.handle, buf.get_obj(), U32(self.timeout)) if ret == 573: unready_count += 1 continue # BufferNotReady, go back and try to post some buffers. else: self.assert_az(ret, buffers_acquired, 'Wait Buffer Complete') buffers_acquired += 1 # Tell worker thread to begin processing buf_ready_events[buf_idx].set() # If a second has elapsed, replot the avg_buffer if (time.time() - start_time) / self.seconds_per_plot > plot_count: if plot: with res_buffer.get_lock(): plotter.msg(buffers_acquired, buffers_completed, bufs_merged.value) plotter.plot(np.frombuffer(res_buffer.get_obj()), 'Data') plot_count += 1 else: print(buffers_acquired, buffers_completed) plot_count += 1 finally: pass # self.Az.AlazarAbortAsyncRead(self.handle) # if buffers_completed: # final_time = time.time() # print 'Unready Count', unready_count # total_time = final_time - start_time # print 'Total time', total_time # actual_time_per_buffer = total_time / buffers_completed # print 'Time per buffer %.2e' % actual_time_per_buffer # errf = lambda a, b: abs(a - b) / min(a, b) # print 'Perceived overhead %.1f%%' % (errf(actual_time_per_buffer, seconds_per_buffer) * 100) # else: # print 'No buffers completed' res = np.frombuffer(res_buffer.get_obj()) return res
class RingBuffer(object): """ A RingBuffer containing complex values. """ def __init__(self, size: int): self.__data = Array("f", 2*size) self.size = size self.__current_index = Value("L", 0) @property def current_index(self): return self.__current_index.value @current_index.setter def current_index(self, value): self.__current_index.value = value @property def is_empty(self) -> bool: return self.current_index == 0 @property def space_left(self): return self.size - self.current_index @property def data(self): return np.frombuffer(self.__data.get_obj(), dtype=np.complex64) def __getitem__(self, index): return self.data[index] def __repr__(self): return "RingBuffer " + str(self.data) def __increase_current_index_by(self, n: int): self.current_index += n if self.current_index > self.size: self.current_index = self.size def clear(self): self.current_index = 0 def will_fit(self, number_values: int) -> bool: return number_values <= self.space_left def push(self, values: np.ndarray): """ Push values to buffer. If buffer can't store all values a ValueError is raised :param values: :return: """ n = len(values) with self.__data.get_lock(): data = np.frombuffer(self.__data.get_obj(), dtype=np.complex64) data[self.current_index:self.current_index+n] = values self.__increase_current_index_by(n) def pop(self, number: int) -> np.ndarray: """ Pop number of elements. If there are not enough elements, all remaining elements are returned and the buffer is cleared afterwards. If buffer is empty, an empty numpy array is returned. """ if number > self.current_index: number = self.current_index with self.__data.get_lock(): self.current_index -= number result = np.copy(self.data[0:number]) data = np.frombuffer(self.__data.get_obj(), dtype=np.complex64) data[:] = np.roll(data, -number) return result
class MemoryCache(object): def __init__(self): self.cacheX = None self.cacheX_base = None self.limitsX = None self.limitsX_base = None self.cache_used_counter_x = Value('i', 0) #self.cache_renewed_counter_x = Value('i', 0) self.image_shape_x = None self.cache_shape_x = None self.numE_x = None self.cacheY = None self.cacheY_base = None self.limitsY = None self.limitsY_base = None self.cache_used_counter_y = Value('i', 0) #self.cache_renewed_counter_y = Value('i', 0) self.image_shape_y = None self.cache_shape_y = None self.numE_y = None self.cache_size = CACHE_SIZE self.cache_period = CACHE_REUSE_PERIOD self.renew_cache = Value(ctypes.c_bool, False) self.cache_used_counter = Value('i', 0) self.cache_renewed_counter = Value('i', 0) self._memlock_ = Lock() def set_image_shape_x(self, image_shape): self.image_shape_x = image_shape self.cache_shape_x = (self.cache_size, ) + self.image_shape_x def set_number_channels_x(self, num_channels): self.numE_x = num_channels def set_image_shape_y(self, image_shape): self.image_shape_y = image_shape self.cache_shape_y = (self.cache_size, ) + self.image_shape_y def set_number_channels_y(self, num_channels): self.numE_y = num_channels def allocate(self): nitems_x = 1 nitems_y = 1 for i in range(0, len(self.cache_shape_x)): nitems_x *= self.cache_shape_x[i] for i in range(0, len(self.cache_shape_y)): nitems_y *= self.cache_shape_y[i] self.cacheX_base = Array(ctypes.c_float, nitems_x) self.cacheX = numpy.ctypeslib.as_array(self.cacheX_base.get_obj()) self.cacheX = self.cacheX.reshape(self.cache_shape_x) self.limitsX_base = Array(ctypes.c_double, self.cache_size * self.numE_x * 2) self.limitsX = numpy.ctypeslib.as_array(self.limitsX_base.get_obj()) self.limitsX = self.limitsX.reshape((self.cache_size, self.numE_x, 2)) self.cacheY_base = Array(ctypes.c_float, nitems_y) self.cacheY = numpy.ctypeslib.as_array(self.cacheY_base.get_obj()) self.cacheY = self.cacheY.reshape(self.cache_shape_y) self.limitsY_base = Array(ctypes.c_double, self.cache_size * self.numE_y * 2) self.limitsY = numpy.ctypeslib.as_array(self.limitsY_base.get_obj()) self.limitsY = self.limitsY.reshape((self.cache_size, self.numE_y, 2)) self.renew_cache = Value(ctypes.c_bool, True) self.cache_used_counter = Value('i', 0) self.cache_used_counter_x = Value('i', 0) self.cache_used_counter_y = Value('i', 0) self.cache_renewed_counter = Value('i', 0) def is_cache_updated(self): return (self.renew_cache.value is False) def get_number_renewed_items(self): return int(self.cache_renewed_counter.value) def get_renew_index(self): #self._memlock_.acquire() result = 0 with self.cache_renewed_counter.get_lock(): result = self.cache_renewed_counter.value self.cache_renewed_counter.value += 1 if self.cache_renewed_counter.value >= self.cache_size: with self.renew_cache.get_lock(): self.renew_cache.value = False with self.cache_renewed_counter.get_lock(): self.cache_renewed_counter.value = 0 if self.cache_used_counter.value >= self.cache_period: with self.cache_used_counter.get_lock(): self.cache_used_counter.value = 0 with self.cache_used_counter_x.get_lock(): self.cache_used_counter_x.value = 0 with self.cache_used_counter_y.get_lock(): self.cache_used_counter_y.value = 0 #self._memlock_.release() return result def get_cache_size(self): return self.cache_size def set_cache_item_x(self, index, item): #self._memlock_.acquire() #with self._memlock_: with self.cacheX_base.get_lock(): self.cacheX[index] = item #print("Cache X - renewed items: {}; used items: {}". format(self.cache_renewed_counter, self.cache_used_counter_x)) #self._memlock_.release() def set_item_limits_x(self, index, minval, maxval): with self.limitsX_base.get_lock(): self.limitsX[index, :, 0] = minval self.limitsX[index, :, 1] = maxval def set_cache_item_y(self, index, item): #self._memlock_.acquire() #with self._memlock_: with self.cacheY_base.get_lock(): self.cacheY[index] = item #self._memlock_.release() def set_item_limits_y(self, index, minval, maxval): with self.limitsY_base.get_lock(): self.limitsY[index, :, 0] = minval self.limitsY[index, :, 1] = maxval def get_cache_item_x(self, index): result = None #self._memlock_.acquire() #with self._memlock_: with self.cacheX_base.get_lock(): result = self.cacheX[index] with self.cache_used_counter_x.get_lock(): self.cache_used_counter_x.value += 1 with self.cache_used_counter.get_lock(): self.cache_used_counter.value = max( self.cache_used_counter_x.value, self.cache_used_counter_y.value) if self.cache_used_counter.value >= self.cache_period: with self.renew_cache.get_lock(): self.renew_cache.value = True #print("Cache X - renewed items: {}; used items: {}".format(self.cache_renewed_counter, self.cache_used_counter_x)) #self._memlock_.release() return result def get_item_limits_x(self, index): minval = None maxval = None with self.limitsX_base.get_lock(): minval = self.limitsX[index, :, 0] maxval = self.limitsX[index, :, 1] return numpy.squeeze(minval), numpy.squeeze(maxval) def get_cache_item_y(self, index): result = None #self._memlock_.acquire() #with self._memlock_: with self.cacheY_base.get_lock(): result = self.cacheY[index] with self.cache_used_counter_y.get_lock(): self.cache_used_counter_y.value += 1 with self.cache_used_counter.get_lock(): self.cache_used_counter.value = max( self.cache_used_counter_x.value, self.cache_used_counter_y.value) if self.cache_used_counter.value >= self.cache_period: with self.renew_cache.get_lock(): self.renew_cache.value = True #self._memlock_.release() return result def get_item_limits_y(self, index): minval = None maxval = None with self.limitsY_base.get_lock(): minval = self.limitsY[index, :, 0] maxval = self.limitsY[index, :, 1] return numpy.squeeze(minval), numpy.squeeze(maxval)
class Screen(Device): def __init__(self, nomenclature="", width=0., height=0., screen_width=0., screen_height=0.): Device.__init__(self, nomenclature, width, height) self.screen_width = screen_width self.screen_height = screen_height self.count = Array('i', 10000) def __repr__(self): r = str(self) + "(" r += "width=" + str(self.width) + "m, " r += "height=" + str(self.height) + "m, " r += "length=" + str(self.length) + "m, " r += "screen_width=" + str(self.screen_width) + "m, " r += "screen_height=" + str(self.screen_height) + "m )" return r def transport(self, particle): if not self.is_particle_lost(particle): self.collect(particle) if self.next: return self.next.transport(particle) else: return particle else: return None def collect(self, particle): half_screen_width = 0.5 * self.screen_width half_screen_height = 0.5 * self.screen_height cell_width = 0.01 * self.screen_width cell_height = 0.01 * self.screen_height if half_screen_width > particle.x > -half_screen_width and half_screen_height > particle.y > -half_screen_height: x = int((particle.x + half_screen_width) / cell_width) y = int((particle.y + half_screen_height) / cell_height) with self.count.get_lock(): self.count[100 * x + y] += 1 def num_of_particles(self): c = 0 for i in self.count: c += i return c def reset(self): self.count = Array('i', 10000) if self.next: self.next.reset() def show(self): x = [] y = [] z = [] for i in range(100): for j in range(100): x.append(float(i)) y.append(float(j)) z.append(float(self.count[100 * i + j])) plt.hist2d(x, y, bins=100, weights=z) plt.colorbar() plt.show()