C++读取NC数据的结果与真实数值不一致的解决方法

  本文介绍基于C++ 语言的netCDF库读取.nc格式的栅格文件时,代码读取到的数据栅格文件的实际数据不一致的解决方法。

  最近,由于需要读取ERA5气象数据,因此使用C++ 语言中的netCDF库读取.nc格式文件。其中,偶然发现在Visual Studio的代码中读取到的.nc文件的数据,和其实际的数据(ArcMap等软件打开所显示的数据)不一致;这里就介绍一种可能导致上述情况的原因,以及对应的解决方法。此外,关于Visual Studio中配置C++ 语言netCDF库的方法,大家可以参考在Visual Studio配置C++的netCDF库的方法(https://blog.csdn.net/zhebushibiaoshifu/article/details/136451536);关于Python语言读取.nc数据的方法,大家可以参考Python读取.nc数据并提取指定时间、经纬度维度对应的变量数值(https://blog.csdn.net/zhebushibiaoshifu/article/details/136264348)。

  首先,在C++ 语言的代码读取.nc格式文件时,出现了如下图所示的情况,可以看到这些值都是负值;而实际上我这里的这个.nc格式文件肯定不应该如此。

  正常情况下,在ArcMap软件中打开上述这个.nc格式的文件,其数值正常范围的区间应该是如下图所示,肯定都是在大于0的区间内;当然,数据中确实可能会有NoData值,但尽管如此,这个.nc格式文件也不可能像上图那样,出现这么多不同的负数值。

  那么,如果出现类似上述这样的情况,大家就可以多多注意,很可能是由于存在scaleoffset导致的问题了。

  首先,什么是scaleoffset呢?简单来说,为了存储方便,.nc格式文件在保存数据的时候,可能会让原本的真实数据先乘以某个数,然后再加上某个数(很多.tif格式的遥感影像也是这么存储的,也就是常说的缩放系数)。例如,假设一个.nc格式文件原本的数值都是大于0、小于1的数值(例如反射率数据,都是0.X的数据),那么直接存储小数就需要占用大量的存储空间(因为需要float格式或者double格式);而如果让这些数据都乘上1000或者10000,也就是尽可能让小数部分消除,那么就可以用int格式来存储数据,从而降低了对存储空间的占用。

  因此,如果我们待读取的.nc格式文件含有这个scaleoffset,那么在使用C++ 语言中的netCDF库读取.nc格式文件时,读到的数据就是经过缩放处理后的数据;对此,我们需要手动将这个缩放后的数据,先乘上scale,再加上offset,从而得到最终的真实结果数据。这一个步骤,在Python语言的netCDF库中,应该是会自动帮我们处理(好像是这样的,因为之前用Python语言读取.nc格式文件的时候,都没有注意到过这个scaleoffset);而在C++ 语言的netCDF库中,就需要我们自行手动处理了。

  在netCDF库的官方网站中,也有关于这个scaleoffset的说明——如下图所示,二者在其中分别写作scale_factoradd_offset;在官方网站中提到,只要在.nc格式文件中看到这2个参数,都需要在读取数据后,自行手动将其乘以或添加到原数据中。

  因此,在用C++ 语言netCDF库读取.nc格式的栅格文件时,如果我们是第一次读取它,那么可以通过如下的代码,获取其变量的属性。

	NcFile file(path, NcFile::read);NcVar var = file.getVar(type);map<string, NcVarAtt> attributes_map = var.getAtts();

  其中,NcFile file(path, NcFile::read);含义为创建一个NcFile对象,path是要打开的.nc格式的栅格文件的路径,NcFile::read表示以只读模式打开文件;随后,NcVar var = file.getVar(type);表示调用file对象的getVar()方法,获取了指定变量名type(也就是我们需要读取的变量)的NcVar对象;最后,map<string, NcVarAtt> attributes_map = var.getAtts();调用var对象的getAtts()方法,获取了变量的所有属性,并将它们存储在一个map<string, NcVarAtt>对象中。在这个map中,属性的名称是键,对应的NcVarAtt对象是值。

  其中,这个attributes_map如下图所示;可以看到,其中是具有scale_factoradd_offset的。

  但是,如果此时我们直接查看这个attributes_map,是看不到scale_factoradd_offset具体的值的,因为它的值还是一个NcAtt对象;如下图所示。

  我们需要通过如下的代码,首先通过.getAtt()方法获取这个属性,然后用.getValues()方法获取这个属性的具体数值

	NcVarAtt attribute_offset = var.getAtt("add_offset");NcVarAtt attribute_scale = var.getAtt("scale_factor");double offset, scale;attribute_offset.getValues(&offset);attribute_scale.getValues(&scale);

  其中,对于上述代码,如果大家对变量值的精度有较高要求,记得要选择double类型的变量来存储scale_factoradd_offset——如果选择的是float,可能会丢失一些精度。

  运行上述代码,我们将得到如下图所示的结果。

  可以看到,scale_factoradd_offset的值都已经显示出来了。

  那么,我们就可以将这个scale_factoradd_offset,分别作用到我们读取得到的原始数据上(因为我这里.nc格式数据的数据量非常大,所以我们就只处理前100个),来看看其数值是否正确;具体代码如下。

	vector<double> var_array(time_size * latitude_size * longitude_size);var.getVar(var_array.data());for (int i = 0; i < 100; ++i) {var_array[i] *= scale;var_array[i] += offset;}

  可以看到,此时得到的结果,就符合实际了;如下图所示。

  此外,我们可以在ArcGIS软件中打开这个.nc格式的数据,找到其左上角的像元,获取一下这个像元的数值,如下图所示。

  可以看到,此时上图中所显示的数据,就和上上图中,我们在Visual Studio的代码中读取到的.nc文件的数据是一致的了。

  当然,这里也需要注意,有些.nc格式的数据,其变量也可能不含有scale_factoradd_offset这两个属性的,如下图所示;所以我们都可以用本文前述的代码,先获取其属性,看看到底有没有scale_factoradd_offset;如果有的话,在执行对应的数据恢复操作即可。

  至此,大功告成。

欢迎关注:疯狂学习GIS

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/727059.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Acwing枚举、模拟与排序(二)

回文日期 原文链接&#xff1a;https://www.acwing.com/problem/content/468/ 由于只有八位数&#xff0c;而且回文串左右对称&#xff0c;因此可以只枚举左半边。然后判断&#xff1a; 整个八位数日期是否合法是否在范围内 一共枚举1e4个数。判断过程是常数级别的&#xff0…

CC攻击的特征和防护措施

随着互联网的快速发展&#xff0c;网络攻击日益频繁。在目前的各种网络攻击中&#xff0c;CC攻击是一种常见的网络攻击手段之一。CC攻击&#xff08;也称为DDoS攻击&#xff09;是指通过大量请求或恶意流量向目标网站或服务器发送请求&#xff0c;以使其服务不可用。可能大家都…

Error:java:JDK isn‘t specified for module “模块名称“

可能是创建模块后不小心删掉了.idea.或.idea出错 只要删除.idea&#xff0c;close project出去&#xff0c;重新进让idea自动下载

VS2022打包C#安装包(最新、最全)

开发c#的一个小工具到打包环境碰壁了&#xff0c;在网上找了很多资料耶踩了很多坑&#xff0c;耗时1hour才打包完毕&#xff0c;避免以后碰到类似的问题再次记录&#xff0c;自认为步骤比较全面&#xff0c;如果有帮助麻烦点个赞呗&#xff01;&#xff01;&#xff01; 一、Mi…

QT状态机入门

Qt状态机&#xff08;QStateMachine&#xff09;是Qt框架中用于管理状态和状态转换的一种工具。它允许您将程序的行为分解为一系列离散的状态&#xff0c;并根据一定的条件进行状态之间的转换。Qt状态机提供了一个灵活的、可视化的方式来描述程序的状态和状态转换关系。 优点&…

网易家居315特别策划 | MLILY梦百合荣获2024年度家居行业服务榜样

3月,网易家居“寻找家居服务榜样”315特别策划如期而至,重磅奖项“2024年度家居行业服务榜样”揭晓,该奖项授予在家居服务方面做出突出贡献、起到示范引领作用的先进企业。其中,MLILY梦百合荣获“2024年度家居行业服务榜样”重磅奖项。 伴随市场需求演变、企业发展驱动、产业升…

echarts使用总结

最近项目大量的曲线图,柱状图,饼图...总结一下使用过程中的小问题及解决方法 . 1.当x轴太拥挤,x轴数据不能全部展示怎么办? 这时候就只需要在xAxis的axisLabel对象中添加属性 interval : 0 就可以显示全部数据 , interval 属性是用来调整x轴数据的间距的 , 数值越大间距越大…

Linux基础命令[11]-find

文章目录 1. find 命令说明2. find 命令语法3. find 命令示例3.1 不加参数3.2 按照时间3.3 -empty&#xff08;空白文件或目录&#xff09;3.4 -name&#xff08;名称查找&#xff09;3.5 -size&#xff08;大小查找&#xff09;3.6 -type&#xff08;类型查找&#xff09;3.7 …

砝码称重 蓝桥杯

在C中&#xff0c;fabs()和abs()都用于计算数字的绝对值&#xff0c;但它们之间有一些区别。 fabs(double x)&#xff1a;计算浮点数x的绝对值&#xff0c;返回一个double类型的结果。 abs(int x)&#xff1a;计算整数x的绝对值&#xff0c;返回一个int类型的结果。 数组的默…

1w字带你快速入门Docker

1. 什么是容器 容器是一种轻量级的、可移植的、自包含的软件单元&#xff0c;它包含运行应用程序所需的所有内容&#xff0c;包括代码、运行时、系统工具、系统库和设置。容器与虚拟机类似&#xff0c;但它们更加轻量级&#xff0c;并且依赖于宿主内核。容器可以使用 Docker 等…

太阳能光伏电池的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 光伏电池的基本结构 4.2 光伏电池的工作原理 5.完整工程文件 1.课题概述 太阳能光伏电池的simulink建模与仿真.分析不同光照温度&#xff0c;光照强度下的光伏电池的U-I特性曲线以及P-V特性曲线。 …

缺一不可!私域运营的三大核心环节

众所周知&#xff0c;私域运营是现如今许多企业重要的发展策略之一&#xff0c;通过建立和管理自己的用户数据库&#xff0c;实现用户粘性和价值的提升。 那么&#xff0c;要想做好私域运营&#xff0c;这三大核心环节一个也不能少&#xff01; 内容运营 内容运营是私域运营…

应用服务器和Web服务器的关系?

应用服务器实现了JavaEE的所有规范。&#xff08;JavaEE有13个不同的规范&#xff09;Web服务器只实现了JavaEE中的ServletJSP两个核心的规范应用服务器是包含WEB服务器的 apache官网地址&#xff1a;https://www.apache.org/ tomcat官网地址&#xff1a;https://tomcat.apach…

java VR全景商城 saas商城 b2b2c商城 o2o商城 积分商城 秒杀商城 拼团商城 分销商城 短视频商城 小程序商城搭建

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

php安装kafka

我的开发环境是php7.3 ,先来部署两个php扩展&#xff0c;php7.3目录下放librdkafka.dll,ext/php_rdkafka.dll&#xff0c;php.ini增加,[rdkafka] extension php_rdkafka.dll php7.3对应的扩展包链接&#xff1a;PECL :: Package :: rdkafka 看自己php版本对应在这里找PECL :: …

OpenAI-Sora学习手册

通过Sora看2024红利&#xff1a;文生视频&#xff0c;虽然AI不一定是风口&#xff0c;但一定是未来深入到生活工作&#xff0c;乃至思考的必备工具。 目录 Sora介绍 Sora基础介绍 Sora官方网址 Sora的价值 1.物理世界的交互 2.创意世界的绽放 3.多角色、更精准、更细节…

Vue时间轴

之前有这样子的需求没有用第三方插件于是自己写一个简单的时间轴 时间轴滚动条并左右切换滚动条位置相对应移动 <div class"time-scrollbar"><div v-if"timeLineData.length>0" class"scrollbar-content"><div class"ar…

SAP PP学习笔记07 - 简单BOM,派生BOM,多重BOM,批量修改工具 CEWB

上一章讲了BOM的操作。 SAP PP学习笔记06 - BOM操作&#xff08;BOM 展开&#xff0c;BOM 使用先一览&#xff0c;BOM比较&#xff0c;批量更改BOM&#xff09;-CSDN博客 本章延续上一章&#xff0c;继续讲BOM操作。 主要讲 派生BOM&#xff0c;多重BOM&#xff0c;以及BOM批…

收费的Excel,不收费的国产WPS、Ever这4款加强版,谁口碑更好?

国产软件存在的问题不在少数&#xff0c;诸如“流氓捆绑”、“广告弹屏”、“APP乱象”、“大数据杀熟”等弊端&#xff0c;让许多人对其嗤之以鼻。 尽管国内软件往往免费&#xff0c;而国外软件需要付费&#xff0c;大家还是更愿意选择付费使用国外软件&#xff0c;并且许多国…

java修改static final String常量值

java修改static final String常量值 背景 在项目中使用的JPA&#xff0c;Table设置实体类表名&#xff0c;使用mysql数据库的话&#xff0c;设置Table中catalog和schema可以在生成查询sql时&#xff0c;加上schema。例如表为sys_node&#xff0c;库名叫stu_manage&#xff0c…