Thursday, August 11, 2022

NO_PUBKEY when updating QGIS in Linux / Ubuntu (2022)

Update the key file (qgis-archive.gpg) by:


wget  -qO  -  https://qgis.org/downloads/qgis-2022.gpg.key  |  gpg  --no-default-keyring  --keyring  gnupg-ring:/etc/apt/trusted.gpg.d/qgis-archive.gpg  --import


The NO_PUBKEY error message will be gone for 'apt update'


Monday, June 6, 2022

Separated dock for multiple workspace in Ubuntu

Separated dock for multiple workspace in Ubuntu, set the following to be true:

gsettings set org.gnome.shell.extensions.dash-to-dock isolate-workspaces true

Monday, May 30, 2022

Skip basic authentication headers before passing a request to proxypass target host

This can be done via "RequestHeader unset Authorization" 


<Location "/some_path">

    Require all granted

    ProxyPass https://target-host

    RequestHeader unset Authorization

</Location>


Reference: 1, 2

Tuesday, January 25, 2022

Extract PDF content (from CHP) with Python

import re

import sys

import urllib.request

import pdfplumber

import pandas as pd



if (len(sys.argv) < 2):

    print("\n\nSyntax: python extract_pdf.py date_string (e.g. 20220124) \n\n")

    exit()


def main():    

    date_string  = sys.argv[1] # e.g. 20220124

    pdf_file_name = f"ctn_{date_string}.pdf" # PDF from CHP: https://www.chp.gov.hk/files/pdf/ctn_20220124.pdf

    #download_pdf( pdf_file_name )

    extract_pdf( pdf_file_name )



def extract_pdf( pdf_file_name ):

    with pdfplumber.open( f"./pdf/{pdf_file_name}" ) as pdf:

        for page in pdf.pages:

            #print(page)

            for table in page.extract_tables():

                df = pd.DataFrame(table[1:], columns=table[0])

                for index, row in df.iterrows():

                    if (isinstance(row[0], str) and len(row[0])>0):

                        rowid = row[0].replace(".","")

                        title = row[1].split("\n")

                        for i in range(0,len(title)):                            

                            if (re.search(u'[\u4e00-\u9fff]', title[i]) is None):

                                title[i] = ""

                        print(rowid, "".join(title))


def download_pdf ( pdf_file_name ) :

    pdfFile = urllib.request.urlopen(f"https://www.chp.gov.hk/files/pdf/{pdf_file_name}")

    file = open(f"./pdf/{pdf_file_name}", "wb")

    file.write(pdfFile.read())

    file.close()



main()

Display cx_oracle error indicating which rows are affected

cursor.executemany("SQL EXEC STATEMENT", data, batcherrors=True)

for error in cursor.getbatcherrors():

    print("Error", error.message, "at row offset", error.offset) 



Monday, January 24, 2022

Calculate the viewing location in Cesium

 Here I summarise two approach for calculating the viewing location in Cesium viewer:


Method 1 (using Camera.computeViewRectangle() method) 


var projection = new Cesium.WebMercatorProjection();

var rect = new Cesium.Rectangle()

viewer.camera.computeViewRectangle(projection.ellipsoid, rect)


let rect_x = (rect.east - rect.west)/2 + rect.west;

let rect_y = (rect.north - rect.south)/2 + rect.south;


var rect_lon = Cesium.Math.toDegrees(rect_y);

var rect_lat = Cesium.Math.toDegrees(rect_x);


console.log(rect_lat, rect_lon)


Note: The computeViewRectangle( ) could be very large when the view pitch is very flat, resulting in a very far point being calculated.


Method 2 (using Camera.computeViewRectangle() method) 


var cc = document.getElementById("cesiumContainer");

var screenCenterPt = new Cesium.Cartesian2(cc.offsetWidth/2, cc.offsetHeight/2);

var pick = viewer.scene.globe.pick(viewer.camera.getPickRay(screenCenterPt), viewer.scene);

if (pick) {

  var geoPt = viewer.scene.globe.ellipsoid.cartesianToCartographic(pick);

  var point = [geoPt.longitude/ Math.PI * 180, geoPt.latitude/ Math.PI * 180];

  

  var rect_lon = point[0];

  var rect_lat = point[1];

  

  console.log(rect_lat, rect_lon);

}


Note: It uses screen center to calculate the point, seems to be more useful.

Friday, January 7, 2022

DOS batch file: Expand * into list of filenames in command line

expand-wildcard.bat

@echo off

setlocal EnableDelayedExpansion


set params=command

for %%a in ("%~1") do (

    set params=!params! %%a

)


echo %params%

%params%

 

Then, running the following command:

C:\>expand-wildcard filename*


Will be executed as following:

C:\>command filename1 filename2 filename3 filename4 ..

Wednesday, August 25, 2021

SSH slow connection issues

When I connect to a Linux machine via ssh, it waits a long time (~ 10secs) before showing me the password prompt.

After some research, I found that it's caused by the GSS API authentication issue. Some suggestions to solve this issues are listed below (either one of this will work):

  1. Disable the GSS API authentication in sshd:

            Modify the file "/etc/ssh/sshd_config", disable the "GSSAPIAuthentication" by:

    GSSAPIAuthentication no 

     

  2. Disable GSS API authentication in PuTTY:

        Connection > SSH > Auth > GSSAPI

                    Uncheck "Attempt GSSAPI authentication (SSH-2 only)" 

 

 

Friday, July 30, 2021

Disabling GeoNetwork XSL caching

In GeoNework (3.x), the XSL caching is enabled by default. To disable this, we can modify the following:

In the ZIP GeoNetwork version, find the file "<GeoNetwork-Directory>/web/geonetwork/WEB-INF/classes/META-INF/services/javax.xml.transform.TransformerFactory"

This file should contains the following:

    de.fzi.dbs.xml.transform.CachingTransformerFactory

Change this to the following:

    net.sf.saxon.TransformerFactoryImpl

Then the XSL transformation will not be cached.


Reference: http://mapas.mda.gov.br/geonetwork/docs/eng/users/quickstartguide/installing/index.html



Upgrade nodejs in conda (from v18 to v26)

If your conda env is nodejs v18, doing a conda install nodejs=26 is likely to create a lot of conflict. Consider remove those conflicting p...