Tutorial

To demonstrate how PyRCS works, this brief tutorial provides a quick guide with examples of getting the following three categories of codes, which are frequently used in the railway system in the UK:

Location identifiers

The location identifiers, including CRS, NLC, TIPLOC and STANOX codes, are categorised as line data on the Railway Codes website. To get these codes via PyRCS, we can use the class LocationIdentifiers, which is contained in the sub-package line_data. Let’s firstly import the class and create an instance:

>>> from pyrcs.line_data import LocationIdentifiers  # from pyrcs import LocationIdentifiers

>>> lid = LocationIdentifiers()

>>> lid.NAME
'CRS, NLC, TIPLOC and STANOX codes'
>>> lid.URL
'http://www.railwaycodes.org.uk/crs/crs0.shtm'

Note

An alternative way of creating the instance is through the class LineData (see below).

>>> from pyrcs.collector import LineData  # from pyrcs import LineData

>>> ld = LineData()
>>> lid_ = ld.LocationIdentifiers

>>> lid.NAME == lid_.NAME
True

Note

  • The instance ld refers to all classes under the category of line data.

  • Here lid_ is equivalent to lid.

Location identifiers given a specific initial letter

Now we can get the codes (in a pandas.DataFrame type) for all locations beginning with a given letter, by using the method LocationIdentifiers.collect_codes_by_initial(). For example, to get the codes for locations whose names begin with 'A' (or 'a'):

>>> loc_a_codes = lid.collect_codes_by_initial(initial='a')  # The input is case-insensitive
>>> type(loc_a_codes)
dict
>>> list(loc_a_codes.keys())
['A', 'Additional notes', 'Last updated date']

As demonstrated above, loc_a_codes is a dictionary (in dict type), which has the following keys:

  • 'A'

  • 'Additional notes'

  • 'Last updated date'

The corresponding values are:

  • loc_a_codes['A'] - CRS, NLC, TIPLOC and STANOX codes for the locations whose names begin with 'A' (referring to the table presented on the web page Locations beginning A);

  • loc_a_codes['Additional notes'] - Additional information on the web page (if available);

  • loc_a_codes['Last updated date'] - The date when the web page Locations beginning A was last updated.

A snapshot of the data contained in loc_a_codes is demonstrated below:

>>> loc_a_codes_dat = loc_a_codes['A']
>>> type(loc_a_codes_dat)
pandas.core.frame.DataFrame
>>> loc_a_codes_dat.head()
                              Location CRS  ... STANME_Note STANOX_Note
0                                   A1      ...
1                       A463 Traded In      ...
2  A483 Road Scheme Supervisors Closed      ...
3                               Aachen      ...
4                     AA Holidays S524      ...

[5 rows x 12 columns]

>>> print("Last updated date: {}".format(loc_a_codes_dat['Last updated date']))

All available location identifiers

In addition to the 'A' group of locations, we can use the method LocationIdentifiers.fetch_codes() to get the codes of all locations (with the initial letters ranging from 'A' to 'Z') available in this category:

>>> loc_codes = lid.fetch_codes()
>>> type(loc_codes)
dict
>>> list(loc_codes.keys())
['LocationID', 'Other systems', 'Additional notes', 'Last updated date']

loc_codes is also in a dictionary, of which the keys are as follows:

  • 'LocationID'

  • 'Other systems'

  • 'Additional notes'

  • 'Latest update date'

The corresponding values are:

  • loc_codes['LocationID'] - CRS, NLC, TIPLOC and STANOX codes for all locations available on the relevant web pages ranging from 'A' to 'Z';

  • loc_codes['Other systems'] - Relevant codes of the Other systems;

  • loc_codes['Additional notes'] - Additional notes and information (if available);

  • loc_codes['Latest update date'] - The latest 'Last updated date' among all initial-specific codes.

A snapshot of the data contained in loc_codes is demonstrated below:

>>> lid.KEY
'LocationID'

>>> loc_codes_dat = loc_codes[lid.KEY]  # loc_codes['LocationID']
>>> type(loc_codes_dat)
pandas.core.frame.DataFrame
>>> loc_codes_dat.head()
                              Location CRS  ... STANME_Note STANOX_Note
