LI Xu's World
LI Xu (LI Hsu), Ph.D. in Management
Thursday, August 20, 2026
Tuesday, August 18, 2026
Video: Air Parcel Trajectory
Two-week HYSPLIT simulations of air parcel trajectories originating in Manitoba and transported across the globe, using ERA5 reanalysis data as meteorological input.
Video: Dust Storm
NOAA GOES-19 imagery showing a dust storm affecting the entire Winnipeg area on the afternoon of May 14, 2026.
Reference:
https://classic107.com/articles/rare-dust-storm-warning-issued-across-southern-manitoba
Thursday, August 6, 2026
Matlab: An example Map script
% Created by LI Xu % Version 1.0 % August 6, 2026 % If you have any question about this code, % please do not hesitate to contact me via E-mail: % jeremy456@163.com % Blog: % http://blog.sciencenet.cn/u/lixujeremy % http://lixuworld.blogspot.com/ clear; clc; close all; timebegin=tic; cur_data=date; cur_time=fix(clock); str1=sprintf('%s %.2d:%.2d:%.2d', cur_data, cur_time(4), cur_time(5), cur_time(6)); fprintf('Time Begin: '); fprintf(str1); fprintf('\n'); % Define the Google Street Map tile URL % name = 'google_streets'; name='streets'; % url = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/${z}/${y}/${x}'; % url = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/${z}/${y}/${x}'; % url = 'https://mt1.google.com/vt/lyrs=m&x=${x}&y=${y}&z=${z}&style=p.v:off|s.t:3|s.e:l|p.v:on'; % % url = 'https://mt1.google.com/vt/lyrs=m&x=${x}&y=${y}&z=${z}&style=p.v:off|s.t:3|s.e:l|p.v:on'; % url = 'https://mt1.google.com/vt/lyrs=m&x=${x}&y=${y}&z=${z}'; % url = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer/tile/${z}/${y}/${x}'; % attribution = 'Map data ©2026 Google'; % url = 'https://cartodb-basemaps-a.global.ssl.fastly.net/light_all/${z}/${x}/${y}.png'; % url = 'https://cartodb-basemaps-a.global.ssl.fastly.net/dark_all/${z}/${x}/${y}.png'; % name = 'carto_voyager'; % attribution = '© OpenStreetMap contributors, © CARTO'; % url = 'https://cartodb-basemaps-a.global.ssl.fastly.net/rastertiles/voyager/${z}/${x}/${y}.png'; % % % % Add it to your MATLAB basemap list % addCustomBasemap(name, url, 'Attribution', attribution); % url = 'https://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/${z}/${y}/${x}'; % url = 'https://server.arcgisonline.com/ArcGIS/rest/services/Specialty/NatGeo_World_Map/MapServer/tile/${z}/${y}/${x}'; % url = 'https://cartodb-basemaps-a.global.ssl.fastly.net/rastertiles/voyager/${z}/${x}/${y}.png'; attribution = '© OpenStreetMap contributors, © CARTO'; url = 'https://mt1.google.com/vt/lyrs=s&x=${x}&y=${y}&z=${z}'; addCustomBasemap(name, url, 'Attribution', attribution); % addCustomBasemap(name, url, 'Attribution', 'Sources: Esri, National Geographic, Garmin'); % url = 'https://stamen-tiles.a.ssl.fastly.net/toner/${z}/${x}/${y}.png'; % addCustomBasemap('stamen_toner', url, 'Attribution', 'Map tiles by Stamen Design, CC BY 3.0'); % Create geographic axes with OpenStreetMap basemap figure; gx = geoaxes('Basemap', name); set(gcf, 'OuterPosition', get(0, 'ScreenSize')); f = gcf; % Define custom latitude/longitude range (Winnipeg-centered) % latRange = [49.76, 50.01]; % lonRange = [-97.45, -96.9]; latRange = [49.79+0.005+0.009, 49.82-0.0068]; lonRange = [-97.15+0.008, -97.13+0.004]; % Calculate aspect ratio for exact limits without expansion mean_lat = mean(latRange); cos_factor = cosd(mean_lat); ar = diff(latRange) / (diff(lonRange) * cos_factor); % Required height/width for axes % Set up resize function to maintain aspect and exact limits gx.Units = 'pixels'; f.Units = 'pixels'; f.SizeChangedFcn = @(~, ~) myresizefcn(gx, f, ar, latRange, lonRange); myresizefcn(gx, f, ar, latRange, lonRange); % Rotate the whole map figure visually view(gx, 2); % rotate3d(f, 'on'); % % rotate3d(gx, 'on'); % gx.View = [30 90]; gx.Grid = 'off'; gx.TickDir = 'none'; gx.LatitudeLabel.String = ''; gx.LongitudeLabel.String = ''; gx.FontSize = 0.01; % dat=cell2mat(dat); % lats=dat(:, 1); % lons=dat(:, 2); % nums=dat(:, 3); % hold on; % for i = 1:length(lats) % % Draw Circle % plot(gx, lats(i), lons(i), 'bo', 'MarkerSize', 18, 'MarkerFaceColor', 'y'); % % Draw Number % text(gx, lats(i), lons(i), num2str(nums(i)), ... % 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle', 'Color', 'blue', 'FontWeight','bold', 'FontSize', 15); % end % 49.81155561273022, -97.13142673818446 plot(gx, 49.81155561273022, -97.13142673818446, 'pentagram', 'MarkerSize', 20, 'MarkerFaceColor', 'blue'); hold off; gx.Grid = 'off'; gx.TickDir = 'none'; gx.LatitudeLabel.String = ''; gx.LongitudeLabel.String = ''; gx.FontSize = 0.01; % dim = [0.1 0.83 0.8 0.1]; % Position at the top center % str = 'Campus Water Fountain Map'; % % hAnn = annotation('textbox', dim, 'String', str, ... % 'EdgeColor', 'none', ... % No border % 'HorizontalAlignment', 'center', ... % 'VerticalAlignment', 'middle', ... % 'FontSize', 25, ... % 'FontWeight', 'bold', ... % 'Color', 'white', ... % 'Interpreter', 'none'); pause(3); otname='kunakmap_vector'; export_fig(otname, '-png', '-painters', '-r300'); close all; fprintf('Time Begin: '); fprintf(str1); fprintf('\n'); cur_data=date; cur_time=fix(clock); str2=sprintf('%s %.2d:%.2d:%.2d', cur_data, cur_time(4), cur_time(5), cur_time(6)); fprintf('Time End: '); disp(str2); timespan=toc(timebegin); fprintf('Time Span: %.4f s\n', timespan); disp('************************************************************'); function myresizefcn(gx, f, ar, latlim, lonlim) if (f.Position(4) / f.Position(3)) < ar % Figure is wide: constrain by height gx.Position(4) = f.Position(4) * 0.8; gx.Position(3) = gx.Position(4) / ar; % Center gx.Position(1) = (f.Position(3) - gx.Position(3)) / 2 + f.Position(1); gx.Position(2) = (f.Position(4) - gx.Position(4)) / 2 + f.Position(2); else % Figure is tall: constrain by width gx.Position(3) = f.Position(3) * 0.8; gx.Position(4) = gx.Position(3) * ar; % Center gx.Position(1) = (f.Position(3) - gx.Position(3)) / 2 + f.Position(1); gx.Position(2) = (f.Position(4) - gx.Position(4)) / 2 + f.Position(2); end % Re-apply limits to maintain exact range geolimits(gx, latlim, lonlim); end
Tuesday, May 12, 2026
Matlab: Table on the PPT created via Matlab
% Created by LI Xu % Version 1.0 % August 28, 2025 % If you have any question about this code, % please do not hesitate to contact me via E-mail: % jeremy456@163.com % Blog: % http://blog.sciencenet.cn/u/lixujeremy % http://lixuworld.blogspot.com/ clear; clc; close all; timebegin=tic; cur_data=date; cur_time=fix(clock); str1=sprintf('%s %.2d:%.2d:%.2d', cur_data, cur_time(4), cur_time(5), cur_time(6)); fprintf('Time Begin: '); fprintf(str1); fprintf('\n'); import mlreportgen.ppt.* % 1. Create a presentation ppt = Presentation('AQ.pptx'); % 2. Create a slide (e.g., 'Blank' or 'Title and Content') slide = add(ppt, 'Title and Content'); replace(slide, 'Title', 'Measured Data Table'); % 3. Prepare your data (Cell array: Rows x Cols) data = {'Variable', 'Campus', 'Winnipeg'; 'Temperature (℃) ', '40', '15'; ... 'Relative Humidity (%)', '65', '70'; ... 'Wind speed (m/s)', '65', '70'; ... 'PM2.5 (μg/m³)', '65', '70'; ... 'PM10 (μg/m³)', '65', '70'; ... 'NO₂ (ppb)', '65', '70'; ... 'O₃ (ppb)', '65', '70'; ... 'CO₂ (ppm)', '65', '70'}; % 4. Create and add the table % 'Table' automatically creates rows/columns based on the data tableObj = Table(data); firstRow = tableObj.Children(1); firstRow.Style = {BackgroundColor('#296080'), FontColor('white'), Bold()}; tableObj.Style = {HAlign('center'), VAlign('middle'), Border('solid'), RowHeight('0.3in')}; % tableObj.ColWidths = {'1.5in', '1.0in', '1.0in'}; % Column 3: 1.0 inches (Winnipeg) spec1 = ColSpec('2.5 in'); spec2 = ColSpec('1.5 in'); spec3 = ColSpec('1.5 in'); % 2. Assign the array of specs to the table tableObj.ColSpecs = [spec1, spec2, spec3]; % 1. Target the specific cell (Row 2, Column 2) using entry(row, col) targetCell = entry(tableObj, 2, 2); % 2. Apply the background color targetCell.Style = {BackgroundColor('red')}; % 1. Target the specific cell (e.g., Row 2, Column 2) targetCell = entry(tableObj, 2, 2); % 2. Apply the font color (e.g., red) % You can use names like 'red', 'white', or hex codes like '#FF0000' targetCell.Style = [targetCell.Style, {FontColor('white')}]; % Add the table to the content placeholder replace(slide, 'Content', tableObj); % 5. Close and View close(ppt); rptview(ppt); fprintf('Time Begin: '); fprintf(str1); fprintf('\n'); cur_data=date; cur_time=fix(clock); str2=sprintf('%s %.2d:%.2d:%.2d', cur_data, cur_time(4), cur_time(5), cur_time(6)); fprintf('Time End: '); disp(str2); timespan=toc(timebegin); fprintf('Time Span: %.4f s\n', timespan); disp('*************************************************************************');
Thursday, April 9, 2026
Data: Manitoba Ag-Weather Network Weather Stations
Manitoba Agriculture operates a network of over 100 weather stations across Manitoba's agricultural region which provide hourly updated air temperature, relative humidity, precipitation, wind speed and direction, soil temperature and soil moisture. The WeatherStations feature class displays the location of the weather stations and its table contains a link to current weather for each station. list
How to download
How to use them:
- Select a Station Name from the dropdown (they match the ones in your CSV).
- Pick a Date (or planting/end dates for seasonal).
- Submit to view the table for that station/date.
- Data goes back several years (stations have varying start dates, many from ~2011 onward, with 15-minute raw intervals rolled up to hourly/daily). Note: Raw data can have occasional sensor issues — use with caution.
Other useful pages:
- Current + summary pages: https://www.gov.mb.ca/agriculture/weather/weather-conditions-and-reports.html (links to the reports above + soil temps).
- Manitoba Ag Weather Program overview: https://www.gov.mb.ca/agriculture/weather/manitoba-ag-weather.html (confirms data is free and archived).
- Interactive current map: From the original dashboard or https://www.gov.mb.ca/agriculture/weather/current-ag-weather-conditions.html.
Code.
Thursday, April 2, 2026
Subscribe to:
Posts (Atom)


