def azimuth(self, t, deg=True, std=False, syst=False): "Return the azimuth with respect to the positive x-axis." x, y, z = self._construct_n(t) azimuth = (atan2(z, x) + 2. * pi) % (2. * pi) if deg: azimuth = degrees(azimuth) return self._return_result(azimuth, std, syst)
def azimuth(self, t, deg=True, std=False, syst=False): "Return the azimuth with respect to the positive x-axis." x, y, z = self._construct_n(t) azimuth = (atan2(z, x) + 2.*pi) % (2.*pi) if deg: azimuth = degrees(azimuth) return self._return_result(azimuth, std, syst)
def get_source_apparent_pos(self, epoch, enlargeFactor=1.0): lensPos = self._lens.getRaDec(epoch) sourcePos = self._source.getRaDec(epoch) shift_mag = self.get_unresolved_centroid_shift_at_epoch(epoch) shift_angle = np.atan2( (sourcePos[0] - lensPos[0]) * np.cos(numpy.deg2rad(lensPos[1])), sourcePos[1] - lensPos[1]) appSourceRa = sourcePos[0] + ( (enlargeFactor * shift_mag * np.cos(shift_angle)) / (3600 * 1000)) appSourceDec = sourcePos[1] + ( (enlargeFactor * shift_mag * np.sin(shift_angle)) / (36000 * 1000)) return numpy.array([appSourceRa, appSourceDec])
def cartesian_to_angular(x, y, z): """Converts from cartesian to angular coordinates """ norm = np.sqrt(x**2 + y**2 + z**2) x = x / norm y = y / norm z = z / norm dec = np.asin(z) ra = np.atan2(y, x) ra = ra * rad2deg dec = dec * rad2deg return numpy.array([ra, dec])
def get_angular_sep(ra1, dec1, ra2, dec2): ra1 = ra1 * deg2rad ra2 = ra2 * deg2rad dec1 = dec1 * deg2rad dec2 = dec2 * deg2rad top = np.sqrt((np.cos(dec2) * np.sin(ra2 - ra1))**(2) + (np.cos(dec1) * np.sin(dec2) - np.sin(dec1) * np.cos(dec2) * np.cos(ra2 - ra1))**(2)) bottom = (np.sin(dec1) * np.sin(dec2)) + (np.cos(dec1) * np.cos(dec2) * np.cos(ra2 - ra1)) dist = np.atan2(top, bottom) return (dist / deg2rad) * 3600.0 * 1000.0
def test_against_uncertainties_package(): try: from uncertainties import ufloat from uncertainties import umath from math import sqrt as math_sqrt except ImportError: return X, varX = 0.5, 0.04 Y, varY = 3, 0.09 N = 3 ux = ufloat(X, math_sqrt(varX)) uy = ufloat(Y, math_sqrt(varY)) def _compare(result, u): Z, varZ = result assert abs(Z-u.n)/u.n < 1e-13 and (varZ-u.s**2)/u.s**2 < 1e-13, \ "expected (%g,%g) got (%g,%g)"%(u.n,u.s**2,Z,varZ) def _check_pow(u): _compare(pow(X, varX, N), u) def _check_unary(op, u): _compare(op(X, varX), u) def _check_binary(op, u): _compare(op(X, varX, Y, varY), u) _check_pow(ux**N) _check_binary(add, ux+uy) _check_binary(sub, ux-uy) _check_binary(mul, ux*uy) _check_binary(div, ux/uy) _check_binary(pow2, ux**uy) _check_unary(exp, umath.exp(ux)) _check_unary(log, umath.log(ux)) _check_unary(sin, umath.sin(ux)) _check_unary(cos, umath.cos(ux)) _check_unary(tan, umath.tan(ux)) _check_unary(arcsin, umath.asin(ux)) _check_unary(arccos, umath.acos(ux)) _check_unary(arctan, umath.atan(ux)) _check_binary(arctan2, umath.atan2(ux, uy))
def test_against_uncertainties_package(): try: from uncertainties import ufloat from uncertainties import umath from math import sqrt as math_sqrt except ImportError: return X, varX = 0.5, 0.04 Y, varY = 3, 0.09 N = 3 ux = ufloat(X, math_sqrt(varX)) uy = ufloat(Y, math_sqrt(varY)) def _compare(result, u): Z, varZ = result assert abs(Z-u.n)/u.n < 1e-13 and (varZ-u.s**2)/u.s**2 < 1e-13, \ "expected (%g,%g) got (%g,%g)"%(u.n, u.s**2, Z, varZ) def _check_pow(u): _compare(pow(X, varX, N), u) def _check_unary(op, u): _compare(op(X, varX), u) def _check_binary(op, u): _compare(op(X, varX, Y, varY), u) _check_pow(ux**N) _check_binary(add, ux + uy) _check_binary(sub, ux - uy) _check_binary(mul, ux * uy) _check_binary(div, ux / uy) _check_binary(pow2, ux**uy) _check_unary(exp, umath.exp(ux)) _check_unary(log, umath.log(ux)) _check_unary(sin, umath.sin(ux)) _check_unary(cos, umath.cos(ux)) _check_unary(tan, umath.tan(ux)) _check_unary(arcsin, umath.asin(ux)) _check_unary(arccos, umath.acos(ux)) _check_unary(arctan, umath.atan(ux)) _check_binary(arctan2, umath.atan2(ux, uy))
def u_get_zenith_azimuth(self, u_dir_x, u_dir_y, u_dir_z, with_flip=True): """Get zeniths and azimuths [in radians] from direction vector. Parameters ---------- u_dir_x : unumpy.array The x-component of the direction vector with uncertainty. u_dir_y : unumpy.array The y-component of the direction vector with uncertainty. u_dir_z : unumpy.array The z-component of the direction vector with uncertainty. with_flip : bool, optional If True, then the direction vectors show in the opposite direction than the zenith/azimuth pairs. This is common within IceCube software, since the direction vector shows along the particle direction, whereas the zenith/azimuth shows to the source position. Returns ------- unumpy.array, unumpy.array The zenith and azimuth angles with uncertainties. """ # normalize if not self.is_normalized(u_dir_x.nominal_value, u_dir_y.nominal_value, u_dir_z.nominal_value): u_dir_x, u_dir_y, u_dir_z = \ self.u_normalize_dir(u_dir_x, u_dir_y, u_dir_z) if with_flip: u_dir_x *= -1 u_dir_y *= -1 u_dir_z *= -1 if np.abs(u_dir_z.nominal_value) > 1.: raise ValueError('Z-component |{!r}| > 1!'.format( u_dir_z.nominal_value)) zenith = umath.acos(u_dir_z) azimuth = (umath.atan2(u_dir_y, u_dir_x) + 2 * np.pi) % (2 * np.pi) return zenith, azimuth
def get_angular_sep(ra1, dec1, ra2, dec2): """ implements the vincinerty distance formular in the case of a sphere. """ ra1 = ra1 * deg2rad ra2 = ra2 * deg2rad dec1 = dec1 * deg2rad dec2 = dec2 * deg2rad top = np.sqrt((np.cos(dec2) * np.sin(ra2 - ra1))**(2) + (np.cos(dec1) * np.sin(dec2) - np.sin(dec1) * np.cos(dec2) * np.cos(ra2 - ra1))**(2)) bottom = (np.sin(dec1) * np.sin(dec2)) + (np.cos(dec1) * np.cos(dec2) * np.cos(ra2 - ra1)) dist = np.atan2(top, bottom) return (dist / deg2rad) * 3600.0 * 1000.0
def get_summary(self, nodmx=False): """Return a human-readable summary of the Fitter results. Parameters ---------- nodmx : bool Set to True to suppress printing DMX parameters in summary """ # Need to check that fit has been done first! if not hasattr(self, "covariance_matrix"): log.warning( "fit_toas() has not been run, so pre-fit and post-fit will be the same!" ) from uncertainties import ufloat import uncertainties.umath as um # First, print fit quality metrics s = "Fitted model using {} method with {} free parameters to {} TOAs\n".format( self.method, len(self.get_fitparams()), self.toas.ntoas) s += "Prefit residuals Wrms = {}, Postfit residuals Wrms = {}\n".format( self.resids_init.rms_weighted(), self.resids.rms_weighted()) s += "Chisq = {:.3f} for {} d.o.f. for reduced Chisq of {:.3f}\n".format( self.resids.chi2, self.resids.dof, self.resids.chi2_reduced) s += "\n" # Next, print the model parameters s += "{:<14s} {:^20s} {:^28s} {}\n".format("PAR", "Prefit", "Postfit", "Units") s += "{:<14s} {:>20s} {:>28s} {}\n".format("=" * 14, "=" * 20, "=" * 28, "=" * 5) for pn in list(self.get_allparams().keys()): if nodmx and pn.startswith("DMX"): continue prefitpar = getattr(self.model_init, pn) par = getattr(self.model, pn) if par.value is not None: if isinstance(par, strParameter): s += "{:14s} {:>20s} {:28s} {}\n".format( pn, prefitpar.value, "", par.units) elif isinstance(par, AngleParameter): # Add special handling here to put uncertainty into arcsec if par.frozen: s += "{:14s} {:>20s} {:>28s} {} \n".format( pn, str(prefitpar.quantity), "", par.units) else: if par.units == u.hourangle: uncertainty_unit = pint.hourangle_second else: uncertainty_unit = u.arcsec s += "{:14s} {:>20s} {:>16s} +/- {:.2g} \n".format( pn, str(prefitpar.quantity), str(par.quantity), par.uncertainty.to(uncertainty_unit), ) else: # Assume a numerical parameter if par.frozen: s += "{:14s} {:20g} {:28s} {} \n".format( pn, prefitpar.value, "", par.units) else: # s += "{:14s} {:20g} {:20g} {:20.2g} {} \n".format( # pn, # prefitpar.value, # par.value, # par.uncertainty.value, # par.units, # ) s += "{:14s} {:20g} {:28SP} {} \n".format( pn, prefitpar.value, ufloat(par.value, par.uncertainty.value), par.units, ) # Now print some useful derived parameters s += "\nDerived Parameters:\n" if hasattr(self.model, "F0"): F0 = self.model.F0.quantity if not self.model.F0.frozen: p, perr = pint.utils.pferrs(F0, self.model.F0.uncertainty) s += "Period = {} +/- {}\n".format(p.to(u.s), perr.to(u.s)) else: s += "Period = {}\n".format((1.0 / F0).to(u.s)) if hasattr(self.model, "F1"): F1 = self.model.F1.quantity if not any([self.model.F1.frozen, self.model.F0.frozen]): p, perr, pd, pderr = pint.utils.pferrs( F0, self.model.F0.uncertainty, F1, self.model.F1.uncertainty) s += "Pdot = {} +/- {}\n".format( pd.to(u.dimensionless_unscaled), pderr.to(u.dimensionless_unscaled)) brakingindex = 3 s += "Characteristic age = {:.4g} (braking index = {})\n".format( pint.utils.pulsar_age(F0, F1, n=brakingindex), brakingindex) s += "Surface magnetic field = {:.3g}\n".format( pint.utils.pulsar_B(F0, F1)) s += "Magnetic field at light cylinder = {:.4g}\n".format( pint.utils.pulsar_B_lightcyl(F0, F1)) I_NS = I = 1.0e45 * u.g * u.cm**2 s += "Spindown Edot = {:.4g} (I={})\n".format( pint.utils.pulsar_edot(F0, F1, I=I_NS), I_NS) if hasattr(self.model, "PX"): if not self.model.PX.frozen: s += "\n" px = ufloat( self.model.PX.quantity.to(u.arcsec).value, self.model.PX.uncertainty.to(u.arcsec).value, ) s += "Parallax distance = {:.3uP} pc\n".format(1.0 / px) # Now binary system derived parameters binary = None for x in self.model.components: if x.startswith("Binary"): binary = x if binary is not None: s += "\n" s += "Binary model {}\n".format(binary) if binary.startswith("BinaryELL1"): if not any([ self.model.EPS1.frozen, self.model.EPS2.frozen, self.model.TASC.frozen, self.model.PB.frozen, ]): eps1 = ufloat( self.model.EPS1.quantity.value, self.model.EPS1.uncertainty.value, ) eps2 = ufloat( self.model.EPS2.quantity.value, self.model.EPS2.uncertainty.value, ) tasc = ufloat( # This is a time in MJD self.model.TASC.quantity.mjd, self.model.TASC.uncertainty.to(u.d).value, ) pb = ufloat( self.model.PB.quantity.to(u.d).value, self.model.PB.uncertainty.to(u.d).value, ) s += "Conversion from ELL1 parameters:\n" ecc = um.sqrt(eps1**2 + eps2**2) s += "ECC = {:P}\n".format(ecc) om = um.atan2(eps1, eps2) * 180.0 / np.pi if om < 0.0: om += 360.0 s += "OM = {:P}\n".format(om) t0 = tasc + pb * om / 360.0 s += "T0 = {:SP}\n".format(t0) s += pint.utils.ELL1_check( self.model.A1.quantity, ecc.nominal_value, self.resids.rms_weighted(), self.toas.ntoas, outstring=True, ) s += "\n" # Masses and inclination if not any([self.model.PB.frozen, self.model.A1.frozen]): pbs = ufloat( self.model.PB.quantity.to(u.s).value, self.model.PB.uncertainty.to(u.s).value, ) a1 = ufloat( self.model.A1.quantity.to(pint.ls).value, self.model.A1.uncertainty.to(pint.ls).value, ) fm = 4.0 * np.pi**2 * a1**3 / (4.925490947e-6 * pbs**2) s += "Mass function = {:SP} Msun\n".format(fm) mcmed = pint.utils.companion_mass( self.model.PB.quantity, self.model.A1.quantity, inc=60.0 * u.deg, mpsr=1.4 * u.solMass, ) mcmin = pint.utils.companion_mass( self.model.PB.quantity, self.model.A1.quantity, inc=90.0 * u.deg, mpsr=1.4 * u.solMass, ) s += "Companion mass min, median (assuming Mpsr = 1.4 Msun) = {:.4f}, {:.4f} Msun\n".format( mcmin, mcmed) if hasattr(self.model, "SINI"): if not self.model.SINI.frozen: si = ufloat( self.model.SINI.quantity.value, self.model.SINI.uncertainty.value, ) s += "From SINI in model:\n" s += " cos(i) = {:SP}\n".format(um.sqrt(1 - si**2)) s += " i = {:SP} deg\n".format( um.asin(si) * 180.0 / np.pi) psrmass = pint.utils.pulsar_mass( self.model.PB.quantity, self.model.A1.quantity, self.model.M2.quantity, np.arcsin(self.model.SINI.quantity), ) s += "Pulsar mass (Shapiro Delay) = {}".format(psrmass) return s
def candid_grid(input_data, step=10, rmin=20, rmax=400, diam=0, obs=['cp', 'v2'], extra_error_cp=0, err_scale=1, extra_error_v2=0, instruments=None, doNotFit=[ 'diam*', ], ncore=1, verbose=False): """ This function is an user friendly interface between the users of amical pipeline and the CANDID analysis package (https://github.com/amerand/CANDID). Parameters: ----------- `input_data` {str or list}: oifits file names or list of oifits files,\n `step` {int}: step used to compute the binary grid positions,\n `rmin`, `rmax` {float}: Bounds of the grid [mas],\n `diam` {float}: Stellar diameter of the primary star [mas] (default=0),\n `obs` {list}: List of observables to be fitted (default: ['cp', 'v2']),\n `doNotFit` {list}: Parameters not fitted (default: ['diam*']),\n `verbose` {boolean}: print some informations {default: False}. Outputs: -------- `res` {dict}: Dictionnary of the results ('best'), uncertainties ('uncer'), reduced chi2 ('chi2') and sigma detection ('nsigma'). """ cprint(' | --- Start CANDID fitting --- :', 'green') o = candid.Open(input_data, extra_error=extra_error_cp, err_scale=err_scale, extra_error_v2=extra_error_v2, instruments=instruments) o.observables = obs o.fitMap(rmax=rmax, rmin=rmin, ncore=ncore, fig=0, step=step, addParam={"diam*": diam}, doNotFit=doNotFit, verbose=verbose) fit = o.bestFit["best"] e_fit = o.bestFit["uncer"] chi2 = o.bestFit['chi2'] nsigma = o.bestFit['nsigma'] f = fit["f"] / 100.0 e_f = e_fit["f"] / 100.0 if (e_f < 0) or (e_fit["x"] < 0) or (e_fit["y"] < 0): print('Warning: error dm is negative.') e_f = abs(e_f) e_fit["x"] = 0 e_fit["y"] = 0 f_u = ufloat(f, e_f) x, y = fit["x"], fit["y"] x_u = ufloat(x, e_fit["x"]) y_u = ufloat(y, e_fit["y"]) dm = -2.5 * umath.log10(f_u) s = (x_u**2 + y_u**2)**0.5 posang = ((umath.atan2(x_u, y_u) * 180 / np.pi)) if posang.nominal_value < 0: posang = 360 + posang cr = 1 / f_u cprint("\nResults binary fit (χ2 = %2.1f, nσ = %2.1f):" % (chi2, nsigma), "cyan") cprint("-------------------", "cyan") print("Sep = %2.1f +/- %2.1f mas" % (s.nominal_value, s.std_dev)) print("Theta = %2.1f +/- %2.1f deg" % (posang.nominal_value, posang.std_dev)) print("CR = %2.1f +/- %2.1f" % (cr.nominal_value, cr.std_dev)) print("dm = %2.2f +/- %2.2f" % (dm.nominal_value, dm.std_dev)) res = { 'best': { 'model': 'binary_res', 'dm': dm.nominal_value, 'theta': posang.nominal_value, 'sep': s.nominal_value, 'diam': fit["diam*"], 'x0': 0, 'y0': 0 }, 'uncer': { 'dm': dm.std_dev, 'theta': posang.std_dev, 'sep': s.std_dev }, 'chi2': chi2, 'nsigma': nsigma, 'comp': o.bestFit["best"] } return res
def candid_grid( input_data: Union[str, List[str]], step: int = 10, rmin: float = 20, rmax: float = 400, diam: float = 0, obs: Optional[List[str]] = None, extra_error_cp: float = 0, err_scale: float = 1, extra_error_v2: float = 0, instruments=None, doNotFit=None, ncore: int = 1, save: bool = False, outputfile: Optional[str] = None, verbose: bool = False, ): """This function is an user friendly interface between the users of amical pipeline and the CANDID analysis package (https://github.com/amerand/CANDID). Parameters: ----------- `input_data`: oifits file names or list of oifits files,\n `step`: step used to compute the binary grid positions,\n `rmin`, `rmax`: Bounds of the grid [mas],\n `diam`: Stellar diameter of the primary star [mas] (default=0),\n `obs`: List of observables to be fitted (default: ['cp', 'v2']),\n `doNotFit`: Parameters not fitted (default: ['diam*']),\n `verbose`: print some informations {default: False}. Outputs: -------- `res` {dict}: Dictionnary of the results ('best'), uncertainties ('uncer'), reduced chi2 ('chi2') and sigma detection ('nsigma'). """ if obs is None: obs = ["cp", "v2"] if doNotFit is None: doNotFit = ["diam*"] cprint(" | --- Start CANDID fitting --- :", "green") o = candid.Open( input_data, extra_error=extra_error_cp, err_scale=err_scale, extra_error_v2=extra_error_v2, instruments=instruments, ) o.observables = obs o.fitMap( rmax=rmax, rmin=rmin, ncore=ncore, fig=0, step=step, addParam={"diam*": diam}, doNotFit=doNotFit, verbose=verbose, ) if save: if isinstance(input_data, list): first_input = input_data[0] else: first_input = input_data filename = os.path.basename(first_input) + "_detection_map_candid.pdf" if outputfile is not None: filename = outputfile plt.savefig(filename, dpi=300) fit = o.bestFit["best"] e_fit = o.bestFit["uncer"] chi2 = o.bestFit["chi2"] nsigma = o.bestFit["nsigma"] f = fit["f"] / 100.0 e_f = e_fit["f"] / 100.0 if (e_f < 0) or (e_fit["x"] < 0) or (e_fit["y"] < 0): print("Warning: error dm is negative.") e_f = abs(e_f) e_fit["x"] = 0 e_fit["y"] = 0 f_u = ufloat(f, e_f) x, y = fit["x"], fit["y"] x_u = ufloat(x, e_fit["x"]) y_u = ufloat(y, e_fit["y"]) dm = -2.5 * umath.log10(f_u) s = (x_u ** 2 + y_u ** 2) ** 0.5 posang = umath.atan2(x_u, y_u) * 180 / np.pi if posang.nominal_value < 0: posang = 360 + posang cr = 1 / f_u cprint(f"\nResults binary fit (χ2 = {chi2:2.1f}, nσ = {nsigma:2.1f}):", "cyan") cprint("-------------------", "cyan") print(f"Sep = {s.nominal_value:2.1f} +/- {s.std_dev:2.1f} mas") print(f"Theta = {posang.nominal_value:2.1f} +/- {posang.std_dev:2.1f} deg") print(f"CR = {cr.nominal_value:2.1f} +/- {cr.std_dev:2.1f}") print(f"dm = {dm.nominal_value:2.2f} +/- {dm.std_dev:2.2f}") res = { "best": { "model": "binary_res", "dm": dm.nominal_value, "theta": posang.nominal_value, "sep": s.nominal_value, "diam": fit["diam*"], "x0": 0, "y0": 0, }, "uncer": {"dm": dm.std_dev, "theta": posang.std_dev, "sep": s.std_dev}, "chi2": chi2, "nsigma": nsigma, "comp": o.bestFit["best"], } return res