0                                   A1      ...
1                       A463 Traded In      ...
2  A483 Road Scheme Supervisors Closed      ...
3                               Aachen      ...
4                     AA Holidays S524      ...

[5 rows x 12 columns]

>>> # Relevant codes of the 'Other systems'
>>> lid.KEY_TO_OTHER_SYSTEMS
'Other systems'
>>> os_codes_dat = loc_codes[lid.KEY_TO_OTHER_SYSTEMS]
>>> type(os_codes_dat)
collections.defaultdict
>>> list(os_codes_dat.keys())
['Córas Iompair Éireann (Republic of Ireland)',
 'Crossrail',
 'Croydon Tramlink',
 'Docklands Light Railway',
 'Manchester Metrolink',
 'Translink (Northern Ireland)',
 'Tyne & Wear Metro']

>>> # Take 'Crossrail' as an example
>>> crossrail_codes_dat = os_codes_dat['Crossrail']
>>> type(crossrail_codes_dat)
pandas.core.frame.DataFrame
>>> crossrail_codes_dat.head()
                                      Location  ... New operating code
0                                   Abbey Wood  ...                ABW
1  Abbey Wood Bolthole Berth/Crossrail Sidings  ...
2                           Abbey Wood Sidings  ...
3                                  Bond Street  ...                BDS
4                                 Canary Wharf  ...                CWX

[5 rows x 5 columns]

ELRs and mileages

Engineer’s Line References (ELRs) are also frequently seen among various data in Britain’s railway system. To get the codes of ELRs (and their associated mileage files), we can use the class ELRMileages:

>>> from pyrcs.line_data import ELRMileages  # from pyrcs import ELRMileages

>>> em = ELRMileages()

>>> em.NAME
"Engineer's Line References (ELRs)"
>>> em.URL
'http://www.railwaycodes.org.uk/elrs/elr0.shtm'

Engineer’s Line References (ELRs)

Similar to the location identifiers, the codes of ELRs on the Railway Codes website are also alphabetically arranged given their initial letters. We can use the method ELRMileages.collect_elr_by_initial() to get the data of ELRs which begin with a specific initial letter. Let’s take 'A' as an example:

>>> elrs_a_codes = em.collect_elr_by_initial(initial='a')  # Data of ELRs beginning with 'A'
>>> type(elrs_a_codes)
dict
>>> list(elrs_a_codes.keys())
['A', 'Last updated date']

elrs_a_codes is a dictionary and has the following keys:

  • 'A'

  • 'Last updated date'

The corresponding values are:

  • elrs_a_codes['A'] - Data of ELRs that begin with 'A' (referring to the table presented on the web page ELRs beginning with A);

  • elrs_a_codes['Last updated date'] - The date when the web page ELRs beginning with A was last updated.

A snapshot of the data contained in elrs_a_codes is demonstrated below:

>>> elrs_a_codes_dat = elrs_a_codes['A']
>>> type(elrs_a_codes_dat)
pandas.core.frame.DataFrame
>>> elrs_a_codes_dat.head()
   ELR  ...         Notes
0  AAL  ...      Now NAJ3
1  AAM  ...  Formerly AML
2  AAV  ...
3  ABB  ...       Now AHB
4  ABB  ...

[5 rows x 5 columns]

>>> print("Last updated date: {}".format(elrs_a_codes['Last updated date']))

To get the data of all ELRs (with the initial letters ranging from 'A' to 'Z') available in this category, we can use the method ELRMileages.fetch_elr():

>>> elrs_codes = em.fetch_elr()
>>> type(elrs_codes)
['ELRs and mileages', 'Last updated date']

In like manner, elrs_codes is also a dictionary, of which the keys are:

  • 'ELRs and mileages'

  • 'Latest update date'

The corresponding values are:

  • elrs_codes['ELRs and mileages'] - Codes of all available ELRs (with the initial letters ranging from 'A' to 'Z');

  • elrs_codes['Latest update date'] - The latest 'Last updated date' among all the initial-specific codes.

