def _create_lines(self): for row in self.line_rows: # Create an object to construct the necessary components forest_obj = ForestLine(row, self.coefficient_radius, self.rounder, self.text_colour) if forest_obj.var_name == "#Delete": self.height_max -= self.height_iter else: self.bound_values = self.bound_values + [ float(forest_obj.lb), float(forest_obj.ub) ] # Create the line current_name = forest_obj.make_line(self.height_max, self.height_iter, self.y_scale) y_mean = forest_obj.make_coefficient(current_name) # Set the variable name make_text(f"{forest_obj.var_name}_var_name", -self.var_bound, y_mean, forest_obj.var_name, self.height_iter, self.text_colour, "LEFT") # Create the numeric string numeric = f"{set_values(forest_obj.coef, self.rounder)} ({set_values(forest_obj.lb, self.rounder)}; " \ f"{set_values(forest_obj.ub, self.rounder)})" make_text(f"{forest_obj.var_name}_CI", 1 + self.ci_bound, y_mean, numeric, self.height_iter, self.text_colour) self.height_max -= self.height_iter
def make_group(self, group, points): print(group) obj, x_mid = self.make_vertex_holder(group, points) if x_mid != 0: make_text(group, x_mid, -(self._text_scale + 1), group, self._text_scale, self._text_colour, 'CENTER') self.link_ico(obj)
def _make_text_and_box(self, name, col_i, position, previous_height): # Set the width, which is the x position, relative to other columns of this row width = sum([self.widths[str(i - 1)] for i in range(col_i + 1)]) if col_i != 0: width += self.spacing # Create the text object and set its origin to geometry obj = make_text(name, width, previous_height, position["Text"], 1, self.text_colour, align="CENTER") obj.select_set(True) bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN') # Isolate the texts center from location and width and height from dimensions x, y, _ = obj.location / 2 x_d, y_d, _ = obj.dimensions / 2 obj.select_set(False) self._make_bounding_box(x, y, x_d, y_d, name, obj)
def _set_dimensions(self): widths = {"-1": 0} dimension_dict = {} for i in range(self.col_count): dimensions = [] for name, position in self.positions.items(): col_id, row_id = name.split("-") if col_id == str(i): obj = make_text(name, 0, 0, position["Text"], 1, self.text_colour, align="CENTER") dimensions.append(obj.dimensions) x, y, z = obj.dimensions dimension_dict[name] = [x, y, z] widths[str(i)] = max([x for x, y, z in dimensions]) collection_cleanup("Collection") return widths, dimension_dict
def _make_axis(self, x_axis_width, axis_colour, line_density, axis_width, bound, significance, significance_colour): # Set the axis y height as the max of axis_y_positions with ceiling to prevent out of bounds points axis_height = math.ceil(max(self.axis_y_positions)) # Make the graphs axis make_graph_axis(axis_colour, x_axis_width, axis_height, axis_width, bound) # make the horizontal dashed line to determine the level of significance make_horizontal_dashed_line("Line", significance_colour, x_axis_width, 0, significance, line_density) # Make a spacer so that elements are relative distances to the axis axis_spacer = -(axis_width + (axis_width * 2) + axis_width / 2) # Label the x axis make_text("Chromosomes", 23.5 / 2, axis_spacer*1.5, "Chromosomes", axis_width * 2, axis_colour, "CENTER") for i in range(23): make_text(f"Chr{i}", i + 0.5, axis_spacer, f"{i + 1}", axis_width * 2, axis_colour, "CENTER") # Label the y axis make_text("Log", axis_spacer * 1.5, axis_height / 2, "-log10(pvalue)", axis_width * 2, axis_colour, "CENTER") # Y axis needs to be rotated obj = bpy.data.objects["Log"] obj.select_set(True) bpy.ops.transform.rotate(value=1.5708, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False) # Add y axis values for i in range(axis_height + 1): if i % 2 == 0: make_text(f"log{i}", axis_spacer, i, f"{i}", axis_width * 2, axis_colour, "CENTER") # Render the scene render_scene(self.camera_position, self.write_directory, f"{self.write_name}__AXIS", x_resolution=self.x_res, y_resolution=self.y_res, camera_scale=self.camera_scale)
def _create_axis(self): # Make y axis from the min and max values of the standardised rows self._make_axis() self.height_max -= self.height_iter # Label left an right most columns make_text("Phenotype", -self.var_bound, self.height_iter, "Phenotype", self.height_iter, self.text_colour) make_text(self.value_title, 1 + self.ci_bound, self.height_iter, self.value_title, self.height_iter, self.text_colour) # Add values based on a range between the min and max equally divided make_text("Min_Bound", 0, self.height_max, set_values(min(self.bound_values), 2), self.height_iter, self.text_colour) make_text("Max_Bound", 1, self.height_max, str(round(max(self.bound_values), 2)), self.height_iter, self.text_colour, "RIGHT") make_text("Mid_Point", self.axis_position, self.height_max, str(self.axis_target), self.height_iter, self.text_colour, "CENTER") # # Add the x axis label make_text("Axis Label", self.axis_position, self.height_max - self.height_iter, self.axis_label, self.height_iter, self.text_colour, align="CENTER")
def make_y_axis(self): iterator = math.ceil(max(self._y_max)) / 10 for i in range(1, 11): make_text(str(iterator * i), -(self._text_scale + 1), iterator * i, str(round(iterator * i, 2)), self._text_scale, self._text_colour, 'RIGHT')
def label_points(self, points, x_points, i, y): name = points[i][self.name_index] make_text(name, x_points[i] + (2 * self.ico_scale), y, name, self._label_scale, self._text_colour)
def _axis(self, x_values, y_values, set_bounds, line_width, axis_colour): # Make the 45% line from the min of the max end_point = min([max(y_values), max(x_values)]) line, line_mesh = make_mesh("Line", axis_colour) line_mesh.from_pydata([(0, 0, 0), (end_point, end_point, 0)], [(0, 1)], []) # Turn line to curve, add width equal to line_width line.select_set(True) bpy.ops.object.convert(target='CURVE') bpy.context.object.data.bevel_resolution = 0 bpy.context.object.data.bevel_depth = line_width # Create the bounds x_bound = max(x_values) y_bound = max(y_values) # define the Bound of the axis if set_bounds != "None": x, y = tuple_convert(set_bounds) if (x_bound > x) or (y_bound > y): x = max([x_bound, x]) y = max([y_bound, y]) self.logger.write( F"WARNING: Set Bound is smaller than p value's, defaulting to native bound" ) else: x, y = x_bound, y_bound # Make the graphs axis make_graph_axis(axis_colour, x, y, line_width, 0.0) # TODO see if we can generalise the axis for make graph axis to also include the annotation # Label the x axis make_text("Theoretical -log10", math.floor(x) / 2, -1, "Theoretical -log10", 0.5, axis_colour, "CENTER") for i in range(math.floor(x)): make_text(f"{i}", i + 0.5, -0.5, f"{i + 1}", 0.5, axis_colour, "CENTER") # Label the y axis make_text("Observed -log 10", -1, math.floor(y) / 2, "Observed -log 10", 0.5, axis_colour, "CENTER") # Y axis needs to be rotated obj = bpy.data.objects["Observed -log 10"] obj.select_set(True) bpy.ops.transform.rotate(value=1.5708, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False) for i in range(math.floor(y)): make_text(f"log{i}", -0.5, i + 0.5, f"{i + 1}", 0.5, axis_colour, "CENTER") # Render the scene render_scene(self.camera_position, self.write_directory, f"{self.write_name}__AXIS.png", "BLENDER_EEVEE", self.x_res, self.y_res, camera_scale=self.camera_scale) self.logger.write(f"Written the AXIS out at {terminal_time()}")
def make_name(self, i, row): """Make the x axis text""" make_text(row[self.name_i], i + 0.5, -1, row[self.name_i], 1, (0, 0, 0, 1), align='CENTER')