def build_superworld(world, new_size): p = int( math.log2(len(world)) ) + 1 # 2^p is number of points along each dimention of the space hc = HilbertCurve(p, 2) node_seq_coords = [(hc.distance_from_coordinates(n[1]['coords']), n[0]) for n in world.nodes(data=True)] node_seq_coords.sort() chunks = np.array_split(node_seq_coords, new_size) center_nodes = [chunk[len(chunk) // 2][1] for chunk in chunks] node_mapping = nx.voronoi_cells(world, center_nodes) new_nodes = [] i = 0 for center_node in center_nodes: new_nodes.append((i, {"nodes": node_mapping[center_node]})) for n in node_mapping[center_node]: world.nodes[n]['supernode'] = i i += 1 superworld = nx.Graph( ) # we always use graph to simplify training, for both world and superworld superworld.add_nodes_from(new_nodes) # we assume all areas are approximately the same size, so we add edges in superworld of the same length edges = set() for e in world.edges(): n1 = world.nodes[e[0]]['supernode'] n2 = world.nodes[e[1]]['supernode'] if n1 != n2 and (n1, n2) not in edges: edges.add((n1, n2)) superworld.add_edges_from(list(edges)) return superworld
class S3DISDataset(Dataset): def __init__(self, data_label, num_features=9, augment=False): self.augment = augment self.num_features = num_features self.data, self.label = data_label self.p = 7 # compute hilbert order for voxelized space logging.info('Computing hilbert distances...') self.hilbert_curve = HilbertCurve(self.p, 3) def __len__(self): return self.data.shape[0] def __getitem__(self, item): pointcloud = self.data[item, ...] label = self.label[item, ...] if self.augment: points = pointcloud[:, :3] points = rotate_points(points) points = scale_points(points) points = add_noise_points(points) pointcloud[:, :3] = points # get coordinates coordinates = pointcloud[:, :3] - pointcloud[:, :3].min(axis=0) # compute hilbert order points_norm = pointcloud[:, :3] - pointcloud[:, :3].min(axis=0) points_norm /= points_norm.max(axis=0) + 1e-23 # order points in hilbert order points_voxel = np.floor(points_norm * (2**self.p - 1)) hilbert_dist = np.zeros(points_voxel.shape[0]) for i in range(points_voxel.shape[0]): hilbert_dist[i] = self.hilbert_curve.distance_from_coordinates( points_voxel[i, :].astype(int)) idx = np.argsort(hilbert_dist) # return appropriate number of features if self.num_features == 4: pointcloud = np.hstack( (pointcloud[:, 3:6], pointcloud[:, 2, np.newaxis])) elif self.num_features == 5: pointcloud = np.hstack((np.ones( (pointcloud.shape[0], 1)), pointcloud[:, 3:6], pointcloud[:, 2, np.newaxis])) elif self.num_features == 9: min_val = pointcloud[:, :3].min(axis=0) pointcloud = np.hstack((pointcloud[:, :3] - min_val, pointcloud[:, 3:6], pointcloud[:, 6:9])) else: raise ValueError( 'Incorrect number of features provided. Values should be 4, 5, or 9, but {} provided' .format(self.num_features)) return pointcloud[idx, :], coordinates[idx, :], label[idx]
def hilbert_sort(conf, D): hc = HilbertCurve(64, D) int_confs = (conf * 1000).astype(np.int64) dists = [] for xyz in int_confs.tolist(): dist = hc.distance_from_coordinates(xyz) dists.append(dist) perm = np.argsort(dists) return perm
def hilbert_distance(coordinates, iterations=5): count_entries, dims = coordinates.shape distances = np.zeros([count_entries]) cells = 2**(iterations * dims) transform = HilbertCurve(iterations, dims) mm = MinMaxScaler((0, transform.max_x)) normed_coords = np.rint(mm.fit_transform(coordinates)).astype('int') for i in range(len(coordinates)): distances[i] = transform.distance_from_coordinates(normed_coords[i]) return distances
class ModelNet40(Dataset): def __init__(self, root_dir, phase='train', augment=False): self.phase = phase self.augment = augment self.data, self.label = load_data(root_dir=root_dir, phase=phase) self.p = 7 # hilbert iteration # by changing the value of p, we can control the level of hilbert curve. # this hyperparameter has to be careful and ideally, p should be different for each point cloud. # (because the density distribution is different # compute hilbert order for voxelized space logging.info('Computing hilbert distances...') self.hilbert_curve = HilbertCurve(self.p, 3) # different from voxelization, we are much more efficient def __len__(self): return self.data.shape[0] def __getitem__(self, item): pointcloud = self.data[item, ...] label = self.label[item] # augment data when requested if self.augment: pointcloud = rotate_pointcloud(pointcloud) # pointcloud = translate_pointcloud(pointcloud) pointcloud = scale_pointcloud(pointcloud) # pointcloud = shear_pointcloud(pointcloud) # todo: check if it is because of augmentation being too big. # normalize points points_norm = pointcloud - pointcloud.min(axis=0) points_norm /= points_norm.max(axis=0) + 1e-23 # order points in hilbert order points_voxel = np.floor(points_norm * (2**self.p - 1)) hilbert_dist = np.zeros(points_voxel.shape[0]) # todo: we want to try two methods. # todo: 1. globally along with locally hilbert curve # todo: 2. multi-level of hilbert curve for i in range(points_voxel.shape[0]): # by doing the astype int, it will assign the same hilbert_dist to the points that belong to the same space # todo: check how much duplicates (multi-points in the same space). # answer is no. p is 7, which partition the space very precise hilbert_dist[i] = self.hilbert_curve.distance_from_coordinates( points_voxel[i, :].astype(int)) idx = np.argsort(hilbert_dist) return pointcloud[idx, :], label
def assign_hilbert_curve(normals: np.ndarray): dtype = np.uint32 max_length_axis = 2**16 - 1 bucket_normals = normals bucket_normals_xy = (azimuth_equidistant(bucket_normals) * max_length_axis).astype(dtype) # print(bucket_normals_xy) hilbert_curve = HilbertCurve(16, 2) bucket_normals_hv = [] for i in range(bucket_normals_xy.shape[0]): hv = hilbert_curve.distance_from_coordinates(bucket_normals_xy[i, :]) bucket_normals_hv.append(hv) bucket_normals_hv = np.array(bucket_normals_hv) return bucket_normals_hv
def encode_sfc(points, M=3, p=10): """ points = [N, D, M] """ hilbert_curve = HilbertCurve(p, M) num_points = 2 ** (M*p) - 1 grid_size = 2**p - 1 N = points.shape[0] D = points.shape[1] s = np.zeros((N, D)) for i in range(N): for j in range(D): # change to integer coords = points[i, j, :] * grid_size + 0.5 coords = coords.astype(int) dist = hilbert_curve.distance_from_coordinates(coords) s[i, j] = dist/num_points return s
def hilbert(df, iterations=12, dim=2, delete_temp_features=True, use_grouping=True): """iterations = 4: i.e. 256 cells (2^(p*n)). Frame cannot use multiindexing when use_grouping is true.""" cells = 2**(iterations * dim) xy_transform = HilbertCurve(iterations, dim) mm = MinMaxScaler((0, xy_transform.max_x)) minmax = lambda x: mm.fit_transform(np.rint(x.values.reshape(-1, 1))) df["_x_hnorm"] = minmax(np.rint(df.x)) df["_y_hnorm"] = minmax(np.rint(df.y)) unique_xy = df[["_x_hnorm", "_y_hnorm"]].drop_duplicates().values print("Found", len(unique_xy), "unique positions.") distance_by_xy = {} for i in unique_xy: distance_by_xy[tuple(i)] = xy_transform.distance_from_coordinates( [int(i[0]), int(i[1])]) if use_grouping: import dask.dataframe as dd to_group = df # [['_x_hnorm', '_y_hnorm']] grouped = to_group.groupby(["_x_hnorm", "_y_hnorm"]) def do(group): first = group.iloc[0] coordinates = (first["_x_hnorm"], first["_y_hnorm"]) group["hilbert_distance"] = distance_by_xy[coordinates] return group.reset_index(drop=True) df = grouped.apply(do) else: df["hilbert_distance"] = df[["_x_hnorm", "_y_hnorm"]].apply( lambda xy: distance_by_xy[tuple(xy)], axis=1) # XXX: very slow df["hilbert_distance"] /= cells if delete_temp_features: df.drop(columns=["_x_hnorm", "_y_hnorm"], inplace=True) return df.reset_index(drop=True)
class S3DIS(Dataset): def __init__(self, data_label, augment=False): self.augment = augment self.data, self.label = data_label self.p = 7 # compute hilbert order for voxelized space logging.info('Computing hilbert distances...') self.hilbert_curve = HilbertCurve(self.p, 3) def __len__(self): return self.data.shape[0] def __getitem__(self, item): pointcloud = self.data[item, ...] label = self.label[item, ...] # nns = self.adj[item, ...] if self.augment: pointcloud = utl.augment_point_cloud(pointcloud) # normalize points points_norm = pointcloud - pointcloud.min(axis=0) points_norm /= points_norm.max(axis=0) + 1e-23 # order points in hilbert order points_voxel = np.floor(points_norm * (2**self.p - 1)) hilbert_dist = np.zeros(points_voxel.shape[0]) # todo: we want to try two methods. # todo: 1. globally along with locally hilbert curve # todo: 2. multi-level of hilbert curve for i in range(points_voxel.shape[0]): # by doing the astype int, it will assign the same hilbert_dist to the points that belong to the same space # todo: check how much duplicates (multi-points in the same space). # answer is no. p is 7, which partition the space very precise hilbert_dist[i] = self.hilbert_curve.distance_from_coordinates( points_voxel[i, 0:3].astype(int)) idx = np.argsort(hilbert_dist) return pointcloud[idx, :], label[ idx] # todo: label also need indexing.
class ModelNet40(Dataset): def __init__(self, root_dir, phase='train', augment=False): self.phase = phase self.augment = augment self.data, self.label = load_data(root_dir=root_dir, phase=phase) self.p = 7 # compute hilbert order for voxelized space logging.info('Computing hilbert distances...') self.hilbert_curve = HilbertCurve(self.p, 3) def __len__(self): return self.data.shape[0] def __getitem__(self, item): pointcloud = self.data[item, ...] label = self.label[item] # augment data when requested if self.augment: pointcloud = rotate_pointcloud(pointcloud) # pointcloud = translate_pointcloud(pointcloud) pointcloud = scale_pointcloud(pointcloud) # pointcloud = shear_pointcloud(pointcloud) # normalize points points_norm = pointcloud - pointcloud.min(axis=0) points_norm /= points_norm.max(axis=0) + 1e-23 # order points in hilbert order points_voxel = np.floor(points_norm * (2**self.p - 1)) hilbert_dist = np.zeros(points_voxel.shape[0]) for i in range(points_voxel.shape[0]): hilbert_dist[i] = self.hilbert_curve.distance_from_coordinates( points_voxel[i, :].astype(int)) idx = np.argsort(hilbert_dist) return pointcloud[idx, :], label
def test_distance_from_coordinates(p, n): side_len = 2**p # build matrix of all possible coordinate coords = np.array(list(product(range(side_len), repeat=n))) # Compute distances as vector result vector_result = distances_from_coordinates(p, coords) # Compare with reference reference_hc = HilbertCurve(p, n) for i in range(coords.shape[0]): coord = coords[i, :] # Reference expected = reference_hc.distance_from_coordinates(coord) # Compute scalar distance and compare scalar_result = distance_from_coordinate(p, coord) assert scalar_result == expected # Compare with vector distance compute above assert vector_result[i] == expected
class Converter(): def __init__(self, method, image_path, max_freq=18000, min_freq=30, im=None, resolution=16, tone_length=1): # Paramters of Conversion self.method = method self.min_freq = min_freq self.max_freq = max_freq self.null_colour = "black" #background colour self.force_null = False #normalises colour to have lowest brightness = 0 self.sample_rate = 44100.0 self.max_vol = 1 self.tone_length = tone_length # in seconds self.resolution = resolution self.image_path = image_path # for reading image (uploaded) self.audio_loc = "./audio/" # for saving audio # Doesn't have image path when live-streaming if image_path: # defines name for audio file self.audio_path = self.audio_loc + image_path.split("/")[-1].split( ".")[0] + ".wav" #reads image as greyscale self.im = imageio.imread(image_path, ignoregamma=True, as_gray=True) else: #When live streaming, images are fed in from camera self.im = im # Read image size self.image_size_x = len(self.im) self.image_size_y = len(self.im[0]) #If still image and it's not the right format, reformat #For livestream images supplied are already right format, no need to check if not self.is_right_format() and self.image_path: self.reformat() # If hilbert is used, initialise the hilbert curve from library if self.method == "hilbert": #requires values p, N for initialisation #variable resolution hilbert curve p = int(np.log2(self.image_size_x)) # 2^(2p) pixels in image N = 2 # number of dimensions, for images always 2 #initialise curve self.hilbert_curve = HilbertCurve(p, N) #get maximum distance from starting point on hilbert curve, this #acts as a reference point for conversion self.max_dist = self.hilbert_curve.distance_from_coordinates( [2**p - 1, 0]) if self.method == "l2r": self.max_dist = self.image_size_x * self.image_size_y # logspace is needed because tones are logarithmically spaced for human hearing self.logspace = np.logspace(np.log2(min_freq), np.log2(self.max_freq), self.max_dist, base=2) # Phase of sin-waves are initially 0, keep track of this for video, # so that waves are continuous when new frame is calculated self.phase = {freq: 0 for freq in self.logspace} # Keeps track of previous volume to emphasize change self.prev_volume = {vol: 0 for vol in self.logspace} return def set_audio_path(self, audio_path): self.audio_loc = audio_path return def set_null_colour(self, colour): self.null_colour = colour return def is_right_format(self): return self.image_size_x == self.image_size_y and type( self.im[0][0]) == np.float def reformat(self): #makes image have the correct format by saving image and using PIL library im = PIL.Image.open(self.image_path) im_resized = im.resize((self.resolution, self.resolution), PIL.Image.ANTIALIAS) new_name = ".".join(self.image_path.split(".")[0:-1]) + "_reduced.png" im_resized.save(new_name) self.im = imageio.imread(new_name, ignoregamma=True, as_gray=True) self.image_size_x = len(self.im) self.image_size_y = len(self.im[0]) def coord_to_freq(self, x, y): ''' Converts x,y position of pixel to corresponding frequency, wraps actual conversion functions -------------------------------------------------------------------- Inputs: x, y: position of pixel -------------------------------------------------------------------- Outputs: frequency ''' if self.method == "hilbert": return self.get_hilbert_freq(x, y) elif self.method == "l2r": return self.get_l2r_freq(x, y) def get_l2r_freq(self, x, y): ''' Converts x,y position of pixel to corresponding frequency using l2r method -------------------------------------------------------------------- Inputs: x, y: position of pixel -------------------------------------------------------------------- Outputs: frequency ''' # calculates distance dist = y * self.image_size_x + x # checks that the distance is smaller than max assert (dist <= self.max_dist), "x = " + str(x) + " y = " + str(y) # returns logarithmically spaced frequency return self.logspace[dist - 1] def get_hilbert_freq(self, x, y): ''' Converts x,y position of pixel to corresponding frequency using pseudo- hilbert-curve -------------------------------------------------------------------- Inputs: x, y: position of pixel -------------------------------------------------------------------- Outputs: frequency ''' #calculates distance along our hilbert curve dist = self.hilbert_curve.distance_from_coordinates([x, y]) #checks that the distance is smaller than max assert (dist <= self.max_dist), "x = " + str(x) + " y = " + str(y) # returns logarithmically spaced frequency return self.logspace[dist - 1] def brightness_to_volume(self, x, y): ''' Converts pixel brightness at x,y position to volume through linear mapping. -------------------------------------------------------------------- Inputs: x, y: position of pixel -------------------------------------------------------------------- Outputs: volume (amplitude) could consider squared mapping for intensity as I~A^2 ''' # maximum brightness, white pixel has this value max_brightness = 255 # for white background if self.null_colour == "white": #divides pixel brightness by max brightness to get relative brightness #multiplies by maximum volume. #This ensures that brightness 0 --> volume = 0 # max brightness --> max volume return self.im[y][ x] / max_brightness * self.max_vol # USE THIS FOR 0 VOLUME = WHITE else: # for black background subtract 255 from brightness and multiply by -1 #This ensures that white --> volume = 0 # black --> max volume return -( self.im[y][x] - 255 ) / max_brightness * self.max_vol #use this for 0 volume = black def f2i(self, f): #maps frequency to corresponding index return int(self.tone_length * f) def complex_entry(self, mag, angle): # needed for fourier transform return mag * np.exp(1j * angle) def convert(self): ''' Converts image to time-signal audio -------------------------------------------------------------------- Inputs: (set by class) -------------------------------------------------------------------- Returns: np.array() holding audio data at specified sample rate ''' # set up initial frequency spectrum as zeros. Needs to have this length # to then have inverse fourier transform of desired SR, tone length spectrum = np.zeros(int(self.sample_rate * self.tone_length), dtype=np.csingle) lowest_vol = 1 #is updated later if self.method != "spectrogram": # spectrogram, not yet implemented, has to be fundamentally differently calculated # loop through rows for y, row in enumerate(self.im): # every new row, update progress bar in gui, not really important self.progress = 80 * y / self.image_size_y #80% of time taken by this #loop through pixels for x, pixel in enumerate(row): # get volume initial_volume = self.brightness_to_volume(x, y) # get frequency freq = self.coord_to_freq(x, y) #set new phases self.phase[ freq] = 2 * np.pi * freq * self.tone_length + self.phase[ freq] #volume is driven by how much pixel changed, at least 0.01, at most 1 volume = max( min(abs(self.prev_volume[freq] - initial_volume), 1), 0.01) # spectrum is mostly empty, use f2i() to get correct index corresponding to right frequency spectrum[self.f2i(freq)] = self.complex_entry( volume, self.phase[freq]) # update lowest volume lowest_vol = min(volume, lowest_vol) #keep track of volume changes for next iteration self.prev_volume[freq] = initial_volume if self.force_null: # if we force the lowest entry to be 0 (normalise), subtract lowest volume from all spectrum -= lowest_vol # now iFFT (inverse fast fourier transform) frequency spectrum to get audio signal self.audio = np.real( fft.ifft(spectrum, self.tone_length * self.sample_rate)) self.audio = self.audio / max( self.audio) #normalise audio to not be too loud/quiet return self.audio def rgb2gray(self): self.im = np.dot(self.im[..., :3], [0.2989, 0.5870, 0.1140]) return def save_audio(self, audio=None): audio_path = self.audio_loc + self.image_path.split("/")[-1].split( ".")[0] + ".wav" if not audio: wavfile.write(self.audio_path, int(self.sample_rate), self.audio) else: wavfile.write(self.audio_path, int(self.sample_rate), audio) return os.path.abspath(audio_path) def set_phase(self, phase): self.phase = phase def set_prev_vol(self, vol): self.prev_volume = vol def save_wav(self, audio, file_name): wavfile.write(file_name, int(self.sample_rate), audio) return
def Hilbert_Mapping(x, p=8, dim=10): hilbert_curve = HilbertCurve(p, dim) aa = [int(xx) for xx in x * 2**p] h = hilbert_curve.distance_from_coordinates(aa) h = np.array(h / (2**(p * dim))) return h
import numpy as np from hilbertcurve.hilbertcurve import HilbertCurve from matplotlib.pyplot import * import cv2 image = cv2.imread('suro.jpg') dim = image.shape center = round(dim[0] / 2) start = center - 170 end = center + 86 reshaped_img = image[start:end, start:end, :] p = 8 N = 3 hill_curve = HilbertCurve(p, N) frequencies = [] for i in range(256 * 256): frequency = hill_curve.distance_from_coordinates( np.reshape(reshaped_img, (256 * 256, 3))[i]) frequencies.append(frequency) print(frequencies) sampling_rate = 44100 # data = np.random.uniform(-1,1,44100) # 44100 random samples between -1 and 1 # scaled = np.int16(data/np.max(np.abs(data)) * 32767) frequencies = np.asarray(frequencies) frequencies = np.interp(frequencies, (frequencies.min(), frequencies.max()), (2000, 20 * 1000)) write('test.wav', sampling_rate, frequencies)
class Hilbertize: """Transforms a batch of coordinates from Euclidean space to pseudo Hilbert distances space.""" # angle that maximizes separation between two Hilbert distance measures ANGLE = np.deg2rad(45) def __init__( self, rotation_axis=((0, 1), (1, 2), (3, 0)), dimension_columns = ['x','y','z','t'], iterations=10 ): # TODO: document rotation_axis self.rotation_axis = rotation_axis self.dimension_columns = dimension_columns self.dims = len(dimension_columns) self.dims_output = 1+ len(self.rotation_axis) self.cells = 2 ** (iterations * self.dims) self.transform = HilbertCurve(iterations, self.dims) self.scale_factor = self.transform.max_x self.edge_resolution = self.transform.max_x def _get_output_column_names(self): return [f"hilbert_{i}" for i in range(self.dims_output)] def __str__(self): return ( f"Hilbertize from {self.dims}D, " f"resolution by edge: {self.edge_resolution+1}, " f"resolution by volume: {self.cells:.1e} cells." ) def __call__(self, x:pd.DataFrame): coordinates = x[self.dimension_columns].values non_coordinates = x.drop(columns=self.dimension_columns) waveforms, dimensions = coordinates.shape assert dimensions == self.dims assert np.all(coordinates >= 0) assert np.all(coordinates <= 1) coordinates -= 0.5 # rotate around center of mass rotations = [coordinates] + [ rotate_2d(coordinates, self.ANGLE, *ax) for ax in self.rotation_axis ] rotations = np.stack(rotations) # XXX: this also manipulates all axis that are not part of the rotations # this leads to a smaller parameter space, but I'm not sure if that's a bad thing rotation_in_01 = rotations / np.sqrt(2) + 0.5 assert rotation_in_01.max() <= 1 assert rotation_in_01.min() >= 0 scaled_rot = rotation_in_01 * self.scale_factor scaled_rot = np.rint(scaled_rot).astype("int") distances = np.zeros([len(coordinates),self.dims_output]) for r, coordinates in enumerate(scaled_rot): for c, coordinate in enumerate(coordinates): distances[c][r] = self.transform.distance_from_coordinates(coordinate) distances /= self.cells # scale distances to [0,1] transformed_x = non_coordinates for dim, key in enumerate(self._get_output_column_names()): transformed_x[key] = distances[:,dim] return transformed_x
class Aceto: """ Interpreter object """ def __init__(self, verbosity, flushness, allerr, encoding): self.stacks = defaultdict(list) self.sticky = set() self.sid = 0 self.quick = "" self.verbosity = verbosity self.flushness = flushness self.allerr = allerr self.encoding = encoding # annotate this! self.commands = self.get_annotations() def get_annotations(self): cmds = {} d = type(self).__dict__ for key in d: try: chars = d[key].__annotations__["return"] for c in chars: cmds[c] = d[key] except KeyError: pass except AttributeError: pass return cmds def print_commands(self): cols, _ = shutil.get_terminal_size((80, 20)) info = [f"{c} {f.__name__[1:]}" for c, f in self.commands.items()] info.sort() maxlen = max(len(x) for x in info) + 1 columns = cols // maxlen iinfo = iter(info) end_character = "" if sys.stdout.isatty() else "\n" try: while True: for _ in range(columns): item = next(iinfo) # skip all numbers except for 0 while item.startswith(tuple("123456789")): item = next(iinfo) print(item.ljust(maxlen), end=end_character) if not end_character: print() except StopIteration: print() @staticmethod def load_code_linear(fileobj): code_helper = defaultdict(lambda: defaultdict(str)) chars = "".join(char for line in fileobj for char in line.strip()) p = (ceil(len(chars)**0.5) - 1).bit_length() hilbert = HilbertCurve(p, 2) for step, char in enumerate(chars): y, x = hilbert.coordinates_from_distance(step) code_helper[x][y] = char return code_helper, p @staticmethod def load_code_hilbert(fileobj): code = [] for line in reversed(fileobj.readlines()): code.append(list(line.rstrip("\n"))) return code, (max(len(code), max(map(len, code))) - 1).bit_length() def load_code(self, filename, linear_mode=False): with open(filename, encoding=self.encoding) as f: if linear_mode: self.code, self.p = self.load_code_linear(f) else: self.code, self.p = self.load_code_hilbert(f) self.s = 2**self.p self.x, self.y = 0, 0 self.timestamp = time.time() self.catch_mark = None self.dir = 1 self.buf = "" self.mode = "command" self.previous_cmd = " " self.hilbert = HilbertCurve(self.p, 2) # side length p, 2 dimensions def run(self): while True: try: self.step() except Exception as e: if self.catch_mark is not None and not self.allerr: self.log(2, "Caught", e) self.x, self.y = self.catch_mark else: raise e def push(self, thing): self.stacks[self.sid].append(thing) def pushiter(self, iterable): self.stacks[self.sid].extend(iterable) def pop(self): try: x = self.stacks[self.sid][-1] if self.sid not in self.sticky: self.stacks[self.sid].pop() return x except IndexError: return 0 def log(self, level, *pargs, **kwargs): if level <= self.verbosity: print(Colors.FAIL.value, file=sys.stderr, end="") print(*pargs, file=sys.stderr, **kwargs) print(Colors.ENDC.value, file=sys.stderr, end="", flush=True) def next_coord(self): """Return the next coordinate""" distance = self.hilbert.distance_from_coordinates([self.y, self.x]) y, x = self.hilbert.coordinates_from_distance(distance + self.dir) return x, y def step_command_mode(self, cmd): method = self.commands.get(cmd, Aceto._nop) method(self, cmd) self.previous_cmd = cmd def step_string_mode(self, cmd): if cmd == '"' and self.mode == "string": self.push(self.buf) self.buf = "" self.mode = "command" elif cmd == "\\" and self.mode == "string": self.mode = "string-escape" elif self.mode == "string-escape" and cmd in "nt": self.buf += {"n": "\n", "t": "\t"}[cmd] self.mode = "string" else: self.buf += cmd self.mode = "string" self.move() def step_char_mode(self, cmd): if cmd == "\\" and self.mode == "char": self.mode = "char-escape" elif self.mode == "char-escape" and cmd in "nt": self.push({"n": "\n", "t": "\t"}[cmd]) self.mode = "command" else: self.push(cmd) self.mode = "command" self.move() def step_escape_mode(self, cmd): self.move() self.mode = "command" def get_command(self): try: return self.code[self.x][self.y] except IndexError: return " " # nop def step(self): cmd = self.get_command() if cmd != " ": self.log(1, cmd, end="") self.log(2, "\nActive stack:", self.stacks[self.sid]) if self.mode == "command": self.step_command_mode(cmd) elif self.mode in ("string", "string-escape"): self.step_string_mode(cmd) elif self.mode in ("char", "char-escape"): self.step_char_mode(cmd) elif self.mode == "escape": self.step_escape_mode(cmd) else: raise CodeException("Invalid mode:", self.mode) def move(self, coords=None): if coords is not None: x, y = coords else: if self.dir == -1 and (0, 0) == (self.x, self.y): x, y = -1, -1 else: try: x, y = self.next_coord() except ValueError: sys.exit() if x >= 2**self.p or y >= 2**self.p or x < 0 or y < 0: sys.exit() self.x, self.y = x, y def _nop(self, cmd) -> " ": self.move() def _left(self, cmd) -> "<W": if cmd == "W": self.code[self.x][self.y] = "N" self.move((self.x, (self.y - 1) % self.s)) def _right(self, cmd) -> ">E": if cmd == "E": self.code[self.x][self.y] = "S" self.move((self.x, ((self.y + 1) % self.s))) def _down(self, cmd) -> "vS": if cmd == "S": self.code[self.x][self.y] = "W" self.log( 2, f"{self.s} From {self.x},{self.y} to " f"{(self.x - 1) % self.s}, {self.y}", ) self.move(((self.x - 1) % self.s, self.y)) def _up(self, cmd) -> "^N": if cmd == "N": self.code[self.x][self.y] = "E" self.move(((self.x + 1) % self.s, self.y)) def _numeric(self, cmd) -> "1234567890": self.push(int(cmd)) self.move() def _plus(self, cmd) -> "+": x = self.pop() y = self.pop() try: self.push(y + x) self.move() except TypeError: raise CodeException(f"Can't add {x!r} to {y!r}") def _pow__find_char(self, cmd) -> "F": x = self.pop() y = self.pop() if isinstance(y, Number): try: self.push(y**x) except TypeError: raise CodeException(f"Can't raise {y!r} to the power of {x!r}") else: try: self.push(y[x]) except IndexError: raise CodeException("Index out of range") self.move() def _minus__split1(self, cmd) -> "-": x = self.pop() if isinstance(x, Number): y = self.pop() try: self.push(y - x) except TypeError: raise CodeException(f"Can't subtract {x!r} from {y!r}") else: self.pushiter(reversed(x.split())) self.move() def _times(self, cmd) -> "*": x = self.pop() y = self.pop() try: self.push(y * x) self.move() except TypeError: raise CodeException(f"Can't multiply {x!r} with {y!r}") def _mod__re_replace(self, cmd) -> "%": x = self.pop() y = self.pop() if isinstance(x, Number): try: self.push(y % x) except TypeError: raise CodeException(f"Can't get modulo of {y!r} and {x!r}") else: z = self.pop() self.push(re.sub(y, z, x)) self.move() def _div__re_matches(self, cmd) -> "/": x = self.pop() y = self.pop() if isinstance(x, Number): try: self.push(y // x) except ZeroDivisionError: raise CodeException("Zero division") except TypeError: raise CodeException(f"Can't idivide {y!r} by {x!r}") else: self.push(len(re.findall(y, x))) self.move() def _floatdiv__split2(self, cmd) -> ":": x = self.pop() if isinstance(x, Number): y = self.pop() try: self.push(y / x) except ZeroDivisionError: raise CodeException("Zero division") except TypeError: raise CodeException(f"Can't fdivide {y!r} by {x!r}") else: y = self.pop() self.pushiter(reversed(y.split(x))) self.move() def _equals(self, cmd) -> "=": x = self.pop() y = self.pop() self.log(2, f"Testing equality of {x!r} and {y!r}") self.push(y == x) self.move() def _print(self, cmd) -> "p": print(self.pop(), end="", flush=self.flushness) self.move() def _print_quick(self, cmd) -> "B": print(self.quick, end="", flush=self.flushness) self.move() def _sticky_mode_on(self, cmd) -> "k": self.sticky.add(self.sid) self.move() def _sticky_mode_off(self, cmd) -> "K": self.sticky.remove(self.sid) self.move() def _newline(self, cmd) -> "n": print() self.move() def _read(self, cmd) -> "r": self.push(input().rstrip("\n")) self.move() def _swap(self, cmd) -> "s": x = self.pop() y = self.pop() self.push(x) self.push(y) self.move() def _cast_int(self, cmd) -> "i": x = self.pop() try: self.push(int(x)) except ValueError: raise CodeException(f"Can't cast {x!r} to int") self.move() def _cast_bool(self, cmd) -> "b": x = self.pop() try: self.push(bool(x)) except ValueError: raise CodeException(f"Can't cast {x!r} to bool") self.move() def _cast_string(self, cmd) -> "∑": x = self.pop() try: self.push(str(x)) except ValueError: raise CodeException(f"Can't cast {x!r} to string") self.move() def _increment(self, cmd) -> "I": x = self.pop() try: self.push(x + 1) except Exception: self.push(1) self.move() def _decrement(self, cmd) -> "D": x = self.pop() try: self.push(x - 1) except Exception: self.push(1) self.move() def _chr(self, cmd) -> "c": x = self.pop() try: self.push(chr(x)) except Exception: self.push("\ufffd") self.move() def _ord(self, cmd) -> "o": x = self.pop() try: self.push(ord(x)) except Exception: self.push(0) self.move() def _cast_float(self, cmd) -> "f": x = self.pop() try: self.push(float(x)) except Exception: self.push(0) self.move() def _duplicate(self, cmd) -> "d": x = self.pop() self.push(x) self.push(x) self.move() def _head(self, cmd) -> "h": x = self.pop() self.stacks[self.sid] = [] self.push(x) self.move() def _next_stack(self, cmd) -> ")": self.sid += 1 self.move() def _prev_stack(self, cmd) -> "(": self.sid -= 1 self.move() def _move_next_stack(self, cmd) -> "}": x = self.pop() self.sid += 1 self.push(x) self.sid -= 1 self.move() def _move_prev_stack(self, cmd) -> "{": x = self.pop() self.sid -= 1 self.push(x) self.sid += 1 self.move() def _move_go_next_stack(self, cmd) -> "]": x = self.pop() self.sid += 1 self.push(x) self.move() def _move_go_prev_stack(self, cmd) -> "[": x = self.pop() self.sid -= 1 self.push(x) self.move() def _negation(self, cmd) -> "!": self.push(not self.pop()) self.move() def _die(self, cmd) -> "X": sys.exit() def _mirror_h(self, cmd) -> "|": cond = self.pop() if cond: new_pos = (self.x, 2**self.p - (self.y + 1)) self.log(2, "Mirroring horizontally from", self.x, self.y, "to", new_pos) self.move(new_pos) else: self.move() def _mirror_v(self, cmd) -> "_": cond = self.pop() if cond: new_pos = (2**self.p - (self.x + 1), self.y) self.log(2, "Mirroring vertically from", self.x, self.y, "to", new_pos) self.move(new_pos) else: self.move() def _mirror_vh(self, cmd) -> "#": cond = self.pop() if cond: new_pos = (2**self.p - (self.x + 1), 2**self.p - (self.y + 1)) self.log(2, "Mirroring (both) from", self.x, self.y, "to", new_pos) self.move(new_pos) else: self.move() def _reverse(self, cmd) -> "u": # reverse direction self.dir *= -1 self.move() def _reverse_stack(self, cmd) -> "U": # reverse stack self.stacks[self.sid].reverse() self.move() def _string_literal(self, cmd) -> '"': self.mode = "string" self.move() def _char_literal(self, cmd) -> "'": self.mode = "char" self.move() def _escape(self, cmd) -> "\\": self.mode = "escape" self.move() def _cond_escape(self, cmd) -> "`": if not self.pop(): self.mode = "escape" self.move() def _random_direction(self, cmd) -> "?": cmd_ = choice("v^<>") method = self.commands.get(cmd_, Aceto._nop) method(self, cmd) def _random_number(self, cmd) -> "R": self.push(random()) self.move() def _pi(self, cmd) -> "P": self.push(pi) self.move() def _euler(self, cmd) -> "e": self.push(euler) self.move() def _invert(self, cmd) -> "~": x = self.pop() if isinstance(x, bool): self.push(not x) elif isinstance(x, Number): self.push(-x) elif isinstance(x, str): self.push(x[::-1]) else: raise CodeException(f"Don't know how to invert {x!r}") self.move() def _bitwise_negate(self, cmd) -> "a": x = self.pop() if isinstance(x, Number): try: self.push(~x) except Exception: raise CodeException(f"Don't know how to invert {x!r}") else: y = self.pop() self.pushiter(reversed(re.findall(y, x))) self.move() def _restart(self, cmd) -> "O": if self.dir == 1: self.x, self.y = 0, 0 else: length = 2**self.p self.x, self.y = 0, length - 1 def _finalize(self, cmd) -> ";": if self.dir == -1: self.x, self.y = 0, 0 else: length = 2**self.p self.x, self.y = 0, length - 1 def _getch(self, cmd) -> ",": ch = getch() if ch == "\r": ch = "" self.push(ch) self.move() def _repeat(self, cmd) -> ".": method = self.commands.get(self.previous_cmd, Aceto._nop) method(self, self.previous_cmd) def _empty_stack(self, cmd) -> "ø": self.stacks[self.sid] = [] self.move() def _jump(self, cmd) -> "j": steps = self.pop() distance = self.hilbert.distance_from_coordinates([self.y, self.x]) y, x = self.hilbert.coordinates_from_distance(distance + self.dir * steps) self.x, self.y = x, y def _goto(self, cmd) -> "§": distance = self.pop() # TODO: should take the direction (self.dir) into account. y, x = self.hilbert.coordinates_from_distance(distance) self.x, self.y = x, y def _join(self, cmd) -> "J": x, y = self.pop(), self.pop() self.push(str(x) + str(y)) self.move() def _catch_mark(self, cmd) -> "@": self.catch_mark = self.x, self.y self.move() def _raise(self, cmd) -> "&": raise CodeException("Raised an &rror.") def _assert(self, cmd) -> "$": if self.pop(): raise CodeException("A$$ertion failed") else: self.move() def _get_stopwatch(self, cmd) -> "t": self.push(time.time() - self.timestamp) self.move() def _set_stopwatch(self, cmd) -> "T": self.timestamp = time.time() self.move() def _get_datetime(self, cmd) -> "™τ": self.pushiter([*time.localtime()][:6][::-1]) self.move() def _drop(self, cmd) -> "x": self.pop() self.move() def _contains(self, cmd) -> "C": x = self.pop() self.push(x in self.stacks[self.sid]) self.move() def _length(self, cmd) -> "l": self.push(len(self.stacks[self.sid])) self.move() def _queue(self, cmd) -> "q": self.stacks[self.sid].insert(0, self.pop()) self.move() def _unqueue(self, cmd) -> "Q": try: self.push(self.stacks[self.sid].pop(0)) except IndexError: self.push(0) self.move() def _memorize_quick(self, cmd) -> "M": self.quick = self.pop() self.move() def _load_quick(self, cmd) -> "L": self.push(self.quick) self.move() def _more(self, cmd) -> "m": x = self.pop() y = self.pop() self.log(2, f"Testing if {y!r} > {x!r}") self.push(y > x) self.move() def _less_or_equal(self, cmd) -> "w": x = self.pop() y = self.pop() self.log(2, f"Testing if {y!r} <= {x!r}") self.push(y <= x) self.move() def _bitwise_and(self, cmd) -> "A": x = self.pop() y = self.pop() self.push(y & x) self.move() def _bitwise_or(self, cmd) -> "V": x = self.pop() y = self.pop() self.push(y | x) self.move() def _bitwise_xor(self, cmd) -> "H": x = self.pop() y = self.pop() self.push(y ^ x) self.move() def _range_down(self, cmd) -> "z": val = self.pop() if not isinstance(val, int) or val == 0: raise CodeException("Can only construct range with non-0 integer") step = -1 if val > 0 else 1 self.pushiter(range(val, 0, step)) self.move() def _range_up(self, cmd) -> "Z": val = self.pop() if not isinstance(val, int) or val == 0: raise CodeException("Can only construct range with non-0 integer") step = 1 if val > 0 else -1 self.pushiter(range(step, val + step, step)) self.move() def _order_up(self, cmd) -> "G": x = [self.pop(), self.pop()] x.sort() self.push(x.pop()) self.push(x.pop()) self.move() def _order_down(self, cmd) -> "g": x = [self.pop(), self.pop()] x.sort(reverse=True) self.push(x.pop()) self.push(x.pop()) self.move() def _shuffle(self, cmd) -> "Y": shuffle(self.stacks[self.sid]) self.move() def _sign(self, cmd) -> "y": x = self.pop() self.push(1 if x > 0 else -1 if x < 0 else 0) self.move() def _bitwise_left(self, cmd) -> "«": x = self.pop() y = self.pop() self.push(y << x) self.move() def _bitwise_right(self, cmd) -> "»": x = self.pop() y = self.pop() self.push(y >> x) self.move() def _multiply_stack(self, cmd) -> "×": x = self.pop() self.stacks[self.sid] *= x self.move() def _abs(self, cmd) -> "±": x = self.pop() self.push(abs(x)) self.move() def _explode_string(self, cmd) -> "€": x = self.pop() self.stacks[self.sid].extend(reversed(x)) self.move() def _implode_string(self, cmd) -> "£¥": s = "".join(map(str, reversed(self.stacks[self.sid]))) self.stacks[self.sid] = [s] self.move()
level=numeric_level) log_format = logging.Formatter('%(asctime)s [%(levelname)-5.5s] [%(filename)s:%(lineno)04d] %(message)s') logger = logging.getLogger() logger.setLevel(numeric_level) root_dir = args.root_dir phases = ['train', 'test'] batch_size = 32 category = 5 # verify hilbert order. p = 7 N = 2 hilbert_curve = HilbertCurve(p, N) for coords in [[0, 0], [0, 1], [1, 1], [1, 0]]: dist = hilbert_curve.distance_from_coordinates(coords) print(f'distance(x={coords}) = {dist}') # datasets, dataloaders, num_classes = get_s3dis_dataloaders(root_dir=root_dir, phases=phases, batch_size=batch_size, category=category) for phase in phases: print(phase.upper()) print('\tDataset {} Dataloder {}'.format(len(datasets[phase]), len(dataloaders[phase]))) for i, data in enumerate(dataloaders[phase]): print(data.pos.shape) x = torch.cat((data.pos, data.x), dim=2).transpose(1, 2) seg_label = data.y print('\tData {} Seg Label {}'.format(x.size(), seg_label.size()))
class S3DIS(InMemoryDataset): r"""The (pre-processed) Stanford Large-Scale 3D Indoor Spaces dataset from the `"3D Semantic Parsing of Large-Scale Indoor Spaces" <http://buildingparser.stanford.edu/images/3D_Semantic_Parsing.pdf>`_ paper, containing point clouds of six large-scale indoor parts in three buildings with 12 semantic elements (and one clutter class). Args: root (string): Root directory where the dataset should be saved. test_area (int, optional): Which area to use for testing (1-6). (default: :obj:`6`) train (bool, optional): If :obj:`True`, loads the training dataset, otherwise the test dataset. (default: :obj:`True`) transform (callable, optional): A function/transform that takes in an :obj:`torch_geometric.data.Data` object and returns a transformed version. The data object will be transformed before every access. (default: :obj:`None`) pre_transform (callable, optional): A function/transform that takes in an :obj:`torch_geometric.data.Data` object and returns a transformed version. The data object will be transformed before being saved to disk. (default: :obj:`None`) pre_filter (callable, optional): A function that takes in an :obj:`torch_geometric.data.Data` object and returns a boolean value, indicating whether the data object should be included in the final dataset. (default: :obj:`None`) """ url = ('https://shapenet.cs.stanford.edu/media/' 'indoor3d_sem_seg_hdf5_data.zip') def __init__(self, root, test_area=5, train=True, transform=None, pre_transform=None, pre_filter=None, hilbert_order=True, hilbert_level=7): assert test_area >= 1 and test_area <= 6 self.test_area = test_area self.p = hilbert_level self.hilbert_order = hilbert_order if self.hilbert_order: self.hilbert_curve = HilbertCurve(self.p, 3) super(S3DIS, self).__init__(root, transform, pre_transform, pre_filter) path = self.processed_paths[0] if train else self.processed_paths[1] self.data, self.slices = torch.load(path) @property def raw_file_names(self): return ['all_files.txt', 'room_filelist.txt'] @property def processed_file_names(self): test_area = self.test_area return ['{}_{}.pt'.format(s, test_area) for s in ['train', 'test']] def download(self): path = download_url(self.url, self.root) extract_zip(path, self.root) os.unlink(path) shutil.rmtree(self.raw_dir) name = self.url.split(os.sep)[-1].split('.')[0] os.rename(osp.join(self.root, name), self.raw_dir) def process(self): with open(self.raw_paths[0], 'r') as f: filenames = [x.split('/')[-1] for x in f.read().split('\n')[:-1]] with open(self.raw_paths[1], 'r') as f: rooms = f.read().split('\n')[:-1] xs, ys = [], [] for filename in filenames: f = h5py.File(osp.join(self.raw_dir, filename)) # todo: check the data range xs += torch.from_numpy(f['data'][:]).unbind(0) ys += torch.from_numpy(f['label'][:]).to(torch.long).unbind(0) test_area = 'Area_{}'.format(self.test_area) train_data_list, test_data_list = [], [] for i, (x, y) in enumerate(tqdm(zip(xs, ys), total=len(xs))): data = Data(pos=x[:, :3], x=x[:, 3:], y=y) if self.pre_filter is not None and not self.pre_filter(data): continue if self.pre_transform is not None: data = self.pre_transform(data) # Hilbert curve if self.hilbert_order: # order points in hilbert order # after normalizaiton, -1 to 1 pos, x, y = data.pos, data.x, data.y point = (pos.numpy()+1)/2 # normalize to 0, 1 points_voxel = np.floor(point * (2 ** self.p - 1)).astype(int) hilbert_dist = np.zeros(points_voxel.shape[0]) # todo: we want to try two methods. # todo: 1. globally along with locally hilbert curve # todo: 2. multi-level of hilbert curve for point_idx in range(points_voxel.shape[0]): hilbert_dist[point_idx] = self.hilbert_curve.distance_from_coordinates(points_voxel[point_idx, :]) idx = np.argsort(hilbert_dist) pos = pos[idx, :] x = x[idx, :] y = y[idx] data = Data(pos=pos, x=x, y=y) if test_area not in rooms[i]: train_data_list.append(data) else: test_data_list.append(data) torch.save(self.collate(train_data_list), self.processed_paths[0]) torch.save(self.collate(test_data_list), self.processed_paths[1])
class HilbertPalette(Palette): def __init__(self, sourceDirectory, file): super().__init__(sourceDirectory, file) self.hilbert_curve = HilbertCurve(255, 3) def MakeNewPalette(self): print("Collecting palette") colours = {} local = Path(__file__).resolve().parents[0] photos = local / self.sourceDirectory total = len(list(photos.iterdir())) with tqdm(total=total) as pbar: for photo in photos.iterdir(): image = Image.open(photo) try: colour = self.FindRegionColour(image) dist = self.hilbert_curve.distance_from_coordinates( np.rint(colour[:3]).astype(int).tolist()) colours[str(photo)] = dist except IndexError as e: print(f"Error processing {photo}: {e}") pbar.update(1) print("Sorting") colours = { k: v for k, v in tqdm(sorted(colours.items(), key=lambda item: item[1])) } self.colours = colours self.colKeys = list(self.colours.keys()) self.colValues = list(self.colours.values()) def GetClosest(self, val1, val2, target): if (target - val1 >= val2 - target): return val2 else: return val1 def FindClosestIndex(self, arr, n, target): if (target <= arr[0]): return 0 if (target >= arr[n - 1]): return n - 1 i = 0 j = n mid = 0 while (i < j): mid = (i + j) // 2 if (arr[mid] == target): return mid if (target < arr[mid]): if (mid > 0 and target > arr[mid - 1]): if (self.GetClosest(arr[mid - 1], arr[mid], target) == mid): return mid else: return mid - 1 j = mid else: if (mid < n - 1 and target < arr[mid + 1]): if (self.GetClosest(arr[mid], arr[mid + 1], target) == arr[mid]): return mid else: return mid + 1 i = mid + 1 return mid def FindMatchingImage(self, RGB): rgbDist = self.hilbert_curve.distance_from_coordinates(list(RGB[:3])) matchIndex = self.FindClosestIndex(self.colValues, len(self.colValues), rgbDist) return self.colKeys[matchIndex]