A snapshot of the data contained in elrs_codes is demonstrated below:

>>> elrs_codes_dat = elrs_codes[em.KEY]
>>> type(elrs_codes_dat)
pandas.core.frame.DataFrame
>>> elrs_codes_dat.head()
   ELR  ...         Notes
0  AAL  ...      Now NAJ3
1  AAM  ...  Formerly AML
2  AAV  ...
3  ABB  ...       Now AHB
4  ABB  ...

[5 rows x 5 columns]

Mileage file of a given ELR

Further to the codes of ELRs, each ELR is associated with a mileage file, which specifies the major mileages for the ELR. To get the mileage data, we can use the method ELRMileages.fetch_mileage_file().

For example, let’s try to get the mileage file for ‘AAM’:

>>> amm_mileage_file = em.fetch_mileage_file(elr='AAM')
>>> type(amm_mileage_file)
dict
>>> list(amm_mileage_file.keys())
['ELR', 'Line', 'Sub-Line', 'Mileage', 'Notes']

As demonstrated above, amm_mileage_file is a dictionary and has the following keys:

  • 'ELR'

  • 'Line'

  • 'Sub-Line'

  • 'Mileage'

  • 'Notes'

The corresponding values are:

  • amm_mileage_file['ELR'] - The given ELR, which, in this example, is 'AAM';

  • amm_mileage_file['Line'] - Name of the line associated with the given ELR;

  • amm_mileage_file['Sub-Line'] - Name of the sub line (if any) associated with the given ELR;

  • amm_mileage_file['Mileage'] - Major mileages for the given ELR;

  • amm_mileage_file['Notes'] - Additional information/notes (if any).

A snapshot of the data contained in amm_mileage_file is demonstrated below:

>>> amm_mileage_file['Line']
'Ashchurch and Malvern Line'

>>> amm_mileage_file['Mileage'].head()
  Mileage Mileage_Note  ... Link_2_ELR Link_2_Mile_Chain
0  0.0000               ...
1  0.0154               ...
2  0.0396               ...
3  1.1012               ...
4  1.1408               ...

[5 rows x 11 columns]

Railway station data

The railway station data (including the station name, ELR, mileage, status, owner, operator, degrees of longitude and latitude, and grid reference) is categorised as one of the other assets on the Railway Codes website. To deal with data in this category, PyRCS offers a sub-package other_assets, from which we can use the contained class Stations to get the railway station data:

Now let’s import the class and create an instance of it:

>>> from pyrcs.other_assets import Stations  # from pyrcs import Stations

>>> stn = Stations()

>>> stn.NAME
'Railway station data'
>>> stn.URL
'http://www.railwaycodes.org.uk/stations/station0.shtm'

Note

  • Alternatively, the instance stn can also be defined through the class OtherAssets, which contains all classes under the category of other assets (see below).

>>> from pyrcs.collector import OtherAssets  # from pyrcs import OtherAssets

>>> oa = OtherAssets()
>>> stn_ = oa.Stations

>>> stn.NAME == stn_.NAME
True

Note

  • The instances stn_ and stn are of the same class Stations.

Railway station locations given a specific initial letter

To get the location data of railway stations whose names start with a given letter, say 'A', we can use the method Stations.collect_locations_by_initial():

>>> stn_loc_a_codes = stn.collect_locations_by_initial(initial='a')
>>> type(stn_loc_a_codes)
dict
>>> list(stn_loc_a_codes.keys())
['A', 'Last updated date']

As demonstrated above, the dictionary stn_loc_a_codes include the following keys:

  • 'A'

  • 'Last updated date'

The corresponding values are:

  • stn_loc_a_codes['A'] - Mileages, operators and grid coordinates of railway stations whose names begin with 'A' (referring to the table presented on the web page of Stations beginning with A);

  • stn_loc_a_codes['Last updated date'] - The date when the web page Stations beginning with A was last updated.

A snapshot of the data contained in stn_loc_a is demonstrated below:

