How to convert Kelvin to Celsius in MODIS LST product in google earth engine? - google-earth-engine

I'm trying to convert Kelvin to Celsius in MODIS LST product in Google Earth Engine. But there is an error in my code.
The code is:
var LST_K = ee.ImageCollection('MODIS/006/MOD11A2')
.filterBounds(AOI)
.filterDate('2021-02-20','2021-05-31')
.select("LST_Day_1km","LST_Night_1km")
.map(function(img){
return img.multiply(0.02)
.copyProperties(img,['system:time_start','system:time_end']);
});
print(LST_K);
// convert LST to celcius
var toCelsius = function(img){
var time = img.get('system:time_start')
var celsius = img.multiply(0.02) // scale factor
.subtract(273.15) // from kelvin to C
.rename('Celcius')
.set('system:time_start',time)
return celsius;
};
var LST = LST_K.map(toCelsius)
print(LST);
print(ui.Chart.image.series(LST, AOI, ee.Reducer.median(), 1000, 'system:time_start'));
and the link code is below:
https://code.earthengine.google.com/61b7668525bd38cd543f72c0ad201886
Many thanks in advance

The error you're getting is about renaming the bands of the imageCollection "LST_K". This imageCollection has 2 bands, the LST_daytime band and the LST_nighttime band, so in your rename statement you should add two names instead of one.
Adding both names will solve this issue:
.rename(['LST_Day_1km_Celcius', 'LST_Night_1km_Celcius'])

Related

plotter only plot the time, not the date

im trying to follow this guide on plotting a time series chart but ive run into a small issue. is there any way to change the bottom label to only show the current time (H:M:S) instead of the current date? ive been trying for a while now to find a way to do this but it still havent been able to. im following the code in the guide so this is the code im working with:
use plotters::prelude::*;
use chrono::{Utc, TimeZone};
fn main() {
let root_area = BitMapBackend::new("images/2.11.png", (600, 400))
.into_drawing_area();
root_area.fill(&WHITE).unwrap();
let start_date = Utc.ymd(2019, 10, 1);
let end_date = Utc.ymd(2019, 10, 18);
let mut ctx = ChartBuilder::on(&root_area)
.set_label_area_size(LabelAreaPosition::Left, 40)
.set_label_area_size(LabelAreaPosition::Bottom, 40)
.caption("MSFT daily close price", ("sans-serif", 40))
.build_cartesian_2d(start_date..end_date, 130.0..145.0)
.unwrap();
ctx.configure_mesh().draw().unwrap();
ctx.draw_series(
LineSeries::new(
(0..).zip(DATA.iter()).map(|(idx, price)| {
let day = (idx / 5) * 7 + idx % 5 + 1;
let date = Utc.ymd(2019,10, day);
(date, *price)
}),
&BLUE,
)
).unwrap();
}
const DATA: [f64; 14] = [ 137.24, 136.37, 138.43, 137.41, 139.69, 140.41, 141.58, 139.55, 139.68, 139.10, 138.24, 135.67, 137.12, 138.12];
ive tried using chrono's NaiveTime but it doesnt seem to be supported, DateTime causes the entire date and time to be printed instead of just the time, and ive also tried creating my own element series but i cant figure out how to get that working. anyone have any ideas?
You can add this line, or something like it to the ChartBuilder:
.x_label_formatter(&|x| format!("{:02}:{:02}", x.hour(), x.minute()))
where x is a DateTime struct. You can use other DateTime functions to get different parts of the time, as required.

Function returns 0x0 table

