Files
x06da/script/data/samples.py
alexgobbo ba17725e75 V2
2025-09-12 16:16:15 +02:00

423 lines
15 KiB
Python

import json
import re
import org.python.core.PyDictionary as PyDictionary
SAMPLE_INFO_KEYS = ["userName", "dewarName", "puckName", "puckBarcode", "puckType", "puckAddress",
"sampleName", "samplePosition", "sampleBarcode", "sampleStatus", "sampleMountCount"]
samples_info = []
def set_samples_info(info):
global samples_info
if (is_string(info)):
if info:
info = json.loads(info)
else:
info=[]
if not is_list(info):
raise Exception("Sample info must be a list (given object type is " + str(type(info)) + ")")
#Sanitize list
remove = []
for sample in info:
try:
if set(sample.keys()) != set(SAMPLE_INFO_KEYS):
raise Exception()
except:
remove.append(sample)
for el in remove:
info.remove(el)
print "Invalid samples info element: " + str(el)
samples_info = info
save_samples_info()
#Trust beamline on assignments, so update puck info
update_puck_table()
def clear_samples_info():
set_samples_info([])
def save_samples_info():
data = get_samples_info(True)
output_file = open( Setup.expandPath("{context}/samples_info.json") , "w")
output_file.write(data)
output_file.close()
get_sequencer().sendEvent("samples_updated", True)
save_puck_info()
def restore_samples_info():
restore_puck_info()
try:
inputfile = open(Setup.expandPath("{context}/samples_info.json"), "r")
info = inputfile.read()
except:
print >> sys.stderr, "Error reading sample info file: " + str(sys.exc_info()[1])
info = []
set_samples_info(info)
def get_samples_info(as_json=True):
global samples_info
return json.dumps(to_list(samples_info)) if as_json else samples_info
def has_puck_datamatrix(datamatrix):
if samples_info is not None:
for si in samples_info:
if si["puckBarcode"] == datamatrix:
return True
return False
def add_puck_datamatrix(barcode, address = "", dewar = "Unknown", user = "Unknown", puck = "Unknown", type = "unipuck", sample_prefix = "Sample"):
if has_puck_datamatrix(barcode):
raise Exception("Datamatrix already defined: " + str(barcode))
for s in range(1,17):
info = \
{ "userName": user, \
"dewarName": dewar, \
"puckName": puck, \
"puckBarcode": address if barcode is None else barcode, \
"puckType": type, \
"puckAddress": address,\
"sampleName": sample_prefix + " " + str(s), \
"samplePosition": str(s),\
"sampleStatus": "Unknown", \
"sampleMountCount": "0",
}
samples_info.append(info)
save_samples_info()
def remove_puck_datamatrix(barcode):
remove = []
for si in samples_info:
if si["puckBarcode"] == barcode:
remove.append(si)
for el in remove: samples_info.remove(el)
save_samples_info()
barcode_clean_re = re.compile("[^a-zA-Z0-9]")
def is_same_datamatrix(table, reading, do_log=True):
if table == reading:
return True
table2 = barcode_clean_re.sub("", table.upper())
reading2 = barcode_clean_re.sub("", reading.upper())
if table2 == reading2:
if do_log:
log("Assigning aproximative datamatrix " + reading )
return True
return False
def set_puck_datamatrix(puck, datamatrix):
if puck is None:
puck = ""
if datamatrix is None:
datamatrix = ""
if samples_info is not None:
for si in samples_info:
#if si["puckBarcode"] == datamatrix:
if is_same_datamatrix(si["puckBarcode"],datamatrix):
si["puckAddress"] = puck
elif si["puckAddress"] == puck:
si["puckAddress"] = ""
save_samples_info()
def reset_puck_datamatrix(puck = None):
if samples_info is not None:
for si in samples_info:
if (si["puckAddress"] == puck) or (puck is None):
si["puckAddress"] = ""
save_samples_info()
for p in BasePlate.getChildren():
if (p.name == puck) or (puck is None):
p.id = None
def get_puck_datamatrix():
ret = {}
for si in samples_info:
if si["puckBarcode"] is not None and si["puckBarcode"]!="":
ret[si["puckBarcode"]] = si["puckAddress"]
return ret
def get_puck_from_datamatrix(datamatrix, use_puck_detection=True):
try:
if use_puck_detection:
detected_pucks = get_puck_info("Present") #
for puck in detected_pucks:
address = str(puck['address'])
barcode = str(puck['barcode'])
if barcode and barcode != str(None):
if is_same_datamatrix(barcode,datamatrix):
return address
for dm,puck in get_puck_datamatrix().items():
if is_same_datamatrix(dm,datamatrix):
return puck
except:
pass
return None
def get_puck_datamatrix_info(use_puck_detection=True):
ret = {}
for si in samples_info:
if si["puckBarcode"] is not None and si["puckBarcode"]!="":
info = {}
info["address"] = si["puckAddress"]
info["dewar"] = si ["dewarName"]
info["name"] = si ["puckName"]
info["user"] = si ["userName"]
info["type"] = si ["puckType"]
ret[si["puckBarcode"]] = info
if use_puck_detection:
detected_pucks = get_puck_info("Present") #
for p in detected_pucks:
address = str(p['address'])
barcode = str(p['barcode'])
if barcode and barcode != str(None):
insert = True
for id,info in ret.items():
add = info["address"]
if is_same_datamatrix(barcode, id, False):
insert = False
if str(add).strip() != address:
log("Apdating address from DM info: " + add )
for entry in ret.values():
if str(entry['address']).strip() == address:
entry['address']=""
info["address"] = address
break
#Different address:
if insert:
info = {}
info["address"] = address
info["dewar"] = ""
info["name"] = ""
info["user"] = ""
info["type"] = ""
ret[barcode] = info
return ret
def get_puck_address(barcode):
try:
return get_puck_datamatrix()[barcode]
except:
return None
def get_puck_address(barcode):
try:
return get_puck_datamatrix()[barcode]
except:
return None
def update_puck_table():
dms = get_puck_datamatrix()
for barcode in dms.keys():
address = dms[barcode]
puck = get_puck_obj(address)
if puck is not None:
puck.id = barcode
#Sample mount/unmount
def same_address(puck_add_1, sample_pos_1, puck_add_2, sample_pos_2):
if str(puck_add_1) != str(puck_add_2):
return False
try:
sample_pos_1 = int(sample_pos_1)
except:
return False
try:
sample_pos_2 = int(sample_pos_2)
except:
return False
return sample_pos_1 == sample_pos_2
def update_samples_info_sample_mount(puck_address, sample_position, sample_detected, sample_id):
try:
if (samples_info is not None) and (puck_address is not None):
for si in samples_info:
if same_address( si["puckAddress"], si["samplePosition"], puck_address, sample_position):
if sample_detected:
if si["sampleStatus"] != "Mounted":
si["sampleStatus"] = "Mounted"
try:
mount_count = int(si["sampleMountCount"])
except:
mount_count = 0
si["sampleMountCount"] = mount_count + 1
else:
si["sampleStatus"] = "Unknown"
if sample_id is not None:
si["sampleBarcode"] = sample_id
else:
if si["sampleStatus"] == "Mounted":
si["sampleStatus"] = "HasBeenMounted"
save_samples_info()
except:
pass
def update_samples_info_sample_unmount(puck_address, sample_position):
try:
if (samples_info is not None) and (puck_address is not None):
for si in samples_info:
if same_address( si["puckAddress"], si["samplePosition"], puck_address, sample_position):
si["sampleStatus"] = "HasBeenMounted"
save_samples_info()
return
except:
pass
def update_samples_info_sample_scan(puck_address, sample_position, sample_detected, sample_id):
try:
if (samples_info is not None) and (puck_address is not None):
for si in samples_info:
if same_address( si["puckAddress"], si["samplePosition"], puck_address, sample_position):
if sample_detected:
if si["sampleStatus"] == "Unknown":
si["sampleStatus"] = "Present"
else:
if si["sampleStatus"] == "Present":
si["sampleStatus"] = "Unknown"
if sample_id is not None:
si["sampleBarcode"] = sample_id
save_samples_info()
return
except:
pass
test_sample_data = [ \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0001", \
"puckType": "unipuck", \
"puckAddress": "A1",\
"sampleName": "MySample 1", \
"samplePosition": 1,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0001", \
"puckType": "unipuck", \
"puckAddress": "A1",\
"sampleName": "MySample 2", \
"samplePosition": 2,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0001", \
"puckType": "unipuck", \
"puckAddress": "A1",\
"sampleName": "MySample 3", \
"samplePosition": 3,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0001", \
"puckType": "unipuck", \
"puckAddress": "A1",\
"sampleName": "MySample 4", \
"samplePosition": 4,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0001", \
"puckType": "unipuck", \
"puckAddress": "A1",\
"sampleName": "MySample 5", \
"sampleBarcode": "", \
"samplePosition": 5,\
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0002", \
"puckType": "unipuck", \
"puckAddress": "C2",\
"sampleName": "MySample 1", \
"samplePosition": 1,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0002", \
"puckType": "unipuck", \
"puckAddress": "C2",\
"sampleName": "MySample 2", \
"samplePosition": 2,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0002", \
"puckType": "unipuck", \
"puckAddress": "C2",\
"sampleName": "MySample 3", \
"samplePosition": 3,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0002", \
"puckType": "unipuck", \
"puckAddress": "C2",\
"sampleName": "MySample 4", \
"samplePosition": 4,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
{ "userName": "Alexandre", \
"dewarName": "TEST", \
"puckName": "My puck", \
"puckBarcode": "AAA0002", \
"puckType": "unipuck", \
"puckAddress": "C2",\
"sampleName": "MySample 5", \
"samplePosition": 5,\
"sampleBarcode": "", \
"sampleStatus": "Present", \
"sampleMountCount": 0,
} , \
]