from .AssemblyReportWriter import AssemblyReportWriter
from ..tools import format_data_dicts_records_for_spreadsheet
import pandas
[docs]class AssemblySimulation:
"""Class to represent and report on the simulation of a single assembly.
Instances are the result of ``assembly.simulate()``.
Parameters
----------
assembly
The Assembly instance from which this is the simulation.
sequence_repository
The SequenceRepository used to get records for the simulation.
construct_records
List of Biopython records (or, sometimes, StickyEndFragment records)
of the final constructs predicted by the simulation.
mixes
A list of AssemblyMix instances generated during the simulation (they
can be plotted at report writing time).
warnings
List of AssemblyFlaw instances that will be flagged as warnings in
reports and summaries.
errors
List of AssemblyFlaw instances that will be flagged as errors in
reports and summaries.
"""
def __init__(
self,
assembly,
sequence_repository,
construct_records=(),
mixes=(),
warnings=(),
errors=(),
):
self.assembly = assembly
self.construct_records = construct_records
self.sequence_repository = sequence_repository
self.mixes = list(mixes)
self.errors = list(errors)
self.warnings = list(warnings)
[docs] @staticmethod
def fragment_part(fragment, mark_reverse=False):
"""Return the name of the fragment, or optionally `NAME_r` if the
fragment is the reverse of another fragment."""
if hasattr(fragment, "original_part"):
name = fragment.original_part.id
else:
name = fragment.id
return name + ("_r" if (fragment.is_reversed and mark_reverse) else "")
[docs] def list_all_parts_used(self):
"""List all parts involved in at least one of the predicted constructs."""
parts = [
self.fragment_part(fragment)
for construct_record in self.construct_records
for fragment in construct_record.fragments
]
return sorted(set(parts))
[docs] def compute_construct_data_dict(self, construct_record):
"""Return a dictionary with infos on a single construct.
fields: construct_id, parts, number_of_parts, construct_size,
assembly_name, depends_on, used_in, assembly_level.
"""
return dict(
construct_id=construct_record.id,
parts=[self.fragment_part(f) for f in construct_record.fragments],
number_of_parts=len(construct_record.fragments),
construct_size=len(construct_record),
assembly_name=self.assembly.name,
depends_on=self.assembly.dependencies["depends_on"],
used_in=self.assembly.dependencies["used_in"],
assembly_level=self.assembly.dependencies["level"],
**self.assembly.get_extra_construct_data()
)
[docs] def compute_all_construct_data_dicts(self):
"""Return a list of dictionnaries with infos on a each construct.
Fields: construct_id, parts, number_of_parts, construct_size,
assembly_name, depends_on, used_in, assembly_level.
"""
return [
self.compute_construct_data_dict(construct_record)
for construct_record in self.construct_records
]
[docs] def compute_summary_dataframe(self):
"""Return a Pandas dataframe with infos on each construct."""
first_columns = [
"assembly_name",
"construct_id",
"assembly_level",
"construct_size",
"number_of_parts",
]
construct_data_dicts = self.compute_all_construct_data_dicts()
extra_data_columns = [
field
for data_dict in construct_data_dicts
for field in data_dict
if field not in first_columns + ["parts"]
]
extra_data_columns = sorted(set(extra_data_columns))
columns = first_columns + extra_data_columns + ["parts"]
data = format_data_dicts_records_for_spreadsheet(construct_data_dicts)
return pandas.DataFrame(data, columns=columns)
[docs] def write_report(self, target, report_writer="default"):
"""Write a comprehensive simulation report in a folder or a zip file.
Parameters
----------
target
Either a path to a folder, to a zip file, or ``"@memory"`` to write
into a virtual zip file whose raw data is then returned.
report_writer
Either the "default" or any AssemblyReportWriter instance.
Returns
-------
zip_data
binary zip data (if target="@memory") else None.
"""
if report_writer == "default":
report_writer = AssemblyReportWriter()
return report_writer.write_report(assembly_simulation=self, target=target)