def load_p0(snapdir,
            snapnum,
            ahf_path=None,
            Rvir=None,
            loud=1,
            keys_to_extract=None,
            calculate_qtys=True):
    '''Loads gas particle snapshot and adds `CoordinatesRelative`, `r`, `r_scaled`, `Vi`, `posC`, and `Rvir` columns to dictionary.
    `Rvir` argument must be in units of physical kpc. If `ahf_path` is passed instead, `Rvir` will be read in with units physical kpc.
    '''
    p0 = openSnapshot(snapdir,
                      snapnum,
                      0,
                      loud=loud,
                      keys_to_extract=keys_to_extract)
    p1 = openSnapshot(snapdir,
                      snapnum,
                      1,
                      loud=loud,
                      keys_to_extract=['Coordinates', 'Masses'])

    if loud:
        print(f"Loading redshift {p0['Redshift']}")

    posC = halo_center_wrapper(p1)[0]

    if ahf_path:
        _, Rvir = load_AHF('',
                           snapnum,
                           p0['Redshift'],
                           hubble=p0['HubbleParam'],
                           ahf_path=ahf_path,
                           extra_names_to_read=[])

    # position relative to center
    p0['CoordinatesRelative'] = p0['Coordinates'] - posC

    if calculate_qtys:
        # distance from halo center
        p0['r'] = np.linalg.norm(p0['CoordinatesRelative'], axis=1)

        # distance from halo center in units of virial radius
        p0['r_scaled'] = p0['r'] / Rvir

        # volume of each particle in units (physical kpc)^3
        p0['Vi'] = p0['Masses'] / p0['Density']

        p0['posC'] = posC  #halo center in units physical kpc
        p0['Rvir'] = Rvir  #virial radius in units physical kpc

    return p0
Esempio n. 2
0
def FIREtoVTK(snapdir, snapnum, ptype, datacols, fn_out):
    pdata = openSnapshot(snapdir, snapnum, ptype, loud=1)
    print(f"Loaded redshift {pdata['Redshift']}")

    x, y, z = pdata['Coordinates'][:,
                                   0].copy(), pdata['Coordinates'][:, 1].copy(
                                   ), pdata['Coordinates'][:, 2].copy()
    data = {k: pdata[k].copy() for k in datacols}
    Points1d(x, y, z, data, fn_out)
Esempio n. 3
0
    def openSnapshot(self,
                     load_stars=0,
                     keys_to_extract=None,
                     star_keys_to_extract=None):

        if (self.snapdict is not None
                and ('star_snapdict' in self.__dict__
                     and self.star_snapdict is not None)):
            return
        elif not self.extract_galaxy:
            ## isolated galaxy huh? good choice.
            ##  don't worry, cosmological will be overwritten in openSnapshot if
            ##  HubbleParam != 1, none of the coordinates will be offset
            ##  and the galaxy won't be rotated or extracted
            snapdict = openSnapshot(self.snapdir,
                                    self.snapnum,
                                    ptype=0,
                                    cosmological=0,
                                    keys_to_extract=keys_to_extract)
            if load_stars:
                star_snapdict = openSnapshot(
                    self.snapdir,
                    self.snapnum,
                    ptype=4,
                    cosmological=0,
                    keys_to_extract=star_keys_to_extract)

                ## could just be a sub-snapshot that's been pre-extracted
                if not star_snapdict['cosmological']:
                    raise Exception("Need to open type 1 and type 2 parts")
        else:
            snapdict = openSnapshot(self.snapdir,
                                    self.snapnum,
                                    ptype=0,
                                    cosmological=1,
                                    keys_to_extract=keys_to_extract)

            if load_stars:
                star_snapdict = openSnapshot(
                    self.snapdir,
                    self.snapnum,
                    ptype=4,
                    cosmological=1,
                    keys_to_extract=star_keys_to_extract)
            else:
                star_snapdict = None

            ## cosmological snapshot it is then...
            scom, rvir, vesc = load_AHF(self.snapdir,
                                        self.snapnum,
                                        snapdict['Redshift'],
                                        ahf_path=self.ahf_path)

            ## filter all the keys in the snapdict as necessary to extract a spherical volume
            ##  centered on scom (the halo center), using 3*frame_half_width
            diskFilterDictionary(
                star_snapdict if load_stars else None,
                snapdict,
                radius=3 * self.frame_half_width,  ## particles to mask
                orient_radius=3 * self.
                frame_half_width,  ## particles to orient on (in principle could orient on inner region and want larger region)
                scom=scom,
                orient_stars=load_stars)

        ## bind the snapdicts
        self.snapdict = snapdict
        if load_stars:
            self.star_snapdict = star_snapdict
