python - 重命名 pcraster Mapstack

标签 python netcdf

我有一个文件夹,里面装满了 20 年降水 pcraster map 堆栈,我已经设法从原始 netcdf 文件中提取出我感兴趣区域的降水值,并将其重命名为该值以避免混淆

precip.19810101 
precip.19810102 
precip.19810103 
precip.19810104 
precip.19810105
...
precip.20111231

但在那之后,我想根据这个日期序列将所有文件重命名为 pcraster mapstack

precip00.001
precip00.002
precip00.003
precip00.004
...

我是Python初学者,有什么帮助或例子可以帮助我弄清楚如何做到这一点吗? 谢谢

最佳答案

这是我根据我曾经编写的一些旧 Python 脚本整理的内容:

#! /usr/bin/env python
# Rename PCRaster map stack with names following prefix.yyymmmdd to stack with valid
# PCRaster time step numbers
# Johan van der Knijff
#
# Example input stack:
#
# precip.19810101
# precip.19810102
# precip.19810103
# precip.19810104
# precip.19810105
#
# Then run script with following arguments:
#
# python renpcrstack.py precip 1
#
# Result:
#
# precip00.001
# precip00.002
# precip00.003
# precip00.004
# precip00.005
#

import sys
import os
import argparse
import math
import datetime
import glob

# Create argument parser
parser = argparse.ArgumentParser(
    description="Rename map stack")

def parseCommandLine():
    # Add arguments
    parser.add_argument('prefix',
                        action="store",
                        type=str,
                        help="prefix of input map stack (also used as output prefix)")
    parser.add_argument('stepStartOut',
                        action="store",
                        type=int,
                        help="time step number that is assigned to first map in output stack")

    # Parse arguments
    args = parser.parse_args()

    return(args)

def dateToJulianDay(date):

    # Calculate Julian Day from date
    # Source: https://en.wikipedia.org/wiki/Julian_day#Converting_Julian_or_Gregorian_calendar_date_to_Julian_day_number

    a = (14 - date.month)/12
    y = date.year + 4800 - a
    m = date.month +12*a - 3

    JulianDay = date.day + math.floor((153*m + 2)/5) + 365*y + math.floor(y/4) \
        - math.floor(y/100) + math.floor(y/400) - 32045

    return(JulianDay)

def genStackNames(prefix,start,end, stepSize):
    # Generate list with names of all maps
    # map name is made up of 11 characters, and chars 8 and 9 are
    # separated by a dot. Name starts with prefix, ends with time step
    # number and all character positions in between are filled with zeroes

    # define list that will contain map names
    listMaps = []

    # Count no chars prefix
    charsPrefix = len(prefix)

    # Maximum no chars needed for suffix (end step)
    maxCharsSuffix = len(str(end))

    # No of free positions between pre- and suffix
    noFreePositions = 11 - charsPrefix - maxCharsSuffix

    # Trim prefix if not enough character positions are available 
    if noFreePositions < 0:
        # No of chars to cut from prefix if 11-char limit is exceeded
        charsToCut = charsPrefix + maxCharsSuffix - 11
        charsToKeep = charsPrefix - charsToCut

        # Updated prefix
        prefix = prefix[0:charsToKeep]

        # Updated prefix length
        charsPrefix = len(prefix)

    # Generate name for each step

    for i in range(start,end + 1,stepSize):

        # No of chars in suffix for this step
        charsSuffix = len(str(i))

        # No of zeroes to fill
        noZeroes = 11 - charsPrefix - charsSuffix

        # Total no of chars right of prefix
        charsAfterPrefix = noZeroes + charsSuffix

        # Name of map

        thisName = prefix + (str(i)).zfill(charsAfterPrefix)
        thisFile = thisName[0:8]+"." + thisName[8:11]

        listMaps.append(thisFile)

    return listMaps    

def main():
    # Parse command line arguments
    args = parseCommandLine()
    prefix = args.prefix
    stepStartOut = args.stepStartOut

    # Glob pattern for input maps: prefix + dot + 8 char extension
    pattern = prefix + ".????????"

    # Get list of all input maps based on glob pattern
    mapsIn = glob.glob(pattern)

    # Set time format
    tfmt = "%Y%m%d"

    # Set up dictionary that will act as lookup table between Julian Days (key) 
    # and Date string
    jDayDate = {}

    for map in mapsIn:
        baseNameIn = os.path.splitext(map)[0]
        dateIn = os.path.splitext(map)[1].strip(".")

        # Convert to date / time format
        dt = datetime.datetime.strptime(dateIn, tfmt)

        # Convert date to Julian day number
        jDay = int(dateToJulianDay(dt))

        # Store as key-value pair in dictionary
        jDayDate[jDay] = dateIn

    # Number of input maps (equals number of key-value pairs)
    noMaps = len(jDayDate)

    # Create list of names for output files 
    mapNamesOut = genStackNames(prefix, stepStartOut, noMaps + stepStartOut -1, 1)

    # Iterate over Julian Days (ascending order)

    i = 0

    for key in sorted(jDayDate):
        # Name of input file
        fileIn = prefix + "."+ jDayDate[key]

        # Name of output file
        fileOut = mapNamesOut[i]

        # Rename file
        os.rename(fileIn, fileOut)

        print("Renamed " + fileIn + " ---> " + fileOut)

        i += 1

main()

(或者从 my Github Gist 下载代码。)

您可以从命令行运行它,使用 map 堆栈的前缀和第一个输出 map 的编号作为参数,例如:

python renpcrmaps.py precip 1

请注意,脚本会重命名文件,因此请确保复制原始 map 堆栈,以防出现问题(我对此仅进行了一些非常有限的测试!) .

此外,该脚本假定一个非稀疏输入 map 堆栈,即在每日 map 的情况下,每一天都存在一个输入 map 。如果缺少天数,输出 map 的编号将不是您所期望的。

所有日期到儒略日的内部转换在这里可能有点矫枉过正,但是一旦您开始进行更高级的转换,它确实会让事情变得更容易,因为它为您提供比日期字符串更容易操作的十进制数字。

关于python - 重命名 pcraster Mapstack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34837194/

相关文章:

python - 使用 Matplotlib 旋转矩阵

Python pandas 将 date_range 应用于两列

python - 命令提示符和 anaconda 提示符之间的区别

python - 在python中对数组列表进行分类

python - 如何使用 AWS SessionToken 从 pyspark 中的 S3 读取数据?

Python:KeyError:分析多个 netCDF 文件时 u'key'

r - 如何将 netcdf 文件中的数据写入 Excel 或文本文件?

r - 从 netcdf 文件 "increasing x y values expected"绘制数据时出错

python - 在Python basemap 中绘制gebco数据

netcdf - 截断 netCDF