I have a function to compute latitude and longitude points in order to create a "ring" around a center location. The problem is that the results print to the screen but are not stored anywhere. My function creates a dataframe with 0 columns and 0 rows. I want to be able to take these coordinates and use them elsewhere. I would like to be able to nest this function as well, but I can't really nest it when it doesn't return anything.
My end goal is to create kml code. I already have the kml code but need to repeat it many times. The kml code creates radius rings, fills them with color, and adds a name for the place. I want to generate the files automatically by using a list of locations in lat/lon.
My question is, how can I get this function to return the list of coordinates that I want so that I may paste them in the kml code accordingly? I can get it to loop using adply and get printed results for the 3 coordinates, but nothing is created.
I am also quite new to coding, please be gentle. Thanks in advance.
make.ring.file=function(dist,df)
{
R = 6378.14 #Radius of the Earth
d = dist*1.609344 #Distance of ring radius in km
lat1 = df$lat*(pi/180) #Current lat point converted to radians
lon1 = df$lon*(pi/180) #Current lon point converted to radians
num3=0
index=seq(from=0,to=360,by=120)
bear=NULL
lat=NULL
lon=NULL
z=NULL
coordlist=NULL
for(n in 1:length(index))
{
bear[n]=index[n]*(pi/180)
lat[n]=(asin(sin(lat1)*cos(d/R) + cos(lat1)*sin(d/R)*cos(bear[n])))*(180/pi)
lon[n]=(lon1 + atan2(sin(bear[n])*sin(d/R)*cos(lat1),
cos(d/R)-sin(lat1)*sin(lat[n]*(pi/180))))*(180/pi)
z[n]=0
coordlist[n]=paste(lon[n],lat[n],z[n],sep=",")
}
return(data.frame(cat(coordlist,"\n","\n")))
}
> head(x1)
lat lon
1 38.86095 -86.51672
2 30.63275 -84.41614
3 31.53697 -87.88780
> results=adply(x1,1,make.ring.file,dist=30)
-86.51672,39.2946592897837,0 -86.0358241901732,38.6431079084023,0 -86.9976158098268,38.6431079084023,0 -86.51672,39.2946592897837,0
-84.41614,31.0664592897837,0 -83.9805971533182,30.4151694949636,0 -84.8516828466818,30.4151694949636,0 -84.41614,31.0664592897837,0
-87.8878,31.9706792897837,0 -87.4481292235866,31.3193631233201,0 -88.3274707764134,31.3193631233201,0 -87.8878,31.9706792897837,0
> str(results)
'data.frame': 0 obs. of 0 variables
> is.data.frame(results)
[1] TRUE
I think this is what you want:
make.ring.file=function(dist,df)
{
R = 6378.14 #Radius of the Earth
d = dist*1.609344 #Distance of ring radius in km
lat1 = df$lat*(pi/180) #Current lat point converted to radians
lon1 = df$lon*(pi/180) #Current lon point converted to radians
num3=0
index=seq(from=0,to=360,by=120)
bear=NULL
lat=NULL
lon=NULL
z=NULL
coordlist=NULL
for(n in 1:length(index))
{
bear[n]=index[n]*(pi/180)
lat[n]=(asin(sin(lat1)*cos(d/R) + cos(lat1)*sin(d/R)*cos(bear[n])))*(180/pi)
lon[n]=(lon1 + atan2(sin(bear[n])*sin(d/R)*cos(lat1),
cos(d/R)-sin(lat1)*sin(lat[n]*(pi/180))))*(180/pi)
z[n]=0
coordlist[n]=paste(lon[n],lat[n],z[n],sep=",")
}
return(data.frame(out=paste(coordlist,collapse=" ")))
}
The key addition is:
return(data.frame(out=paste(coordlist,collapse=" ")))
The function cat, prints to console, so you can't assign it to anything - you were merely making an empty data.frame and printing.
The paste command works by pasting together the 4 lines of coordlist, with a separator of " ". You can modify this as required for your downstream code.

Find specific point between 2 points - three.js

