#!/usr/bin/python -tt # # Dominik Neise # import os.path import numpy as np import math from euclid import * import sys class Coordinator(object): """ class to transform chid <-> hexagonal coordinates and vice versa """ def __init__(self, map_file_path = "../map.txt"): """ read map text file and generate from the three columns chid, xe and ye 3 dictionaries: chid2coor, coor2chid, chid2nn chid2nn means 'chid_to_next_neighbor_chids' this is done by calculating the hexagonal coordinates from the euclidian coordinates given in xe & ye. the center and the two base vectors are hard coded to be: center = Vector2( 0. , 1./2.) ey = Vector2( 0. , 1. ) ex = Vector2( sqrt(3)/2. , 1./2. ) """ _CheckPath(map_file_path) path = os.path.abspath(__file__) path = os.path.dirname(path) map_file_path = os.path.join(path, map_file_path) chid, xe, ye = np.loadtxt(map_file_path, unpack=True) # -ye in order to correct for the sign difference between my mapping file # and FACTmap111030.txt self.x = xe self.y = ye coors = zip(xe,-ye,chid) # this list will contain vectors pointing to the center of pixel # in euclidian space. The coordinate system is in the focalplane of the # camera, the unit is not mm, but something like 9mm. # actually the list will not only contain these vectors, but also # also the CHID of the according pixel, both bundled in a tuple vectors_and_chids = [] for c in coors: vectors_and_chids.append( (Vector2(c[0], c[1]) , int(c[2])) ) # In the next few lines, I will calculate hexagonal coordinates from # the euclidian coordinates. The reason is, that I like to work with # integers. # I could have read these numbers from a file instead of calculating, # but this is error prone, because one has to make sure, the different # coordinates in a file are always conincident. # The center of the coordinate system is not 0. / 0. since there # is not pixel :-) We decided to define the upper one of the two # central pixels, as 'The Center' :-) center = Vector2( 0. , 1./2.) # the y-axis goes up ey = Vector2( 0. , 1. ) # but the x-axis is turned 30degrees up, wrt the euclidian x-axis. ex = Vector2( math.sqrt(3)/2. , 1./2. ) self.center = ( center.x , center.y ) self.ey = ( ey.x, ey.y) self.ex = ( ex.x, ex.y ) # these dicts will serve as translators, # e.g. put a chid into chid2coor and you get a Vector2 out, which points # to the center of the according pixel. coor2chid = {} chid2coor = {} chid2coor_np = {} chid2vec = {} euc2chid = {} # we will fill these translators now. for vector_and_chid in vectors_and_chids: vec = vector_and_chid[0] chid = vector_and_chid[1] # translating from euclidian into hexagonal # coordinates here... x = (vec-center).x / float(ex.x) y = ((vec-center)-x*ex).y / float(ey.y) # I want them to be integger, so I think I have to # treat the values, which are almost zero special, # but maybe rounding is just sufficient, as it is done # in the line after these... if abs(x) < 0.01: x=0.0 if abs(y) < 0.01: y=0.0 # okay, now coor, is the hexagonal coordinate pair of the current pixel # as a tuple coor = (int(round(x)),int(round(y))) # as Vector2 coor_vec = Vector2(coor[0], coor[1]) # since we just calculated this coordinate, we should make # sure, that we did not make an error such, that two pixels have the # same coordinates # other errors like holes in the camera plane cannot be detected so easily if coor in coor2chid: print 'error while filling "coor2chid":' print 'coor:',coor,'of chid:',chid, print 'is equal to coor of chid:',coor2chid[coor] # now we fill the translators chid2coor[ chid ] = coor chid2coor_np[ chid ] = np.array(coor) chid2vec[ chid ] = coor_vec # this translator is hardly used by people, but the next step # the calculation of the neighbors needs it coor2chid[ coor ] = chid euc2chid[(vec[0],vec[1])] = chid # hard code the offsets to the next neighbors # in hexagonal coordinates, the coordinates of neighbors are easily calculated. # just add one of the Vectors below. offsets = [ Vector2(1,0) , # right and up Vector2(-1,0) , # left and down Vector2(1,-1) , # right and down Vector2(0,1) , # up Vector2(0,-1) , # down Vector2(-1,1) ] # left and up # this dict serves as a neighbor look up table # put a CHID in and get a list of neighboring CHIDs out. chid2nn = {} for chid in chid2coor.keys(): coor = Vector2( chid2coor[chid][0] , chid2coor[chid][1] ) nn_coors = [] nn_chids = [] for offset in offsets: nn_coors.append( ((coor+offset).x , (coor+offset).y) ) for coor in nn_coors: if coor in coor2chid: nn_chids.append( coor2chid[coor] ) chid2nn[chid] = nn_chids self.nn = chid2nn self.chid2coor = chid2coor self.chid2coor_np = chid2coor_np self.coor2chid = coor2chid self.chid2vec = chid2vec self.euc2chid = euc2chid # for chid in chid2nn.keys(): # print chid, '->',chid2nn[chid] def first(a): return a[0] def second(a): return a[1] def _CheckPath( inpath ): path = os.path.abspath(__file__) path = os.path.dirname(path) inpath = os.path.join(path, inpath) if not os.path.isfile(inpath): raise IOError('not able to find file: '+inpath)