01 题目
02 代码说明
题目本身很简单,但是我自己加了一些东西进去增加难度。主要包括print函数的封装、格式化字符串,但是不影响代码的阅读。(注:对于没有语言基础的人而言相对阅读困难,但是由于IDL是解释型语言,类似于Python,所以难度不会太难)
提示:
findgen(3, 4, start=2): 定义3列4行的索引数组(先列后行),第一个数组元素值默认为0,这里start为2,故从2开始;
b = 3s:定义整型变量,s可不写;
c = [3]:定义仅有一个元素的数组,该元素值为3;
d = [9, 3, 1]:定义含多个元素的数组;
+:原本只能进行数值之间的运算,这里进行了重载使得可以进行字符串的连接,类似于python;
string(a[3, 4], format='(f5.2)'):格式化输出,输出的变量转为浮点型,总宽度为5(小数点也算一个宽度),小数位宽度为2.string(a[3, 4], format='%.2f'):格式化输出,或许已经发现了,前面的format实际上是fortran语言的格式化输出样式,但是我不太了解该语言所以用不顺手,我更倾向于C语言的格式化的输出(Yeah,IDL支持C语言和Fortran两种的语言的格式化输出<绝大部分一致>)。这里的含义与上一致,具体百度C语言格式化输出即可;
&:这是一个连续化符,用于将多个操作或者指令放在一行执行;
a = [[3, 9, 10], [2, 7, 5], [4, 1, 6]]: 这是自定义一个二维数组,注意,数组的定义均是使用中括号[],高维亦是如此;
printArray:这是定义的一个函数(详见下文),其中的arr是位置参数,prefix,format都是关键字参数;
dims = size(arr, /dimensions):获取数组arr的维度信息(以数组形式返回);
strcompress():返回传入的字符串的副本,这个副本是将原来的字符串中的所有的空白字符和制表符全部换成了一个空白字符或者直接全部移除。自己多用多体会就清楚了。
gt, ge, lt, le, ne, eq:这些很简单,就是大于(greater than, gt),大于等于(greater than or equal, ge),小于(less than,lt),小于等于(less than or equal, le),等于(equal,eq)。比较运算符。
+,-,*,/,^, mod:^是次方数,例如2的8次方就是2 ^ 8,mod是取余运算,例如9 mod 2 等于1.
float():强制转换符,将其他数据类型转换为浮点型。
write_tiff,'D:\Objects\JuniorFallTerm\IDLProgram\Project\ExperimentsMe\Week1\Data\temp.tif', img, /float:第一个参数传入路径名称(\和/都行,但是后面的HDF读取内部数据集的路径只允许/因此建议都用/会更好)。第二个参数传入需要写入的数组。另外如果不传入参数/float那么write_tiff函数默认以整型写入(尽管数组的数据类型为浮点型)。
; @Author: ChaoQiezi
; @Email: chaoqiezi.one@qq.com
; @Time: 2023-09-11
; This script is used to basic practice
; This function is used to print array
function printArray, arr, prefix=prefix, format=format
dims = size(arr, /dimensions)
if n_elements(prefix) then print, prefix
if ~n_elements(format) then format='%.2f'
for row = 0, dims[1] - 1 do begin
arr_row = arr[*, row]
formatted_row = strcompress(string(arr_row, format=format))
output = ' '
for col = 0, dims[0] - 1 do begin
output += formatted_row[col]
if col ne dims[0] - 1 then output += ', '
endfor
print, output
endfor
end
pro basic_pracitce
; question-1
a = findgen(4, 6) ; define the index array(float)
b = 3s ; define the int var
c = [3] ; define the array
d = [9, 3, 1]
print, 'the value for col 3 and row 4 is: ' + string(a[3, 4], format='%.2f')
print, 'the value with index 15: ' + string(a[15], format='%.2f')
printArray, a + b, PREFIX='a plus b is equal to: '
print, 'a[1, 1] plus b is equal to: ' + string(a[1, 1] + b, format='%.2f')
print, 'a plus b is equal to: ', a + c & help, a + c
print, 'a plus c is equal to: ', a + d & help, a + d
; question2
a = [[3, 9, 10], [2, 7, 5], [4, 1, 6]]
b = [[7, 10, 2], [5, 8, 9], [3, 1, 6]]
printArray, a + b, prefix='a plus b is equal: '
printArray, a * b, prefix='a times b is equal to: '
; question3
a = [[0, 5, 3], [4, 0, 2], [0, 7, 8]]
b = [[0, 0, 1], [9, 7, 4], [1, 0, 2]]
printArray, (a gt 3) * a, prefix='keep the result greater than 3 in a, and set all the rest to 0: '
printArray, (b le 4) * b + (b gt 4) * 9, prefix='keep the result less than or equal to 3 in ' + $
'a, and set all the rest to 9: ', format='%i'
printArray, (a + b) / 2.0, prefix='calculate the mean of a and b: '
printArray, ((a ne 0) and (b ne 0)) * ((a + b) / 2.0)+ (a eq 0) * b + (b eq 0) * a, $
prefix='calculate the mean of a and b, and 0 values are not included in the calculation: '
print, (a + b) / float((a ne 0) + (b ne 0)) ; equal above and simple
; question4
img = findgen(1024, 1024)
; image(img, /order)
write_tiff, 'D:\Objects\JuniorFallTerm\IDLProgram\Project\ExperimentsMe\Week1\Data\temp.tif', img, /float
end
03 其它
可以尝试将函数printArray的定义修改为(仅仅是function修改为pro):
pro printArray, arr, prefix=prefix, format=format
dims = size(arr, /dimensions)
if n_elements(prefix) then print, prefix
if ~n_elements(format) then format='%.2f'
for row = 0, dims[1] - 1 do begin
arr_row = arr[*, row]
formatted_row = strcompress(string(arr_row, format=format))
output = ' '
for col = 0, dims[0] - 1 do begin
output += formatted_row[col]
if col ne dims[0] - 1 then output += ', '
endfor
print, output
endfor
end
整个程序仍然可以运行,像这样的话我们就清楚了我们pro文件可以包含多个子程序(多个pro过程),但是我们的pro文件从哪个子pro程序开始运行呢?这就与我们当初pro文件的命名相关,pro文件将与pro文件名一致的子pro程序作为类似main的入口进入顺序运行。
另外,ENVI IDL支持python代码的运行,例如:
其他详见帮助,IDL版本过旧可能不支持,IDL85貌似支持Python3.8以下,因为我目前是IDL8.5,Python3.8.
04 Python代码实现
比较简单,暂无解释
# @Author : ChaoQiezi
# @Time : 2023-09-12 23:20
# @Email : chaoqiezi.one@qq.com
"""
This script is used to learn basic grammar of python.
"""
import numpy as np
from osgeo import gdal
# 第一问
def question1():
a = np.arange(24, dtype=np.float32).reshape(6, 4)
b = 3
c = np.array([3])
d = np.array([9, 3, 1])
print(a[4, 3]) # 取第3列第4行的数值
print(a.flatten()[15]) # 取第15个索引的数值
print(a + b)
print(a[1, 1] + b) # 8.0
print(a + c) # 与IDL结果不一致, 这是因为c是一维数组, 会自动广播
# print(a + d) # 直接报错, 维度不一致
# 第二问
def question2():
a = np.array([[3, 9, 10], [2, 7, 5], [4, 1, 6]])
b = np.array([[7, 10, 2], [5, 8, 9], [3, 1, 6]])
print(a + b)
print(a * b)
# 第三问
def question3():
a = np.array([[0, 5, 3], [4, 0, 2], [0, 7, 8]])
b = np.array([[0, 0, 1], [9, 7, 4], [1, 0, 2]])
# 取a大于3的结果,其余为0
print((a > 3) * a) # or this
print(np.where(a > 3, a, 0))
# 取b中小于等于4的结果,其余为9
print((a <= 4) * a + (a > 4) * 9)
print(np.where(a <= 4, a, 9))
# 计算A和B的均值
print((a + b) / 2)
print(np.mean(a + b)) # or this
# 计算A和B的均值, 0不纳入计算
print((a + b) / ((a > 0) + (b > 0)))
def write_tiff(out_path: str, data: np.ndarray):
driver = gdal.GetDriverByName('GTiff')
out_ds = driver.Create(out_path, data.shape[1], data.shape[0], 1, gdal.GDT_Float32) # col, row
out_ds.GetRasterBand(1).WriteArray(data)
out_ds.FlushCache()
del out_ds
def question4():
a = np.arange(1024*1024, dtype=np.float32).reshape(1024, 1024)
write_tiff(r'D:\Objects\JuniorFallTerm\IDLProgram\Project\PyExperiments\Experiments\week1\temp.tiff', a)
if __name__ == '__main__':
question1()
question2()
question3()
question4()