Esempio n. 4
0
    def loadData(self, com_offset=False):
        """Loads FIRE snapshot data using Alex Gurvich's
        :func:`firefly.data_reader.snapshot_utils.openSnapshot`.
        (reproduced from https://github.com/agurvich/abg_python) and binds it to a 
        corresponding :class:`firefly.data_reader.ParticleGroup` instance.

        :param com_offset: flag to offset all coordinates by the COM of the 
            snapshot, defaults to False 
        :type com_offset: bool, optional
        """

        com = None

        for ptype, UIname, dec_factor in list(
                zip(self.ptypes, self.UInames, self.decimation_factors))[::-1]:
            print("Loading ptype %d" % ptype)

            ## load each particle type's snapshot data
            snapdict = openSnapshot(
                self.snapdir,
                self.snapnum,
                int(ptype),  ## ptype should be 1,2,3,4,etc...
                keys_to_extract=['Coordinates'] + self.fields +
                ['Masses'] * com_offset)

            if com_offset and com is None:
                com = np.zeros(3)
                ## use concentric shells to find an estimate
                ##  for the center of mass
                for i in range(4):
                    rs = np.sqrt(np.sum(snapdict['Coordinates']**2, axis=1))
                    rmax = np.nanmax(rs) / 10**i

                    rmask = rs <= rmax

                    if np.sum(rmask) == 0:
                        break

                    print("Centering on particles within %.2f kpc" % rmax)

                    ## compute the center of mass of the particles within this shell
                    this_com = (np.sum(snapdict['Coordinates'][rmask] *
                                       snapdict['Masses'][rmask][:, None],
                                       axis=0) /
                                np.sum(snapdict['Masses'][rmask]))

                    snapdict['Coordinates'] -= this_com

                    ## keep track of total com
                    com += this_com

                vcom = (np.sum(snapdict['Velocities'][rmask] *
                               snapdict['Masses'][rmask][:, None],
                               axis=0) / np.sum(snapdict['Masses'][rmask]))

                snapdict['Velocities'] -= vcom

            elif com is not None:
                snapdict['Coordinates'] -= com
                snapdict['Velocities'] -= vcom

            ## initialize output arrays for fields
            tracked_names = []
            tracked_arrays = []
            tracked_filter_flags = []
            tracked_colormap_flags = []

            for field, filterFlag, colormapFlag, magFlag, logFlag in list(
                    zip(self.fields, self.filterFlags, self.colormapFlags,
                        self.magFlags, self.logFlags)):

                ## easypeasy, just read from the snapdict
                if field in snapdict:
                    arr = snapdict[field]

                ## if asked to compute galactocentric radius from the coordinates
                elif field == 'GCRadius':
                    arr = np.sqrt(np.sum(snapdict['Coordinates']**2, axis=1))
                ## elif field == ' ':
                ## NOTE: define custom shortcut field here
                else:
                    continue

                ## take the log and/or magnitude if requested
                if magFlag:
                    arr = np.linalg.norm(arr, axis=1)
                    field = 'mag%s' % field
                if logFlag:
                    arr = np.log10(arr)
                    field = 'log10%s' % field

                ## append this field into the arrays
                tracked_names = np.append(tracked_names, [field], axis=0)

                tracked_filter_flags = np.append(tracked_filter_flags,
                                                 [filterFlag],
                                                 axis=0)

                tracked_colormap_flags = np.append(tracked_colormap_flags,
                                                   [colormapFlag],
                                                   axis=0)

                tracked_arrays.append(arr)

            ## initialize a particleGroup instance
            ##  for this particle type
            self.particleGroups = np.append(self.particleGroups, [
                ParticleGroup(UIname,
                              snapdict['Coordinates'],
                              tracked_names=tracked_names,
                              tracked_arrays=tracked_arrays,
                              decimation_factor=dec_factor,
                              tracked_filter_flags=tracked_filter_flags,
                              tracked_colormap_flags=tracked_colormap_flags,
                              doSPHrad='SmoothingLength' in tracked_names)
            ],
                                            axis=0)

        ## reverse the order to match specified ptypes order
        self.particleGroups = self.particleGroups[::-1]

        ## save the filenames that were opened
        ##  so you can re-open them yourself in that order if you need to
        for particleGroup in self.particleGroups:
            particleGroup.filenames_opened = snapdict['fnames']

            ## add this particle group to the reader's settings file
            self.settings.attachSettings(particleGroup)

        return self.particleGroups
