Exemple #1
0
    def apply_fix(self):
        """
        Fix the affected file

        This should replicate the Unix commands:

        ncap2 -h -s 'tos=tos-273.15f' filename.nc filename.nc.temp
        rm filename.nc
        mv filename.nc.temp filename.nc
        ncatted -h -a units,tos,m,c,'degC' filename.nc
        """
        if not self._is_kelvin():
            raise ExistingAttributeError(self.filename, 'units',
                                         'Units are not K.')

        self.command = (f"ncap2 -h -s '{self.variable_name}="
                        f"{self.variable_name}-273.15f'")
        self._run_nco_command(Ncap2Error)
        units_command = (
            f"ncatted -h -a units,{self.variable_name},m,c,'degC' "
            f"{os.path.join(self.directory, self.filename)}")
        try:
            run_command(units_command)
        except Exception:
            raise NcattedError(
                type(self).__name__, self.filename, units_command,
                traceback.format_exc())
Exemple #2
0
    def _run_ncatted(self, nco_mode):
        """
        Run the command

        :param str nco_mode: The mode to run nco in.
        """
        for attr_name in [
                'attribute_name', 'attribute_visibility', 'new_value'
        ]:
            attr_value = getattr(self, attr_name, None)
            if attr_value is None:
                raise InstanceVariableNotDefinedError(
                    type(self).__name__, attr_name)

        # Aiming for:
        # ncatted -h -a branch_time_in_parent,global,o,d,10800.0

        quote_mark = "'" if isinstance(self.new_value, str) else ""

        cmd = 'ncatted -h -a {},{},{},{},{}{}{} {}'.format(
            self.attribute_name, self.attribute_visibility, nco_mode,
            self.attribute_type, quote_mark, self.new_value, quote_mark,
            os.path.join(self.directory, self.filename))
        try:
            run_command(cmd)
        except Exception:
            raise NcattedError(
                type(self).__name__, self.filename, cmd,
                traceback.format_exc())
Exemple #3
0
def _set_attribute(filepath, attr_name, attr_value):
    """
    Overwrite the specified global attribute value on the specified netCDF
    file.

    :param str filepath: The name of the netCDF file to update
    :param str attr_name: The name of the attribute to set
    :param str attr_value: The new value of the specified attribute
    :raises RunTimeError: if ncatted doesn't complete successfully
    """
    cmd = "ncatted -h -a {},global,o,c,'{}' {}".format(attr_name, attr_value,
                                                       filepath)
    run_command(cmd)
Exemple #4
0
    def apply_fix(self):
        """
        Use cdo to set the reference time.
        """
        self.command = f"ncks -h -A -v height {self.reference_file}"
        self._run_ncks_command()

        units_command = (f"ncatted -h -a coordinates,{self.variable_name},o,c,"
                         f"'height' "
                         f"{os.path.join(self.directory, self.filename)}")
        try:
            run_command(units_command)
        except Exception:
            raise NcattedError(
                type(self).__name__, self.filename, units_command,
                traceback.format_exc())
Exemple #5
0
    def apply_fix(self):
        """
        Run ncpdq and then swap the columns in lat_bnds.
        """
        # check that the latitude is decreasing and that the fix is actually
        # needed
        if not self._is_lat_decreasing():
            raise ExistingAttributeError(self.filename, 'latitude',
                                         'Latitude is not decreasing.')
        self.command = 'ncpdq -a -lat'
        self._run_nco_command(NcpdqError)

        original_nc = os.path.join(self.directory, self.filename)
        bnds_file = original_nc + '.bnds'
        corrected_bnds_file = bnds_file + '_corr'

        # Remove any temporary files left over from a previous failed
        # run as they can prevent ncks and ncpdq from running.
        for filename in (bnds_file, corrected_bnds_file):
            if os.path.exists(filename):
                os.remove(filename)

        commands = [
            # Copy lat_bnds to a new file
            f'ncks -v lat_bnds {original_nc} {bnds_file}',
            # Swap the colums
            f'ncpdq -a -bnds {bnds_file} {corrected_bnds_file}',
            # Remove history from lat_bnds as this is pasted back into the file
            f'ncatted -h -a history,global,d,, {corrected_bnds_file}',
            # Paste the fixed bnds back into the original file
            f'ncks -A -v lat_bnds {corrected_bnds_file} {original_nc}'
        ]
        for cmd in commands:
            try:
                run_command(cmd)
            except Exception:
                exceptions = {
                    'ncks': NcksError,
                    'ncpdq': NcpdqError,
                    'ncatted': NcattedError
                }
                cmd_name = cmd.split()[0]
                raise exceptions[cmd_name](type(self).__name__, self.filename,
                                           cmd, traceback.format_exc())
        os.remove(bnds_file)
        os.remove(corrected_bnds_file)
Exemple #6
0
    def _run_command(self, cmd, cmd_error):
        """
        Run `cmd` and raise `cmd_error` if it fails when the specified
        temporary files are deleted.

        :param str cmd: The command to run
        :param PreProcError cmd_error: The exception to raise if the command
            fails
        """
        try:
            run_command(cmd)
        except Exception:
            for fn in self.intermediate_files:
                if os.path.exists(fn):
                    os.remove(fn)
            raise cmd_error(
                type(self).__name__, self.filename, cmd,
                traceback.format_exc())
Exemple #7
0
    def _run_nco_command(self, command_error):
        """
        Run the nco command
        """
        output_file = os.path.join(self.directory, self.filename)
        temp_file = output_file + '.temp'
        # Remove any temporary file left over from a previous failed
        # run as it could prevent some nco commands from running.
        if os.path.exists(temp_file):
            os.remove(temp_file)

        cmd = f'{self.command} {output_file} {temp_file}'
        try:
            run_command(cmd)
        except Exception:
            if os.path.exists(temp_file):
                os.remove(temp_file)
            raise command_error(
                type(self).__name__, self.filename, cmd,
                traceback.format_exc())

        os.remove(output_file)
        os.rename(temp_file, output_file)