| 1 | # -----------------------------------------------------------------------------
|
|---|
| 2 | # Place copies of a Chimera model (volume data, molecular structure, ...)
|
|---|
| 3 | # read from a file at positions and orientations specified in a file.
|
|---|
| 4 | #
|
|---|
| 5 | # Run this with the Chimera 1.4 "runscript" command like
|
|---|
| 6 | #
|
|---|
| 7 | # runscript place.py virus.mrc positions.txt
|
|---|
| 8 | #
|
|---|
| 9 | # where the arguments are a path to data file, and a path to a text file
|
|---|
| 10 | # containing placements specified as 3 by 4 matrices with the first 3 columns
|
|---|
| 11 | # being a rotation and the 4th column being a translation.
|
|---|
| 12 | #
|
|---|
| 13 | # An example positions file containing two positions
|
|---|
| 14 | # z-rotation 30 degrees, x-shift 10 Angstroms
|
|---|
| 15 | # z-rotation -90 degrees, y-shift 5 Angstroms
|
|---|
| 16 | # looks like:
|
|---|
| 17 | #
|
|---|
| 18 | # .866 .5 0 10
|
|---|
| 19 | # -.5 .866 0 0
|
|---|
| 20 | # 0 0 1 0
|
|---|
| 21 | #
|
|---|
| 22 | # 0 -1 0 0
|
|---|
| 23 | # 1 0 0 5
|
|---|
| 24 | # 0 0 1 0
|
|---|
| 25 | #
|
|---|
| 26 | # Each 3 lines specifies one placement.
|
|---|
| 27 | #
|
|---|
| 28 | def parse_arguments():
|
|---|
| 29 |
|
|---|
| 30 | from Midas import MidasError as e
|
|---|
| 31 | if not 'arguments' in globals():
|
|---|
| 32 | raise e, 'Use runscript command to pass file arguments to place.py'
|
|---|
| 33 |
|
|---|
| 34 | if len(arguments) != 2:
|
|---|
| 35 | raise e, 'place.py requires 2 arguments, model and position file paths'
|
|---|
| 36 |
|
|---|
| 37 | model_path, pos_path = arguments
|
|---|
| 38 | from os.path import isfile
|
|---|
| 39 | if not isfile(model_path) or not isfile(pos_path):
|
|---|
| 40 | raise e, 'place.py model or position file does not exist'
|
|---|
| 41 |
|
|---|
| 42 | return model_path, pos_path
|
|---|
| 43 |
|
|---|
| 44 | # -----------------------------------------------------------------------------
|
|---|
| 45 | #
|
|---|
| 46 | def read_positions(pos_path):
|
|---|
| 47 |
|
|---|
| 48 | matrices = [[]]
|
|---|
| 49 | f = open(pos_path,'r')
|
|---|
| 50 | from Midas import MidasError as e
|
|---|
| 51 | for line in f.readlines():
|
|---|
| 52 | l = line.strip()
|
|---|
| 53 | if l and l[0] != '#':
|
|---|
| 54 | try:
|
|---|
| 55 | row = [float(x) for x in l.split()]
|
|---|
| 56 | except ValueError:
|
|---|
| 57 | raise e, "place.py position file '%s' contains a non-numeric value: '%s'" % (pos_path, l)
|
|---|
| 58 | if len(row) != 4:
|
|---|
| 59 | raise e, "place.py position file '%s' contains a line that does not have 4 values: '%s'" % (pos_path, l)
|
|---|
| 60 | if len(matrices[-1]) == 3:
|
|---|
| 61 | matrices.append([]) # New matrix
|
|---|
| 62 | matrices[-1].append(row) # Add row to matrix
|
|---|
| 63 | if len(matrices[-1]) != 3:
|
|---|
| 64 | raise e, "place.py position file '%s' has too few lines" % pos_path
|
|---|
| 65 | return matrices
|
|---|
| 66 |
|
|---|
| 67 | # -----------------------------------------------------------------------------
|
|---|
| 68 | #
|
|---|
| 69 | def place_volumes(model_path, matrices):
|
|---|
| 70 |
|
|---|
| 71 | from chimera import openModels as om
|
|---|
| 72 | models = [om.open(model_path)[0] for m in matrices]
|
|---|
| 73 | import Matrix
|
|---|
| 74 | for model, m in zip(models, matrices):
|
|---|
| 75 | xf = model.openState.xform
|
|---|
| 76 | xf.premultiply(Matrix.chimera_xform(m))
|
|---|
| 77 | model.openState.xform = xf
|
|---|
| 78 |
|
|---|
| 79 | # -----------------------------------------------------------------------------
|
|---|
| 80 | #
|
|---|
| 81 | model_path, pos_path = parse_arguments()
|
|---|
| 82 | matrices = read_positions(pos_path)
|
|---|
| 83 | place_volumes(model_path, matrices)
|
|---|