>>> stn_loc_a_codes_dat = stn_loc_a_codes['A']
>>> type(stn_loc_a_codes_dat)
pandas.core.frame.DataFrame
>>> stn_loc_a_codes_dat.head()
      Station  ...                                    Former Operator
0  Abbey Wood  ...  London & South Eastern Railway from 1 April 20...
1  Abbey Wood  ...  London & South Eastern Railway from 1 April 20...
2        Aber  ...  Keolis Amey Operations/Gweithrediadau Keolis A...
3   Abercynon  ...  Keolis Amey Operations/Gweithrediadau Keolis A...
4   Abercynon  ...  Keolis Amey Operations/Gweithrediadau Keolis A...

[5 rows x 14 columns]

>>> stn_loc_a_codes_dat.columns.to_list()
['Station',
 'Station Note',
 'ELR',
 'Mileage',
 'Status',
 'Degrees Longitude',
 'Degrees Latitude',
 'Grid Reference',
 'CRS',
 'CRS Note',
 'Owner',
 'Former Owner',
 'Operator',
 'Former Operator']
>>> stn_loc_a_codes_dat[['Station', 'ELR', 'Mileage']].head()
      Station  ELR   Mileage
0  Abbey Wood  NKL  11m 43ch
1  Abbey Wood  XRS  24.458km
2        Aber  CAR   8m 69ch
3   Abercynon  CAM  16m 28ch
4   Abercynon  ABD  16m 28ch

>>> print("Last updated date: {}".format(stn_loc_a_codes['Last updated date']))

All available railway station locations

To get the location data of all railway stations (with the initial letters ranging from 'A' to 'Z') available in this category, we can use the method Stations.fetch_locations():

>>> stn_loc_codes = stn.fetch_locations()
>>> type(stn_loc_codes)
dict
>>> list(stn_loc_codes.keys())
['Mileages, operators and grid coordinates', 'Last updated date']

The dictionary stn_loc_codes include the following keys:

  • 'Mileages, operators and grid coordinates'

  • 'Latest update date'

The corresponding values are:

  • stn_loc_codes['Mileages, operators and grid coordinates'] - Location data of all railway stations available on the relevant web pages ranging from 'A' to 'Z';

  • stn_loc_codes['Latest update date'] - The latest 'Last updated date' among all initial-specific codes.

A snapshot of the data contained in stn_loc_codes is demonstrated below:

>>> stn.KEY_TO_STN
'Mileages, operators and grid coordinates'

>>> stn_loc_codes_dat = stn_loc_codes[stn.KEY_TO_STN]
>>> type(stn_loc_codes_dat)
pandas.core.frame.DataFrame
>>> stn_loc_codes_dat.head()
      Station  ...                                    Former Operator
0  Abbey Wood  ...  London & South Eastern Railway from 1 April 20...
1  Abbey Wood  ...  London & South Eastern Railway from 1 April 20...
2        Aber  ...  Keolis Amey Operations/Gweithrediadau Keolis A...
3   Abercynon  ...  Keolis Amey Operations/Gweithrediadau Keolis A...
4   Abercynon  ...  Keolis Amey Operations/Gweithrediadau Keolis A...

[5 rows x 14 columns]

>>> stn_loc_codes_dat.columns.to_list()
['Station',
 'Station Note',
 'ELR',
 'Mileage',
 'Status',
 'Degrees Longitude',
 'Degrees Latitude',
 'Grid Reference',
 'CRS',
 'CRS Note',
 'Owner',
 'Former Owner',
 'Operator',
 'Former Operator']
>>> stn_loc_codes_dat[['Station', 'ELR', 'Mileage']].head()
      Station  ELR   Mileage
0  Abbey Wood  NKL  11m 43ch
1  Abbey Wood  XRS  24.458km
2        Aber  CAR   8m 69ch
3   Abercynon  CAM  16m 28ch
4   Abercynon  ABD  16m 28ch

>>> print("Last updated date: {}".format(stn_loc_data['Last updated date']))

This is the end of the tutorial.


Any issues regarding the use of the package are all welcome and should be logged/reported onto the Bug Tracker.

For more details and examples, check sub-packages and modules.