Esempio n. 5
0
    def loadData(self):
        """
        Loads the snapshot data using Alex Gurvich's openSnapshot utility
        (originally from github.com/abg_python) and binds it to a ParticleGroup.
        Converts to physical coordinates (removes factors of h and scale factor)
        and will calculate the temperature and age in gyr of star particles for you
        (You're welcome!!). Also adds these particle groups to the reader's options file.
        """
        for ptype, UIname, dec_factor in list(
                zip(self.ptypes, self.UInames, self.decimation_factors)):
            FireflyMessage("Loading ptype %s" % ptype)
            snapdict = openSnapshot(
                self.snapdir,
                self.snapnum,
                int(ptype),  ## ptype should be PartType4,etc...
                keys_to_extract=['Coordinates'] + self.returnKeys)

            tracked_names,tracked_arrays,tracked_filter_flags,tracked_colormap_flags = [],[],[],[]
            for returnKey, filterFlag, colormapFlag, doMag, doLog in list(
                    zip(self.returnKeys, self.filterFlags, self.colormapFlags,
                        self.doMags, self.doLogs)):
                if returnKey in snapdict:
                    arr = snapdict[returnKey]
                ## if asked to compute galactocentric radius from the coordinates
                elif returnKey in ['GCRadius']:
                    arr = np.sqrt(np.sum(snapdict['Coordinates']**2, axis=1))
                else:
                    continue

                if doLog:
                    arr = np.log10(arr)
                    returnKey = 'log10%s' % returnKey
                elif doMag:
                    arr = np.linalg.norm(arr, axis=1)
                    returnKey = 'mag%s' % returnKey

                tracked_names = np.append(tracked_names, [returnKey], axis=0)

                tracked_filter_flags = np.append(tracked_filter_flags,
                                                 [filterFlag],
                                                 axis=0)

                tracked_colormap_flags = np.append(tracked_colormap_flags,
                                                   [colormapFlag],
                                                   axis=0)

                tracked_arrays.append(arr)

            self.particleGroups = np.append(self.particleGroups, [
                ParticleGroup(UIname,
                              snapdict['Coordinates'],
                              tracked_names=tracked_names,
                              tracked_arrays=tracked_arrays,
                              decimation_factor=dec_factor,
                              tracked_filter_flags=tracked_filter_flags,
                              tracked_colormap_flags=tracked_colormap_flags,
                              doSPHrad='SmoothingLength' in tracked_names)
            ],
                                            axis=0)

            ## save the filenames that were opened (so you can re-open them yourself in that order)
            self.particleGroups[-1].filenames_opened = snapdict['fnames']

            ## add this particle group to the reader's options file
            self.options.addToOptions(self.particleGroups[-1])

        return self.particleGroups
def load_allparticles(snapdir,
                      snapnum,
                      particle_types=[0, 1, 2, 4, 5],
                      keys_to_extract={},
                      ptype_centering=1,
                      Rvir=None,
                      ahf_path=None,
                      loud=1):
    '''Loads all particle data from simulation directory `snapdir` for a snapshot  `snapnum`, and returns dict of dicts for each particle type.

    Notes:
        - `posC` (array of len 3; halo center in units physical kpc) is added to each particle dicts. 
        - If either `Rvir` or `ahf_path` is defined, `r_scaled` (array; particle distances from halo center in units of Rvir) and `Rvir` (scalar; virial radius in units physical kpc) columns are added to each particle dict.
        - If a particle dict contains `'Masses'` and `'Density'` keys, `Vi` (array; particle volumes in units (physical kpc)^3) column is added to that particle dict.

    Optional parameters:
        `particle_types`: list of particle types to load
        `keys_to_extract`: dict that maps each particle type to a list of keys to read. If dict does not contain a particle type, ALL keys are read in for that particle type.
        `ptype_centering`: particle type used to find halo center (shrinking sphere method)
        `Rvir`: virial radius in units of physical kpc
        `ahf_path`: directory with AHF file. If defined, `Rvir` will be read in with units physical kpc (this will overwrite any value passed for `Rvir`).
        `loud`: verbose output if `True`
    '''
    keys_to_extract = {
        **{ptype: None
           for ptype in particle_types},
        **keys_to_extract
    }  #load all keys for particle types for which keys were not given

    part = {
        ptype: openSnapshot(snapdir,
                            snapnum,
                            ptype,
                            loud=loud,
                            keys_to_extract=keys_to_extract[ptype])
        for ptype in particle_types
    }

    if loud:
        print(f"Loading redshift {part[particle_types[0]]['Redshift']}")

    posC = halo_center_wrapper(part[ptype_centering])[0]

    if ahf_path:
        _, Rvir = load_AHF('',
                           snapnum,
                           part[particle_types[0]]['Redshift'],
                           hubble=part[particle_types[0]]['HubbleParam'],
                           ahf_path=ahf_path,
                           extra_names_to_read=[])

    for ptype, p_i in part.items():
        p_i['posC'] = posC  #halo center in units physical kpc

        if Rvir is not None:
            p_i['Rvir'] = Rvir  #virial radius in units physical kpc

            # position relative to center
            p_i_CoordinatesRelative = p_i['Coordinates'] - posC

            # distance from halo center
            p_i_r = np.linalg.norm(p_i_CoordinatesRelative, axis=1)

            # distance from halo center in units of virial radius
            p_i['r_scaled'] = p_i_r / Rvir

        if ('Masses' in p_i) and ('Density' in p_i):
            # volume of each particle in units (physical kpc)^3
            p_i['Vi'] = p_i['Masses'] / p_i['Density']

    return part