将@Ignacio Vazquez-Abrams 的回答再往前走几步。. .这里有两种方法:
- 适用于几乎任何尺寸的机架(行 X 列)
- 从 A1、B1 等风格的井位转换为数字位置和从数字位置转换。
@staticmethod
def convertNumericWellPosToA1Style(numericPos, contRows, contCols, colOrRowMajor, padWithZeros):
"""
Convert a numeric position to an A1 style position.
Parameters
----------
numericPos : int
Numeric well position to be converted.
contMaxRows : int
Max number of container rows.
contMaxCols : int
Max number of container cols.
colOrRowMajor : str
'col' or 'row' for column or row major addressing.
padWithZeros : bool
Whether to pad the numeric portion returned, with zeros or not.
i.e., A1 or A01
"""
if numericPos < 1:
raise ValueError("Container position value '" + str(numericPos) + "' must be 1 or greater.")
if contCols < 1:
raise ValueError("Container columns value '" + str(contCols) + "' must be 1 or greater.")
if contRows < 1:
raise ValueError("Container rows value '" + str(contRows) + "' must be 1 or greater.")
if numericPos > contCols * contRows:
raise ValueError("Container position value '" + str(numericPos) + "' exceeds the maximum container wells possible of '" + str(contCols * contRows) + "'.")
if colOrRowMajor == "row":
if padWithZeros:
return 'ABCDEFGH'[(numericPos - 1) // contCols] + '%02d' % ((numericPos - 1) % contCols + 1,)
else:
return 'ABCDEFGH'[(numericPos - 1) // contCols] + str((numericPos - 1) % contCols + 1)
elif colOrRowMajor == "col":
if padWithZeros:
return 'ABCDEFGH'[(numericPos - 1) % contRows] + '%02d' % (math.ceil(numericPos / contRows),)
else:
return 'ABCDEFGH'[(numericPos - 1) % contRows] + str(math.ceil(numericPos / contRows))
else:
raise ValueError("Container traversal value '" + colOrRowMajor + "' must be 'col' or 'row'.")
@staticmethod
def ConvertA1StylePositionToNumeric(A1StylePos : str, contRows : int, contCols : int, colOrRowMajor : str):
#Check for at least two chars
if len(A1StylePos) == 0:
raise ValueError("An empty A1 style well position can't be converted.")
if len(A1StylePos) == 1:
raise ValueError("At least 2 characters are required in an A1 style well position.")
#make upper case
A1StylePos = A1StylePos.upper()
colPart = 0
#get parts of the A1 style rack position
rowPart = A1StylePos.upper()[0:1]
if ord(rowPart) < 65 or ord(rowPart) > 90:
raise ValueError("The first character of the A1 style well position must be a letter A - Z.")
colPartAsString = A1StylePos[1:len(A1StylePos)]
if colPartAsString.isdigit():
colPart = int(colPartAsString)
else:
raise ValueError("The characters after the first character of the well position must be numeric.")
#error checking
if ord(A1StylePos[0]) < 65 or ord(A1StylePos[0]) > 90:
raise ValueError("The first character of the well position '" + A1StylePos + "' must be a character A through Z.")
if contCols < 1:
raise ValueError("Container columns value '" + str(contCols) + "' must be 1 or greater.")
if contRows < 1:
raise ValueError("Container rows value '" + str(contRows) + "' must be 1 or greater.")
if contRows > 26:
raise ValueError("Container rows value '" + str(contRows) + "' must not be greater than 26.")
if colPart > contCols:
raise ValueError("Well position value '" + A1StylePos + "' exceeds the maximum container columns possible of '" + str(contCols) + "'.")
if colPart < 1:
raise ValueError("Well position value '" + A1StylePos + "' must be 1 or greater.")
if (ord(rowPart) - 64) > contRows:
raise ValueError("Well position value '" + A1StylePos + "' refers to a well that exceeds the maximum container columns possible of '" + str(contCols) + "'.")
#convert
if colOrRowMajor == "col":
return (int)(((colPart - 1) * contRows) + (ord(rowPart) - 64))
elif colOrRowMajor == "row":
return (int)(((ord(rowPart) - 65) * contCols) + colPart);
else:
raise ValueError("Container traversal value '" + colOrRowMajor + "' must be 'col' or 'row'.")