def getBarcodeStats(self): """ Simple project / subject / barcode stats """ self.getGUIFieldValue() if self.stats_type == 'Project': proj_stats = self.redcapExec.getProjectStats() curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.appendPlainText("\n\n%s\nProject Stats:\n%s" % (str(cur_date), proj_stats)) elif self.stats_type == 'Subject': if self.subjectId == '' or self.subjectId == None: QMessageBox.about( self, "WARNING", "Subject id is empty. Get stats for subject %s failed." % str(self.subjectId)) return self.getSubjectType() # --> force to select correct subject type if self.studyType == '' or self.studyType == None: QMessageBox.about( self, "WARNING", "Study type is empty. Get stats for subject %s failed." % str(self.subjectId)) return # a hacking here because we don't care if the subject contains extra frozen id or not. barcodeExec = BarcodeGenerator(self.subjectId, self.studyType) barcodeExec.execute() tmp_barcode_list = barcodeExec.get_barcode_list(self.custom_option) subj_stats = self.redcapExec.getSubjectStats(tmp_barcode_list) curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.appendPlainText( "\n\n%s\nSubject %s Stats:\n%s" % (str(cur_date), self.subjectId, subj_stats)) elif self.stats_type == 'Barcode': if self.barcode_id is '' or self.barcode_id is None: QMessageBox.about( self, "WARNING", "Barcode id is empty. Set scan status failed. \n\n Please fill up barcode id box" ) return barcode_stats = self.redcapExec.getBarcodeStats(self.barcode_id) curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.appendPlainText( "\n\n%s\nBarcode %s Stats is stored in :\n%s" % (str(cur_date), self.barcode_id, barcode_stats)) self.plain_console.repaint() self.plain_console.moveCursor(QTextCursor.End)
def setStatusSetAction(self): """ Set all actions of individual barcode """ self.getGUIFieldValue() if self.studyType == '' or self.studyType == None: QMessageBox.about( self, "WARNING", "Study type is empty. Do action for barcode %s failed." % str(self.barcode_id)) return if self.processed_by == '' or self.processed_by == None: QMessageBox.about(self, "WARNING", "Please select current user.") return # check barcode exists and return custom option self.subjectId = self.barcode_id[3:6] #GCAxxx -> xxx tmp_custom_option = self.redcapExec.getSubjectLastestCustomOption( self.barcode_id, self.subjectId) if tmp_custom_option is False: QMessageBox.about( self, "WARNING", "Barcode %s is not found \n\n please generate barcode first" % str(self.barcode_id)) return nextAvailActionId = self.redcapExec.getNextAvailActionId() self.subjectId = self.barcode_id[3:6] # add real barcode to ean8 code barcodeExec = BarcodeGenerator(self.subjectId, self.studyType) ean8_code = barcodeExec.recordId_to_ean8(self.barcode_id) if ean8_code is None: QMessageBox.about( self, "WARNING", "Something wrong with barcode id %s? \n Or please double-check your subject type" % (self.barcode_id)) return # Re-print a missing barcode doesn't need to update Sophie's REDCap form, only update barcode tuple table if self.action_type == 'Re-print a missing barcode': self.rePrintSingleLabel(ean8_code) # Re-print a destroyed barcode need to be update Sophie's REDCap form, because the field is empty. if self.action_type == 'Re-print a destroyed barcode': self.rePrintSingleLabel(ean8_code) # NEED TO WORK ON IT -> bool_update_redcap_sophie = self.redcapExec.update_REDCAP_SOPHIE_SINGLE_BARCODE(self.studyType,str(int(self.subjectId)),self.barcode_id,tmp_custom_option) self.redcapExec.setAction(nextAvailActionId, self.barcode_id, self.studyType, self.processed_by, self.action_type, self.action_comment, ean8_code, tmp_custom_option) self.plain_comment.clear() curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.appendPlainText( "\n\n%s\nbarcode %s action: %s DONE!" % (str(cur_date), str(self.barcode_id), self.action_type)) self.plain_console.repaint() self.plain_console.moveCursor(QTextCursor.End) self.textbox_barcode_id.selectAll()
def set_scanned_id(self, scanned_id): """ Convert ean8 id to real barcode id """ barcodeExec = BarcodeGenerator() tmp_barcode_id = '' # hacking because location app does not have self.subject field if scanned_id[0:3] == 'GCA': # in case users manaully type the barcode. No need ean8 conversion. self.barcode_id = scanned_id # self.subject is not set in barcode_generator... else: if barcodeExec.is_valid(str(scanned_id)) is False: QtWidgets.QMessageBox.about( Form, "WARNING", "Barcode is not valid(1). Please contact to administrator") self.plain_console.repaint() return False tmp_barcode_id = barcodeExec.ean8_to_recordId(scanned_id) if tmp_barcode_id is None: QtWidgets.QMessageBox.about( Form, "WARNING", "Barcode is not valid(2). Please contact to administrator") self.plain_console.repaint() return False # set GUI self.barcode_id = tmp_barcode_id # set GUI self.textbox_barcode_id.setText(self.barcode_id) self.subjectId = self.barcode_id[3:6] tmp_custom_option = self.redcapExec.getSubjectLastestCustomOption( self.barcode_id, self.subjectId) if tmp_custom_option is False: QMessageBox.about( self, "WARNING", "Barcode %s is not found \n\n please generate barcode first" % str(self.barcode_id)) return tmp_studyType = scanned_id[0:1] if tmp_studyType == '1': self.cb_study_type.setCurrentIndex(1) elif tmp_studyType == '2': self.cb_study_type.setCurrentIndex(2) elif tmp_studyType == '3': self.cb_study_type.setCurrentIndex(3) elif tmp_studyType == '4': self.cb_study_type.setCurrentIndex(4) # add a new barcode actoin record nextAvailActionId = self.redcapExec.getNextAvailActionId() self.redcapExec.setScannedAction(nextAvailActionId, self.barcode_id, self.studyType, self.processed_by, self.action_comment, scanned_id, tmp_custom_option) self.plain_comment.clear() curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.appendPlainText( "\n\n%s\nSet barcode %s scanned status DONE!" % (str(cur_date), str(self.barcode_id))) self.plain_console.repaint() self.plain_console.moveCursor(QTextCursor.End)
def genPrintNewPack(self): """ Generate and print new full pack of barcodes """ self.getGUIFieldValue() if self.subjectId == '' or self.subjectId == None: QMessageBox.about( self, "WARNING", "Subject id is empty. Generate / Print new pack for subject %s failed." % str(self.subjectId)) return if len(self.subjectId) != 3: QMessageBox.about( self, "WARNING", "Subject id should be three digit. Please double-check") return if self.studyType == '' or self.studyType == None: QMessageBox.about( self, "WARNING", "Study type is empty. Generate / Print new pack for subject %s failed." % str(self.subjectId)) return if self.processed_by == '' or self.processed_by == None: QMessageBox.about(self, "WARNING", "Please select current user.") return if self.custom_option == '' or self.custom_option == None: QMessageBox.about(self, "WARNING", "Please select custom option for printing.") return ###add constraint to restrict one patient can only be one type curSubj = self.redcapExec.getInputPatient() df = pd.DataFrame.from_dict(curSubj) record = df.loc[df['record_id_dem_endo'] == str(int(self.subjectId))] if len(record) is 0 or None: QMessageBox.about( self, "WARNING", "--- Please create subject %s form first.\nPlease double check the Id in Redcap entry.\nThe Id should be in numeric format (i.e., 17, 20, 99), \nnot in 3-digit format (i.e., 017, 020, 099)" % str(self.subjectId)) return studyType_redcap = record.get('redcap_event_name').values if len(studyType_redcap) > 1: QMessageBox.about( self, "WARNING", "--- Please check subject %s Redcap data entry.\nOnly one category per patient is allowed.\nIf there is only one catogory has been selected" % str(self.subjectId)) return #"CD_ENDO", "CTL_ENDO", "CD_Surgery","CTL_Surgery" if studyType_redcap == 'cd_arm_1': studyType_checker = 'CD_ENDO' elif studyType_redcap == 'control_arm_1': studyType_checker = 'CTL_ENDO' elif studyType_redcap == 'cd_arm_2': studyType_checker = 'CD_Surgery' elif studyType_redcap == 'control_arm_2': studyType_checker = 'CTL_Surgery' if studyType_checker != self.studyType: print(studyType_redcap) QMessageBox.about( self, "WARNING", "Study type for subject %s does not match. Should it be %s?" % (str(self.subjectId), str(studyType_checker))) return # all set, ready to generate barcode pack barcodeExec = BarcodeGenerator(self.subjectId, self.studyType) barcodeExec.execute() #can optimize - done? nextAvailActionId = self.redcapExec.getNextAvailActionId() # new feature 12/19/2019 tmp_barcode_list = barcodeExec.get_barcode_list( self.custom_option) # More constraint before Christmas... #set generate action for tmp_barcode_id in tmp_barcode_list: if tmp_barcode_id == '': # no need to print continue ean8_code = barcodeExec.recordId_to_ean8(tmp_barcode_id) # generate ean8 code to make sure it matches our criteria if ean8_code is None: QMessageBox.about( self, "WARNING", "Something wrong with barcode id %s?" % (tmp_barcode_id)) return self.printLabel(tmp_barcode_id, ean8_code) # add barcode ean8 code self.redcapExec.setPrintedAction(nextAvailActionId, tmp_barcode_id, self.studyType, self.processed_by, self.action_comment, ean8_code, self.custom_option) nextAvailActionId += 1 bool_update_redcap_sophie = self.redcapExec.update_REDCAP_SOPHIE( self.studyType, str(int(self.subjectId)), tmp_barcode_list, self.custom_option) self.plain_comment.clear() curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.appendPlainText( "\n\n%s\nGenerate new pack for subject %s DONE!\nCustom option:%s\n Printing may takes time, please be patient.\nTotal barcodes to print: %s" % (str(cur_date), str(self.subjectId), str( self.custom_option), str(len(tmp_barcode_list)))) self.cb_option_type.setCurrentIndex(0) self.plain_console.repaint() self.plain_console.moveCursor(QTextCursor.End)
def printExtraFrozenOnly(self): """ Generate and print new pack of barcodes """ self.getGUIFieldValue() if self.subjectId == '' or self.subjectId == None: QMessageBox.about( self, "WARNING", "Subject id is empty. Print extra frozen specimen for subject %s failed." % str(self.subjectId)) return if len(self.subjectId) != 3: QMessageBox.about( self, "WARNING", "Subject id should be three digit. Please double-check") return if self.studyType == '' or self.studyType == None: QMessageBox.about( self, "WARNING", "Study type is empty. Generate / Print new pack for subject %s failed." % str(self.subjectId)) return if self.processed_by == '' or self.processed_by == None: QMessageBox.about(self, "WARNING", "Please select current user.") return curSubj = self.redcapExec.getInputPatient() df = pd.DataFrame.from_dict(curSubj) record = df.loc[df['record_id_dem_endo'] == str(int(self.subjectId))] if len(record) is 0 or None: QMessageBox.about( self, "WARNING", "---(1)Please create subject %s form first.\n(2)Please double check the Id in Redcap entry.\nThe Id should be in numeric format (i.e., 17, 20, 99), \nnot in 3-digit format (i.e., 017, 020, 099)\n(3)In Redcap, please check if you choose a category" % str(self.subjectId)) return studyType_redcap = record.get('redcap_event_name').values #"CD_ENDO", "CTL_ENDO", "CD_Surgery","CTL_Surgery" if studyType_redcap == 'cd_arm_1': studyType_checker = 'CD_ENDO' elif studyType_redcap == 'control_arm_1': studyType_checker = 'CTL_ENDO' elif studyType_redcap == 'cd_arm_2': studyType_checker = 'CD_Surgery' elif studyType_redcap == 'control_arm_2': studyType_checker = 'CTL_Surgery' if studyType_checker != self.studyType: print(studyType_redcap) QMessageBox.about( self, "WARNING", "Study type for subject %s does not match. Should it be %s?" % (str(self.subjectId), str(studyType_checker))) return ###add constraint to restrict one patient can only be one type self.custom_option = self.redcapExec.getIfFreshNeedOrNot( self.subjectId) if self.custom_option == '' or self.custom_option == None: QMessageBox.about( self, "WARNING", "Subject %s id not found. Print new pack first" % str(self.subjectId)) return barcodeExec = BarcodeGenerator(self.subjectId, self.studyType) #can optimize - done? nextAvailActionId = self.redcapExec.getNextAvailActionId() tmp_barcode_list = barcodeExec.get_extra_frozen_barcode_list( ) # a hack way to get ADD frozen id only #set generate action for tmp_barcode_id in tmp_barcode_list: if tmp_barcode_id == '': # no need to print continue ean8_code = barcodeExec.recordId_to_ean8(tmp_barcode_id) # generate ean8 code to make sure it matches our criteria if ean8_code is None: QMessageBox.about( self, "WARNING", "Something wrong with barcode id %s?" % (tmp_barcode_id)) return self.printLabel(tmp_barcode_id, ean8_code) # add barcode ean8 code self.redcapExec.setPrintedAction(nextAvailActionId, tmp_barcode_id, self.studyType, self.processed_by, self.action_comment, ean8_code, self.custom_option) nextAvailActionId += 1 bool_update_redcap_sophie = self.redcapExec.update_REDCAP_SOPHIE_EXTRA_FROZEN( self.studyType, str(int(self.subjectId)), tmp_barcode_list, self.custom_option) self.plain_comment.clear() curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.appendPlainText( "\n\n%s\nGenerate Extra Frozen Barcodes IDs for subject %s DONE! Printing may takes time, please be patient.\nTotal barcodes to print: %s" % (str(cur_date), str(self.subjectId), str(len(tmp_barcode_list)))) self.cb_option_type.setCurrentIndex(0) self.plain_console.repaint() self.plain_console.moveCursor(QTextCursor.End)
def set_scanned_id(self, scanned_id): """ Convert ean8 id to real barcode id """ barcodeExec = BarcodeGenerator() # hacking in case the input code is GCA blabla blabla # tmp_barcode_id = '' # hacking because location app does not have self.subject field if scanned_id[0:3] == 'GCA': self.barcode_id = self.stringUpperLowerHack(scanned_id) else: if barcodeExec.is_valid(str(scanned_id)) is False: QtWidgets.QMessageBox.about( Form, "WARNING", "Barcode is not valid(1). Please contact to administrator") #self.plain_console.repaint() self.plain_console_repaint() return False tmp_barcode_id = barcodeExec.ean8_to_recordId(scanned_id) if tmp_barcode_id is None: QtWidgets.QMessageBox.about( Form, "WARNING", "Barcode is not valid(2). Please contact to administrator") #self.plain_console.repaint() self.plain_console_repaint() return False # set GUI self.barcode_id = tmp_barcode_id self.subjectId = self.barcode_id[3:6] self.redcapExec.getBarcodeSubset_StudyType_Action_CustomOption( ) # for one time query... tmp_study_type, tmp_action_type, tmp_custom_option = self.redcapExec.getSubjectLastestActionAndCustomOption( self.barcode_id, self.subjectId) if tmp_custom_option is False: QtWidgets.QMessageBox.about( Form, "WARNING", "Barcode %s is not found \n\n " % str(self.barcode_id)) return False # initialize barcodeExec class variables barcodeExec._subject_id = self.subjectId barcodeExec._studyType = tmp_study_type # self.textbox_barcode_id.setText(self.barcode_id) self.fillScannedBarcodeToTable(self.barcode_id) nextAvailActionId = self.redcapExec.getNextAvailActionId() # once we confirmed the input id exists, we can safely convert the id to ean8 code. # This is only for manually input... if scanned_id[0:3] == 'GCA': scanned_id = barcodeExec.recordId_to_ean8(self.barcode_id) self.redcapExec.setScannedAction(nextAvailActionId, self.barcode_id, tmp_study_type, self.processed_by, self.plain_comment.toPlainText(), scanned_id, tmp_custom_option) curTime = datetime.now() curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.append( "\n\n%s\nSet barcode %s scanned status DONE!" % (str(cur_date), str(self.barcode_id))) self.plain_console_repaint() return True
def locationSync(self): """ Function to distribute, store the barcode. We can set the action based on barcode ID. """ to_import = [] self.autofillForm() self.getGUIFieldValue() col_barcode_id = 0 col_freezer = 1 col_rack = 2 col_box_id = 3 col_box_pos = 4 self.redcapExec.getBarcodeSubset_StudyType_Action_CustomOption( ) # for one time query... for row in range(0, self.total_rows): tmpBarcodeId = self.tableWidget_Group.item(row, col_barcode_id).text() if tmpBarcodeId is not "" and tmpBarcodeId is not None: # get subject_id tmpBarcodeSubjectId = tmpBarcodeId[3:6] tmpLocationTuple = [ self.tableWidget_Group.item(row, col_barcode_id).text(), self.tableWidget_Group.item(row, col_freezer).text(), self.tableWidget_Group.item(row, col_rack).text(), self.tableWidget_Group.item(row, col_box_id).text(), self.tableWidget_Group.item(row, col_box_pos).text() ] tmpSubjStudyType, tmp_action_type, tmp_custom_option = self.redcapExec.getSubjectLastestActionAndCustomOption( tmpBarcodeId, tmpBarcodeSubjectId) barcodeExec = BarcodeGenerator(tmpBarcodeSubjectId, tmpSubjStudyType) ean8_code = barcodeExec.recordId_to_ean8(tmpBarcodeId) if 'destroyed' in tmp_action_type: reply = QtWidgets.QMessageBox.question( Form, u'destroy barcode', u'Barcode %s should be destroyed, location sync failed...' % str(tmpBarcodeId), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.No: continue if 'rack' in tmp_action_type: reply = QtWidgets.QMessageBox.question( Form, u'destroy barcode', u'Barcode %s should be storaged, do you want to store it again?' % str(tmpBarcodeId), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.No: continue if 'Lau' in tmp_action_type or 'TPSR' in tmp_action_type or 'Vantage' in tmp_action_type: reply = QtWidgets.QMessageBox.question( Form, u'destroy barcode', u'Barcode %s should be distributed, do you want to distribute it again?' % str(tmpBarcodeId), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.No: continue nextAvailActionId = self.redcapExec.getNextAvailActionId() tmpActionType = '' if 'SR' in tmpBarcodeId: tmpActionType = 'Serum stored in rack' elif 'ST' in tmpBarcodeId: tmpActionType = 'Stool stored in rack' elif 'Frozen' in tmpBarcodeId: tmpActionType = 'Frozen stored in rack' elif 'Fresh' in tmpBarcodeId: tmpActionType = 'Fresh distributed to Lau' elif 'DNA' in tmpBarcodeId: tmpActionType = 'DNA distributed to Vantage. Relevant DNA field will be filled manually.' elif 'Fixed' in tmpBarcodeId: tmpActionType = 'Fixed distributed to TPSR. Relevant Fixed specimen field will be filled manually.' # currently we don't have add comment field.... need to add in future.... # update barcode redcap form :-) self.redcapExec.execLocationAppSync( nextAvailActionId, tmpBarcodeId, tmpSubjStudyType, self.processed_by, tmpActionType, tmpLocationTuple, self.plain_comment.toPlainText(), ean8_code, tmp_custom_option) # only update for # (1) SR # (2) ST # (3) Frozen # (4) Fresh - distribute to lau and update the table # (5) - (6) fixed need to update the table tmpRackSophie = '' if self.tableWidget_Group.item(row, col_rack).text() == 'A': tmpRackSophie = '1' elif self.tableWidget_Group.item(row, col_rack).text() == 'B': tmpRackSophie = '2' elif self.tableWidget_Group.item(row, col_rack).text() == 'C': tmpRackSophie = '3' tmpLocationTuple = [ self.tableWidget_Group.item(row, col_barcode_id).text(), '1', # always freezer c tmpRackSophie, self.tableWidget_Group.item(row, col_box_id).text(), self.tableWidget_Group.item(row, col_box_pos).text() ] self.redcapExec.update_REDCAP_SOPHIE_FROM_LOCATION_APP( str(int(tmpBarcodeSubjectId)), tmpBarcodeId, tmpSubjStudyType, tmpLocationTuple) # to be continued. - DONE? curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.append("\n%s\nsync Barcode list DONE!" % (str(cur_date))) #self.plain_console.repaint() self.plain_console_repaint()
def destroyBarcode(self): to_import = [] col_barcode_id = 0 self.redcapExec.getBarcodeSubset_StudyType_Action_CustomOption( ) # for one time query... for row in range(0, self.total_rows): tmpBarcodeId = self.tableWidget_Group.item(row, col_barcode_id).text() if tmpBarcodeId is not "": # get subject_id tmpBarcodeSubjectId = tmpBarcodeId[3:6] # remove for reduce duplicate query... tmpSubjStudyType, tmp_action_type, tmp_custom_option = self.redcapExec.getSubjectLastestActionAndCustomOption( tmpBarcodeId, tmpBarcodeSubjectId) # get subject study type, action type and custom options for current action records input barcodeExec = BarcodeGenerator(tmpBarcodeSubjectId, tmpSubjStudyType) ean8_code = barcodeExec.recordId_to_ean8(tmpBarcodeId) # the barcode has already been destroyed if 'destroyed' in tmp_action_type: reply = QtWidgets.QMessageBox.question( Form, u'destroy barcode', u'Barcode %s should be destroyed, do you want to destroy it again?' % str(tmpBarcodeId), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.No: continue # the barcode has already been storaged if 'rack' in tmp_action_type: reply = QtWidgets.QMessageBox.question( Form, u'destroy barcode', u'Barcode %s should be storaged, do you want to destroy it?' % str(tmpBarcodeId), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.No: continue # the barcode has already been distributed if 'Lau' in tmp_action_type or 'TPSR' in tmp_action_type or 'Vantage' in tmp_action_type: reply = QtWidgets.QMessageBox.question( Form, u'destroy barcode', u'Barcode %s should be distributed, do you want to destroy it?' % str(tmpBarcodeId), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.No: continue nextAvailActionId = self.redcapExec.getNextAvailActionId() tmpActionType = 'Barcode destroyed' # currently we don't have add comment field.... need to add in future.... # update my valuable barcode redcap form :-) self.redcapExec.destroyBarcode( nextAvailActionId, tmpBarcodeId, tmpSubjStudyType, self.processed_by, tmpActionType, self.plain_comment.toPlainText(), ean8_code, tmp_custom_option) self.redcapExec.destroy_REDCAP_SOPHIE_FROM_LOCATION_APP( str(int(tmpBarcodeSubjectId)), tmpBarcodeId, tmpSubjStudyType) curTime = datetime.now() cur_date = curTime.strftime('%Y-%m-%d %H:%M') self.plain_console.append("\n%s\nDestroy Barcode %s DONE!" % (str(cur_date), str(tmpBarcodeId))) #self.plain_console.repaint() self.plain_console_repaint()