def generate_clips_df(constructs_list): """Generates a dataframe containing information about all the unique CLIP reactions required to synthesise the constructs in constructs_list. """ merged_construct_dfs = pd.concat( constructs_list, ignore_index=True) # converts list of dfs into one large df unique_clips_df = merged_construct_dfs.drop_duplicates() # drop duplicates unique_clips_df = unique_clips_df.reset_index( drop=True) # reset index (this creates a df of all unique clips) clips_df = unique_clips_df.copy( ) # makes a copy which is disconnected to the original # Error if len(unique_clips_df.index) > MAX_CLIPS: raise ValueError( 'Number of CLIP reactions exceeds 48. Reduce number of constructs in construct.csv.' ) # Count number of each CLIP reaction clip_count = np.zeros(len( clips_df.index)) # creates an empty array the for each unique clip for i, unique_clip in unique_clips_df.iterrows( ): # for every unique clip... for _, clip in merged_construct_dfs.iterrows(): # ...for every clip... if unique_clip.equals(clip): # ...if they are the same clip_count[i] = clip_count[i] + 1 # ...tally that unique clip clip_count = clip_count // FINAL_ASSEMBLIES_PER_CLIP + 1 # find the number of clip wells needed (ie there is a max number of clip uses per reaction/well, if required clips exceeds this for a unique clip then start a new well) clips_df['number'] = [int(i) for i in clip_count.tolist() ] # add a count column to unique clips df # Associate well/s for each CLIP reaction clips_df['mag_well'] = pd.Series( ['0'] * len(clips_df.index), index=clips_df.index) # adds new column 'mag_well' for index, number in clips_df['number'].iteritems( ): # for every unique clip... if index == 0: # ...if its the first clip... mag_wells = [] for x in range(number): # ...for every count of that clip... mag_wells.append(mplates.final_well( x + 1 + 48)) # parse into mag wells to return list clips_df.at[index, 'mag_well'] = tuple( mag_wells) # return tuple to mag_well col else: mag_wells = [] for x in range(number): well_count = clips_df.loc[:index - 1, 'number'].sum( ) + x + 1 + 48 # adds all previous clips to clip count mag_wells.append(mplates.final_well(well_count)) clips_df.at[index, 'mag_well'] = tuple(mag_wells) return clips_df
def generate_spotting_tuples(constructs_list, spotting_vols_dict): """Using constructs_list, generates a spotting tuple (Refer to 'transformation_spotting_template.py') for every column of constructs, assuming the 1st construct is located in well A1 and wells increase linearly. Target wells locations are equivalent to construct well locations and spotting volumes are defined by spotting_vols_dict. Args: spotting_vols_dict (dict): Part number defined by keys, spottting volumes defined by corresponding value. """ # Calculate wells and volumes wells = [mplates.final_well(x + 1) for x in range(len(constructs_list))] vols = [SPOTTING_VOLS_DICT[len(construct_df.index)] for construct_df in constructs_list] # Package spotting tuples spotting_tuple_num = len(constructs_list)//8 + (1 if len(constructs_list) % 8 > 0 else 0) spotting_tuples = [] for x in range(spotting_tuple_num): if x == spotting_tuple_num - 1: tuple_wells = tuple(wells[8*x:]) tuple_vols = tuple(vols[8*x:]) else: tuple_wells = tuple(wells[8*x:8*x + 8]) tuple_vols = tuple(vols[8*x:8*x + 8]) spotting_tuples.append((tuple_wells, tuple_wells, tuple_vols)) return spotting_tuples
def generate_clips_df(constructs_list): """Generates a dataframe containing information about all the unique CLIP reactions required to synthesise the constructs in constructs_list. """ merged_construct_dfs = pd.concat(constructs_list, ignore_index=True) unique_clips_df = merged_construct_dfs.drop_duplicates() unique_clips_df = unique_clips_df.reset_index(drop=True) clips_df = unique_clips_df.copy() # Error if len(unique_clips_df.index) > MAX_CLIPS: raise ValueError( 'Number of CLIP reactions exceeds 48. Reduce number of constructs in construct.csv.' ) # Count number of each CLIP reaction clip_count = np.zeros(len(clips_df.index)) for i, unique_clip in unique_clips_df.iterrows(): for _, clip in merged_construct_dfs.iterrows(): if unique_clip.equals(clip): clip_count[i] = clip_count[i] + 1 clip_count = clip_count // FINAL_ASSEMBLIES_PER_CLIP + 1 clips_df['number'] = [int(i) for i in clip_count.tolist()] # Associate well/s for each CLIP reaction clips_df['mag_well'] = pd.Series(['0'] * len(clips_df.index), index=clips_df.index) for index, number in clips_df['number'].iteritems(): if index == 0: mag_wells = [] for x in range(number): mag_wells.append(mplates.final_well(x + 1 + 48)) clips_df.at[index, 'mag_well'] = tuple(mag_wells) else: mag_wells = [] for x in range(number): well_count = clips_df.loc[:index - 1, 'number'].sum() + x + 1 + 48 mag_wells.append(mplates.final_well(well_count)) clips_df.at[index, 'mag_well'] = tuple(mag_wells) return clips_df
def generate_final_assembly_dict(constructs_list, clips_df): """Using constructs_list and clips_df, returns a dictionary of final assemblies with keys defining destination plate well positions and values indicating which clip reaction wells are used. """ final_assembly_dict = {} clips_count = np.zeros(len(clips_df.index)) for construct_index, construct_df in enumerate(constructs_list): construct_well_list = [] for _, clip in construct_df.iterrows(): clip_info = clips_df[(clips_df['prefixes'] == clip['prefixes']) & (clips_df['parts'] == clip['parts']) & (clips_df['suffixes'] == clip['suffixes'])] clip_wells = clip_info.at[clip_info.index[0], 'mag_well'] clip_num = int(clip_info.index[0]) clip_well = clip_wells[int(clips_count[clip_num] // FINAL_ASSEMBLIES_PER_CLIP)] clips_count[clip_num] = clips_count[clip_num] + 1 construct_well_list.append(clip_well) final_assembly_dict[mplates.final_well( construct_index + 1)] = construct_well_list return final_assembly_dict
def generate_spotting_tuples(constructs_list, spotting_vols_dict): """Using constructs_list, generates a spotting tuple (Refer to 'transformation_spotting_template.py') for every column of constructs, assuming the 1st construct is located in well A1 and wells increase linearly. Target wells locations are equivalent to construct well locations and spotting volumes are defined by spotting_vols_dict. Args: spotting_vols_dict (dict): Part number defined by keys, spotting volumes defined by corresponding value. """ # Calculate wells and volumes wells = [ mplates.final_well(x + 1) for x in range(len(constructs_list)) ] # assigns a final well for every assembly using a list comprehension vols = [ SPOTTING_VOLS_DICT[len( construct_df.index )] # assigns spotting vol based on how many clips there are in each reaction for construct_df in constructs_list ] # Package spotting tuples spotting_tuple_num = len(constructs_list) // 8 + ( 1 # number of spotting steps with the 8 channel pipette if len(constructs_list) % 8 > 0 else 0) spotting_tuples = [] for x in range(spotting_tuple_num): # for every spotting step... if x == spotting_tuple_num - 1: # tuple_wells = tuple(wells[8 * x:]) tuple_vols = tuple(vols[8 * x:]) else: tuple_wells = tuple(wells[8 * x:8 * x + 8]) tuple_vols = tuple(vols[8 * x:8 * x + 8]) spotting_tuples.append((tuple_wells, tuple_wells, tuple_vols)) return spotting_tuples