예제 #1
0
    def make_lightcurve(self,
        inclinations=None,
        n_gridz=None,
        H0=None,
        R0=None,
        H_power=None,
        n_angle=None,
        dtheta=None,
        theta=None,
        unit="deg",
        n_radius=None,
        dr=None,
        lcurve_show=False,
        lcurve_savefig=False,
        lcurve_savecsv=False,
        dprofile_show=False,
        dprofile_savefig=False,
        normalizations=["stellar"],
        short_title=True,
        outfolder=None,
    ):
        """Makes a lightcurve by calling the other methods for each orientation
        of the dataset. Sort of a main method.

        TODO: Complete docstring.
        """

        # Default setting for theta is a full revolution:
        if theta is None:
            if unit == "rad":
                theta = 2*np.pi
            elif unit == "deg":
                theta = 360.
            elif unit == "arcmin":
                theta = 360. * 60
            elif unit == "arcsec":
                theta = 360. * 3600

        if inclinations is None:
            inclinations = self.inclinations
        # If the inclination is a single number, put it in a list:
        inclinations = func.to_list(inclinations)

        if H0 is None:
            H0 = self.H0
        if R0 is None:
            R0 = self.R0
        if H_power is None:
            H_power = self.H_power

        if n_angle is None:
            n_angle = int(round(float(theta) / dtheta))
        elif dtheta is None:
            dtheta = float(theta) / n_angle

        angles = np.linspace(0, theta-dtheta, n_angle)
        lightcurve = np.zeros((len(inclinations), n_angle))

        # Density profile:
        if dprofile_show or dprofile_savefig:
            fig_dprof = plt.figure(figsize=(12,6))
            fig_dprof.suptitle("%s" % self.dataname)
            axes_dprof = []
            nplots = [
                int(round(np.sqrt(len(inclinations)))),  # No of columns.
                int(np.ceil(np.sqrt(len(inclinations)))),  # No of rows.
                len(inclinations),  # Total no of density profile plots.
            ]
            radius_max = None
            density_min = np.inf
            density_max = None
            plotcolors = ("b", "g", "r", "c", "m", "y")
            plotlinestyles = ('-', '--', '-.', ':')

        for i, angle in enumerate(angles):
            print "%6.2f / %g" % (angle, theta)
            self.rotate(
                angle_z=angle,
                unit=unit,
            )
            for k, star in enumerate(self.stars):
                sylinder = Sylinder(
                    star=star,
                    data=self.get_sylinder(star=star),
                    unit=self.unit,
                    radius_in=self.radius_in,
                    radius_out=self.radius_out,
                    kappa=self.kappa
                )
                for j, inclination in enumerate(inclinations):
                    sylinder.space_sylinder(
                        inclination=inclination,
                        unit=unit,
                        H0=H0,
                        R0=R0,
                        H_power=H_power,
                        n_steps=n_radius,
                        n_gridz=n_gridz,
                        dr=dr,
                    )
                    lightcurve[j, i] += sylinder.integrate()

                    # Density profile:
                    if (dprofile_show or dprofile_savefig) and (k < 4):
                        # Only do for maximum 4 stars.
                        if (i == 0) and (k == 0):  # Only initialize axes once:
                            axes_dprof.append(fig_dprof.add_subplot(
                                nplots[1],
                                nplots[0],
                                j+1,
                            ))
                        if k == 0:
                            axes_dprof[j].plot(
                                sylinder.radiuses,
                                sylinder.densities *
                                    u.Unit(
                                        u.Unit(self.unit["mass"]) /
                                        u.Unit(self.unit["distance"])**3
                                    ).to("gram/cm3"),
                                "%s%s" % (plotcolors[i], plotlinestyles[k]),
                                label="%3g" % angle,
                            )
                        else:
                            axes_dprof[j].plot(
                                sylinder.radiuses,
                                sylinder.densities *
                                    u.Unit(
                                        u.Unit(self.unit["mass"]) /
                                        u.Unit(self.unit["distance"])**3
                                    ).to("gram/cm3"),
                                "%s%s" % (plotcolors[i], plotlinestyles[k]),
                            )
                        for l, density in enumerate(sylinder.densities):
                            if density == 0:
                                if sylinder.radiuses[l] > radius_max:
                                    radius_max = sylinder.radiuses[l]
                                break
                        for l, density in enumerate(sylinder.densities):
                            if density > density_max:
                                density_max = density
                            if density < density_min:
                                density_min = density
                        axes_dprof[j].set_title("inc=%2g" % inclination)

        # Density profile:
        if density_min == 0:
            density_min = 1e-30
        if dprofile_show or dprofile_savefig:
            if radius_max is None:
                radius_max = self.radius_out
            else:
                radius_max *= 1.01  # Small buffer.
            for j in range(nplots[2]):  # All subplots.
                axes_dprof[j].set_xlim([self.radius_in, radius_max])
                axes_dprof[j].set_ylim([density_min, density_max])
                try:
                    axes_dprof[j].set_yscale("log")  # Does not work if all 0s.
                except:
                    pass
                axes_dprof[j].yaxis.set_major_formatter( \
                    ticker.FormatStrFormatter('%.1e'))
            for j in range(nplots[0]):  # Bottom row.
                axes_dprof[~j].set_xlabel("radius [a]")
            for j in range(nplots[2] - nplots[0]):  # All except bottom row.
                axes_dprof[j].set_xticklabels([])
            for j in range(0, nplots[2], nplots[0]):  # Left coumn.
                axes_dprof[j].set_ylabel("density [g/cm^3]")
            axes_dprof[nplots[0]-1].legend(  # Only top right.
                title="v.angle [deg]=",
                loc="best",
            )

        print "%6.2f / %g" % (theta, theta)

        if "all" in normalizations:
            normalizations = ["stellar", "max", "mean"]

        for normalization in normalizations:

            if "stellar" in normalization or "unobscured" in normalization:
                unobscured_flux = 0.
                for star in self.stars:
                    unobscured_flux += star.intensity
                lightcurve /= unobscured_flux
            elif "max" in normalization:
                for j, maxflux in enumerate(lightcurve.max(axis=1)):
                    if maxflux > 0:
                        lightcurve[j] /= maxflux
                    # else lightcurve[j] is all zeros, so avoid dividing by 0
            elif "mean" in normalization:
                for j, maxflux in enumerate(lightcurve.max(axis=1)):
                    if maxflux > 0:
                        lightcurve[j] /= maxflux
                    # else lightcurve[j] is all zeros, so avoid dividing by 0

            if lcurve_show or lcurve_savefig:
                fig = plt.figure(figsize=(12,6))
                fig.gca().get_yaxis().get_major_formatter().set_useOffset(False)
                    # Always use absolute labels and not offsets.
                plt.minorticks_on()  # Turn default minorticks on for y-axis.
                ax = fig.add_subplot(1,1,1)
                ax.set_xlim([0, 360])
                ax.set_xticks(range(0, 360+1, 30))
                ax.xaxis.set_minor_locator(ticker.AutoMinorLocator(3))
                    # A major tick every 30 deg and minor tick every 10 deg.

                # Set a specific tick step (hardcoded switch):
                if False:
                    step = 0.1
                    stepmin = lightcurve.min()
                    stepmax = lightcurve.max()
                    stepdiff = stepmax - stepmin
                    stepmin -= stepdiff  # Increase the range of the ticks just
                    stepmax += stepdiff  # to be sure.
                    stepmin = step * round(stepmin / step)  # Round off to the
                    stepmax = step * round(stepmax / step)  # nearest step.
                    ax.set_yticks(np.linspace(
                        stepmin,
                        stepmax,
                        int(round((stepmax - stepmin) / step)) + 1,
                    ))
                    # Set a specific label step (hardcoded switch):
                    if True:
                        # Automatic minor ticks between steps.
                        ax.yaxis.set_minor_locator(ticker.AutoMinorLocator(5))
                    elif True:
                        # Manual label removal of certain steps.
                        steplabel = 2 * step
                        ylabels = []
                        for ytick in ax.get_yticks():
                            if (int(round(ytick/step)) %
                                int(round(steplabel/step)) == 0
                            ):
                                ylabels.append(ytick)
                            else:
                                ylabels.append("")
                        ax.set_yticklabels(ylabels)

            for j, inclination in enumerate(inclinations):

                starradius = ""
                starflux = ""
                for star in self.stars:
                    starradius += "%g-" % star.radius
                    starflux += "%g-" % star.intensity
                starradius = starradius.rstrip("-")
                starflux = starflux.rstrip("-")
                header = (
                    "%s, H=%g, kappa=%g, "
                    "r_star=%s, flux_star=%s, r_in=%g, r_out=%g, dr=%g, "
                    "dtheta=%g%s, inc=%g%s"
                    % ( self.dataname,
                        H0,
                        self.kappa,
                        starradius,
                        starflux,
                        self.radius_in,
                        self.radius_out,
                        (self.radius_out - self.radius_in) / n_radius,
                        float(theta) / n_angle,
                        unit,
                        inclination,
                        unit,
                    )
                )
                if lcurve_savecsv:
                    outname = (
                        "%s__H=%g__"
                        "r_in=%g__r_out=%g__"
                        "inc=%02g__%snorm"
                        % ( self.dataname,
                            H0,
                            self.radius_in,
                            self.radius_out,
                            inclination,
                            normalization,
                        )
                    )
                    if outfolder is None:
                        outfolder = self.outfolder
                    func.make_folder(outfolder)
                    func.make_folder(outfolder + "/csvtables")
                    outfile = open("%s/csvtables/%s.csv" \
                        % (outfolder, outname), "w")
                    outfile.write("#" + header + "\n")
                    for angle, flux in zip(angles, lightcurve[j]):
                        outfile.write("%f,%f\n" % (angle, flux))
                    outfile.close()

                if lcurve_show or lcurve_savefig:
                    ax.plot(
                        angles,
                        lightcurve[j],
                        label="%2g" % inclinations[j],
                    )

            if lcurve_show or lcurve_savefig:
                if short_title:
                    # Only use the name of the data in the title.
                    ax.set_title(self.dataname)
                    ax.set_position([0.10, 0.10, 0.80, 0.83])
                else:
                    # Use all metadata in the title.
                    ax.set_title(
                        "\n".join(textwrap.wrap(header.split(", inc")[0], 70))
                    )
                    ax.set_position([0.10, 0.10, 0.80, 0.80])
                ax.set_xlabel("viewing angle [degree]")
                ax.set_ylabel("flux [%s flux]" % normalization)
                ax.legend(
                    bbox_to_anchor=(1.11, 0.5),
                    title="inc [deg]=",
                    loc="right",
                    borderaxespad=0.,
                )

            if lcurve_savefig or dprofile_savefig:
                if outfolder is None:
                    outfolder = self.outfolder
                func.make_folder(outfolder)
                func.make_folder(outfolder + "/plots")
                outname = (
                    "%s__H=%g__"
                    "r_in=%g__r_out=%g__"
                    % ( self.dataname,
                        H0,
                        self.radius_in,
                        self.radius_out,
                    )
                )

            if lcurve_savefig:
                fig.savefig("%s/plots/%s%snorm.png" \
                    % (outfolder, outname, normalization))
            if dprofile_savefig:
                fig_dprof.savefig("%s/plots/%sdprofiles.png" \
                    % (outfolder, outname))

        if lcurve_show or dprofile_show:
            raw_input("Press <enter> to view the plots: ")
            if lcurve_show:
                fig.show()
            if dprofile_show:
                fig_dprof.show()
            raw_input("Press <enter> to close plots and exit: ")
예제 #2
0
            print "CirBinDis version %s" % __version__
        sys.exit(1)
    try:
        input_ = xmltodict.parse(infile)["input"]
    except Exception:
        print (
            "usage: python %s input_file.xml\n"
            "  Specify the (path)name of an input xml file. "
            % sys.argv[0]
        )
        raise
    infile.close()
    input_ = func.extract_booleans(input_)


    for radius_in in func.to_list(input_["radius_in"], float):
        if radius_in is None or np.isnan(radius_in):
            radius_largest = 0.
            for stardict in func.to_list(input_["star"]):
                star = Star(stardict)
                radius = np.linalg.norm(star.position) + star.radius
                if radius > radius_largest:
                    radius_largest = radius
            radius_in = radius_largest

        for radius_out in func.to_list(input_["radius_out"], float):
            if radius_out is None or np.isnan(radius_out):
                radius_out = np.inf

            have_resaved = False