def save_sample_attribute(request): """ save sample attribute """ if request.method == 'POST': queryDict = request.POST logger.debug("views.save_sample_attribute POST queryDict=%s; " %(queryDict)) intent = queryDict.get('intent',None) sampleAttribute_id = queryDict.get("id", None) attribute_type_id = queryDict.get('attributeType', None) if attribute_type_id == "0": attribute_type_id = None attribute_name = queryDict.get('sampleAttributeName', None) attribute_description = queryDict.get('attributeDescription', None) if not attribute_name or not attribute_name.strip(): ##return HttpResponse(json.dumps({"status": "Error: Attribute name is required"}), mimetype="text/html") return HttpResponse(json.dumps(["Error, Attribute name is required."]), mimetype="application/json") try: sample_attribute_type = SampleAttributeDataType.objects.get(id = attribute_type_id) except: #return HttpResponse(json.dumps({"status": "Error: Attribute type is required"}), mimetype="text/html") return HttpResponse(json.dumps(["Error, Attribute type is required."]), mimetype="application/json") is_mandatory = toBoolean(queryDict.get('is_mandatory', False)) #TODO: validation (including checking the status again!! isValid = True if isValid: try: userName = request.user.username user = User.objects.get(username=userName) currentDateTime = timezone.now() ##datetime.datetime.now() underscored_attribute_name = str(attribute_name.strip().replace(' ', '_')).lower() isValid, errorMessage = sample_validator.validate_sampleAttribute_definition(underscored_attribute_name, attribute_description.strip()) if errorMessage: #return HttpResponse(errorMessage, mimetype="text/html") return HttpResponse(json.dumps([errorMessage]), mimetype="application/json") if intent == "add": new_sample_attribute = SampleAttribute( displayedName = underscored_attribute_name, dataType = sample_attribute_type, description = attribute_description.strip(), isMandatory = is_mandatory, isActive = True, creator = user, creationDate = currentDateTime, lastModifiedUser = user, lastModifiedDate = currentDateTime ) new_sample_attribute.save() else: orig_sampleAttribute = get_object_or_404(SampleAttribute, pk = sampleAttribute_id) if (orig_sampleAttribute.displayedName == underscored_attribute_name and str(orig_sampleAttribute.dataType_id) == attribute_type_id and orig_sampleAttribute.description == attribute_description.strip() and orig_sampleAttribute.isMandatory == is_mandatory): logger.debug("views.save_sample_attribute() - NO UPDATE NEEDED!! sampleAttribute.id=%d" %(orig_sampleAttribute.id)) else: sampleAttribute_kwargs = { 'displayedName' : underscored_attribute_name, 'description' : attribute_description.strip(), 'dataType_id' : attribute_type_id, 'isMandatory' : is_mandatory, 'lastModifiedUser' : user, 'lastModifiedDate' : currentDateTime } for field, value in sampleAttribute_kwargs.iteritems(): setattr(orig_sampleAttribute, field, value) orig_sampleAttribute.save() logger.debug("views.save_sample_attribute - UPDATED sampleAttribute.id=%d" %(orig_sampleAttribute.id)) except: logger.exception(format_exc()) #return HttpResponse(json.dumps({"status": "Error: Cannot save user-defined sample attribute to database"}), mimetype="text/html") message = "Cannot save sample attribute to database. " if settings.DEBUG: message += format_exc() return HttpResponse(json.dumps([message]), mimetype="application/json") return HttpResponse("true") else: #errors = form._errors.setdefault(forms.forms.NON_FIELD_ERRORS, forms.util.ErrorList()) #return HttpResponse(errors) ##return HttpResponse(json.dumps({"status": "Could not save sample attribute due to validation errors"}), mimetype="text/html") return HttpResponse(json.dumps(["Cannot save sample attribute due to validation errors."]), mimetype="application/json") else: #return HttpResponse(json.dumps({"status": "Error: Request method to save user-defined sample attribute is invalid"}), mimetype="text/html") return HttpResponse(json.dumps(["Request method for save_sample_attribute is invalid."]), mimetype="application/json")
def __get_universal_params(self, step_helper, username): if not step_helper.isPlan(): if step_helper.isTemplateBySample(): save_template_step_data = step_helper.steps[ StepNames.SAVE_TEMPLATE_BY_SAMPLE] else: save_template_step_data = step_helper.steps[ StepNames.SAVE_TEMPLATE] application_step_data = step_helper.steps[StepNames.APPLICATION] kits_step_data = step_helper.steps[StepNames.KITS] reference_step_data = step_helper.steps[StepNames.REFERENCE] plugins_step_data = step_helper.steps[StepNames.PLUGINS] ionreporter_step_data = step_helper.steps[StepNames.IONREPORTER] if not step_helper.isPlan(): isFavorite = save_template_step_data.savedFields['setAsFavorite'] else: isFavorite = False runType = '' application_group = None sampleGrouping = None if application_step_data.savedObjects['runType']: runType = application_step_data.savedObjects['runType'].runType application_group = application_step_data.savedObjects[ 'runType'].applicationGroups.all()[0:1][0] if application_step_data.savedFields['applicationGroup']: application_group = ApplicationGroup.objects.get( pk=application_step_data.savedFields['applicationGroup']) if ionreporter_step_data.savedFields['sampleGrouping']: sampleGrouping = ionreporter_step_data.savedObjects[ 'sampleGrouping'] templatingKitName = kits_step_data.savedFields['templatekitname'] controlSequencekitname = kits_step_data.savedFields['controlsequence'] samplePrepKitName = kits_step_data.savedFields['samplePreparationKit'] x_barcodeId = kits_step_data.savedFields['barcodeId'] x_chipType = kits_step_data.savedFields['chipType'] if not x_chipType: x_chipType = '' x_flows = kits_step_data.savedFields['flows'] x_forward3primeadapter = kits_step_data.savedFields[ 'forward3primeAdapter'] x_libraryKey = kits_step_data.savedFields['libraryKey'] x_librarykitname = kits_step_data.savedFields['librarykitname'] x_sequencekitname = kits_step_data.savedFields['sequencekitname'] x_isDuplicateReads = kits_step_data.savedFields['isDuplicateReads'] x_bedfile = reference_step_data.savedFields['targetBedFile'] x_library = reference_step_data.savedFields["reference"] x_regionfile = reference_step_data.savedFields['hotSpotBedFile'] selectedPluginsValue = plugins_step_data.getSelectedPluginsValue() planStatus = "planned" if not step_helper.isEditRun(): if step_helper.isIonChef(): if step_helper.isPlan() or step_helper.isPlanBySample(): planStatus = "pending" else: planStatus = "run" retval = { 'applicationGroup': application_group, 'sampleGrouping': sampleGrouping, 'usePreBeadfind': True, 'usePostBeadfind': True, 'preAnalysis': True, 'runType': runType, 'templatingKitName': templatingKitName, 'controlSequencekitname': controlSequencekitname, 'runMode': 'single', 'isSystem': False, 'isPlanGroup': False, 'username': username, 'isFavorite': toBoolean(isFavorite, False), 'pairedEndLibraryAdapterName': '', 'samplePrepKitName': samplePrepKitName, 'planStatus': planStatus, 'x_autoAnalyze': True, 'x_barcodeId': x_barcodeId, 'x_bedfile': x_bedfile, 'x_chipType': x_chipType, 'x_flows': x_flows, 'x_forward3primeadapter': x_forward3primeadapter, 'x_library': x_library, 'x_libraryKey': x_libraryKey, 'x_librarykitname': x_librarykitname, 'x_regionfile': x_regionfile, 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': x_sequencekitname, 'x_variantfrequency': '', 'x_isDuplicateReads': False if x_isDuplicateReads is None else x_isDuplicateReads } return retval
def __get_universal_params(self, step_helper, username): if not step_helper.isPlan(): if step_helper.isTemplateBySample(): save_template_step_data = step_helper.steps[ StepNames.SAVE_TEMPLATE_BY_SAMPLE] else: save_template_step_data = step_helper.steps[ StepNames.SAVE_TEMPLATE] application_step_data = step_helper.steps[StepNames.APPLICATION] kits_step_data = step_helper.steps[StepNames.KITS] reference_step_data = step_helper.steps[StepNames.REFERENCE] plugins_step_data = step_helper.steps[StepNames.PLUGINS] ionreporter_step_data = step_helper.steps[StepNames.IONREPORTER] analysisParams_step_data = step_helper.steps[StepNames.ANALYSIS_PARAMS] save_plan_step_data = step_helper.steps.get(StepNames.SAVE_PLAN, "") isFavorite = False categories = application_step_data.prepopulatedFields.get( ApplicationFieldNames.CATEGORIES, "") runType = "" if application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE]: runType = application_step_data.savedObjects[ ApplicationFieldNames.RUN_TYPE].runType if not step_helper.isPlan(): isFavorite = save_template_step_data.savedFields[ SaveTemplateStepDataFieldNames.SET_AS_FAVORITE] application_group = None sampleGrouping = None if application_step_data.savedFields[ ApplicationFieldNames.APPLICATION_GROUP_NAME]: application_group = ApplicationGroup.objects.get( name=application_step_data.savedFields[ ApplicationFieldNames.APPLICATION_GROUP_NAME]) elif application_step_data.savedObjects[ ApplicationFieldNames.RUN_TYPE]: application_group = application_step_data.savedObjects[ ApplicationFieldNames.RUN_TYPE].applicationGroups.all()[0:1][0] # if user has changed the application or target technique during template copying, reset categories value if application_group and application_group.name != "DNA + RNA": # workaround: OCP DNA has DNA as applicationGroupName and AMPS as run type so it can be ambiguous. # If user creates/copies/edits a template or plan from an OCP template, preserve the categories that starts out with. if categories and application_group.name != "DNA" and runType != "AMPS": categories = categories.replace("Onconet", "") categories = categories.replace("Oncomine", "") # if user has changed the application or target technique during template copying/editing, reset categories value if outdated customer-facing category value is found if runType: if categories: tokens = categories.split(';') for token in tokens: categories_cv = common_CV.objects.filter( cv_type="applicationCategory", isVisible=True, value__iexact=token) if (categories_cv.count() > 0): category_cv = categories_cv[0] if category_cv.categories and runType not in category_cv.categories: categories = "" else: categories = "" if ionreporter_step_data.savedFields[ IonReporterFieldNames.SAMPLE_GROUPING]: sampleGrouping = ionreporter_step_data.savedObjects[ IonReporterFieldNames.SAMPLE_GROUPING] templatingKitName = kits_step_data.savedFields[ KitsFieldNames.TEMPLATE_KIT_NAME] controlSequencekitname = kits_step_data.savedFields[ KitsFieldNames.CONTROL_SEQUENCE] samplePrepKitName = kits_step_data.savedFields[ KitsFieldNames.SAMPLE_PREPARATION_KIT] if kits_step_data.savedFields[KitsFieldNames.READ_LENGTH] > 0: libraryReadLength = kits_step_data.savedFields[ KitsFieldNames.READ_LENGTH] else: libraryReadLength = kits_step_data.savedFields[ KitsFieldNames.LIBRARY_READ_LENGTH] templatingSize = kits_step_data.savedFields[ KitsFieldNames.TEMPLATING_SIZE] samplePrepProtocol = kits_step_data.savedFields[ KitsFieldNames.SAMPLE_PREP_PROTOCOL] isCustom_kitSettings = kits_step_data.savedFields[ KitsFieldNames.ADVANCED_SETTINGS_CHOICE] == "custom" x_barcodeId = kits_step_data.savedFields[KitsFieldNames.BARCODE_ID] if save_plan_step_data and x_barcodeId: x_endBarcodeKitName = save_plan_step_data.savedFields[ SavePlanFieldNames.END_BARCODE_SET] else: x_endBarcodeKitName = "" x_chipType = kits_step_data.savedFields[KitsFieldNames.CHIP_TYPE] if not x_chipType: x_chipType = '' x_flows = kits_step_data.savedFields[KitsFieldNames.FLOWS] x_forward3primeadapter = kits_step_data.savedFields[ KitsFieldNames.FORWARD_3_PRIME_ADAPTER] x_flowsInOrder = kits_step_data.savedFields[KitsFieldNames.FLOW_ORDER] x_libraryKey = kits_step_data.savedFields[KitsFieldNames.LIBRARY_KEY] tfKey = kits_step_data.savedFields[KitsFieldNames.TF_KEY] x_librarykitname = kits_step_data.savedFields[ KitsFieldNames.LIBRARY_KIT_NAME] x_sequencekitname = kits_step_data.savedFields[ KitsFieldNames.SEQUENCE_KIT_NAME] x_isDuplicateReads = kits_step_data.savedFields[ KitsFieldNames.IS_DUPLICATED_READS] x_base_recalibration_mode = kits_step_data.savedFields[ KitsFieldNames.BASE_RECALIBRATE] x_realign = kits_step_data.savedFields[KitsFieldNames.REALIGN] x_bedfile = reference_step_data.savedFields[ ReferenceFieldNames.TARGET_BED_FILE] x_library = reference_step_data.savedFields[ ReferenceFieldNames.REFERENCE] x_regionfile = reference_step_data.savedFields[ ReferenceFieldNames.HOT_SPOT_BED_FILE] x_sseBedFile = reference_step_data.get_sseBedFile(x_bedfile) x_mixedTypeRNA_bedfile = reference_step_data.savedFields[ ReferenceFieldNames.MIXED_TYPE_RNA_TARGET_BED_FILE] x_mixedTypeRNA_library = reference_step_data.savedFields[ ReferenceFieldNames.MIXED_TYPE_RNA_REFERENCE] x_mixedTypeRNA_regionfile = reference_step_data.savedFields[ ReferenceFieldNames.MIXED_TYPE_RNA_HOT_SPOT_BED_FILE] x_beadfindargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_BEADFIND_SELECTED] x_analysisargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_ANALYSISARGS_SELECTED] x_prebasecallerargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_PREBASECALLER_SELECTED] x_calibrateargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_CALIBRATE_SELECTED] x_basecallerargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_BASECALLER_SELECTED] x_alignmentargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_ALIGNMENT_SELECTED] x_ionstatsargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_IONSTATS_SELECTED] x_thumbnailbeadfindargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_THUMBNAIL_BEADFIND_SELECTED] x_thumbnailanalysisargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_THUMBNAIL_ANALYSISARGS_SELECTED] x_prethumbnailbasecallerargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_THUMBNAIL_PREBASECALLER_SELECTED] x_thumbnailcalibrateargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_THUMBNAIL_CALIBRATE_SELECTED] x_thumbnailbasecallerargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_THUMBNAIL_BASECALLER_SELECTED] x_thumbnailalignmentargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_THUMBNAIL_ALIGNMENT_SELECTED] x_thumbnailionstatsargs = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_THUMBNAIL_IONSTATS_SELECTED] x_custom_args = analysisParams_step_data.savedFields[ AnalysisParamsFieldNames.AP_CUSTOM] == "True" selectedPluginsValue = plugins_step_data.getSelectedPluginsValue() logger.debug( "step_helper_db_saver.__get_universal_params() application_step_data.prepopulatedFields[planStatus]=%s" % (application_step_data.prepopulatedFields[ ApplicationFieldNames.PLAN_STATUS])) logger.debug( "step_helper_db_saver.__get_universal_params() isEditRun=%s; isEdit=%s; isIonChef=%s; isPlan=%s; isPlanBySample=%s" % (str(step_helper.isEditRun()), str(step_helper.isEdit()), str(step_helper.isIonChef()), str( step_helper.isPlan()), str(step_helper.isPlanBySample()))) planStatus = application_step_data.prepopulatedFields[ ApplicationFieldNames.PLAN_STATUS] # preserve the plan status during plan editing # Also, update the planStatus when InstrumentType is changed from OT to IC if step_helper.isCreate() or step_helper.isCopy(): if step_helper.isIonChef(): planStatus = "pending" else: planStatus = "planned" elif step_helper.isEdit() and not step_helper.isEditRun(): isTemplatekitTypeChange = step_helper.getChangedFields().get( 'templatekitType', None) if isTemplatekitTypeChange: if isTemplatekitTypeChange[1] == 'IonChef': planStatus = "pending" else: planStatus = "planned" # logger.debug("step_helper_db_saver.__get_universal_params() planStatus=%s" %(planStatus)) usePostBeadfind = True if step_helper.isProton() or step_helper.isS5(): usePostBeadfind = False retval = { 'applicationGroup': application_group, 'sampleGrouping': sampleGrouping, 'usePreBeadfind': True, 'usePostBeadfind': usePostBeadfind, 'preAnalysis': True, 'runType': runType, 'templatingKitName': templatingKitName, 'controlSequencekitname': controlSequencekitname, 'runMode': 'single', 'isSystem': False, 'isPlanGroup': False, 'username': username, 'isFavorite': toBoolean(isFavorite, False), 'pairedEndLibraryAdapterName': '', 'samplePrepKitName': samplePrepKitName, 'libraryReadLength': libraryReadLength, 'templatingSize': templatingSize, 'samplePrepProtocol': samplePrepProtocol, 'planStatus': planStatus, 'categories': categories, 'isCustom_kitSettings': isCustom_kitSettings, 'x_usePreBeadfind': True, 'x_autoAnalyze': True, 'x_barcodeId': x_barcodeId, 'x_endBarcodeKitName': x_endBarcodeKitName, 'x_bedfile': x_bedfile, 'x_chipType': x_chipType, 'x_flows': x_flows, 'x_forward3primeadapter': x_forward3primeadapter, 'x_flowsInOrder': x_flowsInOrder, 'x_library': x_library, 'x_libraryKey': x_libraryKey, 'tfKey': tfKey, 'x_librarykitname': x_librarykitname, 'x_regionfile': x_regionfile, 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': x_sequencekitname, 'x_sseBedFile': x_sseBedFile, 'x_variantfrequency': '', 'x_isDuplicateReads': False if x_isDuplicateReads is None else x_isDuplicateReads, 'x_base_recalibration_mode': "no_recal" if x_base_recalibration_mode is None else x_base_recalibration_mode, 'x_realign': False if x_realign is None else x_realign, 'x_mixedTypeRNA_bedfile': x_mixedTypeRNA_bedfile, 'x_mixedTypeRNA_regionfile': x_mixedTypeRNA_regionfile, 'x_mixedTypeRNA_library': x_mixedTypeRNA_library, "x_beadfindargs": x_beadfindargs, "x_analysisargs": x_analysisargs, "x_prebasecallerargs": x_prebasecallerargs, "x_calibrateargs": x_calibrateargs, "x_basecallerargs": x_basecallerargs, "x_alignmentargs": x_alignmentargs, "x_ionstatsargs": x_ionstatsargs, "x_thumbnailbeadfindargs": x_thumbnailbeadfindargs, "x_thumbnailanalysisargs": x_thumbnailanalysisargs, "x_prethumbnailbasecallerargs": x_prethumbnailbasecallerargs, "x_thumbnailcalibrateargs": x_thumbnailcalibrateargs, "x_thumbnailbasecallerargs": x_thumbnailbasecallerargs, "x_thumbnailalignmentargs": x_thumbnailalignmentargs, "x_thumbnailionstatsargs": x_thumbnailionstatsargs, "x_custom_args": x_custom_args, } return retval
def save_plan_or_template(request, planOid): """ Saving new or edited plan/template to db (source: plan template wizard) Editing a planned run from having 1 sample to 2 samples will result in one edited planned run and one new planned run """ def isReusable(submitIntent): return not (submitIntent == 'savePlan' or submitIntent == 'updatePlan') if request.method != 'POST': logger.exception(format_exc()) return HttpResponse(json.dumps({ "error": "Error, unsupported HTTP Request method (%s) for plan update." % request.method }), mimetype="application/json") # Process Inputs # pylint:disable=E1103 json_data = simplejson.loads(request.raw_post_data) submitIntent = json_data.get('submitIntent', '') logger.debug( 'views.save_plan_or_template POST.raw_post_data... simplejson Data: "%s"' % json_data) logger.debug("views.save_plan_or_template submitIntent=%s" % submitIntent) # saving Template or Planned Run isReusable = isReusable(submitIntent) runModeValue = json_data.get('runMode', 'single') isPlanGroupValue = runModeValue == 'pe' and not isReusable libraryKeyValue = json_data.get('libraryKey', '') forward3primeAdapterValue = json_data.get('forward3primeAdapter', '') msgvalue = 'Run Plan' if not isReusable else 'Template' if runModeValue == 'pe': return HttpResponse(json.dumps({ "error": "Error, paired-end plan is no longer supported. %s will not be saved." % (msgvalue) }), mimetype="application/html") planDisplayedNameValue = json_data.get('planDisplayedName', '').strip() noteValue = json_data.get('notes_workaround', '') # perform server-side validation to avoid things falling through the crack if not planDisplayedNameValue: return HttpResponse(json.dumps( {"error": "Error, please enter a %s Name." % (msgvalue)}), mimetype="application/html") if not is_valid_chars(planDisplayedNameValue): return HttpResponse(json.dumps( {"error": "Error, %s Name" % (msgvalue) + ERROR_MSG_INVALID_CHARS}), mimetype="application/html") if not is_valid_length(planDisplayedNameValue, MAX_LENGTH_PLAN_NAME): return HttpResponse(json.dumps({ "error": "Error, %s Name" % (msgvalue) + ERROR_MSG_INVALID_LENGTH % (str(MAX_LENGTH_PLAN_NAME)) }), mimetype="application/html") if noteValue: if not is_valid_chars(noteValue): return HttpResponse(json.dumps({ "error": "Error, %s note" % (msgvalue) + ERROR_MSG_INVALID_CHARS }), mimetype="application/html") if not is_valid_length(noteValue, MAX_LENGTH_NOTES): return HttpResponse(json.dumps({ "error": "Error, Note" + ERROR_MSG_INVALID_LENGTH % (str(MAX_LENGTH_NOTES)) }), mimetype="application/html") # Projects projectObjList = get_projects(request.user, json_data) # IonReporterUploader configuration and samples selectedPlugins = json_data.get('selectedPlugins', {}) IRconfigList = json_data.get('irConfigList', []) IRU_selected = False for uploader in selectedPlugins.values(): if 'ionreporteruploader' in uploader['name'].lower( ) and uploader['name'] != 'IonReporterUploader_V1_0': IRU_selected = True #if IRU is set to autoRun, user does not need to select the plugin explicitly. user could have set all IRU versions to autorun IRU_autorun_count = 0 if not IRU_selected: IRU_autoruns = Plugin.objects.filter( name__icontains="IonReporter", selected=True, active=True, autorun=True).exclude( name__icontains="IonReporterUploader_V1_0").order_by('-name') IRU_autorun_count = IRU_autoruns.count() if IRU_autorun_count > 0: IRU_selected = True if IRU_selected: samples_IRconfig = json_data.get('sample_irConfig', '') if samples_IRconfig: samples_IRconfig = ','.join(samples_IRconfig) #generate UUID for unique setIds id_uuid = {} setids = [ir.get('setid', "") for ir in IRconfigList] if setids: for setid in set(setids): if setid: id_uuid[setid] = str(uuid.uuid4()) for ir_config in IRconfigList: setid = ir_config.get('setid', '') if setid: ir_config['setid'] += '__' + id_uuid[setid] if IRU_autorun_count > 0 and not samples_IRconfig: #if more than one IRU version is set to autorun and user does not explicitly select one, #gui shows workflow config for IRU v1.0 samples_IRconfig = json_data.get('samples_workaround', '') # Samples barcodeIdValue = json_data.get('barcodeId', '') barcodedSamples = '' sampleValidationErrorMsg = '' sampleValidationErrorMsg_leadingChars = '' sampleValidationErrorMsg_length = '' # one Plan will be created per entry in sampleList # samples for barcoded Plan have a separate field (barcodedSamples) if isReusable: # samples entered only when saving planned run (not template) sampleList = [''] elif barcodeIdValue: # a barcode Set is selected sampleList = [''] bcSamplesValues = json_data.get('bcSamples_workaround', '') bcDictionary = {} bcId = "" for token in bcSamplesValues.split(","): if ((token.find("bcKey|")) == 0): bcId, bcId_str = token.split("|")[1:] else: sample = token.strip() if bcId and sample: if not is_valid_chars(sample): sampleValidationErrorMsg += sample + ', ' elif is_invalid_leading_chars(sample): sampleValidationErrorMsg_leadingChars += sample + ", " elif not is_valid_length(sample, MAX_LENGTH_SAMPLE_NAME): sampleValidationErrorMsg_length += sample + ", " bcDictionary.setdefault(sample, {}).setdefault('barcodes', []).append(bcId_str) bcId = "" barcodedSamples = simplejson.dumps(bcDictionary) logger.debug( "views.save_plan_or_template after simplejson.dumps... barcodedSamples=%s;" % (barcodedSamples)) if not bcDictionary: transaction.rollback() return HttpResponse(json.dumps({ "error": "Error, please enter at least one barcode sample name." }), mimetype="application/html") else: # Non-barcoded samples sampleList = [] if IRU_selected: samples = samples_IRconfig else: samples = json_data.get('samples_workaround', '') for sample in samples.split(','): if sample.strip(): if not is_valid_chars(sample): sampleValidationErrorMsg += sample + ', ' elif is_invalid_leading_chars(sample): sampleValidationErrorMsg_leadingChars += sample + ", " elif not is_valid_length(sample, MAX_LENGTH_SAMPLE_NAME): sampleValidationErrorMsg_length += sample + ", " else: sampleList.append(sample) logger.debug("views.save_plan_or_template sampleList=%s " % (sampleList)) if len( sampleList ) == 0 and not sampleValidationErrorMsg and not sampleValidationErrorMsg_leadingChars and not sampleValidationErrorMsg_length: transaction.rollback() return HttpResponse(json.dumps({ "error": "Error, please enter a sample name for the run plan." }), mimetype="application/html") # Samples validation if sampleValidationErrorMsg or sampleValidationErrorMsg_leadingChars or sampleValidationErrorMsg_length: message = "" if sampleValidationErrorMsg: message = "Error, sample name" + ERROR_MSG_INVALID_CHARS message = message + ' <br>Please fix: ' + sampleValidationErrorMsg + '<br>' if sampleValidationErrorMsg_leadingChars: message = message + "Error, sample name" + ERROR_MSG_INVALID_LEADING_CHARS message = message + ' <br>Please fix: ' + sampleValidationErrorMsg_leadingChars + '<br>' if sampleValidationErrorMsg_length: message = message + "Error, sample name" + ERROR_MSG_INVALID_LENGTH % ( str(MAX_LENGTH_SAMPLE_NAME)) message = message + ' <br>Please fix: ' + sampleValidationErrorMsg_length transaction.rollback() return HttpResponse(json.dumps({"error": message}), mimetype="application/html") selectedPluginsValue = json_data.get('selectedPlugins', {}) # end processing input data # Edit/Create Plan(s) if int(planOid) == 0: edit_existing_plan = False else: edit_existing_plan = True for i, sample in enumerate(sampleList): logger.debug( "...LOOP... views.save_plan_or_template SAMPLE=%s; isSystem=%s; isReusable=%s; isPlanGroup=%s " % (sample.strip(), json_data["isSystem"], isReusable, isPlanGroupValue)) # add IonReporter config values for each sample if len(IRconfigList) > 0: for uploader in selectedPluginsValue.values(): if 'ionreporteruploader' in uploader['name'].lower(): if len(IRconfigList) > 1 and not barcodeIdValue: uploader['userInput'] = [IRconfigList[i]] else: uploader['userInput'] = IRconfigList if len(sampleList) > 1: inputPlanDisplayedName = planDisplayedNameValue + '_' + sample.strip( ) else: inputPlanDisplayedName = planDisplayedNameValue selectedTemplatingKit = json_data.get('templatekitname', '') samplePrepInstrumentType = json_data.get('samplePrepInstrumentType', '') if samplePrepInstrumentType == 'ionChef': selectedTemplatingKit = json_data.get('templatekitionchefname', '') #PDD-TODO: remove the x_ prefix. the x_ prefix is just a reminder what the obsolete attributes to remove during the next phase kwargs = { 'planDisplayedName': inputPlanDisplayedName, "planName": inputPlanDisplayedName.replace(' ', '_'), 'usePreBeadfind': toBoolean(json_data['usePreBeadfind'], False), 'usePostBeadfind': toBoolean(json_data['usePostBeadfind'], False), 'preAnalysis': True, 'runType': json_data['runType'], 'templatingKitName': selectedTemplatingKit, 'controlSequencekitname': json_data.get('controlsequence', ''), 'runMode': runModeValue, 'isSystem': toBoolean(json_data['isSystem'], False), 'isReusable': isReusable, 'isPlanGroup': isPlanGroupValue, 'username': request.user.username, 'isFavorite': toBoolean(json_data.get('isFavorite', 'False'), False), 'pairedEndLibraryAdapterName': json_data.get('pairedEndLibraryAdapterName', ''), 'samplePrepKitName': json_data.get('samplePrepKitName', ''), 'planStatus': "planned", 'x_autoAnalyze': True, 'x_barcodedSamples': barcodedSamples, 'x_barcodeId': barcodeIdValue, 'x_bedfile': json_data.get('bedfile', ''), 'x_chipType': json_data.get('chipType', ''), 'x_flows': json_data.get('flows', None), 'x_forward3primeadapter': forward3primeAdapterValue, ###'_isReverseRun': = self.isReverseRun 'x_library': json_data.get('library', ''), 'x_libraryKey': libraryKeyValue, 'x_librarykitname': json_data.get('librarykitname', ''), 'x_notes': noteValue, 'x_regionfile': json_data.get('regionfile', ''), 'x_sample': sample.strip().replace(' ', '_'), 'x_sampleDisplayedName': sample.strip(), 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': json_data.get('sequencekitname', ''), 'x_variantfrequency': json_data.get('variantfrequency', ''), } planTemplate = None #if we're changing a plan from having 1 sample to say 2 samples, we need to UPDATE 1 plan and CREATE 1 plan!! try: if not edit_existing_plan: planTemplate, extra_kwargs = PlannedExperiment.objects.save_plan( -1, **kwargs) else: planTemplate, extra_kwargs = PlannedExperiment.objects.save_plan( planOid, **kwargs) edit_existing_plan = False # Update QCtype thresholds qcTypes = QCType.objects.all() for qcType in qcTypes: qc_threshold = json_data.get(qcType.qcName, '') if qc_threshold: # get existing PlannedExperimentQC if any plannedExpQcs = PlannedExperimentQC.objects.filter( plannedExperiment=planTemplate.id, qcType=qcType.id) if len(plannedExpQcs) > 0: for plannedExpQc in plannedExpQcs: plannedExpQc.threshold = qc_threshold plannedExpQc.save() else: kwargs = { 'plannedExperiment': planTemplate, 'qcType': qcType, 'threshold': qc_threshold } plannedExpQc = PlannedExperimentQC(**kwargs) plannedExpQc.save() # add/remove projects if projectObjList: #TODO: refactor this logic to simplify using django orm projectNameList = [project.name for project in projectObjList] for currentProject in planTemplate.projects.all(): if currentProject.name not in projectNameList: planTemplate.projects.remove(currentProject) for projectObj in projectObjList: planTemplate.projects.add(projectObj) else: planTemplate.projects.clear() except ValidationError, err: transaction.rollback() logger.exception(format_exc()) message = "Internal error while trying to save the plan. " for msg in err.messages: message += str(msg) message += " " return HttpResponse(json.dumps({"error": message}), mimetype="application/json") except Exception as excp: transaction.rollback() logger.exception(format_exc()) message = "Internal error while trying to save the plan. %s" % ( excp.message) return HttpResponse(json.dumps({"error": message}), mimetype="application/json")
def __get_universal_params(self, step_helper, username): if not step_helper.isPlan(): if step_helper.isTemplateBySample(): save_template_step_data = step_helper.steps[StepNames.SAVE_TEMPLATE_BY_SAMPLE] else: save_template_step_data = step_helper.steps[StepNames.SAVE_TEMPLATE] application_step_data = step_helper.steps[StepNames.APPLICATION] kits_step_data = step_helper.steps[StepNames.KITS] reference_step_data = step_helper.steps[StepNames.REFERENCE] plugins_step_data = step_helper.steps[StepNames.PLUGINS] ionreporter_step_data = step_helper.steps[StepNames.IONREPORTER] isFavorite = False categories = application_step_data.prepopulatedFields.get(ApplicationFieldNames.CATEGORIES, "") runType = "" if application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE]: runType = application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE].runType #if user has changed the application or target technique during template copying, reset categories value applicationGroup = application_step_data.savedFields[ApplicationFieldNames.APPLICATION_GROUP] applicationGroupNames = ApplicationGroup.objects.filter(pk = applicationGroup) if (applicationGroupNames): applicationGroupName = applicationGroupNames[0].name else: applicationGroupName = application_step_data.prepopulatedFields.get(ApplicationFieldNames.APPLICATION_GROUP_NAME, "") #if user has changed the application or target technique during template copying, reset categories value if applicationGroupName != "DNA + RNA": #workaround: OCP DNA has DNA as applicationGroupName and AMPS as run type so it can be ambiguous. #If user creates/copies/edits a template or plan from an OCP template, preserve the categories that starts out with. if categories and applicationGroupName != "DNA" and runType != "AMPS": categories = categories.replace("Onconet", ""); categories = categories.replace("Oncomine", ""); if not step_helper.isPlan(): isFavorite = save_template_step_data.savedFields[SaveTemplateStepDataFieldNames.SET_AS_FAVORITE] logger.debug(" step_helper_db_saver.__get_universal_params() applicationGroupName=%s; categories=%s" %(applicationGroupName, categories)) #logger.debug("step_helper_db_saver.__get_universal_params() application_step_data.savedFields=%s" %(application_step_data.savedFields)) application_group = None sampleGrouping = None if application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE]: application_group = application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE].applicationGroups.all()[0:1][0] if application_step_data.savedFields[ApplicationFieldNames.APPLICATION_GROUP]: application_group = ApplicationGroup.objects.get(pk=application_step_data.savedFields[ApplicationFieldNames.APPLICATION_GROUP]) if ionreporter_step_data.savedFields[IonReporterFieldNames.SAMPLE_GROUPING]: sampleGrouping = ionreporter_step_data.savedObjects[IonReporterFieldNames.SAMPLE_GROUPING] templatingKitName = kits_step_data.savedFields[KitsFieldNames.TEMPLATE_KIT_NAME] controlSequencekitname = kits_step_data.savedFields[KitsFieldNames.CONTROL_SEQUENCE] samplePrepKitName = kits_step_data.savedFields[KitsFieldNames.SAMPLE_PREPARATION_KIT] libraryReadLength = kits_step_data.savedFields[KitsFieldNames.LIBRARY_READ_LENGTH] templatingSize = kits_step_data.savedFields[KitsFieldNames.TEMPLATING_SIZE] x_barcodeId = kits_step_data.savedFields[KitsFieldNames.BARCODE_ID] x_chipType = kits_step_data.savedFields[KitsFieldNames.CHIP_TYPE] if not x_chipType: x_chipType = '' x_flows = kits_step_data.savedFields[KitsFieldNames.FLOWS] x_forward3primeadapter = kits_step_data.savedFields[KitsFieldNames.FORWARD_3_PRIME_ADAPTER] x_libraryKey = kits_step_data.savedFields[KitsFieldNames.LIBRARY_KEY] tfKey = kits_step_data.savedFields[KitsFieldNames.TF_KEY] x_librarykitname = kits_step_data.savedFields[KitsFieldNames.LIBRARY_KIT_NAME] x_sequencekitname = kits_step_data.savedFields[KitsFieldNames.SEQUENCE_KIT_NAME] x_isDuplicateReads = kits_step_data.savedFields[KitsFieldNames.IS_DUPLICATED_READS] x_base_recalibration_mode = kits_step_data.savedFields[KitsFieldNames.BASE_RECALIBRATE] x_realign = kits_step_data.savedFields[KitsFieldNames.REALIGN] x_bedfile = reference_step_data.savedFields[ReferenceFieldNames.TARGET_BED_FILE] x_library = reference_step_data.savedFields[ReferenceFieldNames.REFERENCE] x_regionfile = reference_step_data.savedFields[ReferenceFieldNames.HOT_SPOT_BED_FILE] x_mixedTypeRNA_bedfile = reference_step_data.savedFields[ReferenceFieldNames.MIXED_TYPE_RNA_TARGET_BED_FILE] x_mixedTypeRNA_library = reference_step_data.savedFields[ReferenceFieldNames.MIXED_TYPE_RNA_REFERENCE] x_mixedTypeRNA_regionfile = reference_step_data.savedFields[ReferenceFieldNames.MIXED_TYPE_RNA_HOT_SPOT_BED_FILE] selectedPluginsValue = plugins_step_data.getSelectedPluginsValue() logger.debug("step_helper_db_saver.__get_universal_params() application_step_data.prepopulatedFields[planStatus]=%s" %(application_step_data.prepopulatedFields[ApplicationFieldNames.PLAN_STATUS])) logger.debug("step_helper_db_saver.__get_universal_params() isEditRun=%s; isEdit=%s; isIonChef=%s; isPlan=%s; isPlanBySample=%s" %(str(step_helper.isEditRun()), str(step_helper.isEdit()), str(step_helper.isIonChef()), str(step_helper.isPlan()), str(step_helper.isPlanBySample()))) planStatus = application_step_data.prepopulatedFields[ApplicationFieldNames.PLAN_STATUS] #preserve the plan status during plan editing if not step_helper.isEditRun() and not step_helper.isEdit(): if step_helper.isIonChef(): if step_helper.isPlan() or step_helper.isPlanBySample(): if step_helper.isCreate(): planStatus = "pending" elif (step_helper.sh_type == StepHelperType.COPY_PLAN or step_helper.sh_type == StepHelperType.COPY_PLAN_BY_SAMPLE): planStatus = "pending" else: planStatus = "pending" else: #when copying a sequenced plan, reseting the plan status is necessary planStatus = "planned" #logger.debug("step_helper_db_saver.__get_universal_params() planStatus=%s" %(planStatus)) retval = { 'applicationGroup': application_group, 'sampleGrouping' : sampleGrouping, 'usePreBeadfind': True, 'usePostBeadfind': False if step_helper.isProton() else True, 'preAnalysis': True, 'runType': runType, 'templatingKitName': templatingKitName, 'controlSequencekitname': controlSequencekitname, 'runMode': 'single', 'isSystem': False, 'isPlanGroup': False, 'username': username, 'isFavorite': toBoolean(isFavorite, False), 'pairedEndLibraryAdapterName': '', 'samplePrepKitName': samplePrepKitName, 'libraryReadLength' : libraryReadLength, 'templatingSize' : templatingSize, 'planStatus' : planStatus, 'categories' : categories, 'x_usePreBeadfind': True, 'x_autoAnalyze': True, 'x_barcodeId': x_barcodeId, 'x_bedfile': x_bedfile, 'x_chipType': x_chipType, 'x_flows': x_flows, 'x_forward3primeadapter': x_forward3primeadapter, 'x_library': x_library, 'x_libraryKey': x_libraryKey, 'tfKey': tfKey, 'x_librarykitname': x_librarykitname, 'x_regionfile': x_regionfile, 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': x_sequencekitname, 'x_variantfrequency': '', 'x_isDuplicateReads': False if x_isDuplicateReads is None else x_isDuplicateReads, 'x_base_recalibration_mode': "no_recal" if x_base_recalibration_mode is None else x_base_recalibration_mode, 'x_realign': False if x_realign is None else x_realign, 'x_mixedTypeRNA_bedfile': x_mixedTypeRNA_bedfile, 'x_mixedTypeRNA_regionfile': x_mixedTypeRNA_regionfile, 'x_mixedTypeRNA_library': x_mixedTypeRNA_library, } return retval
def __get_universal_params(self, step_helper, username): if not step_helper.isPlan(): if step_helper.isTemplateBySample(): save_template_step_data = step_helper.steps[StepNames.SAVE_TEMPLATE_BY_SAMPLE] else: save_template_step_data = step_helper.steps[StepNames.SAVE_TEMPLATE] application_step_data = step_helper.steps[StepNames.APPLICATION] kits_step_data = step_helper.steps[StepNames.KITS] reference_step_data = step_helper.steps[StepNames.REFERENCE] plugins_step_data = step_helper.steps[StepNames.PLUGINS] ionreporter_step_data = step_helper.steps[StepNames.IONREPORTER] if not step_helper.isPlan(): isFavorite = save_template_step_data.savedFields['setAsFavorite'] else: isFavorite = False runType = '' application_group = None sampleGrouping = None if application_step_data.savedObjects['runType']: runType = application_step_data.savedObjects['runType'].runType application_group = application_step_data.savedObjects['runType'].applicationGroups.all()[0:1][0] if application_step_data.savedFields['applicationGroup']: application_group = ApplicationGroup.objects.get(pk=application_step_data.savedFields['applicationGroup']) if ionreporter_step_data.savedFields['sampleGrouping']: sampleGrouping = ionreporter_step_data.savedObjects['sampleGrouping'] templatingKitName = kits_step_data.savedFields['templatekitname'] controlSequencekitname = kits_step_data.savedFields['controlsequence'] samplePrepKitName = kits_step_data.savedFields['samplePreparationKit'] x_barcodeId = kits_step_data.savedFields['barcodeId'] x_chipType = kits_step_data.savedFields['chipType'] if not x_chipType: x_chipType = '' x_flows = kits_step_data.savedFields['flows'] x_forward3primeadapter = kits_step_data.savedFields['forward3primeAdapter'] x_libraryKey = kits_step_data.savedFields['libraryKey'] x_librarykitname = kits_step_data.savedFields['librarykitname'] x_sequencekitname = kits_step_data.savedFields['sequencekitname'] x_isDuplicateReads = kits_step_data.savedFields['isDuplicateReads'] x_bedfile = reference_step_data.savedFields['targetBedFile'] x_library = reference_step_data.savedFields["reference"] x_regionfile = reference_step_data.savedFields['hotSpotBedFile'] selectedPluginsValue = plugins_step_data.getSelectedPluginsValue() planStatus = "planned" if not step_helper.isEditRun(): if step_helper.isIonChef(): if step_helper.isPlan() or step_helper.isPlanBySample(): planStatus = "pending" else: planStatus = "run" retval = { 'applicationGroup': application_group, 'sampleGrouping' : sampleGrouping, 'usePreBeadfind': True, 'usePostBeadfind': True, 'preAnalysis': True, 'runType': runType, 'templatingKitName': templatingKitName, 'controlSequencekitname': controlSequencekitname, 'runMode': 'single', 'isSystem': False, 'isPlanGroup': False, 'username': username, 'isFavorite': toBoolean(isFavorite, False), 'pairedEndLibraryAdapterName': '', 'samplePrepKitName': samplePrepKitName, 'planStatus' : planStatus, 'x_autoAnalyze': True, 'x_barcodeId': x_barcodeId, 'x_bedfile': x_bedfile, 'x_chipType': x_chipType, 'x_flows': x_flows, 'x_forward3primeadapter': x_forward3primeadapter, 'x_library': x_library, 'x_libraryKey': x_libraryKey, 'x_librarykitname': x_librarykitname, 'x_regionfile': x_regionfile, 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': x_sequencekitname, 'x_variantfrequency': '', 'x_isDuplicateReads': False if x_isDuplicateReads is None else x_isDuplicateReads } return retval
def __get_universal_params(self, step_helper, username): if not step_helper.isPlan(): if step_helper.isTemplateBySample(): save_template_step_data = step_helper.steps[StepNames.SAVE_TEMPLATE_BY_SAMPLE] else: save_template_step_data = step_helper.steps[StepNames.SAVE_TEMPLATE] application_step_data = step_helper.steps[StepNames.APPLICATION] kits_step_data = step_helper.steps[StepNames.KITS] reference_step_data = step_helper.steps[StepNames.REFERENCE] plugins_step_data = step_helper.steps[StepNames.PLUGINS] ionreporter_step_data = step_helper.steps[StepNames.IONREPORTER] analysisParams_step_data = step_helper.steps[StepNames.ANALYSIS_PARAMS] save_plan_step_data = step_helper.steps.get(StepNames.SAVE_PLAN, "") isFavorite = False categories = application_step_data.prepopulatedFields.get(ApplicationFieldNames.CATEGORIES, "") runType = "" if application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE]: runType = application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE].runType if not step_helper.isPlan(): isFavorite = save_template_step_data.savedFields[SaveTemplateStepDataFieldNames.SET_AS_FAVORITE] application_group = None sampleGrouping = None if application_step_data.savedFields[ApplicationFieldNames.APPLICATION_GROUP_NAME]: application_group = ApplicationGroup.objects.get(name=application_step_data.savedFields[ApplicationFieldNames.APPLICATION_GROUP_NAME]) elif application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE]: application_group = application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE].applicationGroups.all()[0:1][0] # if user has changed the application or target technique during template copying, reset categories value if application_group and application_group.name != "DNA + RNA": # workaround: OCP DNA has DNA as applicationGroupName and AMPS as run type so it can be ambiguous. # If user creates/copies/edits a template or plan from an OCP template, preserve the categories that starts out with. if categories and application_group.name != "DNA" and runType != "AMPS": categories = categories.replace("Onconet", ""); categories = categories.replace("Oncomine", ""); # if user has changed the application or target technique during template copying/editing, reset categories value if outdated customer-facing category value is found if runType: if categories: tokens = categories.split(';') for token in tokens: categories_cv = common_CV.objects.filter(cv_type = "applicationCategory", isVisible = True, value__iexact = token) if (categories_cv.count() > 0): category_cv = categories_cv[0] if category_cv.categories and runType not in category_cv.categories: categories = "" else: categories = "" if ionreporter_step_data.savedFields[IonReporterFieldNames.SAMPLE_GROUPING]: sampleGrouping = ionreporter_step_data.savedObjects[IonReporterFieldNames.SAMPLE_GROUPING] templatingKitName = kits_step_data.savedFields[KitsFieldNames.TEMPLATE_KIT_NAME] controlSequencekitname = kits_step_data.savedFields[KitsFieldNames.CONTROL_SEQUENCE] samplePrepKitName = kits_step_data.savedFields[KitsFieldNames.SAMPLE_PREPARATION_KIT] if kits_step_data.savedFields[KitsFieldNames.READ_LENGTH] > 0: libraryReadLength = kits_step_data.savedFields[KitsFieldNames.READ_LENGTH] else: libraryReadLength = kits_step_data.savedFields[KitsFieldNames.LIBRARY_READ_LENGTH] samplePrepProtocol = kits_step_data.savedFields[KitsFieldNames.SAMPLE_PREP_PROTOCOL] isCustom_kitSettings = kits_step_data.savedFields[KitsFieldNames.ADVANCED_SETTINGS_CHOICE] == "custom" x_barcodeId = kits_step_data.savedFields[KitsFieldNames.BARCODE_ID] if save_plan_step_data and x_barcodeId: x_endBarcodeKitName = save_plan_step_data.savedFields[SavePlanFieldNames.END_BARCODE_SET] else: x_endBarcodeKitName = "" x_chipType = kits_step_data.savedFields[KitsFieldNames.CHIP_TYPE] if not x_chipType: x_chipType = '' x_flows = kits_step_data.savedFields[KitsFieldNames.FLOWS] x_forward3primeadapter = kits_step_data.savedFields[KitsFieldNames.FORWARD_3_PRIME_ADAPTER] x_flowsInOrder = kits_step_data.savedFields[KitsFieldNames.FLOW_ORDER] x_libraryKey = kits_step_data.savedFields[KitsFieldNames.LIBRARY_KEY] tfKey = kits_step_data.savedFields[KitsFieldNames.TF_KEY] x_librarykitname = kits_step_data.savedFields[KitsFieldNames.LIBRARY_KIT_NAME] x_sequencekitname = kits_step_data.savedFields[KitsFieldNames.SEQUENCE_KIT_NAME] x_isDuplicateReads = kits_step_data.savedFields[KitsFieldNames.IS_DUPLICATED_READS] x_base_recalibration_mode = kits_step_data.savedFields[KitsFieldNames.BASE_RECALIBRATE] x_realign = kits_step_data.savedFields[KitsFieldNames.REALIGN] x_bedfile = reference_step_data.savedFields[ReferenceFieldNames.TARGET_BED_FILE] x_library = reference_step_data.savedFields[ReferenceFieldNames.REFERENCE] x_regionfile = reference_step_data.savedFields[ReferenceFieldNames.HOT_SPOT_BED_FILE] x_sseBedFile = reference_step_data.get_sseBedFile(x_bedfile) x_mixedTypeRNA_bedfile = reference_step_data.savedFields[ReferenceFieldNames.MIXED_TYPE_RNA_TARGET_BED_FILE] x_mixedTypeRNA_library = reference_step_data.savedFields[ReferenceFieldNames.MIXED_TYPE_RNA_REFERENCE] x_mixedTypeRNA_regionfile = reference_step_data.savedFields[ReferenceFieldNames.MIXED_TYPE_RNA_HOT_SPOT_BED_FILE] x_beadfindargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_BEADFIND_SELECTED] x_analysisargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_ANALYSISARGS_SELECTED] x_prebasecallerargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_PREBASECALLER_SELECTED] x_calibrateargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_CALIBRATE_SELECTED] x_basecallerargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_BASECALLER_SELECTED] x_alignmentargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_ALIGNMENT_SELECTED] x_ionstatsargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_IONSTATS_SELECTED] x_thumbnailbeadfindargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_THUMBNAIL_BEADFIND_SELECTED] x_thumbnailanalysisargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_THUMBNAIL_ANALYSISARGS_SELECTED] x_prethumbnailbasecallerargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_THUMBNAIL_PREBASECALLER_SELECTED] x_thumbnailcalibrateargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_THUMBNAIL_CALIBRATE_SELECTED] x_thumbnailbasecallerargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_THUMBNAIL_BASECALLER_SELECTED] x_thumbnailalignmentargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_THUMBNAIL_ALIGNMENT_SELECTED] x_thumbnailionstatsargs = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_THUMBNAIL_IONSTATS_SELECTED] x_custom_args = analysisParams_step_data.savedFields[AnalysisParamsFieldNames.AP_CUSTOM] == "True" selectedPluginsValue = plugins_step_data.getSelectedPluginsValue() logger.debug("step_helper_db_saver.__get_universal_params() application_step_data.prepopulatedFields[planStatus]=%s" % (application_step_data.prepopulatedFields[ApplicationFieldNames.PLAN_STATUS])) logger.debug("step_helper_db_saver.__get_universal_params() isEditRun=%s; isEdit=%s; isIonChef=%s; isPlan=%s; isPlanBySample=%s" % (str(step_helper.isEditRun()), str(step_helper.isEdit()), str(step_helper.isIonChef()), str(step_helper.isPlan()), str(step_helper.isPlanBySample()))) planStatus = application_step_data.prepopulatedFields[ApplicationFieldNames.PLAN_STATUS] # preserve the plan status during plan editing # Also, update the planStatus when InstrumentType is changed from OT to IC if step_helper.isCreate() or step_helper.isCopy(): if step_helper.isIonChef(): planStatus = "pending" else: planStatus = "planned" elif step_helper.isEdit() and not step_helper.isEditRun(): isTemplatekitTypeChange = step_helper.getChangedFields().get('templatekitType', None) if isTemplatekitTypeChange: if isTemplatekitTypeChange[1] == 'IonChef': planStatus = "pending" else: planStatus = "planned" # logger.debug("step_helper_db_saver.__get_universal_params() planStatus=%s" %(planStatus)) usePostBeadfind = True if step_helper.isProton() or step_helper.isS5(): usePostBeadfind = False retval = { 'applicationGroup': application_group, 'sampleGrouping': sampleGrouping, 'usePreBeadfind': True, 'usePostBeadfind': usePostBeadfind, 'preAnalysis': True, 'runType': runType, 'templatingKitName': templatingKitName, 'controlSequencekitname': controlSequencekitname, 'runMode': 'single', 'isSystem': False, 'isPlanGroup': False, 'username': username, 'isFavorite': toBoolean(isFavorite, False), 'pairedEndLibraryAdapterName': '', 'samplePrepKitName': samplePrepKitName, 'libraryReadLength': libraryReadLength, 'samplePrepProtocol': samplePrepProtocol, 'planStatus': planStatus, 'categories': categories, 'isCustom_kitSettings': isCustom_kitSettings, 'x_usePreBeadfind': True, 'x_autoAnalyze': True, 'x_barcodeId': x_barcodeId, 'x_endBarcodeKitName': x_endBarcodeKitName, 'x_bedfile': x_bedfile, 'x_chipType': x_chipType, 'x_flows': x_flows, 'x_forward3primeadapter': x_forward3primeadapter, 'x_flowsInOrder': x_flowsInOrder, 'x_library': x_library, 'x_libraryKey': x_libraryKey, 'tfKey': tfKey, 'x_librarykitname': x_librarykitname, 'x_regionfile': x_regionfile, 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': x_sequencekitname, 'x_sseBedFile': x_sseBedFile, 'x_variantfrequency': '', 'x_isDuplicateReads': False if x_isDuplicateReads is None else x_isDuplicateReads, 'x_base_recalibration_mode': "no_recal" if x_base_recalibration_mode is None else x_base_recalibration_mode, 'x_realign': False if x_realign is None else x_realign, 'x_mixedTypeRNA_bedfile': x_mixedTypeRNA_bedfile, 'x_mixedTypeRNA_regionfile': x_mixedTypeRNA_regionfile, 'x_mixedTypeRNA_library': x_mixedTypeRNA_library, "x_beadfindargs": x_beadfindargs, "x_analysisargs": x_analysisargs, "x_prebasecallerargs": x_prebasecallerargs, "x_calibrateargs": x_calibrateargs, "x_basecallerargs": x_basecallerargs, "x_alignmentargs": x_alignmentargs, "x_ionstatsargs": x_ionstatsargs, "x_thumbnailbeadfindargs": x_thumbnailbeadfindargs, "x_thumbnailanalysisargs": x_thumbnailanalysisargs, "x_prethumbnailbasecallerargs": x_prethumbnailbasecallerargs, "x_thumbnailcalibrateargs": x_thumbnailcalibrateargs, "x_thumbnailbasecallerargs": x_thumbnailbasecallerargs, "x_thumbnailalignmentargs": x_thumbnailalignmentargs, "x_thumbnailionstatsargs": x_thumbnailionstatsargs, "x_custom_args": x_custom_args, } return retval
def __get_universal_params(self, step_helper, username): if not step_helper.isPlan(): if step_helper.isTemplateBySample(): save_template_step_data = step_helper.steps[ StepNames.SAVE_TEMPLATE_BY_SAMPLE] else: save_template_step_data = step_helper.steps[ StepNames.SAVE_TEMPLATE] application_step_data = step_helper.steps[StepNames.APPLICATION] kits_step_data = step_helper.steps[StepNames.KITS] reference_step_data = step_helper.steps[StepNames.REFERENCE] plugins_step_data = step_helper.steps[StepNames.PLUGINS] ionreporter_step_data = step_helper.steps[StepNames.IONREPORTER] isFavorite = False ##categories = application_step_data.savedFields.get(ApplicationFieldNames.CATEGORIES, "") categories = application_step_data.savedFields.get('categories', "") #if user has changed the application or target technique during template copying, reset categories value ##applicationGroupName = application_step_data.savedFields.get(ApplicationFieldNames.APPLICATION_GROUP_NAME, "") applicationGroupName = application_step_data.savedFields.get( "applicationGroupName", "") if applicationGroupName != "DNA + RNA": if categories: categories.replace("Onconet", "") categories.replace("Oncomine", "") if not step_helper.isPlan(): ##isFavorite = save_template_step_data.savedFields[SaveTemplateStepDataFieldNames.SET_AS_FAVORITE] isFavorite = save_template_step_data.savedFields['setAsFavorite'] logger.debug( "step_helper_db_saver.__get_universal_params() applicationGroupName=%s; categories=%s" % (applicationGroupName, categories)) #logger.debug("step_helper_db_saver.__get_universal_params() application_step_data.savedFields=%s" %(application_step_data.savedFields)) runType = '' application_group = None sampleGrouping = None if application_step_data.savedObjects['runType']: runType = application_step_data.savedObjects['runType'].runType application_group = application_step_data.savedObjects[ 'runType'].applicationGroups.all()[0:1][0] if application_step_data.savedFields['applicationGroup']: application_group = ApplicationGroup.objects.get( pk=application_step_data.savedFields['applicationGroup']) if ionreporter_step_data.savedFields['sampleGrouping']: sampleGrouping = ionreporter_step_data.savedObjects[ 'sampleGrouping'] templatingKitName = kits_step_data.savedFields['templatekitname'] controlSequencekitname = kits_step_data.savedFields['controlsequence'] samplePrepKitName = kits_step_data.savedFields['samplePreparationKit'] x_barcodeId = kits_step_data.savedFields['barcodeId'] x_chipType = kits_step_data.savedFields['chipType'] if not x_chipType: x_chipType = '' x_flows = kits_step_data.savedFields['flows'] x_forward3primeadapter = kits_step_data.savedFields[ 'forward3primeAdapter'] x_libraryKey = kits_step_data.savedFields['libraryKey'] tfKey = kits_step_data.savedFields['tfKey'] x_librarykitname = kits_step_data.savedFields['librarykitname'] x_sequencekitname = kits_step_data.savedFields['sequencekitname'] x_isDuplicateReads = kits_step_data.savedFields['isDuplicateReads'] x_base_recalibrate = kits_step_data.savedFields['base_recalibrate'] x_realign = kits_step_data.savedFields['realign'] x_bedfile = reference_step_data.savedFields['targetBedFile'] x_library = reference_step_data.savedFields["reference"] x_regionfile = reference_step_data.savedFields['hotSpotBedFile'] selectedPluginsValue = plugins_step_data.getSelectedPluginsValue() logger.debug( "step_helper_db_saver.__get_universal_params() application_step_data.savedFields[planStatus]=%s" % (application_step_data.savedFields["planStatus"])) logger.debug( "step_helper_db_saver.__get_universal_params() isEditRun=%s; isEdit=%s; isIonChef=%s; isPlan=%s; isPlanBySample=%s" % (str(step_helper.isEditRun()), str(step_helper.isEdit()), str(step_helper.isIonChef()), str( step_helper.isPlan()), str(step_helper.isPlanBySample()))) planStatus = application_step_data.savedFields["planStatus"] if not step_helper.isEditRun(): if step_helper.isIonChef(): if step_helper.isPlan() or step_helper.isPlanBySample(): if step_helper.isCreate(): planStatus = "pending" elif step_helper.isEdit( ) and application_step_data.savedFields[ "planStatus"] != "reserved": planStatus = "pending" elif (step_helper.sh_type == StepHelperType.COPY_PLAN or step_helper.sh_type == StepHelperType.COPY_PLAN_BY_SAMPLE): planStatus = "pending" else: planStatus = "pending" else: #when copying a sequenced plan, reseting the plan status is necessary planStatus = "planned" else: planStatus = "run" #logger.debug("step_helper_db_saver.__get_universal_params() planStatus=%s" %(planStatus)) retval = { 'applicationGroup': application_group, 'sampleGrouping': sampleGrouping, 'usePreBeadfind': True, 'usePostBeadfind': False if step_helper.isProton() else True, 'preAnalysis': True, 'runType': runType, 'templatingKitName': templatingKitName, 'controlSequencekitname': controlSequencekitname, 'runMode': 'single', 'isSystem': False, 'isPlanGroup': False, 'username': username, 'isFavorite': toBoolean(isFavorite, False), 'pairedEndLibraryAdapterName': '', 'samplePrepKitName': samplePrepKitName, 'planStatus': planStatus, 'categories': categories, 'x_usePreBeadfind': True, 'x_autoAnalyze': True, 'x_barcodeId': x_barcodeId, 'x_bedfile': x_bedfile, 'x_chipType': x_chipType, 'x_flows': x_flows, 'x_forward3primeadapter': x_forward3primeadapter, 'x_library': x_library, 'x_libraryKey': x_libraryKey, 'tfKey': tfKey, 'x_librarykitname': x_librarykitname, 'x_regionfile': x_regionfile, 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': x_sequencekitname, 'x_variantfrequency': '', 'x_isDuplicateReads': False if x_isDuplicateReads is None else x_isDuplicateReads, 'x_base_recalibrate': False if x_base_recalibrate is None else x_base_recalibrate, 'x_realign': False if x_realign is None else x_realign } return retval
def save_plan_or_template(request, planOid): """ Saving new or edited plan/template to db (source: plan template wizard) Editing a planned run from having 1 sample to 2 samples will result in one edited planned run and one new planned run """ def isReusable(submitIntent): return not (submitIntent == 'savePlan' or submitIntent == 'updatePlan') if request.method != 'POST': logger.exception(format_exc()) return HttpResponse(json.dumps({"error": "Error, unsupported HTTP Request method (%s) for plan update." % request.method}), mimetype="application/json") # Process Inputs # pylint:disable=E1103 json_data = simplejson.loads(request.raw_post_data) submitIntent = json_data.get('submitIntent', '') logger.debug('views.save_plan_or_template POST.raw_post_data... simplejson Data: "%s"' % json_data) logger.debug("views.save_plan_or_template submitIntent=%s" % submitIntent) # saving Template or Planned Run isReusable = isReusable(submitIntent) runModeValue = json_data.get('runMode', 'single') isPlanGroupValue = runModeValue == 'pe' and not isReusable libraryKeyValue = json_data.get('libraryKey', '') forward3primeAdapterValue = json_data.get('forward3primeAdapter', '') msgvalue = 'Run Plan' if not isReusable else 'Template' if runModeValue == 'pe': return HttpResponse(json.dumps({"error": "Error, paired-end plan is no longer supported. %s will not be saved." % (msgvalue)}), mimetype="application/html") planDisplayedNameValue = json_data.get('planDisplayedName', '').strip() noteValue = json_data.get('notes_workaround', '') # perform server-side validation to avoid things falling through the crack if not planDisplayedNameValue: return HttpResponse(json.dumps({"error": "Error, please enter a %s Name." %(msgvalue)}), mimetype="application/html") if not is_valid_chars(planDisplayedNameValue): return HttpResponse(json.dumps({"error": "Error, %s Name" %(msgvalue) + ERROR_MSG_INVALID_CHARS}), mimetype="application/html") if not is_valid_length(planDisplayedNameValue, MAX_LENGTH_PLAN_NAME): return HttpResponse(json.dumps({"error": "Error, %s Name" %(msgvalue) + ERROR_MSG_INVALID_LENGTH %(str(MAX_LENGTH_PLAN_NAME))}), mimetype="application/html") if noteValue: if not is_valid_chars(noteValue): return HttpResponse(json.dumps({"error": "Error, %s note" %(msgvalue) + ERROR_MSG_INVALID_CHARS}), mimetype="application/html") if not is_valid_length(noteValue, MAX_LENGTH_NOTES): return HttpResponse(json.dumps({"error": "Error, Note" + ERROR_MSG_INVALID_LENGTH %(str(MAX_LENGTH_NOTES))}), mimetype="application/html") # Projects projectObjList = get_projects(request.user, json_data) # IonReporterUploader configuration and samples selectedPlugins = json_data.get('selectedPlugins', {}) IRconfigList = json_data.get('irConfigList', []) IRU_selected = False for uploader in selectedPlugins.values(): if 'ionreporteruploader' in uploader['name'].lower() and uploader['name'] != 'IonReporterUploader_V1_0': IRU_selected = True #if IRU is set to autoRun, user does not need to select the plugin explicitly. user could have set all IRU versions to autorun IRU_autorun_count = 0 if not IRU_selected: IRU_autoruns = Plugin.objects.filter(name__icontains="IonReporter", selected=True, active=True, autorun=True).exclude(name__icontains="IonReporterUploader_V1_0").order_by('-name') IRU_autorun_count = IRU_autoruns.count() if IRU_autorun_count > 0: IRU_selected = True if IRU_selected: samples_IRconfig = json_data.get('sample_irConfig', '') if samples_IRconfig: samples_IRconfig = ','.join(samples_IRconfig) #generate UUID for unique setIds id_uuid = {} setids = [ir.get('setid', "") for ir in IRconfigList] if setids: for setid in set(setids): if setid: id_uuid[setid] = str(uuid.uuid4()) for ir_config in IRconfigList: setid = ir_config.get('setid', '') if setid: ir_config['setid'] += '__' + id_uuid[setid] if IRU_autorun_count > 0 and not samples_IRconfig: #if more than one IRU version is set to autorun and user does not explicitly select one, #gui shows workflow config for IRU v1.0 samples_IRconfig = json_data.get('samples_workaround', '') # Samples barcodeIdValue = json_data.get('barcodeId', '') barcodedSamples = '' sampleValidationErrorMsg = '' sampleValidationErrorMsg_leadingChars = '' sampleValidationErrorMsg_length = '' # one Plan will be created per entry in sampleList # samples for barcoded Plan have a separate field (barcodedSamples) if isReusable: # samples entered only when saving planned run (not template) sampleList = [''] elif barcodeIdValue: # a barcode Set is selected sampleList = [''] bcSamplesValues = json_data.get('bcSamples_workaround', '') bcDictionary = {} bcId = "" for token in bcSamplesValues.split(","): if ((token.find("bcKey|")) == 0): bcId, bcId_str = token.split("|")[1:] else: sample = token.strip() if bcId and sample: if not is_valid_chars(sample): sampleValidationErrorMsg += sample + ', ' elif is_invalid_leading_chars(sample): sampleValidationErrorMsg_leadingChars += sample + ", " elif not is_valid_length(sample, MAX_LENGTH_SAMPLE_NAME): sampleValidationErrorMsg_length += sample + ", " bcDictionary.setdefault(sample, {}).setdefault('barcodes',[]).append(bcId_str) bcId = "" barcodedSamples = simplejson.dumps(bcDictionary) logger.debug("views.save_plan_or_template after simplejson.dumps... barcodedSamples=%s;" % (barcodedSamples)) if not bcDictionary: transaction.rollback() return HttpResponse(json.dumps({"error": "Error, please enter at least one barcode sample name."}), mimetype="application/html") else: # Non-barcoded samples sampleList = [] if IRU_selected: samples = samples_IRconfig else: samples = json_data.get('samples_workaround', '') for sample in samples.split(','): if sample.strip(): if not is_valid_chars(sample): sampleValidationErrorMsg += sample + ', ' elif is_invalid_leading_chars(sample): sampleValidationErrorMsg_leadingChars += sample + ", " elif not is_valid_length(sample, MAX_LENGTH_SAMPLE_NAME): sampleValidationErrorMsg_length += sample + ", " else: sampleList.append(sample) logger.debug("views.save_plan_or_template sampleList=%s " % (sampleList)) if len(sampleList) == 0 and not sampleValidationErrorMsg and not sampleValidationErrorMsg_leadingChars and not sampleValidationErrorMsg_length: transaction.rollback() return HttpResponse(json.dumps({"error": "Error, please enter a sample name for the run plan."}), mimetype="application/html") # Samples validation if sampleValidationErrorMsg or sampleValidationErrorMsg_leadingChars or sampleValidationErrorMsg_length: message = "" if sampleValidationErrorMsg: message = "Error, sample name" + ERROR_MSG_INVALID_CHARS message = message + ' <br>Please fix: ' + sampleValidationErrorMsg + '<br>' if sampleValidationErrorMsg_leadingChars: message = message + "Error, sample name" + ERROR_MSG_INVALID_LEADING_CHARS message = message + ' <br>Please fix: ' + sampleValidationErrorMsg_leadingChars + '<br>' if sampleValidationErrorMsg_length: message = message + "Error, sample name" + ERROR_MSG_INVALID_LENGTH %(str(MAX_LENGTH_SAMPLE_NAME)) message = message + ' <br>Please fix: ' + sampleValidationErrorMsg_length transaction.rollback() return HttpResponse(json.dumps({"error": message}), mimetype="application/html") selectedPluginsValue = json_data.get('selectedPlugins', {}) # end processing input data # Edit/Create Plan(s) if int(planOid) == 0: edit_existing_plan = False else: edit_existing_plan = True for i, sample in enumerate(sampleList): logger.debug("...LOOP... views.save_plan_or_template SAMPLE=%s; isSystem=%s; isReusable=%s; isPlanGroup=%s " % (sample.strip(), json_data["isSystem"], isReusable, isPlanGroupValue)) # add IonReporter config values for each sample if len(IRconfigList) > 0: for uploader in selectedPluginsValue.values(): if 'ionreporteruploader' in uploader['name'].lower(): if len(IRconfigList) > 1 and not barcodeIdValue: uploader['userInput'] = [IRconfigList[i]] else: uploader['userInput'] = IRconfigList if len(sampleList) > 1: inputPlanDisplayedName = planDisplayedNameValue + '_' + sample.strip() else: inputPlanDisplayedName = planDisplayedNameValue selectedTemplatingKit = json_data.get('templatekitname', '') samplePrepInstrumentType = json_data.get('samplePrepInstrumentType', '') if samplePrepInstrumentType == 'ionChef': selectedTemplatingKit = json_data.get('templatekitionchefname', '') #PDD-TODO: remove the x_ prefix. the x_ prefix is just a reminder what the obsolete attributes to remove during the next phase kwargs = { 'planDisplayedName': inputPlanDisplayedName, "planName": inputPlanDisplayedName.replace(' ', '_'), 'usePreBeadfind': toBoolean(json_data['usePreBeadfind'], False), 'usePostBeadfind': toBoolean(json_data['usePostBeadfind'], False), 'preAnalysis': True, 'runType': json_data['runType'], 'templatingKitName': selectedTemplatingKit, 'controlSequencekitname': json_data.get('controlsequence', ''), 'runMode': runModeValue, 'isSystem': toBoolean(json_data['isSystem'], False), 'isReusable': isReusable, 'isPlanGroup': isPlanGroupValue, 'username': request.user.username, 'isFavorite': toBoolean(json_data.get('isFavorite', 'False'), False), 'pairedEndLibraryAdapterName': json_data.get('pairedEndLibraryAdapterName', ''), 'samplePrepKitName': json_data.get('samplePrepKitName', ''), 'planStatus' : "planned", 'x_autoAnalyze': True, 'x_barcodedSamples': barcodedSamples, 'x_barcodeId': barcodeIdValue, 'x_bedfile': json_data.get('bedfile', ''), 'x_chipType': json_data.get('chipType', ''), 'x_flows': json_data.get('flows', None), 'x_forward3primeadapter': forward3primeAdapterValue, ###'_isReverseRun': = self.isReverseRun 'x_library': json_data.get('library', ''), 'x_libraryKey': libraryKeyValue, 'x_librarykitname': json_data.get('librarykitname', ''), 'x_notes': noteValue, 'x_regionfile': json_data.get('regionfile', ''), 'x_sample': sample.strip().replace(' ', '_'), 'x_sampleDisplayedName': sample.strip(), 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': json_data.get('sequencekitname', ''), 'x_variantfrequency': json_data.get('variantfrequency', ''), } planTemplate = None #if we're changing a plan from having 1 sample to say 2 samples, we need to UPDATE 1 plan and CREATE 1 plan!! try: if not edit_existing_plan: planTemplate, extra_kwargs = PlannedExperiment.objects.save_plan(-1, **kwargs) else: planTemplate, extra_kwargs = PlannedExperiment.objects.save_plan(planOid, **kwargs) edit_existing_plan = False # Update QCtype thresholds qcTypes = QCType.objects.all() for qcType in qcTypes: qc_threshold = json_data.get(qcType.qcName, '') if qc_threshold: # get existing PlannedExperimentQC if any plannedExpQcs = PlannedExperimentQC.objects.filter(plannedExperiment=planTemplate.id, qcType=qcType.id) if len(plannedExpQcs) > 0: for plannedExpQc in plannedExpQcs: plannedExpQc.threshold = qc_threshold plannedExpQc.save() else: kwargs = { 'plannedExperiment': planTemplate, 'qcType': qcType, 'threshold': qc_threshold } plannedExpQc = PlannedExperimentQC(**kwargs) plannedExpQc.save() # add/remove projects if projectObjList: #TODO: refactor this logic to simplify using django orm projectNameList = [project.name for project in projectObjList] for currentProject in planTemplate.projects.all(): if currentProject.name not in projectNameList: planTemplate.projects.remove(currentProject) for projectObj in projectObjList: planTemplate.projects.add(projectObj) else: planTemplate.projects.clear() except ValidationError, err: transaction.rollback() logger.exception(format_exc()) message = "Internal error while trying to save the plan. " for msg in err.messages: message += str(msg) message += " " return HttpResponse(json.dumps({"error": message}), mimetype="application/json") except Exception as excp: transaction.rollback() logger.exception(format_exc()) message = "Internal error while trying to save the plan. %s" %(excp.message) return HttpResponse(json.dumps({"error": message}), mimetype="application/json")
def __get_universal_params(self, step_helper, username): if not step_helper.isPlan(): if step_helper.isTemplateBySample(): save_template_step_data = step_helper.steps[ StepNames.SAVE_TEMPLATE_BY_SAMPLE] else: save_template_step_data = step_helper.steps[ StepNames.SAVE_TEMPLATE] application_step_data = step_helper.steps[StepNames.APPLICATION] kits_step_data = step_helper.steps[StepNames.KITS] reference_step_data = step_helper.steps[StepNames.REFERENCE] plugins_step_data = step_helper.steps[StepNames.PLUGINS] ionreporter_step_data = step_helper.steps[StepNames.IONREPORTER] isFavorite = False categories = application_step_data.savedFields.get( ApplicationFieldNames.CATEGORIES, "") #if user has changed the application or target technique during template copying, reset categories value applicationGroupName = application_step_data.savedFields.get( ApplicationFieldNames.APPLICATION_GROUP_NAME, "") if applicationGroupName != "DNA + RNA": if categories: categories.replace("Onconet", "") categories.replace("Oncomine", "") if not step_helper.isPlan(): isFavorite = save_template_step_data.savedFields[ SaveTemplateStepDataFieldNames.SET_AS_FAVORITE] logger.debug( "step_helper_db_saver.__get_universal_params() applicationGroupName=%s; categories=%s" % (applicationGroupName, categories)) #logger.debug("step_helper_db_saver.__get_universal_params() application_step_data.savedFields=%s" %(application_step_data.savedFields)) runType = '' application_group = None sampleGrouping = None if application_step_data.savedObjects[ApplicationFieldNames.RUN_TYPE]: runType = application_step_data.savedObjects[ ApplicationFieldNames.RUN_TYPE].runType application_group = application_step_data.savedObjects[ ApplicationFieldNames.RUN_TYPE].applicationGroups.all()[0:1][0] if application_step_data.savedFields[ ApplicationFieldNames.APPLICATION_GROUP]: application_group = ApplicationGroup.objects.get( pk=application_step_data.savedFields[ ApplicationFieldNames.APPLICATION_GROUP]) if ionreporter_step_data.savedFields[ IonReporterFieldNames.SAMPLE_GROUPING]: sampleGrouping = ionreporter_step_data.savedObjects[ IonReporterFieldNames.SAMPLE_GROUPING] templatingKitName = kits_step_data.savedFields[ KitsFieldNames.TEMPLATE_KIT_NAME] controlSequencekitname = kits_step_data.savedFields[ KitsFieldNames.CONTROL_SEQUENCE] samplePrepKitName = kits_step_data.savedFields[ KitsFieldNames.SAMPLE_PREPARATION_KIT] libraryReadLength = kits_step_data.savedFields[ KitsFieldNames.LIBRARY_READ_LENGTH] templatingSize = kits_step_data.savedFields[ KitsFieldNames.TEMPLATING_SIZE] x_barcodeId = kits_step_data.savedFields[KitsFieldNames.BARCODE_ID] x_chipType = kits_step_data.savedFields[KitsFieldNames.CHIP_TYPE] if not x_chipType: x_chipType = '' x_flows = kits_step_data.savedFields[KitsFieldNames.FLOWS] x_forward3primeadapter = kits_step_data.savedFields[ KitsFieldNames.FORWARD_3_PRIME_ADAPTER] x_libraryKey = kits_step_data.savedFields[KitsFieldNames.LIBRARY_KEY] tfKey = kits_step_data.savedFields[KitsFieldNames.TF_KEY] x_librarykitname = kits_step_data.savedFields[ KitsFieldNames.LIBRARY_KIT_NAME] x_sequencekitname = kits_step_data.savedFields[ KitsFieldNames.SEQUENCE_KIT_NAME] x_isDuplicateReads = kits_step_data.savedFields[ KitsFieldNames.IS_DUPLICATED_READS] x_base_recalibration_mode = kits_step_data.savedFields[ KitsFieldNames.BASE_RECALIBRATE] x_realign = kits_step_data.savedFields[KitsFieldNames.REALIGN] x_bedfile = reference_step_data.savedFields[ ReferenceFieldNames.TARGET_BED_FILE] x_library = reference_step_data.savedFields[ ReferenceFieldNames.REFERENCE] x_regionfile = reference_step_data.savedFields[ ReferenceFieldNames.HOT_SPOT_BED_FILE] x_mixedTypeRNA_bedfile = reference_step_data.savedFields[ ReferenceFieldNames.MIXED_TYPE_RNA_TARGET_BED_FILE] x_mixedTypeRNA_library = reference_step_data.savedFields[ ReferenceFieldNames.MIXED_TYPE_RNA_REFERENCE] x_mixedTypeRNA_regionfile = reference_step_data.savedFields[ ReferenceFieldNames.MIXED_TYPE_RNA_HOT_SPOT_BED_FILE] selectedPluginsValue = plugins_step_data.getSelectedPluginsValue() logger.debug( "step_helper_db_saver.__get_universal_params() application_step_data.prepopulatedFields[planStatus]=%s" % (application_step_data.prepopulatedFields[ ApplicationFieldNames.PLAN_STATUS])) logger.debug( "step_helper_db_saver.__get_universal_params() isEditRun=%s; isEdit=%s; isIonChef=%s; isPlan=%s; isPlanBySample=%s" % (str(step_helper.isEditRun()), str(step_helper.isEdit()), str(step_helper.isIonChef()), str( step_helper.isPlan()), str(step_helper.isPlanBySample()))) planStatus = application_step_data.prepopulatedFields[ ApplicationFieldNames.PLAN_STATUS] #preserve the plan status during plan editing if not step_helper.isEditRun() and not step_helper.isEdit(): if step_helper.isIonChef(): if step_helper.isPlan() or step_helper.isPlanBySample(): if step_helper.isCreate(): planStatus = "pending" elif (step_helper.sh_type == StepHelperType.COPY_PLAN or step_helper.sh_type == StepHelperType.COPY_PLAN_BY_SAMPLE): planStatus = "pending" else: planStatus = "pending" else: #when copying a sequenced plan, reseting the plan status is necessary planStatus = "planned" #logger.debug("step_helper_db_saver.__get_universal_params() planStatus=%s" %(planStatus)) retval = { 'applicationGroup': application_group, 'sampleGrouping': sampleGrouping, 'usePreBeadfind': True, 'usePostBeadfind': False if step_helper.isProton() else True, 'preAnalysis': True, 'runType': runType, 'templatingKitName': templatingKitName, 'controlSequencekitname': controlSequencekitname, 'runMode': 'single', 'isSystem': False, 'isPlanGroup': False, 'username': username, 'isFavorite': toBoolean(isFavorite, False), 'pairedEndLibraryAdapterName': '', 'samplePrepKitName': samplePrepKitName, 'libraryReadLength': libraryReadLength, 'templatingSize': templatingSize, 'planStatus': planStatus, 'categories': categories, 'x_usePreBeadfind': True, 'x_autoAnalyze': True, 'x_barcodeId': x_barcodeId, 'x_bedfile': x_bedfile, 'x_chipType': x_chipType, 'x_flows': x_flows, 'x_forward3primeadapter': x_forward3primeadapter, 'x_library': x_library, 'x_libraryKey': x_libraryKey, 'tfKey': tfKey, 'x_librarykitname': x_librarykitname, 'x_regionfile': x_regionfile, 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': x_sequencekitname, 'x_variantfrequency': '', 'x_isDuplicateReads': False if x_isDuplicateReads is None else x_isDuplicateReads, 'x_base_recalibration_mode': "no_recal" if x_base_recalibration_mode is None else x_base_recalibration_mode, 'x_realign': False if x_realign is None else x_realign, 'x_mixedTypeRNA_bedfile': x_mixedTypeRNA_bedfile, 'x_mixedTypeRNA_regionfile': x_mixedTypeRNA_regionfile, 'x_mixedTypeRNA_library': x_mixedTypeRNA_library, } return retval
def __get_universal_params(self, step_helper, username): if not step_helper.isPlan(): if step_helper.isTemplateBySample(): save_template_step_data = step_helper.steps[StepNames.SAVE_TEMPLATE_BY_SAMPLE] else: save_template_step_data = step_helper.steps[StepNames.SAVE_TEMPLATE] application_step_data = step_helper.steps[StepNames.APPLICATION] kits_step_data = step_helper.steps[StepNames.KITS] reference_step_data = step_helper.steps[StepNames.REFERENCE] plugins_step_data = step_helper.steps[StepNames.PLUGINS] ionreporter_step_data = step_helper.steps[StepNames.IONREPORTER] isFavorite = False categories = '' if not step_helper.isPlan(): isFavorite = save_template_step_data.savedFields['setAsFavorite'] categories = application_step_data.savedFields.get('categories', "") #if user has changed the application or target technique during template copying, reset categories value applicationGroupName = application_step_data.savedFields.get("applicationGroupName", "") if applicationGroupName != "DNA + RNA": #logger.debug("step_helper_db_saver.__get_universal_params() applicationGroupName=%s; replacing categories=%s" %(applicationGroupName, categories)) if categories: categories.replace("Onconet", ""); categories.replace("Oncomine", ""); else: categories = "" #logger.debug("step_helper_db_saver.__get_universal_params() application_step_data.savedFields=%s" %(application_step_data.savedFields)) runType = '' application_group = None sampleGrouping = None if application_step_data.savedObjects['runType']: runType = application_step_data.savedObjects['runType'].runType application_group = application_step_data.savedObjects['runType'].applicationGroups.all()[0:1][0] if application_step_data.savedFields['applicationGroup']: application_group = ApplicationGroup.objects.get(pk=application_step_data.savedFields['applicationGroup']) if ionreporter_step_data.savedFields['sampleGrouping']: sampleGrouping = ionreporter_step_data.savedObjects['sampleGrouping'] templatingKitName = kits_step_data.savedFields['templatekitname'] controlSequencekitname = kits_step_data.savedFields['controlsequence'] samplePrepKitName = kits_step_data.savedFields['samplePreparationKit'] x_barcodeId = kits_step_data.savedFields['barcodeId'] x_chipType = kits_step_data.savedFields['chipType'] if not x_chipType: x_chipType = '' x_flows = kits_step_data.savedFields['flows'] x_forward3primeadapter = kits_step_data.savedFields['forward3primeAdapter'] x_libraryKey = kits_step_data.savedFields['libraryKey'] tfKey = kits_step_data.savedFields['tfKey'] x_librarykitname = kits_step_data.savedFields['librarykitname'] x_sequencekitname = kits_step_data.savedFields['sequencekitname'] x_isDuplicateReads = kits_step_data.savedFields['isDuplicateReads'] x_base_recalibrate = kits_step_data.savedFields['base_recalibrate'] x_realign = kits_step_data.savedFields['realign'] x_bedfile = reference_step_data.savedFields['targetBedFile'] x_library = reference_step_data.savedFields["reference"] x_regionfile = reference_step_data.savedFields['hotSpotBedFile'] selectedPluginsValue = plugins_step_data.getSelectedPluginsValue() logger.debug("step_helper_db_saver.__get_universal_params() application_step_data.savedFields[planStatus]=%s" %(application_step_data.savedFields["planStatus"])) logger.debug("step_helper_db_saver.__get_universal_params() isEditRun=%s; isEdit=%s; isIonChef=%s; isPlan=%s; isPlanBySample=%s" %(str(step_helper.isEditRun()), str(step_helper.isEdit()), str(step_helper.isIonChef()), str(step_helper.isPlan()), str(step_helper.isPlanBySample()))) planStatus = application_step_data.savedFields["planStatus"] if not step_helper.isEditRun(): if step_helper.isIonChef(): if step_helper.isPlan() or step_helper.isPlanBySample(): if step_helper.isCreate(): planStatus = "pending" elif step_helper.isEdit() and application_step_data.savedFields["planStatus"] != "reserved": planStatus = "pending" elif (step_helper.sh_type == StepHelperType.COPY_PLAN or step_helper.sh_type == StepHelperType.COPY_PLAN_BY_SAMPLE): planStatus = "pending" else: planStatus = "pending" else: #when copying a sequenced plan, reseting the plan status is necessary planStatus = "planned" else: planStatus = "run" #logger.debug("step_helper_db_saver.__get_universal_params() planStatus=%s" %(planStatus)) retval = { 'applicationGroup': application_group, 'sampleGrouping' : sampleGrouping, 'usePreBeadfind': True, 'usePostBeadfind': False if step_helper.isProton() else True, 'preAnalysis': True, 'runType': runType, 'templatingKitName': templatingKitName, 'controlSequencekitname': controlSequencekitname, 'runMode': 'single', 'isSystem': False, 'isPlanGroup': False, 'username': username, 'isFavorite': toBoolean(isFavorite, False), 'pairedEndLibraryAdapterName': '', 'samplePrepKitName': samplePrepKitName, 'planStatus' : planStatus, 'categories' : categories, 'x_usePreBeadfind': True, 'x_autoAnalyze': True, 'x_barcodeId': x_barcodeId, 'x_bedfile': x_bedfile, 'x_chipType': x_chipType, 'x_flows': x_flows, 'x_forward3primeadapter': x_forward3primeadapter, 'x_library': x_library, 'x_libraryKey': x_libraryKey, 'tfKey': tfKey, 'x_librarykitname': x_librarykitname, 'x_regionfile': x_regionfile, 'x_selectedPlugins': selectedPluginsValue, 'x_sequencekitname': x_sequencekitname, 'x_variantfrequency': '', 'x_isDuplicateReads': False if x_isDuplicateReads is None else x_isDuplicateReads, 'x_base_recalibrate': False if x_base_recalibrate is None else x_base_recalibrate, 'x_realign': False if x_realign is None else x_realign } return retval
def add_plans(request): """Take care of adding plans. The POST method will do the CSV parsing and database additions""" def validate_plan(plan): """validate a dict that is a plan""" failed = [] requiredList = ["planName"] for req in requiredList: if req in plan: if not plan[req]: failed.append( (req, "Required column is empty") ) else: failed.append( (req, "Required column is missing") ) charCheckList = ["planName","sample","project"] for charCheck in charCheckList: if charCheck in plan: if not set(plan[charCheck]).issubset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-"): failed.append((charCheck, "Must only have letters, numbers, or the characters _ . - ")) if 'cycles' in plan: if plan["cycles"]: try: minCheck = int(str(plan["cycles"])) if minCheck < 1: failed.append( ("cycles","flows must be at least 1") ) except ValueError: failed.append( ("cycles","flows must be a whole number") ) alphaNumList = ["chipBarcode","seqKitBarcode", "forwardLibraryKey", "forward3PrimeAdapter", "reverseLibraryKey", "reverse3PrimeAdapter"] for alphaNum in alphaNumList: if alphaNum in plan: if not set(plan[alphaNum]).issubset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"): failed.append((alphaNum, "Must only have letters or numbers")) checkList = ["autoAnalyze","preAnalysis"] checkWord = ["false", "False", "FALSE","f", "no", "n", "none", "0" , "true", "True", "TRUE","t", "yes", "y", "1", "" ] for check in checkList: if check in plan: if not plan[check] in checkWord: failed.append((check, 'Must contain only one of the values for false ("false", "False", "FALSE","f", "no", "n", "none", "0" ) or for true ("true", "True", "TRUE","t", "yes", "y", "1", "") ')) checkList = ["isPairedEnd"] checkWord = ["false", "False", "FALSE", "f", "no", "No", "NO", "n", "none", "0", "true", "True", "TRUE", "t", "yes", "Yes", "YES", "y", "1", "" ] for check in checkList: if check in plan: if not plan[check] in checkWord: failed.append((check, 'Must contain only one of the values for false ("false", "False", "FALSE", "f", "no", "No", "NO", "n", "none", "0", "") or for true ("true", "True", "TRUE", "t", "yes", "Yes", "YES", "y", "1") ')) if 'notes' in plan: if not set(plan["notes"]).issubset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.- "): failed.append((alphaNum, "Must only have letters, numbers, spaces, or the characters _ . - ")) #runType: items in the list runTypes = models.RunType.objects.all().order_by("id") runTypes = [r.runType for r in runTypes] if 'runType' in plan: if plan['runType']: if not plan['runType'] in runTypes: failed.append(("runType", "Must be a valid runType, default is GENS",plan['runType'],runTypes)) #barcodeId: items in the list barcodes = models.dnaBarcode.objects.values_list('name').distinct().order_by('name') barcodes = [b[0] for b in barcodes] if 'barcodeID' in plan: if plan["barcodeID"]: if not plan["barcodeID"] in barcodes: failed.append(("barcodeID", "Must be a valid barcode id of an existing barcode set")) if plan.get("library", False): if not models.ReferenceGenome.objects.all().filter( short_name=plan["library"], index_version=settings.TMAP_VERSION): failed.append(("library", "Must be a valid genome reference library short form name. (also known as reference sequence)")) return failed if request.method == 'POST': #this POST method will verify the data sent in was good file = request.FILES['postedfile'] destination = tempfile.NamedTemporaryFile(delete=False) for chunk in file.chunks(): destination.write(chunk) destination.close() #check to ensure it is not empty headerCheck = open(destination.name, "rU") firstCSV = [] for firstRow in csv.reader(headerCheck): firstCSV.append(firstRow) headerCheck.close() if not firstRow: os.unlink(destination.name) return http.HttpResponse(json.dumps({"status":"Error: Plan file is empty"}) , mimetype="text/html") expectedHeader = [ "planName", "sample", "project", "flows", "runType", "library", "barcodeId", "seqKitBarcode", "autoAnalyze", "preAnalysis", "bedfile", "regionfile", "notes", "forwardLibraryKey", "forward3PrimeAdapter", "isPairedEnd", "reverseLibraryKey", "reverse3PrimeAdapter" ] if sorted(firstCSV[0]) != sorted(expectedHeader): os.unlink(destination.name) return http.HttpResponse(json.dumps({"status":"Plan csv header is not as expected. Please try again starting with the provided example"}) , mimetype="text/html") index = 0 failed = {} plans = [] file = open(destination.name, "rU") reader = csv.DictReader(file) for index, row in enumerate(reader, start=1): invalid = validate_plan(row) if invalid: #don't make dna object or add it to the list failed[index] = invalid continue newPlan = models.PlannedExperiment() #save it to get the pk for key, value in row.items(): #convert to bool if key == 'autoAnalyze' or key == 'preAnalysis': value = toBoolean(value) if key == 'isPairedEnd': value = toBoolean(value, False) #don't save if the cycles is blank if key == 'flows' and value == '': pass elif key =='forwardLibraryKey': setattr(newPlan, 'libraryKey', value) elif key == 'forward3PrimeAdapter': setattr(newPlan, 'forward3primeadapter', value) elif key == 'isPairedEnd': setattr(newPlan, 'isReverseRun', value) elif key == 'reverseLibraryKey': setattr(newPlan, 'reverselibrarykey', value) elif key == 'reverse3PrimeAdapter': setattr(newPlan, 'reverse3primeadapter', value) else: setattr(newPlan, key, value) #default runtype is GENS if not newPlan.runType: newPlan.runType = "GENS" newPlan.usePreBeadfind = True newPlan.usePostBeadfind = True plans.append(newPlan) #now remove the file and close others file.close() os.unlink(destination.name) if index == 0: return http.HttpResponse(json.dumps({"status":"Error: There must be at least one Plan! Please reload the page and try again."}) , mimetype="text/html") if failed: r = {"status": "Plan validation failed. The plans set has not been saved.", "failed" : failed } return http.HttpResponse(json.dumps(r) , mimetype="text/html") for plan in plans: try: plan.save() except: return http.HttpResponse(json.dumps({"status":"Error saving plan to database!","plan":plan.planName }) , mimetype="text/html") r = {"status": "Plans Uploaded! The plans will be listed on the planning page.", "failed" : failed } return http.HttpResponse(json.dumps(r) , mimetype="text/html") ctx = template.RequestContext(request, {} ) return shortcuts.render_to_response("rundb/ion_addplans.html",context_instance=ctx, mimetype="text/html")
def save_plan_or_template(request, planOid): """ Saving new or edited plan/template to db (source: plan template wizard) Editing a planned run from having 1 sample to 2 samples will result in one edited planned run and one new planned run """ def isReusable(submitIntent): return not (submitIntent == 'savePlan' or submitIntent == 'updatePlan') def isValidChars(value, validChars=r'^[a-zA-Z0-9-_\.\s\,]+$'): ''' Determines if value is valid: letters, numbers, spaces, dashes, underscores only ''' return bool(re.compile(validChars).match(value)) if request.method != 'POST': logger.exception(format_exc()) return HttpResponse(json.dumps({ "error": "Error, unsupported HTTP Request method (%s) for plan update." % request.method }), mimetype="application/json") # Process Inputs # pylint:disable=E1103 json_data = simplejson.loads(request.raw_post_data) submitIntent = json_data.get('submitIntent', '') logger.debug( 'views.editplannedexperiment POST.raw_post_data... simplejson Data: "%s"' % json_data) logger.debug("views.editplannedexperiment submitIntent=%s" % submitIntent) # saving Template or Planned Run isReusable = isReusable(submitIntent) runModeValue = json_data.get('runMode', 'single') isPlanGroupValue = runModeValue == 'pe' and not isReusable libraryKeyValue = json_data.get('libraryKey', '') forward3primeAdapterValue = json_data.get('forward3primeAdapter', '') msgvalue = 'Run Plan' if not isReusable else 'Template' if runModeValue == 'pe': return HttpResponse(json.dumps({ "error": "Error, paired-end plan is no longer supported. %s will not be saved." % (msgvalue) }), mimetype="application/html") planDisplayedNameValue = json_data.get('planDisplayedName', '').strip() noteValue = json_data.get('notes_workaround', '') # perform server-side validation to avoid things falling through the crack if not planDisplayedNameValue: return HttpResponse(json.dumps( {"error": "Error, please enter a %s Name." % (msgvalue)}), mimetype="application/html") if not isValidChars(planDisplayedNameValue): return HttpResponse(json.dumps({ "error": "Error, %s Name should contain only numbers, letters, spaces, and the following: . - _" % (msgvalue) }), mimetype="application/html") if noteValue and not isValidChars(noteValue): return HttpResponse(json.dumps({ "error": "Error, %s note should contain only numbers, letters, spaces, and the following: . - _" % (msgvalue) }), mimetype="application/html") # Projects projectObjList = get_projects(request.user, json_data) # IonReporterUploader configuration and samples selectedPlugins = json_data.get('selectedPlugins', {}) IRconfigList = json_data.get('irConfigList', []) IRU_1_2_selected = False for uploader in selectedPlugins.get('planuploaders', []): if 'ionreporteruploader' in uploader['name'].lower( ) and uploader['name'] != 'IonReporterUploader_V1_0': IRU_1_2_selected = True samples_IRconfig = json_data.get('sample_irConfig', '') samples_IRconfig = ','.join(samples_IRconfig) #generate UUID for unique setIds id_uuid = {} setids = [ir['setid'] for ir in IRconfigList] for setid in set(setids): id_uuid[setid] = str(uuid.uuid4()) for ir_config in IRconfigList: ir_config['setid'] += '__' + id_uuid[ir_config['setid']] # Samples barcodeIdValue = json_data.get('barcodeId', '') barcodedSamples = '' sampleValidationErrorMsg = '' # one Plan will be created per entry in sampleList # samples for barcoded Plan have a separate field (barcodedSamples) if isReusable: # samples entered only when saving planned run (not template) sampleList = [''] elif barcodeIdValue: # a barcode Set is selected sampleList = [''] bcSamplesValues = json_data.get('bcSamples_workaround', '') bcDictionary = {} bcId = "" for token in bcSamplesValues.split(","): if ((token.find("bcKey|")) == 0): bcId, bcId_str = token.split("|")[1:] else: sample = token.strip() if bcId and sample: if not isValidChars(sample): sampleValidationErrorMsg += sample + ', ' bcDictionary.setdefault(sample, {}).setdefault('barcodes', []).append(bcId_str) bcId = "" barcodedSamples = simplejson.dumps(bcDictionary) logger.debug( "views.editplannedexperiment after simplejson.dumps... barcodedSamples=%s;" % (barcodedSamples)) if not bcDictionary: transaction.rollback() return HttpResponse(json.dumps({ "error": "Error, please enter at least one barcode sample name." }), mimetype="application/html") else: # Non-barcoded samples sampleList = [] if IRU_1_2_selected: samples = samples_IRconfig else: samples = json_data.get('samples_workaround', '') for sample in samples.split(','): if sample.strip(): if not isValidChars(sample): sampleValidationErrorMsg += sample + ', ' else: sampleList.append(sample) logger.debug("views.editplannedexperiment sampleList=%s " % (sampleList)) if len(sampleList) == 0: transaction.rollback() return HttpResponse(json.dumps({ "error": "Error, please enter a sample name for the run plan." }), mimetype="application/html") # Samples validation if sampleValidationErrorMsg: message = "Error, sample name should contain only numbers, letters, spaces, and the following: . - _" message = message + ' <br>Please fix: ' + sampleValidationErrorMsg transaction.rollback() return HttpResponse(json.dumps({"error": message}), mimetype="application/html") selectedPluginsValue = json_data.get('selectedPlugins', []) # end processing input data # Edit/Create Plan(s) if int(planOid) == 0: edit_existing_plan = False else: edit_existing_plan = True for i, sample in enumerate(sampleList): logger.debug( "...LOOP... views.editplannedexperiment SAMPLE=%s; isSystem=%s; isReusable=%s; isPlanGroup=%s " % (sample.strip(), json_data["isSystem"], isReusable, isPlanGroupValue)) # add IonReporter config values for each sample if len(IRconfigList) > 0: for uploader in selectedPluginsValue['planuploaders']: if 'ionreporter' in uploader['name'].lower(): if len(IRconfigList) > 1 and not barcodeIdValue: uploader['userInput'] = [IRconfigList[i]] else: uploader['userInput'] = IRconfigList if len(sampleList) > 1: inputPlanDisplayedName = planDisplayedNameValue + '_' + sample.strip( ) else: inputPlanDisplayedName = planDisplayedNameValue kwargs = { 'planDisplayedName': inputPlanDisplayedName, "planName": inputPlanDisplayedName.replace(' ', '_'), 'chipType': json_data.get('chipType', ''), 'usePreBeadfind': toBoolean(json_data['usePreBeadfind'], False), 'usePostBeadfind': toBoolean(json_data['usePostBeadfind'], False), 'flows': json_data.get('flows', None), 'autoAnalyze': True, 'preAnalysis': True, 'runType': json_data['runType'], 'library': json_data.get('library', ''), 'notes': noteValue, 'bedfile': json_data.get('bedfile', ''), 'regionfile': json_data.get('regionfile', ''), 'variantfrequency': json_data.get('variantfrequency', ''), 'librarykitname': json_data.get('librarykitname', ''), 'sequencekitname': json_data.get('sequencekitname', ''), 'barcodeId': barcodeIdValue, 'templatingKitName': json_data.get('templatekitname', ''), 'controlSequencekitname': json_data.get('controlsequence', ''), 'runMode': runModeValue, 'isSystem': toBoolean(json_data['isSystem'], False), 'isReusable': isReusable, 'isPlanGroup': isPlanGroupValue, 'sampleDisplayedName': sample.strip(), "sample": sample.strip().replace(' ', '_'), 'username': request.user.username, 'isFavorite': toBoolean(json_data.get('isFavorite', 'False'), False), 'barcodedSamples': barcodedSamples, 'libraryKey': libraryKeyValue, 'forward3primeadapter': forward3primeAdapterValue, 'reverselibrarykey': json_data.get('reverselibrarykey', ''), 'reverse3primeadapter': json_data.get('reverse3primeAdapter', ''), 'pairedEndLibraryAdapterName': json_data.get('pairedEndLibraryAdapterName', ''), 'samplePrepKitName': json_data.get('samplePrepKitName', ''), 'selectedPlugins': selectedPluginsValue } #if we're changing a plan from having 1 sample to say 2 samples, we need to UPDATE 1 plan and CREATE 1 plan!! try: if not edit_existing_plan: planTemplate = PlannedExperiment(**kwargs) else: planTemplate = PlannedExperiment.objects.get(pk=planOid) for key, value in kwargs.items(): setattr(planTemplate, key, value) edit_existing_plan = False planTemplate.save() # Update QCtype thresholds qcTypes = QCType.objects.all() for qcType in qcTypes: qc_threshold = json_data.get(qcType.qcName, '') if qc_threshold: # get existing PlannedExperimentQC if any plannedExpQcs = PlannedExperimentQC.objects.filter( plannedExperiment=planTemplate.id, qcType=qcType.id) if len(plannedExpQcs) > 0: for plannedExpQc in plannedExpQcs: plannedExpQc.threshold = qc_threshold plannedExpQc.save() else: kwargs = { 'plannedExperiment': planTemplate, 'qcType': qcType, 'threshold': qc_threshold } plannedExpQc = PlannedExperimentQC(**kwargs) plannedExpQc.save() # add/remove projects if projectObjList: #TODO: refactor this logic to simplify using django orm projectNameList = [project.name for project in projectObjList] for currentProject in planTemplate.projects.all(): if currentProject.name not in projectNameList: planTemplate.projects.remove(currentProject) for projectObj in projectObjList: planTemplate.projects.add(projectObj) else: planTemplate.projects.clear() except: transaction.rollback() logger.exception(format_exc()) return HttpResponse(json.dumps( {"error": "Internal error while trying to save the plan."}), mimetype="application/json") else: transaction.commit() return HttpResponse(json.dumps( {"status": "plan template updated successfully"}), mimetype="application/json")
def add_plans(request): """Take care of adding plans. The POST method will do the CSV parsing and database additions""" def validate_plan(plan): """validate a dict that is a plan""" failed = [] requiredList = ["planName"] for req in requiredList: if req in plan: if not plan[req]: failed.append((req, "Required column is empty")) else: failed.append((req, "Required column is missing")) charCheckList = ["planName", "sample", "project"] for charCheck in charCheckList: if charCheck in plan: if not set(plan[charCheck]).issubset( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-" ): failed.append(( charCheck, "Must only have letters, numbers, or the characters _ . - " )) if 'cycles' in plan: if plan["cycles"]: try: minCheck = int(str(plan["cycles"])) if minCheck < 1: failed.append(("cycles", "flows must be at least 1")) except ValueError: failed.append(("cycles", "flows must be a whole number")) alphaNumList = [ "chipBarcode", "seqKitBarcode", "forwardLibraryKey", "forward3PrimeAdapter", "reverseLibraryKey", "reverse3PrimeAdapter" ] for alphaNum in alphaNumList: if alphaNum in plan: if not set(plan[alphaNum]).issubset( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ): failed.append( (alphaNum, "Must only have letters or numbers")) checkList = ["autoAnalyze", "preAnalysis"] checkWord = [ "false", "False", "FALSE", "f", "no", "n", "none", "0", "true", "True", "TRUE", "t", "yes", "y", "1", "" ] for check in checkList: if check in plan: if not plan[check] in checkWord: failed.append(( check, 'Must contain only one of the values for false ("false", "False", "FALSE","f", "no", "n", "none", "0" ) or for true ("true", "True", "TRUE","t", "yes", "y", "1", "") ' )) checkList = ["isPairedEnd"] checkWord = [ "false", "False", "FALSE", "f", "no", "No", "NO", "n", "none", "0", "true", "True", "TRUE", "t", "yes", "Yes", "YES", "y", "1", "" ] for check in checkList: if check in plan: if not plan[check] in checkWord: failed.append(( check, 'Must contain only one of the values for false ("false", "False", "FALSE", "f", "no", "No", "NO", "n", "none", "0", "") or for true ("true", "True", "TRUE", "t", "yes", "Yes", "YES", "y", "1") ' )) if 'notes' in plan: if not set(plan["notes"]).issubset( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.- " ): failed.append(( alphaNum, "Must only have letters, numbers, spaces, or the characters _ . - " )) #runType: items in the list runTypes = models.RunType.objects.all().order_by("id") runTypes = [r.runType for r in runTypes] if 'runType' in plan: if plan['runType']: if not plan['runType'] in runTypes: failed.append( ("runType", "Must be a valid runType, default is GENS", plan['runType'], runTypes)) #barcodeId: items in the list barcodes = models.dnaBarcode.objects.values_list( 'name').distinct().order_by('name') barcodes = [b[0] for b in barcodes] if 'barcodeID' in plan: if plan["barcodeID"]: if not plan["barcodeID"] in barcodes: failed.append(( "barcodeID", "Must be a valid barcode id of an existing barcode set" )) if plan.get("library", False): if not models.ReferenceGenome.objects.all().filter( short_name=plan["library"], index_version=settings.TMAP_VERSION): failed.append(( "library", "Must be a valid genome reference library short form name. (also known as reference sequence)" )) return failed if request.method == 'POST': #this POST method will verify the data sent in was good file = request.FILES['postedfile'] destination = tempfile.NamedTemporaryFile(delete=False) for chunk in file.chunks(): destination.write(chunk) destination.close() #check to ensure it is not empty headerCheck = open(destination.name, "rU") firstCSV = [] for firstRow in csv.reader(headerCheck): firstCSV.append(firstRow) headerCheck.close() if not firstRow: os.unlink(destination.name) return http.HttpResponse(json.dumps( {"status": "Error: Plan file is empty"}), mimetype="text/html") expectedHeader = [ "planName", "sample", "project", "flows", "runType", "library", "barcodeId", "seqKitBarcode", "autoAnalyze", "preAnalysis", "bedfile", "regionfile", "notes", "forwardLibraryKey", "forward3PrimeAdapter", "isPairedEnd", "reverseLibraryKey", "reverse3PrimeAdapter" ] if sorted(firstCSV[0]) != sorted(expectedHeader): os.unlink(destination.name) return http.HttpResponse(json.dumps({ "status": "Plan csv header is not as expected. Please try again starting with the provided example" }), mimetype="text/html") index = 0 failed = {} plans = [] file = open(destination.name, "rU") reader = csv.DictReader(file) for index, row in enumerate(reader, start=1): invalid = validate_plan(row) if invalid: #don't make dna object or add it to the list failed[index] = invalid continue newPlan = models.PlannedExperiment() #save it to get the pk for key, value in row.items(): #convert to bool if key == 'autoAnalyze' or key == 'preAnalysis': value = toBoolean(value) if key == 'isPairedEnd': value = toBoolean(value, False) #don't save if the cycles is blank if key == 'flows' and value == '': pass elif key == 'forwardLibraryKey': setattr(newPlan, 'libraryKey', value) elif key == 'forward3PrimeAdapter': setattr(newPlan, 'forward3primeadapter', value) elif key == 'isPairedEnd': setattr(newPlan, 'isReverseRun', value) elif key == 'reverseLibraryKey': setattr(newPlan, 'reverselibrarykey', value) elif key == 'reverse3PrimeAdapter': setattr(newPlan, 'reverse3primeadapter', value) else: setattr(newPlan, key, value) #default runtype is GENS if not newPlan.runType: newPlan.runType = "GENS" newPlan.usePreBeadfind = True newPlan.usePostBeadfind = True plans.append(newPlan) #now remove the file and close others file.close() os.unlink(destination.name) if index == 0: return http.HttpResponse(json.dumps({ "status": "Error: There must be at least one Plan! Please reload the page and try again." }), mimetype="text/html") if failed: r = { "status": "Plan validation failed. The plans set has not been saved.", "failed": failed } return http.HttpResponse(json.dumps(r), mimetype="text/html") for plan in plans: try: plan.save() except: return http.HttpResponse(json.dumps({ "status": "Error saving plan to database!", "plan": plan.planName }), mimetype="text/html") r = { "status": "Plans Uploaded! The plans will be listed on the planning page.", "failed": failed } return http.HttpResponse(json.dumps(r), mimetype="text/html") ctx = template.RequestContext(request, {}) return shortcuts.render_to_response("rundb/ion_addplans.html", context_instance=ctx, mimetype="text/html")