def construct(self): # Atom level adenine = Text(ADENINE_SMILES) # Nucleotide level dna = Text('ACTGAATATAGACTATA', t2c={ 'A': RED, 'C': BLUE, 'T': GREEN, 'G': PURPLE }) # Amino acid level aas = 'VQGGAAVQQEVLA' aas = Text(aas, t2c=get_aa_hex_color_dict('skylign_protein')) # Logo level logo = LoLLogo() # Animate... from nucleotide to LoL Commons self.wait() self.play(Write(adenine)) self.wait() if self.add_vector_transform: # FIXME: This is not quite pretty / useful at the moment numbers = Text( '[0.12 0.32 0.01 0.88 0.99 0.22 0.55 0.42 0.13 0.07]') replacements = [adenine, dna, aas, numbers, logo.lol] else: replacements = [adenine, dna, aas, logo.lol] for source, target in zip(replacements, replacements[1:]): self.play(ReplacementTransform(source, target)) self.wait() self.play(Write(logo.commons), FadeIn(logo.commons_left), FadeIn(logo.commons_right)) self.wait() for replacer in self.replacers: logo.replace_left_right(self, replacer, run_time_s=0.8) self.wait(0.3) # Move logo to left lower corner if self.logo_down: mini_logo = logo.copy() mini_logo.scale(0.5) mini_logo.to_corner() self.play(Transform(logo, mini_logo)) # And keep the scene # self.play(Write(Text('Corporate info follows...'))) self.wait(5)
def construct(self): rng = np.random.RandomState(self.seed) moleculizer = partial( new_molecule, colors=lambda: rng.choice(MOLECULE_COLORS, size=3, replace=True)) proteins = molecule_universe_grid( moleculizer, num_molecules=(5, 8)).scale(0.3).center() proteins_frame = SurroundingRectangle(proteins, color=WHITE).round_corners(0.5) universe_title = Text('Known proteins').scale(0.7).next_to( proteins_frame, UP) framed_proteins = VGroup(universe_title, proteins_frame, proteins).to_edge(LEFT) self.play(FadeIn(framed_proteins)) self.wait(3) # --- Sequence -> Number -> MLM heavy, hcdr3 = hiv_antibody() heavy.next_to(framed_proteins, RIGHT) self.play(Transform(proteins[23], heavy)) self.wait(5) mlm = MLM().next_to(framed_proteins, RIGHT) self.play(ShrinkToCenter(heavy)) # , mlm.text self.wait(5) # FIXME: just to break here if mlm.text is not None: return # --- Subsets selected_proteins = [ proteins[i].copy() for i in rng.choice( len(proteins), replace=False, size=len(proteins) // 3) ] antibodies = VGroup( * [molecule_from_molecule(protein) for protein in selected_proteins]) antibodies_frame = (SurroundingRectangle(antibodies).match_color( proteins_frame).match_width(proteins_frame).match_height( proteins_frame)).round_corners(0.5) framed_antibodies = VGroup(antibodies_frame, antibodies) framed_antibodies.next_to(proteins, RIGHT, buff=MED_LARGE_BUFF) self.play( *[ ReplacementTransform(protein, antibody) for protein, antibody in zip(selected_proteins, antibodies) ], Write(antibodies_frame)) self.wait(4)
def setup_axes(self, animate=False, x_vals=None, y_vals=None, run_time=1): self.get_y_axis().shift( self.center_point ) # Replace with self.shift(self.center_point) once this bug is fixed! self.get_x_axis().shift(self.center_point) if animate: self.play(Write(self.axes, run_time=run_time)) else: self.add(*self.axes)
def add_to_scene(self, scene, initial_blank_seconds=0., end_blank_seconds=0.): scene.wait(initial_blank_seconds) scene.play(FadeIn(self.lol)) scene.wait() scene.play(Write(self.commons), FadeIn(self.commons_left), FadeIn(self.commons_right)) scene.wait(end_blank_seconds)
def insert(self, bt_node, side_offset_multiply: float = 2.5, down_offset_multiply: float = 2.5, direction=LEFT, start_from_root=True) -> BinaryTreeNode: if self.is_full(): raise AttributeError("This node %s is completed" % str(self.node_id)) bt_node.parent = self if start_from_root: parents = [self] while parents[-1].parent is not None: parents.append(parents[-1].parent) self.scene.add(bt_node) bt_node.next_to(parents[-1], buff=0, direction=UP) parents.pop() self.scene.play(FadeIn(bt_node.value), run_time=bt_node.animation_duration) while len(parents) > 0: elem = parents[-1] self.scene.play(bt_node.value.animate.next_to(elem, buff=0), run_time=bt_node.animation_duration) parents.pop() else: bt_node.next_to(self.value, buff=0) self.scene.play(Write(bt_node.value), run_time=bt_node.animation_duration) if direction is LEFT and self.has_left(): direction = RIGHT self.right = bt_node else: self.left = bt_node child_location = self.value.get_center() + \ side_offset_multiply * self.radius * direction + \ down_offset_multiply * self.radius * DOWN parent_child_vector = normalize(child_location - self.value.get_center()) edge_start = (self.value.get_center() + parent_child_vector * self.radius) edge_end = child_location - parent_child_vector * self.radius edge = Line(edge_start, edge_end) self.scene.play(bt_node.value.animate.move_to(child_location), FadeIn(edge), run_time=bt_node.animation_duration) return bt_node
def mark_tex_caption(node, tex) -> Write: nd = Tex(tex) nd.scale(0.45) nd.next_to(node, aligned_edge=UR) return Write(nd)
def construct(self): matrix1 = Matrix( m1, v_buff=1.3, h_buff=0.8, bracket_h_buff=SMALL_BUFF, bracket_v_buff=SMALL_BUFF) matrix1.set_color(DEFAULT_COLOR) matrix1.get_entries()[0].set_color(RECT_COLOR) matrix1.get_entries()[-1].set_color(RECT_COLOR) self.add(matrix1) matrix2 = Matrix( m2, v_buff=1.3, h_buff=0.8, bracket_h_buff=SMALL_BUFF, bracket_v_buff=SMALL_BUFF) matrix2.set_color(DEFAULT_COLOR) self.add(matrix2) equals = MathTex(r'=') self.add(equals) m3 = (m1@m2) matrix3 = Matrix( m3, v_buff=1.3, h_buff=0.8, bracket_h_buff=SMALL_BUFF, bracket_v_buff=SMALL_BUFF) matrix3.set_color(DEFAULT_COLOR) # args = [BLACK]*m3.shape[1] # matrix3.set_column_colors(*args) for i in matrix3.get_entries(): i.set_opacity(0) self.add(matrix3) g = Group(matrix1, matrix2, equals, matrix3).arrange(buff=1).shift(UP) g.set_color(DEFAULT_COLOR) self.add(g) i = 0 for m1_row in matrix1.get_rows(): for m2_column in matrix2.get_columns(): rect_1 = SurroundingRectangle(m1_row).set_stroke(color=RECT_COLOR) rect_2 = SurroundingRectangle(m2_column).set_stroke(color=RECT_COLOR) self.play(Create(rect_1)) self.wait() self.play(ReplacementTransform(rect_1, rect_2)) math_strings = [] values_to_sum = [] for m1_val, m2_val in zip(m1_row, m2_column): val_left = int(m1_val.get_tex_string()) val_right = int(m2_val.get_tex_string()) values_to_sum.append(val_left * val_right) text_left = m1_val.get_tex_string() text_right = m2_val.get_tex_string() if val_left < 0: text_left = f'({text_left})' if val_right < 0: text_right = f'({text_right})' math_strings.extend([text_left, " \\times ", text_right, " + "]) math_strings = math_strings[:-1] math_strings.extend([" = ", sum(values_to_sum)]) ds_m = MathTex(*math_strings) ds_m.set_color(BLACK) offset = 0 for j in range(m1.shape[0]): pos = j + offset # ds_m[pos].set_color(M1_COLOR) # ds_m[pos + 2].set_color(M2_COLOR) offset += 3 ds_m[-1].set_opacity(0) # ds_m[-1].set_color(CALCULATED_COLOR) ds_m.shift(2 * DOWN) self.play(ReplacementTransform(rect_1, rect_2), Write(ds_m)) self.wait() rect_3 = SurroundingRectangle(matrix3.get_entries()[i]).set_color(RECT_COLOR) # matrix3.get_entries()[i].set_color(CALCULATED_COLOR) self.play( ReplacementTransform(rect_2, rect_3), ApplyMethod(matrix3.get_entries()[i].set_opacity, 1), ApplyMethod(ds_m[-1].set_opacity, 1) ) self.wait() self.remove(ds_m) self.remove(rect_3) m1_row.set_color(BLACK) m2_column.set_color(BLACK) i += 1 self.wait()
def construct(self): super().construct() # Group first row and second row use_cases = [] for use_case1, use_case2 in zip(USE_CASES, USE_CASES[5:]): use_case2.next_to(use_case1, DOWN, buff=0.5) use_cases.append(VGroup(use_case1, use_case2)) use_cases = VGroup(*use_cases) # Make all use cases same width and height widest = sorted(use_cases, key=lambda x: x.width)[-1] tallest = sorted(chain.from_iterable(use_cases), key=lambda x: x.height)[-1] for use_case_top, use_case_bottom in use_cases: use_case_top.frame.stretch_to_fit_width(widest.width) use_case_top.frame.stretch_to_fit_height(tallest.height) use_case_bottom.frame.stretch_to_fit_width(widest.width) use_case_bottom.frame.stretch_to_fit_height(tallest.height) use_cases.arrange().scale(0.8).center() # Human friendly names for use cases antibodies = use_cases[0][0] peptides_ppi = use_cases[0][1] toxins = use_cases[1][0] peptides_sol = use_cases[1][1] enzyme_stabilisation = use_cases[2][0] microbiome = use_cases[2][1] codons = use_cases[3][0] detoxification = use_cases[3][1] clinical = use_cases[4][0] mutation = use_cases[4][1] # --- Animate! # Create the use cases self.play(Write(use_cases)) self.wait(1) # Example setting the camera old_width = self.camera.frame_width if self.zoom_each_use_case: for use_case in chain.from_iterable(use_cases): self.play( self.camera.frame.animate.move_to(use_case).set( width=use_case.width * 2)) self.wait(2) self.play( self.camera.frame.animate.move_to(ORIGIN).set(width=old_width)) self.wait(2) # Highlight groups with common / synergies # Indications to apply to group visually, temporarily, use cases # https://docs.manim.community/en/stable/reference/manim.animation.indication.html # Similar modalities (some of these are a bit of a stretch to group together) if self.all_groups_at_same_time: self.play( FocusOn(antibodies), # Peptides Wiggle(peptides_sol), Wiggle(peptides_ppi), # DNA + RNA Indicate(codons), Indicate(mutation), Indicate(clinical), # Proteins Circumscribe(toxins.frame), Circumscribe(detoxification.frame), # Enzyme ApplyWave(enzyme_stabilisation), ApplyWave(microbiome), run_time=3) self.wait(6)
def construct(self): a_million_forks = Text('A million forks in the road to our products' ) # to drug development a_million_forks.to_edge(UP) new_drugs_per_billion_RD = [('1950', 100), ('1960', 50), ('1970', 10), ('1980', 5), ('1990', 3), ('2000', 2), ('2010', 1), ('2020', 1)] x = [x for x, _ in new_drugs_per_billion_RD] y = [y for _, y in new_drugs_per_billion_RD] colors = ["#003f5c", "#58508d", "#bc5090", "#ff6361", "#ffa600"] chart = BarChart( values=y, max_value=max(y), bar_colors=colors, bar_names=x, bar_label_scale_val=0.5, ).scale(0.8).to_edge(LEFT).shift(0.5 * DOWN) # text_top = ( # Text('EROOM\'s Law: More expensive, slower drug discovery') # .scale(0.9) # .next_to(chart, UP, buff=0.1) # ) # text_left = ( # Text('Number of drugs per billion US$ R&D spending') # .rotate(angle=TAU / 4, axis=OUT) # .scale(0.3) # .next_to(chart, LEFT, buff=0.5) # ) text_top = ( Text('Number of drugs per billion US$ R&D spending (log-scale)' ).scale(0.3).next_to(chart, UP, buff=0.5)) text_bottom = ( Text("Eroom's law: a continuous decline in Pharma R&D productivity" ).scale(0.3).next_to(chart, DOWN, buff=0.5)) # --- Examples of forks in the road icons_text = [ (SVGMobject(SVGS.ANTIBODY).set_color(BLUE).scale(0.8), Text('Is my antibody a potent, functional binder?')), (SVGMobject(SVGS.CYCLIC_PEPTIDE).set_color_by_gradient( BLUE, GREEN).scale(0.8), Text('Can we generate peptides without liabilities?')), (SVGMobject(SVGS.DNA).set_color_by_gradient(GREEN, BLUE).scale(0.8), Text( 'Can we optimize DNA to better express traits in plants or humans?' )), (SVGMobject(SVGS.PACMAN).set_color(RED).scale(0.8), Text('What will an enzyme in the human gut do?')), # ( # SVGMobject(SVGS.PACMAN).set_color_by_gradient(GREEN, BLUE, RED).scale(0.8), # Text('Can we optimize enzymes to better manufacture bioproducts?') # ), (SVGMobject(SVGS.PROTEIN3D).set_color_by_gradient( GREEN, BLUE, RED).scale(0.8), Text('What is the 3D structure of my biomolecule?')), (SVGMobject(SVGS.PATIENT).set_color_by_gradient(BLUE, RED).scale(0.8), Text('Will a patient respond to treatment in a clinical trial?')), (SVGMobject(SVGS.MUTATION).set_color_by_gradient(BLUE, GREEN, RED).scale(0.8), Text('...')) ] # icons_text = icons_text[:1] for (icon1, _), (icon2, _) in zip(icons_text, icons_text[1:]): icon2.next_to(icon1, DOWN, buff=0.5) for icon, text in icons_text: text.next_to(icon, RIGHT) questions = VGroup(*chain.from_iterable(icons_text)) questions.scale(0.32) questions.next_to(chart, RIGHT, buff=1).shift(0.5 * UP) logo = LoLLogo().scale(0.7) # logo.next_to(questions, DOWN, buff=0.5) logo.move_to(questions) # --- Animate self.play(FadeIn(text_top)) self.play(Write(chart), Write(text_bottom), run_time=4) self.wait(2) self.play(Write(a_million_forks)) for icon, text in icons_text: self.play(FadeIn(icon, text)) self.wait(3) # if we have put the logo under the questions... # self.play(FadeIn(logo)) # if we prefer the logo to morph from the questions actionable_insights = (Text( 'Getting actionable insights from biological sequences').next_to( logo, DOWN, buff=0.5).scale(0.4)) self.play(ReplacementTransform(questions, logo)) self.play(Write(actionable_insights)) self.wait(2)