How can I find a point ( C (x,y,z) ) between 2 points ( A(x,y,z) , B(x,y,z) ) in a thgree.js scene?
I know that with this: mid point I can find the middle point between them, but I don't want the middle point, I want to find the point which is between them and also has distance a from the A point?
in this picture you can see what I mean :
Thank you.
Basically you need to get the direction vector between the two points (D), normalize it, and you'll use it for getting the new point in the way: NewPoint = PointA + D*Length.
You could use length normalized (0..1) or as an absolute value from 0 to length of the direction vector.
Here you can see some examples using both methods:
Using absolute value:
function getPointInBetweenByLen(pointA, pointB, length) {
var dir = pointB.clone().sub(pointA).normalize().multiplyScalar(length);
return pointA.clone().add(dir);
}
And to use with percentage (0..1)
function getPointInBetweenByPerc(pointA, pointB, percentage) {
var dir = pointB.clone().sub(pointA);
var len = dir.length();
dir = dir.normalize().multiplyScalar(len*percentage);
return pointA.clone().add(dir);
}
See it in action: http://jsfiddle.net/8mnqjsge/
Hope it helps.
I know the question is for THREE.JS and I end up looking for something similar in Babylon JS.
Just in case if you are using Babylon JS Vector3 then the formula would translate to:
function getPointInBetweenByPerc(pointA, pointB, percentage) {
var dir = pointB.clone().subtract(pointA);
var length = dir.length();
dir = dir.normalize().scale(length *percentage);
return pointA.clone().add(dir);
}
Hope it help somebody.
This is known as lerp between two points
e.g. in Three:
C = new Three.Vector3()
C.lerpVectors(A, B, a)
also in generic this is just a single lerp (linear interpolation) math (basically (a * t) + b * (1 - t)) on each axis. Lerp can be described as follows:
function lerp (a, b, t) {
return a + t * (b - a)
}
in your case (see above) :
A = {
x: lerp(A.x, B.x, a),
y: lerp(A.y, B.y, a),
z: lerp(A.z, B.z, a)
}

scilab submatrix incorrectly defined

I am stuck at creating a matrix of a matrix (vector in this case)
What I have so far
index = zeros(size(A)) // This is some matrix but isn't important to the question
indexIndex = 1;
for rows=1:length(R)
for columns=1:length(K)
if(A(rows,columns)==x)
V=[rows columns]; // I create a vector holding the row + column
index(indexIndex) = V(1,2) // I want to store all these vectors
indexIndex = indexIndex + 1
end
end
end
I have tried various ways of getting the information out of V (such as V(1:2)) but nothing seems to work correctly.
In other words, I'm trying to get an array of points.
Thanks in advance
I do not understand your question exactly. What is the size of A? What is x, K and R? But under some assumptions,
Using list
You could use a list
// Create some matrix A
A = zeros(8,8)
//initialize the list
index = list();
// Get the dimensions of A
rows = size(A,1);
cols = size(A,2);
x = 0;
for row=1:rows
for col=1:cols
if(A(row,col)==x)
// Create a vector holding row and col
V=[row col];
// Append it to list using $ (last index) + 1
index($+1) = V
end
end
end
Single indexed matrices
Another approach would be to make use of the fact an multi-dimensional matrix can also be indexed by a single value.
For instance create a random matrix named a:
-->a = rand(3,3)
a =
0.6212882 0.5211472 0.0881335
0.3454984 0.2870401 0.4498763
0.7064868 0.6502795 0.7227253
Access the first value:
-->a(1)
ans =
0.6212882
-->a(1,1)
ans =
0.6212882
Access the second value:
-->a(2)
ans =
0.3454984
-->a(2,1)
ans =
0.3454984
So that proves how the single indexing works. Now to apply it to your problem and knocking out a for-loop.
// Create some matrix A
A = zeros(8,8)
//initialize the array of indices
index = [];
// Get the dimensions of A
rows = size(A,1);
cols = size(A,2);
x = 0;
for i=1:length(A)
if(A(i)==x)
// Append it to list using $ (last index) + 1
index($+1) = i;
end
end
Without for-loop
If you just need the values that adhere to a certain condition you could also do something like this
values = A(A==x);
Be carefull when comparing doubles, these are not always (un)equal when you expect.

JFreechart: Count each series over an intervals

I am trying get the count of each series point over specific areas of my plot.
The plot is made up of grids (boxes) and I wish to know the count of each of my series points that is present in each of these boxes. I want to get information like (grid 1 had 2 of series 1, 0 of series 2, 3 of series3, 4 of series 5, etc)
Any help is greatly appreciated.
When you have XYItems you can get the bounds of each item:
final Collection<ChartEntity> entities =
chartpanel.getChartRenderingInfo().getEntityCollection().getEntities();
for (final ChartEntity e : entities) {
if (e instanceof XYItemEntity) {
final XYItemEntity xyItem = (XYItemEntity) e;
final int index = xyItem.getItem();
final int series = xyItem.getSeriesIndex();
Rectangle2D r = e.getArea().getBounds2D();
checkPosition(r); // here you can check if the coordinates are inside your "box"
}
}

Resources