マージする時や mtz ファイルを解釈する時など、与えられた指数を標準的な asymmetric unit 内の指数に変換する必要が生じる。もっとも単純なアルゴリズムは以下のとおり。
- あらかじめ点群における対称操作 を列挙しておく
- 与えられた指数 h に、上の対称操作を適用して、 を作る
- 指数のうち、asymmetric unit 内に入るもの(unique に決まる)を選ぶ
最初のステップは、単位元 E しかもたない点群 (P1) から初めて、生成子を1つずつ足していけばよい。CrystFEL での実装は symmetry.c の expand_ops() 関数 にある。
最後のステップは、愚直に行うと、asymmetric unit を点群ごとに定義しなければならず、煩雑に思える。1つの工夫としては、指数 に順序を入れることができる(単純に、h で大小比較し、h が同じなら k で大小比較し、それでも同じなら l で比較すればよい)ので、 の中から最小のものを選ぶことにすれば、それが1つの asymmetric unit となっている。CrystFEL の実装(symmetry.c の get_asymm() 関数) はこうなっている。一方、Clipper は、真面目に asymmetric unit を定義していて、asymmetric unit 内の指数を発見したらループを抜けるようになっている。
このアルゴリズムには O(n) の時間がかかる。気になる場合は、結果をキャッシュしておくとよい。また、フーリエ変換などでは、逆空間で隣接した指数に連続してアクセスすることが多い。この場合、隣り合う指数は同じ対称操作で asymmetric unit に落ちることが多いので、前回採用された操作を覚えておいて、それを優先的に試すようにすると効率的である。Clipper はこのテクニックを使っている(Clipper: Developing using Reflection Data 参照)。