重命名pcraster mapstack

时间:2016-01-17 10:14:41

标签: python netcdf

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

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

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

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

我是python的初学者,有什么帮助或示例让我弄清楚如何做到这一点? 谢谢

3 个答案:

答案 0 :(得分:1)

这是我根据我曾写过的一些旧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下载代码。)

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

python renpcrmaps.py precip 1

请注意,脚本会重新命名文件,因此请确保制作原始地图堆栈的副本,​​以防出现问题(我只对此进行了一些非常限制测试!)

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

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

答案 1 :(得分:0)

当您提供[batch-file]标记时,我认为,批处理正常:

@echo off
setlocal enabledelayedexpansion
set /a counti=0
for /f "delims=" %%a in ('dir /b /on precip.*') do (
  set /a counti+=1
  set "counts=000000000!counti!"
  ECHO ren "%%a" "precip!counts:~-6,3!.!counts:~-3!"
)

成功检查输出

后删除ECHO

已编辑以符合您的precip00.999 is precip01.000 ... until precip07.300要求(在您的问题precip000.001中,您的评论为precip00.001 - 我决定使用第一个格式,可以轻松对于第二种格式,请更改为ECHO ren "%%a" "precip!counts:~-5,2!.!counts:~-3!"。)。虽然它不再是Batch,但我会留下答案,也许你至少可以使用逻辑。

如果您对Batch不熟悉,%variable:~-6,3%语法将以set /?

解释

答案 2 :(得分:0)

我不久前就遇到过这个问题。请注意我是python和PCRaster的新手,所以不要在没有检查的情况下拿我的例子。

import os
import shutil
import fnmatch
import subprocess
from os import listdir
from os.path import isfile, join
from shutil import copyfile

TipeofFile = 'precip.????????' # original file   
Files = []
for iListFile in sorted(os.listdir('.')):
    if fnmatch.fnmatch(iListFile, TipeofFile):
        Files.append(iListFile)

digiafter = 3 #after the point: .001, .002, 0.003
digitTotal = 8 #total: precipi00000.000 (5.3)
for j in xrange(0, len(Files)):
    num = str(j + 1)    
    nameFile = Files[j]
    putZeros = digitTotal - len(num)
    for x in xrange(0,putZeros):
        num = "0" + num
    precip = num[0:digitTotal-digiafter]+ '.' +num[digitTotal-digiafter:digitTotal]
    precip = str(precip)    
    precip = 'precip' + precip 

    copyfile(nameFile, precip)