def upload_reagent_prep_info(rdict, sheetobject): uploadtarget = sheetobject.range('D3:F11') uploadlist = [] reagentcount = 1 for reagentnum, reagentobject in rdict.items(): while int(reagentnum) > reagentcount: uploadlist.extend( ['null'] * 3 ) #3 setby number of steps in reagent prep (see if section below) reagentcount += 1 if int(reagentnum) == reagentcount: uploadlist.append(reagentobject.preptemperature) uploadlist.append(reagentobject.prepstirrate) uploadlist.append(reagentobject.prepduration) reagentcount += 1 count = 0 for cell in uploadtarget: try: cell.value = uploadlist[count] count += 1 except: count += 1 sheetobject.update_cells(uploadtarget) # Upload prerxntemps prerxn_temp_cells = _get_reagent_header_cells(column='H') num_reagents = int( lab_safeget(config.lab_vars, globals.get_lab(), 'max_reagents')) + 1 for i in range(1, num_reagents): try: payload = rdict[str(i)].prerxntemp except KeyError: payload = 'null' sheetobject.update_acell(prerxn_temp_cells[i - 1], payload)
def quasirandom_generation_pipeline(vardict, chemdf, rxndict, edict, rdict, old_reagents, climits): """ TODO: Document rdict :param vardict: dictionary built from devconfig :param chemdf: chemical dataframe with descriptions of all chemicals in the reaction :param rxndict: complete key-value pairing from specification interface (front end xlsx as of 2.56) :param edict: dictionary of experiments (see documentation) :param rdict: dictionary of reagents defining the concentration space to be sampled. (see documentation) :param old_reagents: dictionary of reagents to subtract from statespace (same structure as rdict) :param climits: :return: """ erdf, ermmoldf, emsumdf, model_info_df = qrandom.preprocess_and_sample( chemdf, vardict, rxndict, edict, rdict, old_reagents, climits) # Clean up dataframe for robot file -> create xls --> upload erdf = expint.cleanvolarray(erdf, maxr=lab_safeget(config.lab_vars, globals.get_lab(), 'max_reagents')) # Export additional information files for later use / storage ermmolcsv = ('localfiles/%s_mmolbreakout.csv' % rxndict['RunID']) abstract_reagent_colnames(ermmoldf) ermmoldf.to_csv(ermmolcsv) emsumcsv = ('localfiles/%s_nominalMolarity.csv' % rxndict['RunID']) emsumdf.to_csv(emsumcsv) # List to send for uploads secfilelist = [ermmolcsv, emsumcsv, vardict['exefilename']] return emsumdf, secfilelist, erdf, model_info_df
def prebuildvalidation(rxndict, vardict): '''handles validation functions for xls input file takes the rxndict as input and performs validation on the input to ensure the proper structure -- currently underdeveloped ''' reagent_alias = lab_safeget(config.lab_vars, globals.get_lab(), 'reagent_alias') modlog = logging.getLogger('capture.prebuildvalidation') validate_experiment_form_and_number(rxndict) expcount(rxndict) expwellcount(rxndict) reagconcdefs(rxndict) used_reagents_are_specified(rxndict, vardict['exefilename'], reagent_alias) # multi_stock only supported for wolfram if rxndict.get('multi_stock_sampling'): modlog.warning('Using Multi Stock Sampling') if config.sampler != 'wolfram': raise ValueError( 'Multistock sampling is activated but sampler is set to "{}"'. format(config.sampler), 'Sampler must be "wolfram" to use multistock sampling') modlog.info('User entry is configured correctly. Proceeding with run') if not rxndict['lab'] in config.lab_vars.keys(): modlog.error('User selected a lab that was not supported. Closing run') sys.exit()
def upload_reagent_specifications(finalexportdf, sheet): """upload rxndict, finalexportdf to gc target, returns the used gsheets object :param finalexportdf: datframe containing pre-ordered and normalized abbreviations, nomial amounts and units \n :type finalexportdf: pandas dataframe object \n :param sheet: google sheet string indicating the target file for uploading the finalexport df \n :type sheet: str \n :return: NONE - creates online object in run directory """ # get lab-specific config variables reagent_interface_amount_startrow = lab_safeget( config.lab_vars, globals.get_lab(), 'reagent_interface_amount_startrow') max_reagents = lab_safeget(config.lab_vars, globals.get_lab(), 'max_reagents') update_sheet_column(sheet, finalexportdf['chemabbr'], col_index='B', start_row=reagent_interface_amount_startrow) update_sheet_column(sheet, finalexportdf['nominal_amount'], col_index='C', start_row=reagent_interface_amount_startrow) update_sheet_column(sheet, finalexportdf['Unit'], col_index='E', start_row=reagent_interface_amount_startrow) # add in actual amount column for specified reagents # only adds null to rows where there is no chemical nulls = finalexportdf['actualsnull'].values.tolist() nulls = [val if val == 'null' else '' for val in nulls] update_sheet_column(sheet, nulls, col_index='D', start_row=reagent_interface_amount_startrow) # add nulls to actual amount column for unspecified reagents null_start = reagent_interface_amount_startrow + len(finalexportdf) maxreagentchemicals = lab_safeget(config.lab_vars, globals.get_lab(), 'maxreagentchemicals') num_nulls = (max_reagents - len(finalexportdf.reagentnames.unique())) * ( maxreagentchemicals + 1) nulls = ['null'] * num_nulls
def upload_files_to_gdrive(opdir, secdir, secfilelist, filelist, runID, eclogfile): """Upload files to Google Drive :param opdir: main google drive directory to upload to :param secdir: subdirectory in opdir in which logfiles and executables are written :param secfilelist: files to be written to secdir :param filelist: files that go in opdir :param runID: the ID of this run of ESCALATE :param eclogfile: local path to logfile for the run :return: None """ drive = get_drive_auth() for file in filelist: outfile = drive.CreateFile( {"parents": [{ "kind": "drive#fileLink", "id": opdir }]}) outfile.SetContentFile(file) outfile['title'] = file.split('/')[1] outfile.Upload() # Data files that need to be stored but are not crucial for performers for secfile in secfilelist: outfile = drive.CreateFile( {"parents": [{ "kind": "drive#fileLink", "id": secdir }]}) outfile.SetContentFile(secfile) outfile['title'] = secfile.split('/')[1] outfile.Upload() requested_folders = lab_safeget(config.lab_vars, globals.get_lab(), 'required_folders') if requested_folders: for folder in requested_folders: create_drive_folder(folder, opdir) logfile = drive.CreateFile( {"parents": [{ "kind": "drive#fileLink", "id": opdir }]}) logfile.SetContentFile(eclogfile) logfile['title'] = '%s.log' % runID logfile.Upload() wdir = drive.CreateFile({'id': opdir}) swdir = drive.CreateFile({'id': secdir}) modlog.info('%s successfully uploaded to %s' % (logfile['title'], swdir['title'])) for item in filelist: modlog.info('%s successfully uploaded to %s' % (item, wdir['title'])) for item in secfilelist: modlog.info('%s successfully uploaded to %s' % (item, swdir['title'])) print('File Upload Complete')
def stateset_generation_pipeline(vardict, chemdf, rxndict, edict, rdict, volspacing): """Generate stateset and associated files """ erdf, ermmoldf, emsumdf = statespace.preprocess_and_enumerate( chemdf, rxndict, edict, rdict, volspacing) # Clean up dataframe for robot file -> create xls --> upload erdfrows = erdf.shape[0] erdf = expint.cleanvolarray( erdf, lab_safeget(config.lab_vars, globals.get_lab(), 'max_reagents')) abstract_reagent_colnames(erdf) ermmolcsv = 'localfiles/%s_mmolbreakout.csv' % rxndict['RunID'] abstract_reagent_colnames(ermmoldf) ermmoldf.to_csv(ermmolcsv) # has no reagent names emsumcsv = 'localfiles/%s_nominalMolarity.csv' % rxndict['RunID'] emsumdf.to_csv(emsumcsv) statesetfile = 'localfiles/%sstateset.csv' % rdict['2'].chemicals prerun = 'localfiles/%sstateset.link.csv' % rdict['2'].chemicals # Hardcode the inchikey lookup for the "amine" aka chemical 3 for the time being, though there must be a BETTER WAY! inchilist = [(chemdf.loc[rdict['2'].chemicals[1], "InChI Key (ID)"]) ] * erdfrows inchidf = pd.DataFrame(inchilist, columns=['_rxn_organic-inchikey']) #highly specific curation for the wf1 cp dataflow # drops solvent column for chemical in emsumdf.columns: chemicalname = chemical.split(' ')[0] if chemicalname in vardict['solventlist'] and chemicalname != "FAH": solventheader = chemical emsumdf.drop(columns=[solventheader], inplace=True) emsumdf.rename(columns={ "%s [M]" % rdict['2'].chemicals[0]: "_rxn_M_inorganic", "%s [M]" % rdict['2'].chemicals[1]: "_rxn_M_organic", "%s [M]" % rdict['7'].chemicals[0]: "_rxn_M_acid" }, inplace=True) modlog.warning( "The following chemicals have been assigned generic column names:") modlog.warning("%s [M] --> _rxn_M_inorganic" % rdict['2'].chemicals[0]) modlog.warning("%s [M] --> _rxn_M_organic" % rdict['2'].chemicals[1]) modlog.warning("%s [M] --> _rxn_M_acid" % rdict['7'].chemicals[0]) ddf = stateset.augdescriptors(inchidf, rxndict, erdfrows) prerun_df = pd.concat([erdf, emsumdf, ddf], axis=1) stateset_df = pd.concat([emsumdf, ddf], axis=1) # stateset_df = emsumdf #toggle to prevent state space from having all of the features added # todo ?? prerun_df.to_csv(prerun) stateset_df.to_csv(statesetfile) uploadlist = [prerun, statesetfile] secfilelist = [ermmolcsv, emsumcsv, vardict['exefilename']] return emsumdf, uploadlist, secfilelist, rdict
def _get_reagent_header_cells(column: str): """Get all cells in the rows that start each reagent for a given colum :param column: (str) in {A, B, ..., Z, AA, AB, ...} """ startrow = lab_safeget(config.lab_vars, globals.get_lab(), 'reagent_interface_amount_startrow') reagent_interface_step = int( lab_safeget(config.lab_vars, globals.get_lab(), 'maxreagentchemicals')) + 1 num_reagents = lab_safeget(config.lab_vars, globals.get_lab(), 'max_reagents') stoprow = startrow + reagent_interface_step * num_reagents result = [ column + str(i) for i in range(startrow, stoprow, reagent_interface_step) ] return result
def postbuildvalidation(rxndict, vardict, rdict, edict, chemdf): reagent_alias = lab_safeget(config.lab_vars, globals.get_lab(), 'reagent_alias') modlog = logging.getLogger('capture.postbuildvalidation') # modlog.error("Fatal error. Reagents and chemicals are over constrained. Recheck user options!") validate_solvent_positions(rdict, vardict['solventlist'], reagent_alias, chemdf) modlog.info('Experiment successfully constructed.')
def abstract_reagent_colnames(df, inplace=True): """Replace instances of 'Reagent' with devconfig.REAGENT_ALIAS :param df: dataframe to rename :return: None or pandas.DataFrame (depending on inplace) """ reagent_alias = lab_safeget(config.lab_vars, globals.get_lab(), 'reagent_alias') result = df.rename( columns=lambda x: re.sub('[Rr]eagent', reagent_alias, x), inplace=inplace) return result
def build_reagent_spec_df(rxndict, vardict, erdf, rdict, chemdf): """Build the dataframe for the bottom portion of the reagent preparation_interface :param rxndict: :param vardict: :param erdf: :param rdict: :param chemdf: :return: """ modlog.info('Starting reagent interface upload') chemical_names_df = build_chemical_names_df( rdict, lab_safeget(config.lab_vars, globals.get_lab(), 'maxreagentchemicals')) reagent_target_volumes = get_reagent_target_volumes( erdf, rxndict['reagent_dead_volume'] * 1000) nominals_df = build_nominals_v1( rdict, chemical_names_df, reagent_target_volumes, vardict['solventlist'], lab_safeget(config.lab_vars, globals.get_lab(), 'maxreagentchemicals'), chemdf) reagent_spec_df = pd.concat([chemical_names_df, nominals_df], axis=1) return reagent_spec_df
def upload_aliased_cells(sheet): """Upload cells containing reagent alias to the reagent interface""" # Value used in googlesheet as placeholder for reagent alias cell_alias_pat = '<Reagent>' # Cells in googlesheet containing reagent alias: aliased_cells = ['C1', 'C2'] # Reagent<i> cells at bottom of sheet (all in col A, regularly spaced): aliased_cells.extend(_get_reagent_header_cells('A')) reagent_alias = lab_safeget(config.lab_vars, globals.get_lab(), 'reagent_alias') for cell in aliased_cells: current_value = sheet.acell(cell).value new_value = current_value.replace(cell_alias_pat, reagent_alias) sheet.update_acell(cell, new_value) return
def ChemicalData(lab): """ Uses google api to gather the chemical inventory targeted by labsheet 'chemsheetid' in dev config Parameters ---------- lab : abbreviation of the lab lab is specified as the suffix of a folder and the available options are included in the lab_vars of the devconfig.py file Returns -------- chemdf : pandas df of the chemical inventory """ sleep_timer = 0 chemdf = 0 #just create a 'blank' object while not isinstance(chemdf, pd.DataFrame): try: gc = get_gdrive_client() chemsheetid = globals.lab_safeget(lab_vars, lab, 'chemsheetid') ChemicalBook = gc.open_by_key(chemsheetid) chemicalsheet = ChemicalBook.get_worksheet(0) chemical_list = chemicalsheet.get_all_values() chemdf = pd.DataFrame(chemical_list, columns=chemical_list[0]) chemdf = chemdf.iloc[1:] chemdf = chemdf.reset_index(drop=True) chemdf = chemdf.set_index(['InChI Key (ID)']) except APIError as e: modlog.info(e.response) modlog.info(sys.exc_info()) modlog.info( 'During download of {} chemical inventory sever request limit was met' .format(lab)) sleep_timer = 15.0 time.sleep(sleep_timer) modlog.info(f'Successfully loaded the chemical inventory from {lab}') return (chemdf)
def upload_modelinfo_observation_interface(model_info_df, gc, interface_uid): '''push the model information to the observation interface :param model_info_df: 2xN data frame with 'modelname' and 'participantname' as columns and N being the total number of experiments :param interface_uid: google sheets observation UID :return: NULL ''' sheet = gc.open_by_key(interface_uid).sheet1 observation_dict = lab_safeget(config.lab_vars, globals.get_lab(), 'observation_interface') modeluid_col = observation_dict['modeluid_col'] participantuid_col = observation_dict['participantuid_col'] update_sheet_column(sheet, data=model_info_df['modelname'], col_index=modeluid_col, start_row=2) update_sheet_column(sheet, data=model_info_df['participantname'], col_index=participantuid_col, start_row=2) return
def copy_drive_templates(opdir, RunID, includedfiles): """Copy template gdrive files into gdrive directory for this run :param opdir: gdrive directory for this run :param RunID: ID of this run :param includedfiles: files to be copied from template gdrive directory :return: a referenced dictionary of files (title, Gdrive ID) """ drive = get_drive_auth() template_folder = lab_safeget(config.lab_vars, globals.get_lab(), 'template_folder') file_template_list = drive.ListFile({ 'q': "'%s' in parents and trashed=false" % template_folder }).GetList() for templatefile in file_template_list: basename = templatefile['title'] if basename in includedfiles: drive.auth.service.files().copy(fileId=templatefile['id'], body={ "parents": [{ "kind": "drive#fileLink", "id": opdir }], 'title': '%s_%s' % (RunID, basename) }).execute() newdir_list = drive.ListFile({ 'q': "'%s' in parents and trashed=false" % opdir }).GetList() new_dict = {} for file1 in newdir_list: new_dict[file1['title']] = file1['id'] return new_dict
def get_reagent_number_as_string(reagent_str): """Get the number from a string representation""" reagent_alias = lab_safeget(config.lab_vars, globals.get_lab(), 'reagent_alias') reagent_pat = re.compile('([Rr]eagent|{})(\d+)'.format(reagent_alias)) return reagent_pat.match(reagent_str).group(2)
def upload_observation_interface_data(rxndict, vardict, gc, interface_uid): """ :param gc: :param interface_uid: :return: """ sheet = gc.open_by_key(interface_uid).sheet1 # todo: only build this once: we now read the manual spec sheet three times... experiment_names = build_experiment_names_df(rxndict, vardict) # experiment_index = range(1, len(experiment_names) + 1) total_exp_entries = int(rxndict['wellcount']) #TODO: organize code around workflow handling... at this moment moving to specify level seems appropriate # Maybe setting the variables for actions in dictionaries that can be created through some interface # TODO: This needs to be moved to a dict in the devconfig with clear configuration standards uploadlist = [] if rxndict['ExpWorkflowVer'] >= 3 and rxndict['ExpWorkflowVer'] < 4: uploadtarget = sheet.range(f'A2:D{total_exp_entries+1}') df = MakeWellList_WF3_small("nothing", total_exp_entries) exp_counter = list(range(1, total_exp_entries + 1)) # +1 to fix off by 1 wellnamelist = df['Vial Site'].values.tolist() letter_list = [x[:1] for x in wellnamelist] number_list = [x[1:] for x in wellnamelist] count = 0 while count < len(exp_counter): uploadlist.append(exp_counter[count]) uploadlist.append(letter_list[count]) uploadlist.append(number_list[count]) uploadlist.append(wellnamelist[count]) count += 1 count = 0 for cell in uploadtarget: try: cell.value = uploadlist[count] count += 1 except: count += 1 sheet.update_cells(uploadtarget) else: if globals.get_lab() == 'MIT_PVLab': uploadtarget = sheet.range(f'A2:A{total_exp_entries+1}') df = MakeWellList("nothing", total_exp_entries) uploadlist = list(range(1, total_exp_entries + 1)) # +1 to fix off by 1 count = 0 for cell in uploadtarget: try: cell.value = uploadlist[count] count += 1 except: count += 1 sheet.update_cells(uploadtarget) else: uploadtarget = sheet.range(f'A2:D{total_exp_entries+1}') df = MakeWellList("nothing", total_exp_entries) exp_counter = list(range(1, total_exp_entries + 1)) # +1 to fix off by 1 wellnamelist = df['Vial Site'].values.tolist() letter_list = [x[:1] for x in wellnamelist] number_list = [x[1:] for x in wellnamelist] count = 0 while count < len(exp_counter): uploadlist.append(exp_counter[count]) uploadlist.append(letter_list[count]) uploadlist.append(number_list[count]) uploadlist.append(wellnamelist[count]) count += 1 count = 0 for cell in uploadtarget: try: cell.value = uploadlist[count] count += 1 except: count += 1 sheet.update_cells(uploadtarget) obs_columns = lab_safeget(config.lab_vars, globals.get_lab(), 'observation_interface') update_sheet_column(sheet, data=experiment_names['Experiment Names'], col_index=obs_columns['uid_col'], start_row=2) return
def LBLrobotfile(rxndict, vardict, erdf): """Write to excel file for LBL Nimbus and return filename TODO: denote these as LBL specific, generalize action specification and sequences :param erdf: should contain the experimental reaction data frame which consists of the volumes of each reagent in each experiment to be performed. ALSO CONTAINS: New Development code .... needs debugging Write to excel file for MIT Human and return filename todo: * write this file for ALL experiments * robot just reads this general representation and writes to specific format * e.g. Nimbus gets its own format * This solves report issue * report looks for specification file, and if it cant find it looks for RobotInput.xls :param erdf: should contain the experimental reaction data frame which consists of the volumes of each reagent in each experiment to be performed. """ vol_ar = volarray(erdf, lab_safeget(config.lab_vars, globals.get_lab(), 'max_reagents')) # If the additional actions were not specified, just leave the cells blank. # TODO: CLEAN UP THE ABOVE AFTER THE IMMEDIATE MIT PUSH. userAction0 = rxndict.get('Additional_action_1_description', 0) userAction1 = rxndict.get('Additional_action_2_description', '') userActionValue0 = rxndict.get('Additional_action_1_value', 0) userActionValue1 = rxndict.get('Additional_action_2_value', '') if userAction0 == 0: userAction0 = "" userActionValue0 = '' if userAction1 == 0: userAction1 = "" userActionValue1 = '' reagent_alias = lab_safeget(config.lab_vars, globals.get_lab(), 'reagent_alias') rxn_conditions = pd.DataFrame({ reagent_alias + 's': [reagent_alias + str(i+1) for i in range(len(vol_ar))], reagent_alias + ' identity': [str(i+1) for i in range(len(vol_ar))], 'Liquid Class': vol_ar, reagent_alias + ' Temperature': [rxndict['reagents_prerxn_temperature']] * len(vol_ar) }) robotfiles = [] if rxndict['ExpWorkflowVer'] >= 3 and rxndict['ExpWorkflowVer'] < 4: rxn_parameters = pd.DataFrame({ 'Reaction Parameters': ['Temperature (C):', 'Stir Rate (rpm):', 'Mixing time (s):', 'Mixing time2 (s):', 'Reaction time (s):', 'Temperature Cool (C):', userAction0, userAction1 ], 'Parameter Values': [rxndict['temperature1_nominal'], rxndict['stirrate'], rxndict['duratation_stir1'], rxndict['duratation_stir2'], rxndict['duration_reaction'], rxndict['temperature2_nominal'], userActionValue0, userActionValue1 ], }) rxn_parameters_small = pd.DataFrame({ 'Reaction Parameters': ['Temperature (C):', 'Stir Rate (rpm):', 'Mixing time (s):', '', '', '', '', '' ], 'Parameter Values': [rxndict['temperature1_nominal'], rxndict['stirrate'], rxndict['duratation_stir1'], '', '', '', '', '' ], }) # For WF3 tray implementation to work df_Tray2 = MakeWellList_WF3(rxndict['plate_container'], rxndict['wellcount']*2) erdf_new = WF3_split(erdf, rxndict['WF3_split']) outframe1 = pd.concat([df_Tray2.iloc[:, 0], erdf_new, df_Tray2.iloc[:, 1], rxn_parameters_small, rxn_conditions], sort=False, axis=1) if globals.get_lab() == 'LBL': robotfile = ('localfiles/%s_RUNME_RobotFile.xls' %rxndict['RunID']) else: robotfile = ('localfiles/%s_RUNME_RobotFile.xls' %rxndict['RunID']) ## For report code to work df_Tray = MakeWellList_WF3_small(rxndict['plate_container'], rxndict['wellcount']*1) outframe2 = pd.concat([df_Tray.iloc[:, 0], erdf, df_Tray.iloc[:,1],rxn_parameters, rxn_conditions], sort=False, axis=1) robotfile2 = ('localfiles/%s_RobotInput.xls' % rxndict['RunID']) outframe1.to_excel(robotfile, sheet_name='NIMBUS_reaction', index=False) outframe2.to_excel(robotfile2, sheet_name='NIMBUS_reaction', index=False) robotfiles.append(robotfile) robotfiles.append(robotfile2) else: if globals.get_lab() == 'MIT_PVLab': rxn_parameters = pd.DataFrame({ 'Reaction Parameters': ['Spincoating Temperature ( C )', 'Spincoating Speed (rpm):', 'Spincoating Duration (s)', 'Spincoating Duration 2 (s)', 'Annealing Temperature ( C )', 'Annealing Duration (s)', userAction0, userAction1, ""], 'Parameter Values': [rxndict['temperature1_nominal'], rxndict['stirrate'], rxndict['duratation_stir1'], rxndict['duratation_stir2'], rxndict['temperature2_nominal'], rxndict['duration_reaction'], userActionValue0, userActionValue1, ''], }) experiment_names = build_experiment_names_df(rxndict, vardict) df_Tray = pd.DataFrame({ 'Experiment Index': range(1, int(rxndict['wellcount']) + 1), 'Labware ID': rxndict['plate_container'] }) outframe = pd.concat([df_Tray.iloc[:, 0], experiment_names, erdf, df_Tray.iloc[:, 1], rxn_parameters, rxn_conditions], sort=False, axis=1) else: rxn_parameters = pd.DataFrame({ 'Reaction Parameters': ['Temperature (C):', 'Stir Rate (rpm):', 'Mixing time1 (s):', 'Mixing time2 (s):', 'Reaction time (s):', 'Preheat Temperature (C):', userAction0, userAction1 ], 'Parameter Values': [rxndict['temperature2_nominal'], rxndict['stirrate'], rxndict['duratation_stir1'], rxndict['duratation_stir2'], rxndict['duration_reaction'], rxndict['temperature1_nominal'], userActionValue0, userActionValue1 ], }) df_Tray = MakeWellList(rxndict['plate_container'], rxndict['wellcount']) outframe = pd.concat([df_Tray.iloc[:, 0], erdf, df_Tray.iloc[:, 1], rxn_parameters, rxn_conditions], sort=False, axis=1) if globals.get_lab() == 'LBL': volume_file = ('localfiles/%s_RobotInput.xls' % rxndict['RunID']) else: volume_file = ('localfiles/%s_ExperimentSpecification.xls' %rxndict['RunID']) outframe = abstract_reagent_colnames(outframe, inplace=False) robotfiles.append(volume_file) outframe.to_excel(volume_file, sheet_name='NIMBUS_reaction', index=False) return robotfiles
def parse_exp_volumes(exp_volume_spec_fname, experiment_lab): """ Parses the experiment interface. For example of the complete structure see: https://drive.google.com/open?id=1rNPfcOiseQSTTB8E7VsKp77h8hv8VSCj Link targets 4-DataDebug Robotinput example Parameters ---------- exp_volume_spec_fname : filename which contains volumes actions predifined structure is hardcoded based on a specific labs needs experiment_lab : name of lab all labs except MIT are handled the same, this is hard coded and brittle Returns ------- lists and dataframes, complex return Notes: TODO: Generalize this function to any new lab TODO: clean up the return of this function If this function breaks pytest will catch the malfunction """ robot_dict = pd.read_excel(open(exp_volume_spec_fname, 'rb'), header=[0], sheet_name=0) reagentlist = [] for header in robot_dict.columns: reagent_alias_name = lab_safeget(config.lab_vars, experiment_lab, 'reagent_alias') if reagent_alias_name in header and "ul" in header: reagentlist.append(header) rnum = len(reagentlist) pipette_list = range(0, rnum + 2) #MIT_PVLab has an additional column in the second row 'Experiment Name' in additiona # to the 'Experiment Index'. The +1 accounts for that during parsing if experiment_lab == 'MIT_PVLab': rnum += 1 pipette_list = [0] pipette_list.extend(range(2, rnum + 2)) pipette_volumes = pd.read_excel(exp_volume_spec_fname, sheet_name=0, usecols=pipette_list) pipette_volumes.dropna(how='all', inplace=True) reaction_parameters = pd.read_excel(exp_volume_spec_fname, sheet_name=0, usecols=[rnum + 2, rnum + 3]).dropna() reagent_info = pd.read_excel( exp_volume_spec_fname, sheet_name=0, usecols=[rnum + 4, rnum + 5, rnum + 6, rnum + 7]).dropna() validate_experimental_volumes(pipette_volumes) validate_reaction_parameters(reaction_parameters) validate_reagent_info(reagent_info) pipette_dump = json.dumps(pipette_volumes.values.tolist()) reaction_dump = json.dumps(reaction_parameters.values.tolist()) reagent_dump = json.dumps(reagent_info.values.tolist()) return pipette_dump, reaction_dump, reagent_dump