def process_message(self, in_msg): msg_type = in_msg.GetHeader().msg_type if msg_type == rc.MT_POLARIS_POSITION: # handling input message in_mdf = rc.MDF_POLARIS_POSITION() copy_from_msg(in_mdf, in_msg) positions = np.array(in_mdf.xyz[:]) orientations = self.shuffle_q(np.array(in_mdf.ori[:])) # np.testing.assert_array_equal(positions[:,0], orientations[:,0], err_msg='Samples are not aligned') if self.calibrated: if in_mdf.tool_id == (self.marker + 1): # calculating output self.Qk = qa.norm( orientations ) # need to find a way to discriminate the tools files in the messages??? Qr = qa.mult(self.Qk, qa.inv(self.Qi)).flatten() Tk = positions hotspot_position = (qa.rotate(Qr, self.Xi) + Tk).flatten() hotspot_vector_head = qa.rotate(Qr, plate_vector) if np.any(np.isnan(hotspot_position)) == True: print "x", # print ' *****nan present, check coil is within frame!*****' # creating output message out_mdf = rc.MDF_HOTSPOT_POSITION() out_mdf.xyz[:] = hotspot_position out_mdf.ori[:3] = hotspot_vector_head # Qk - coil active orientation out_mdf.sample_header = in_mdf.sample_header msg = CMessage(rc.MT_HOTSPOT_POSITION) copy_to_msg(out_mdf, msg) self.mod.SendMessage(msg) sys.stdout.write("o") else: if np.any(np.isnan(positions)) == True: raise Exception, "nan present" if np.any(np.isnan(orientations)) == True: raise Exception, "nan present" if ( (self.store_plate >= self.store_plate_pos.shape[0]) & (self.store_plate >= self.store_plate_ori.shape[0]) & (self.store_coil >= self.store_coil_pos.shape[0]) & (self.store_coil >= self.store_coil_ori.shape[0]) ): self.calibrating = False self.make_calibration_vector() elif in_mdf.tool_id == (self.marker + 1): self.store_coil_pos[self.store_coil, :] = positions self.store_coil_ori[self.store_coil, :] = orientations self.store_coil += 1 elif in_mdf.tool_id == (self.plate + 1): self.store_plate_pos[self.store_plate, :] = positions self.store_plate_ori[self.store_plate, :] = orientations self.store_plate += 1
def sim2(fp, freq, borequats, hwpang, hits, alps, inpp=None, hwprate=88.0, outdir = ''): nsim = borequats.shape[0] nhpix = hits.shape[0] nside = int(np.sqrt(nhpix / 12)) if nhpix != 12*nside*nside: raise RuntimeError('invalid healpix nside value') if hwpang.shape[0] != borequats.shape[0]: raise RuntimeError('HWP angle vector must be same length as boresight quaternions') if inpp is not None: if inpp.shape[0] != nhpix: raise RuntimeError('N_pp^-1 number of pixels must match N_hits') if inpp.shape[1] != 6: raise RuntimeError('N_pp^-1 must have 6 elements per pixel') xaxis = np.array([1,0,0], dtype=np.float64) yaxis = np.array([0,1,0], dtype=np.float64) zaxis = np.array([0,0,1], dtype=np.float64) # generate hitcount map and alpha for i, det in enumerate(fp.detectors(freq=freq)): detrot = qa.mult(borequats, fp.quat(det)) detdir = qa.rotate(detrot, np.tile(zaxis, nsim).reshape(-1,3)) dettheta, detphi = hp.vec2ang(detdir) detpix = hp.vec2pix(nside, detdir[:,0], detdir[:,1], detdir[:,2]) detbinned = np.bincount(detpix) hits[0:detbinned.shape[0]] += detbinned[:] outfile = os.path.join(outdir, 'theta.bin') with open(outfile, 'wb') as f: dettheta.tofile(f) outfile = os.path.join(outdir, 'phi.bin') with open(outfile, 'wb') as f: detphi.tofile(f) outfile = os.path.join(outdir, 'pix.bin') with open(outfile, 'wb') as f: detpix.tofile(f) if np.mod(i,2)!=1: alpdir = qa.rotate(detrot, np.tile(xaxis, nsim).reshape(-1,3)) x = alpdir[:,0]*detdir[:,1] - alpdir[:,1]*detdir[:,0] y = alpdir[:,0]*(-detdir[:,2]*detdir[:,0]) + alpdir[:,1]*(-detdir[:,2]*detdir[:,1]) + alpdir[:,2]*(detdir[:,0]*detdir[:,0]+detdir[:,1]*detdir[:,1]) angle = np.arctan2(y,x) outfile = os.path.join(outdir, 'angle.bin') with open(outfile, 'wb') as f: angle.tofile(f)
def test_calibration(self, axis): if self.calibration_loaded: self.pointer_test = np.zeros((250, 3)) self.headP_test = np.zeros((250, 3)) self.headQ_test = np.zeros((250, 4)) self.Ptest_count = 0 self.Gtest_count = 0 self.status = True self.testing = True test_result = np.zeros((250, 3)) print 'doing calculations' for i in np.arange(250): cz_pos, rot = self.glasses_to_cz.get_pos( self.headQ_test[i], self.headP_test[i]) test_result[i] = qa.rotate( rot, qa.rotate(self.calibration_matrix, (self.pointer_test[i] - cz_pos))) print 'complete' if axis == 'x': diff = np.diff(test_result[~np.isnan(test_result).any(axis=1), 0], axis=0) if np.any(diff < 0): return False else: return True if axis == 'y': diff = np.diff(test_result[~np.isnan(test_result).any(axis=1), 1], axis=0) if np.any(diff < 0): return False else: return True if axis == 'z': diff = np.diff(test_result[~np.isnan(test_result).any(axis=1), 2], axis=0) if np.any(diff < 0): return False else: return True self.status = False self.testing = False
def compute_psi_dx8(self, theta, phi, rad): z = np.dot(self.siam.get(rad),[0, 0, 1]) vecz = qarray.norm(qarray.rotate(self.qsatgal_interp, z)) e_phi = np.hstack([-np.sin(phi)[:,np.newaxis], np.cos(phi)[:,np.newaxis], np.zeros([len(phi),1])]) e_theta = np.hstack([(np.cos(theta)*np.cos(phi))[:,np.newaxis], (np.cos(theta)*np.sin(phi))[:,np.newaxis], -np.sin(theta)[:,np.newaxis]]) psi = np.arctan2(-qarray.arraylist_dot(vecz, e_phi), -qarray.arraylist_dot(vecz, e_theta)) return psi.flatten()
def process_message(self, msg): # read a Dragonfly message msg_type = msg.GetHeader().msg_type dest_mod_id = msg.GetHeader().dest_mod_id if msg_type == MT_EXIT: if (dest_mod_id == 0) or (dest_mod_id == self.mod.GetModuleID()): print 'Received MT_EXIT, disconnecting...' self.mod.SendSignal(rc.MT_EXIT_ACK) self.mod.DisconnectFromMMM() return elif msg_type == rc.MT_PING: respond_to_ping(self.mod, msg, 'PlotHead') elif msg_type == rc.MT_POLARIS_POSITION: in_mdf = rc.MDF_POLARIS_POSITION() copy_from_msg(in_mdf, msg) positions = np.asarray(in_mdf.xyz[:]) orientations = self.shuffle_q(np.asarray(in_mdf.ori[:])) if in_mdf.tool_id == (self.pointer + 1): Qf = qa.norm(orientations) Qr = qa.mult(Qf, qa.inv(self.pointer_Qi)).flatten() #find_nans(self.store_head, Qr, 'Qr') Tk = positions #find_nans(self.store_head, Tk, 'Tk') tip_pos = (qa.rotate(Qr, self.pointer_Xi) + Tk).flatten() self.pointer_position = np.append(self.pointer_position, (tip_pos[np.newaxis, :]), axis=0) #self.pl.reset(x=self.pointer_position[:,0], y=self.pointer_position[:,1], z=self.pointer_position[:,2]) print("old=", tip_pos) print("new=", self.tp.get_pos(orientations, positions)[0])
def get_4piconv(self, ch, theta, phi, psi, horn_pointing=False): l.info('Computing dipole temperature with 4pi convolver') vel = qarray.amplitude(self.satellite_v).flatten() beta = vel / physcon.c gamma = 1./np.sqrt(1-beta**2) unit_vel = self.satellite_v/vel[:,None] if horn_pointing: # psi comes from the S channel, so there is no need # to remove psi_pol psi_nopol = psi else: # remove psi_pol psi_nopol = psi - np.radians(ch.get_instrument_db_field("psi_pol")) # rotate vel to ecliptic # phi around z #ecl_rotation = qarray.rotation([0,0,1], -phi) # theta around y ecl_rotation = qarray.norm( qarray.mult( qarray.rotation([0,0,1], -psi_nopol) , qarray.mult( qarray.rotation([0,1,0], -theta) , qarray.rotation([0,0,1], -phi) ) )) # psi around z #ecl_rotation = qarray.mult(qarray.rotation([0,0,1], -psi) , ecl_rotation) # vel in beam ref frame vel_rad = qarray.rotate(ecl_rotation, unit_vel) cosdir = qarray.arraylist_dot(vel_rad, self.beam_sum[ch.tag]).flatten() #return beta * cosdir * T_CMB return (1. / ( gamma * (1 - beta * cosdir ) ) - 1) * T_CMB
def interp_get(self, rad): '''Interpolation after rotation to gal frame''' from Quaternion import Quat l.info('Rotating to detector %s' % rad) siam_quat = Quat(self.siam.get(rad)).q totquat = qarray.mult(self.qsatgal_interp, siam_quat) totquat_interp = qarray.nlerp(self.obt, self.ahfobt, totquat) x = np.array([1, 0, 0]) vec = qarray.rotate(totquat_interp, x) l.info('Rotated to detector %s' % rad) return vec
def get(self, rad): rad = parse_channel(rad) l.info("Rotating to detector %s" % rad) x = np.dot(self.siam.get(rad), [1, 0, 0]) vec = qarray.rotate(self.qsatgal_interp, x) qarray.norm_inplace(vec) if self.deaberration: l.warning("Applying deaberration correction") vec += correction.simple_deaberration(vec, self.obt, self.coord) qarray.norm_inplace(vec) l.info("Rotated to detector %s" % rad) return vec
def inv(self, rad, vec): rad = parse_channel(rad) l.info("Rotating to detector %s" % rad) if self.deaberration: l.warning("Applying deaberration correction") vec -= correction.simple_deaberration(vec, self.obt, self.coord) qarray.norm_inplace(vec) vec_rad = qarray.rotate(qarray.inv(self.qsatgal_interp), vec) invsiam = np.linalg.inv(self.siam.get(rad)) # invsiamquat = qarray.inv(qarray.norm(qarray.from_rotmat(self.siam.get(rad)))) # qarray.rotate(invsiamquat, vec_rad) return np.array([np.dot(invsiam, row) for row in vec_rad])
def get_4piconv_dx10(self, ch, theta, phi, psi): l.info('Computing dipole temperature with 4pi convolver') rel_vel = self.satellite_v/physcon.c # remove psi_pol psi_nopol = psi - np.radians(ch.get_instrument_db_field("psi_pol")) # rotate vel to horn reference frame tohorn_rotation = qarray.norm( qarray.mult( qarray.rotation([0,0,1], -psi_nopol) , qarray.mult( qarray.rotation([0,1,0], -theta) , qarray.rotation([0,0,1], -phi) ) )) # vel in beam ref frame vel_rad = qarray.rotate(tohorn_rotation, rel_vel) dipole_amplitude = self.get_fourpi_prod(vel_rad, ["S100", "S010", "S001"], ch) # relative corrections dipole_amplitude += vel_rad[:,0] * self.get_fourpi_prod(vel_rad, ["S200", "S110", "S101"], ch)/2 dipole_amplitude += vel_rad[:,1] * self.get_fourpi_prod(vel_rad, ["S110", "S020", "S011"], ch)/2 dipole_amplitude += vel_rad[:,2] * self.get_fourpi_prod(vel_rad, ["S101", "S011", "S002"], ch)/2 return dipole_amplitude * T_CMB
prec_angles = (timestamps * prec_ang_speed) % (2 * np.pi) rot_prec = qa.mult(qa.rotation(x_axis, prec_angles), rot_prec_opening) # Spin spin_period_seconds = 60 spin_ang_speed = 2 * np.pi / spin_period_seconds spin_angles = (timestamps * spin_ang_speed) % (2 * np.pi) rot_opening = qa.rotation(z_axis, -np.radians(10)) rot_spin = qa.mult(qa.rotation(x_axis, spin_angles), rot_opening) # Total quaternions to boresight bore_quat = qa.norm(qa.mult(rot_earth_orbit, qa.mult(rot_prec, rot_spin))) bore_v = qa.rotate(bore_quat, x_axis) pix_1det = hp.vec2pix(nside, bore_v[:, 0], bore_v[:, 1], bore_v[:, 2], nest=True) pixels = np.tile(pix_1det, ndet) # polarization weights bore_v_proj_ortog = np.hstack([ -bore_v[:, [1]], bore_v[:, [0]], np.zeros(len(bore_v))[:, np.newaxis] ]) bore_v_proj_ortog /= np.linalg.norm(bore_v_proj_ortog, axis=1)[:,
def plot_detectors( dets, outfile, width=None, height=None, labels=False, bandcolor=None ): """Visualize a dictionary of detectors. This makes a simple plot of the detector positions on the projected focalplane. The size of detector circles are controlled by the detector "fwhm" key, which is in arcminutes. If the bandcolor is specified it will override the defaults. Args: outfile (str): Output PDF path. dets (dict): Dictionary of detector properties. width (float): Width of plot in degrees (None = autoscale). height (float): Height of plot in degrees (None = autoscale). labels (bool): If True, label each detector. bandcolor (dict, optional): Dictionary of color values for each band. Returns: None """ try: plt = set_matplotlib_pdf_backend() except: warnings.warn( """Couldn't set the PDF matplotlib backend, focal plane plots will not render properly, proceeding with the default matplotlib backend""" ) import matplotlib.pyplot as plt xaxis = np.array([1.0, 0.0, 0.0], dtype=np.float64) zaxis = np.array([0.0, 0.0, 1.0], dtype=np.float64) wmin = 1.0 wmax = -1.0 hmin = 1.0 hmax = -1.0 if (width is None) or (height is None): # We are autoscaling. Compute the angular extent of all detectors # and add some buffer. for d, props in dets.items(): quat = np.array(props["quat"]).astype(np.float64) dir = qa.rotate(quat, zaxis).flatten() if (dir[0] > wmax): wmax = dir[0] if (dir[0] < wmin): wmin = dir[0] if (dir[1] > hmax): hmax = dir[1] if (dir[1] < hmin): hmin = dir[1] wmin = np.arcsin(wmin) * 180.0 / np.pi wmax = np.arcsin(wmax) * 180.0 / np.pi hmin = np.arcsin(hmin) * 180.0 / np.pi hmax = np.arcsin(hmax) * 180.0 / np.pi wbuf = 0.1 * (wmax - wmin) hbuf = 0.1 * (hmax - hmin) wmin -= wbuf wmax += wbuf hmin -= hbuf hmax += hbuf width = wmax - wmin height = hmax - hmin else: half_width = 0.5 * width half_height = 0.5 * height wmin = -half_width wmax = half_width hmin = -half_height hmax = half_height wafer_centers = dict() if labels: # We are plotting labels and will want to plot a wafer_slot label for each # wafer. To decide where to place the label, we find the average location # of all detectors from each wafer and put the label there. for d, props in dets.items(): dwslot = props["wafer_slot"] if dwslot not in wafer_centers: wafer_centers[dwslot] = dict() wafer_centers[dwslot]["x"] = 0.0 wafer_centers[dwslot]["y"] = 0.0 wafer_centers[dwslot]["n"] = 0 quat = np.array(props["quat"]).astype(np.float64) dir = qa.rotate(quat, zaxis).flatten() wafer_centers[dwslot]["x"] += np.arcsin(dir[0]) * 180.0 / np.pi wafer_centers[dwslot]["y"] += np.arcsin(dir[1]) * 180.0 / np.pi wafer_centers[dwslot]["n"] += 1 for k in wafer_centers.keys(): wafer_centers[k]["x"] /= wafer_centers[k]["n"] wafer_centers[k]["y"] /= wafer_centers[k]["n"] if bandcolor is None: bandcolor = default_band_colors xfigsize = 10.0 yfigsize = xfigsize * (height / width) figdpi = 75 yfigpix = int(figdpi * yfigsize) ypixperdeg = yfigpix / height fig = plt.figure(figsize=(xfigsize, yfigsize), dpi=figdpi) ax = fig.add_subplot(1, 1, 1) ax.set_xlabel("Degrees", fontsize="large") ax.set_ylabel("Degrees", fontsize="large") ax.set_xlim([wmin, wmax]) ax.set_ylim([hmin, hmax]) # Draw wafer labels in the background if labels: # Compute the font size to use for detector labels fontpix = 0.2 * ypixperdeg for k, v in wafer_centers.items(): ax.text(v["x"] + 0.2, v["y"], k, color='k', fontsize=fontpix, horizontalalignment='center', verticalalignment='center', bbox=dict(fc='white', ec='none', pad=0.2, alpha=1.0)) for d, props in dets.items(): band = props["band"] pixel = props["pixel"] pol = props["pol"] quat = np.array(props["quat"]).astype(np.float64) fwhm = props["fwhm"] # radius in degrees detradius = 0.5 * fwhm / 60.0 # rotation from boresight rdir = qa.rotate(quat, zaxis).flatten() ang = np.arctan2(rdir[1], rdir[0]) orient = qa.rotate(quat, xaxis).flatten() polang = np.arctan2(orient[1], orient[0]) mag = np.arccos(rdir[2]) * 180.0 / np.pi xpos = mag * np.cos(ang) ypos = mag * np.sin(ang) detface = bandcolor[band] circ = plt.Circle((xpos, ypos), radius=detradius, fc=detface, ec="black", linewidth=0.05*detradius) ax.add_artist(circ) ascale = 1.5 xtail = xpos - ascale * detradius * np.cos(polang) ytail = ypos - ascale * detradius * np.sin(polang) dx = ascale * 2.0 * detradius * np.cos(polang) dy = ascale * 2.0 * detradius * np.sin(polang) detcolor = "black" if pol == "A": detcolor = (1.0, 0.0, 0.0, 1.0) if pol == "B": detcolor = (0.0, 0.0, 1.0, 1.0) ax.arrow(xtail, ytail, dx, dy, width=0.1*detradius, head_width=0.3*detradius, head_length=0.3*detradius, fc=detcolor, ec="none", length_includes_head=True) if labels: # Compute the font size to use for detector labels fontpix = 0.1 * detradius * ypixperdeg ax.text((xpos), (ypos), pixel, color='k', fontsize=fontpix, horizontalalignment='center', verticalalignment='center', bbox=dict(fc='white', ec='none', pad=0.2, alpha=1.0)) xsgn = 1.0 if dx < 0.0: xsgn = -1.0 labeloff = 1.0 * xsgn * fontpix * len(pol) / ypixperdeg ax.text((xtail+1.0*dx+labeloff), (ytail+1.0*dy), pol, color='k', fontsize=fontpix, horizontalalignment='center', verticalalignment='center', bbox=dict(fc='none', ec='none', pad=0, alpha=1.0)) plt.savefig(outfile) plt.close() return
detstring = dets2detstring(dets) ndet = len(dets) spin_period_seconds = 60 x_axis, y_axis, z_axis = np.eye(3) spin_ang_speed = 2 * np.pi / spin_period_seconds spin_angles = (timestamps * spin_ang_speed) % (2 * np.pi) rot_opening = qa.rotation(z_axis, -np.radians(10)) rot_spin = qa.mult(qa.rotation(x_axis, spin_angles), rot_opening) bore_v = qa.rotate(rot_spin, x_axis) pix_1det = hp.vec2pix(nside, bore_v[:, 0], bore_v[:, 1], bore_v[:, 2], nest=True) pixels = np.tile(pix_1det, ndet) del pix_1det, bore_v, rot_spin pars = {} pars["base_first"] = 60.0 pars["fsample"] = fsample pars["nside_map"] = nside pars["nside_cross"] = nside // 2 pars["nside_submap"] = nside // 4
def vector_gal2ecl(vecl): '''Convert arrays from Ecliptic to Galactic''' l.info('Rotating to Galactic frame') return qarray.rotate(qarray.inv(QECL2GAL) ,vecl)
def test_rotate_qarray(self): my_rot_result = qarray.rotate(np.vstack([self.q1,self.q2]), self.vec) np.testing.assert_array_almost_equal(my_rot_result , np.vstack([self.rot_by_q1, self.rot_by_q2]))
def test_rotate_onequaternion(self): my_rot_result = qarray.rotate(self.q1, self.vec) np.testing.assert_array_almost_equal(my_rot_result , self.rot_by_q1)
prec_angles = (timestamps * prec_ang_speed) % (2 * np.pi) rot_prec = qa.mult(qa.rotation(x_axis, prec_angles), rot_prec_opening) # Spin spin_period_seconds = 60 spin_ang_speed = 2 * np.pi / spin_period_seconds spin_angles = (timestamps * spin_ang_speed) % (2 * np.pi) rot_opening = qa.rotation(z_axis, -np.radians(10)) rot_spin = qa.mult(qa.rotation(x_axis, spin_angles), rot_opening) # Total quaternions to boresight bore_quat = qa.norm(qa.mult(rot_earth_orbit, qa.mult(rot_prec, rot_spin))) bore_v = qa.rotate(bore_quat, x_axis) # Focalplane import pickle with open("pico_09.pkl", "rb") as f: fp = pickle.load(f) dets = ["19C9-000A", "19C9-000B", "19C9-001A", "19C9-001B"] detstring = dets2detstring(dets) ndet = len(dets) pixels = np.empty(nsamp * ndet, dtype=np.int64) psi = {}
def gal2ecl(vec): return qarray.rotate(qarray.inv(QECL2GAL) , vec)
# Rotation is a rotation with respect to the `z` axis # In[ ]: rotation_speed = np.radians(-1 * 360/60) az = rotation_speed * (target_ut_h * 3600.) % (2*np.pi) q_rotation = qa.rotation(z, az) # We compose the rotations direction = qa.rotate( qa.mult(qfull, qa.mult(q_rotation, q_elev)), z) lon, lat= hp.vec2dir(direction[:,0], direction[:,1], direction[:,2], lonlat=True) # ### Hitmap pix = hp.vec2pix(NSIDE,direction[:,0], direction[:,1], direction[:,2] ) hit += hp.ma(pix2map(pix, NSIDE)) hit.mask = hit == 0 hp.write_map('hitmap_%s_%d_opening.fits' % (LOCATION, OPENING_ANGLE),hit)
def plot_detectors(dets, outfile, width=None, height=None, labels=False, bandcolor=None): """Visualize a dictionary of detectors. This makes a simple plot of the detector positions on the projected focalplane. The size of detector circles are controlled by the detector "fwhm" key, which is in arcminutes. If the bandcolor is specified it will override the defaults. Args: outfile (str): Output PDF path. dets (dict): Dictionary of detector properties. width (float): Width of plot in degrees (None = autoscale). height (float): Height of plot in degrees (None = autoscale). labels (bool): If True, label each detector. bandcolor (dict, optional): Dictionary of color values for each band. Returns: None """ import matplotlib matplotlib.use("pdf") import matplotlib.pyplot as plt xaxis = np.array([1.0, 0.0, 0.0], dtype=np.float64) zaxis = np.array([0.0, 0.0, 1.0], dtype=np.float64) wmin = 1.0 wmax = -1.0 hmin = 1.0 hmax = -1.0 if (width is None) or (height is None): # We are autoscaling. Compute the angular extent of all detectors # and add some buffer. for d, props in dets.items(): quat = np.array(props["quat"]).astype(np.float64) dir = qa.rotate(quat, zaxis).flatten() if dir[0] > wmax: wmax = dir[0] if dir[0] < wmin: wmin = dir[0] if dir[1] > hmax: hmax = dir[1] if dir[1] < hmin: hmin = dir[1] wmin = np.arcsin(wmin) * 180.0 / np.pi wmax = np.arcsin(wmax) * 180.0 / np.pi hmin = np.arcsin(hmin) * 180.0 / np.pi hmax = np.arcsin(hmax) * 180.0 / np.pi wbuf = 0.1 * (wmax - wmin) hbuf = 0.1 * (hmax - hmin) wmin -= wbuf wmax += wbuf hmin -= hbuf hmax += hbuf width = wmax - wmin height = hmax - hmin else: half_width = 0.5 * width half_height = 0.5 * height wmin = -half_width wmax = half_width hmin = -half_height hmax = half_height if bandcolor is None: bandcolor = default_band_colors xfigsize = 10.0 yfigsize = xfigsize * (height / width) figdpi = 75 yfigpix = int(figdpi * yfigsize) ypixperdeg = yfigpix / height fig = plt.figure(figsize=(xfigsize, yfigsize), dpi=figdpi) ax = fig.add_subplot(1, 1, 1) ax.set_xlabel("Degrees", fontsize="large") ax.set_ylabel("Degrees", fontsize="large") ax.set_xlim([wmin, wmax]) ax.set_ylim([hmin, hmax]) for d, props in dets.items(): band = props["band"] pixel = props["pixel"] pol = props["pol"] quat = np.array(props["quat"]).astype(np.float64) fwhm = props["fwhm"] # radius in degrees detradius = 0.5 * fwhm / 60.0 # rotation from boresight rdir = qa.rotate(quat, zaxis).flatten() ang = np.arctan2(rdir[1], rdir[0]) orient = qa.rotate(quat, xaxis).flatten() polang = np.arctan2(orient[1], orient[0]) mag = np.arccos(rdir[2]) * 180.0 / np.pi xpos = mag * np.cos(ang) ypos = mag * np.sin(ang) detface = bandcolor[band] circ = plt.Circle( (xpos, ypos), radius=detradius, fc=detface, ec="black", linewidth=0.05 * detradius, ) ax.add_artist(circ) ascale = 1.5 xtail = xpos - ascale * detradius * np.cos(polang) ytail = ypos - ascale * detradius * np.sin(polang) dx = ascale * 2.0 * detradius * np.cos(polang) dy = ascale * 2.0 * detradius * np.sin(polang) detcolor = "black" if pol == "A": detcolor = (1.0, 0.0, 0.0, 1.0) if pol == "B": detcolor = (0.0, 0.0, 1.0, 1.0) ax.arrow( xtail, ytail, dx, dy, width=0.1 * detradius, head_width=0.3 * detradius, head_length=0.3 * detradius, fc=detcolor, ec="none", length_includes_head=True, ) if labels: # Compute the font size to use for detector labels fontpix = 0.1 * detradius * ypixperdeg ax.text( (xpos), (ypos), pixel, color="k", fontsize=fontpix, horizontalalignment="center", verticalalignment="center", bbox=dict(fc="white", ec="none", pad=0.2, alpha=1.0), ) xsgn = 1.0 if dx < 0.0: xsgn = -1.0 labeloff = 1.0 * xsgn * fontpix * len(pol) / ypixperdeg ax.text( (xtail + 1.0 * dx + labeloff), (ytail + 1.0 * dy), pol, color="k", fontsize=fontpix, horizontalalignment="center", verticalalignment="center", bbox=dict(fc="none", ec="none", pad=0, alpha=1.0), ) plt.savefig(outfile) plt.close() return
def ecl2gal(vec): return qarray.rotate(QECL2GAL , vec)
def get_pos(self, Qk, Tk): Qk = qa.norm(Qk) Qr = (qa.mult(Qk, qa.inv(self.Qi))).flatten() pos = (qa.rotate(Qr, self.Xi)).flatten() + Tk return pos, Qr
def plot_detectors(dets, outfile, width=None, height=None, labels=False, bandcolor=None): """Visualize a dictionary of detectors. This makes a simple plot of the detector positions on the projected focalplane. The size of detector circles are controlled by the detector "fwhm" key, which is in arcminutes. If the bandcolor is specified it will override the defaults. Args: outfile (str): Output PDF path. dets (dict): Dictionary of detector properties. width (float): Width of plot in degrees (None = autoscale). height (float): Height of plot in degrees (None = autoscale). labels (bool): If True, label each detector. bandcolor (dict, optional): Dictionary of color values for each band. Returns: None """ try: plt = set_matplotlib_pdf_backend() except: warnings.warn("""Couldn't set the PDF matplotlib backend, focal plane plots will not render properly, proceeding with the default matplotlib backend""") import matplotlib.pyplot as plt # If you rotate the zaxis by quat, then the X axis is upwards in # the focal plane and the Y axis is to the right. (This is what # TOAST expects.) Below we use "x" and "y" for those directions, # and in plotting functions pass them in the order (y, x). xaxis = np.array([1.0, 0.0, 0.0], dtype=np.float64) zaxis = np.array([0.0, 0.0, 1.0], dtype=np.float64) quats = np.array([p['quat'] for p in dets.values()]).astype(float) pos = qa.rotate(quats, zaxis) # shape (n_det, 3) # arc_factor returns a scaling that can be used to reproject (X, # Y) to units corresponding to the angle subtended from (0,0,1) to # (X, Y, sqrt(X^2 + Y^2)). This is called "ARC" (Zenithal # Equidistant) projection in FITS. def arc_factor(x, y): r = (x**2 + y**2)**.5 if r < 1e-6: return 1. + r**2 / 6 return np.arcsin(r) / r detx = { k: p[0] * 180.0 / np.pi * arc_factor(p[0], p[1]) for k, p in zip(dets.keys(), pos) } dety = { k: p[1] * 180.0 / np.pi * arc_factor(p[0], p[1]) for k, p in zip(dets.keys(), pos) } # The detang is the polarization angle, measured CCW from vertical. pol = qa.rotate(quats, xaxis) # shape (n_det, 3) detang = {k: np.arctan2(p[1], p[0]) for k, p in zip(dets.keys(), pol)} wmin = 1.0 wmax = -1.0 hmin = 1.0 hmax = -1.0 if (width is None) or (height is None): # We are autoscaling. Compute the angular extent of all detectors # and add some buffer. if len(detx): _y = np.array(list(dety.values())) _x = np.array(list(detx.values())) wmin, wmax = _y.min(), _y.max() hmin, hmax = _x.min(), _x.max() wbuf = 0.1 * (wmax - wmin) hbuf = 0.1 * (hmax - hmin) wmin -= wbuf wmax += wbuf hmin -= hbuf hmax += hbuf width = wmax - wmin height = hmax - hmin else: half_width = 0.5 * width half_height = 0.5 * height wmin = -half_width wmax = half_width hmin = -half_height hmax = half_height wafer_centers = dict() if labels: # We are plotting labels and will want to plot a wafer_slot label for each # wafer. To decide where to place the label, we find the average location # of all detectors from each wafer and put the label there. for d, props in dets.items(): dwslot = props["wafer_slot"] if dwslot not in wafer_centers: wafer_centers[dwslot] = [] wafer_centers[dwslot].append((detx[d], dety[d])) for k in wafer_centers.keys(): center = np.mean(wafer_centers[k], axis=0) size = (np.array(wafer_centers[k]) - center).std() wafer_centers[k] = (center, size) if bandcolor is None: bandcolor = default_band_colors wfigsize = 10.0 hfigsize = wfigsize * (height / width) figdpi = 75 hfigpix = int(figdpi * hfigsize) hpixperdeg = hfigpix / height fig = plt.figure(figsize=(wfigsize, hfigsize), dpi=figdpi) ax = fig.add_subplot(1, 1, 1) ax.set_xlabel("Degrees", fontsize="large") ax.set_ylabel("Degrees", fontsize="large") ax.set_xlim([wmin, wmax]) ax.set_ylim([hmin, hmax]) # Draw wafer labels in the background if labels: # The font size depends on the wafer size ... but keep it # between (0.01 and 0.1) times the size of the figure. for k, (center, size) in wafer_centers.items(): fontpix = np.clip(0.7 * size * hpixperdeg, 0.01 * hfigpix, 0.10 * hfigpix) ax.text(center[1] + fontpix / hpixperdeg, center[0], k, color='k', fontsize=fontpix, horizontalalignment='center', verticalalignment='center', zorder=100, bbox=dict(fc='white', ec='none', pad=0.2, alpha=1.0)) for d, props in dets.items(): band = props["band"] pixel = props["pixel"] pol = props["pol"] quat = np.array(props["quat"]).astype(np.float64) fwhm = props["fwhm"] # radius in degrees detradius = 0.5 * fwhm / 60.0 # Position and polarization angle xpos, ypos = detx[d], dety[d] polang = detang[d] detface = bandcolor[band] circ = plt.Circle((ypos, xpos), radius=detradius, fc=detface, ec="black", linewidth=0.05 * detradius) ax.add_artist(circ) ascale = 1.5 xtail = xpos - ascale * detradius * np.cos(polang) ytail = ypos - ascale * detradius * np.sin(polang) dx = ascale * 2.0 * detradius * np.cos(polang) dy = ascale * 2.0 * detradius * np.sin(polang) detcolor = "black" if pol == "A": detcolor = (1.0, 0.0, 0.0, 1.0) if pol == "B": detcolor = (0.0, 0.0, 1.0, 1.0) ax.arrow(ytail, xtail, dy, dx, width=0.1 * detradius, head_width=0.3 * detradius, head_length=0.3 * detradius, fc=detcolor, ec="none", length_includes_head=True) if labels: # Compute the font size to use for detector labels fontpix = 0.1 * detradius * hpixperdeg ax.text(ypos, xpos, pixel, color='k', fontsize=fontpix, horizontalalignment='center', verticalalignment='center', bbox=dict(fc='white', ec='none', pad=0.2, alpha=1.0)) labeloff = fontpix * len(pol) / hpixperdeg if dy < 0: labeloff = -labeloff ax.text((ytail + 1.0 * dy + labeloff), (xtail + 1.0 * dx), pol, color='k', fontsize=fontpix, horizontalalignment='center', verticalalignment='center', bbox=dict(fc='none', ec='none', pad=0, alpha=1.0)) plt.savefig(outfile) plt.close() return
def find_hotspot_to_cz( self, HS_GCS, glasses_orientation, glasses_position, coil_vector): #Saves 0, 0, 0 array to file when object called check_HS_GCS = self.check(HS_GCS) check_glasses_orientation = self.check(glasses_orientation) check_glasses_position = self.check(glasses_position) check_coil_vector = self.check(coil_vector) if np.any( np.array([ check_HS_GCS, check_glasses_orientation, check_glasses_position, check_coil_vector ])): print np.array([ check_HS_GCS, check_glasses_orientation, check_glasses_position, check_coil_vector ]) HS_LCS = (np.zeros(3) * np.NaN)[None] print HS_LCS vector_LCS = (np.zeros(3) * np.NaN)[None] with open(self.location, 'a') as location: np.savetxt(location, np.array(HS_LCS), fmt='%f', delimiter=',', newline='\r\n') location.close() with open(self.vector, 'a') as data: np.savetxt(data, np.array(vector_LCS), fmt='%f', delimiter=',', newline='\r\n') data.close() sys.stdout.write("No position\n") else: cz_pos, cz_rot = self.glasses_to_cz.get_pos( glasses_orientation, glasses_position) LT_pos, LT_rot = self.glasses_to_LT.get_pos( glasses_orientation, glasses_position) RT_pos, RT_rot = self.glasses_to_RT.get_pos( glasses_orientation, glasses_position) Nasion_pos, Nasion_rot = self.glasses_to_Nasion.get_pos( glasses_orientation, glasses_position) calibration_matrix = self.make_head_axis(LT_pos, RT_pos, Nasion_pos) HS_LCS = qa.rotate(calibration_matrix, (HS_GCS - cz_pos)) vector_LCS = qa.rotate(calibration_matrix, coil_vector) #HS_LCS = qa.rotate(rot, qa.rotate(self.calibration_matrix, (HS_GCS - cz_pos))) #vector_LCS = qa.rotate(rot, qa.rotate(self.calibration_matrix, (coil_vector))) with open(self.location, 'a') as location: np.savetxt(location, np.array(HS_LCS), fmt='%f', delimiter=',', newline='\r\n') location.close() with open(self.vector, 'a') as data: np.savetxt(data, np.array(vector_LCS), fmt='%f', delimiter=',', newline='\r\n') data.close() self.stimulus_no += 1 print self.stimulus_no in_mdf = rc.MDF_POLARIS_POSITION() out_mdf = rc.MDF_PLOT_POSITION() out_mdf.xyz[:] = HS_LCS[0] out_mdf.ori[:] = np.append(vector_LCS[0], 0) # Qk - coil active orientation out_mdf.sample_header = in_mdf.sample_header msg = CMessage(rc.MT_PLOT_POSITION) copy_to_msg(out_mdf, msg) self.mod.SendMessage(msg) sys.stdout.write("C")