pygnss 0.0.0__cp312-cp312-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pygnss might be problematic. Click here for more details.

pygnss/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "6.10.2"
@@ -0,0 +1,93 @@
1
+ #include <Python.h>
2
+ #include <datetime.h>
3
+
4
+ #include "hatanaka/include/crx2rnx.h"
5
+
6
+ static const int N_FIELDS = 4; // Number of fields for struct gnss_meas
7
+
8
+ static char* get_crx_line(void* _args, size_t n_max, char* dst) {
9
+
10
+ FILE* input_fh = (FILE*)_args;
11
+ return fgets(dst, n_max, input_fh);
12
+
13
+ }
14
+
15
+ static bool is_eof(void* _args) {
16
+
17
+ FILE* input_fh = (FILE*)_args;
18
+ return (fgetc(input_fh) == EOF);
19
+
20
+ }
21
+
22
+ static int on_measurement(const struct gnss_meas* gnss_meas, void* _args) {
23
+
24
+ int ret = -1;
25
+ PyObject* list = (PyObject*)_args;
26
+
27
+ if (gnss_meas == NULL) {
28
+ goto exit;
29
+ }
30
+
31
+ PyDateTime_IMPORT;
32
+
33
+ // Create Python lists for each inner list
34
+ PyObject* row = PyList_New(N_FIELDS);
35
+
36
+ double timestamp = (double)gnss_meas->gps_time.tv_sec + (double)gnss_meas->gps_time.tv_nsec / 1e9;
37
+ PyObject* time_tuple = Py_BuildValue("(d)", timestamp);
38
+ PyObject* date_time = PyDateTime_FromTimestamp(time_tuple);
39
+
40
+ PyList_SetItem(row, 0, date_time);
41
+ PyList_SetItem(row, 1, PyUnicode_FromStringAndSize(gnss_meas->satid, 3));
42
+ PyList_SetItem(row, 2, PyUnicode_FromStringAndSize(gnss_meas->rinex3_code, 3));
43
+ PyList_SetItem(row, 3, PyFloat_FromDouble(gnss_meas->value));
44
+
45
+ // Add inner lists to the outer list
46
+ PyList_Append(list, row);
47
+ Py_DECREF(row); // Decrement the reference count of 'row'
48
+
49
+ ret = 0;
50
+ exit:
51
+ return ret;
52
+ }
53
+
54
+ PyObject *_read_crx(PyObject* self, PyObject* args, PyObject* kwargs) {
55
+
56
+ char *filename = NULL;
57
+ struct crx2rnx* crx2rnx = NULL;
58
+ int ret = -1;
59
+ PyObject* list = PyList_New(0);
60
+
61
+ struct crx2rnx_callbacks callbacks = {
62
+ .on_measurement = on_measurement,
63
+ .on_measurement_args = list
64
+ };
65
+
66
+ // Parse the filename argument
67
+ if (!PyArg_ParseTuple(args, "s", &filename)) {
68
+ PyErr_SetString(PyExc_TypeError, "Expected a string filename");
69
+ goto end;
70
+ }
71
+
72
+ // Open the file
73
+ FILE* fp = fopen(filename, "r");
74
+ if (fp == NULL) {
75
+ PyErr_SetString(PyExc_IOError, "Could not open file");
76
+ goto end;
77
+ }
78
+
79
+ crx2rnx = crx2rnx__init(false, false, NULL, get_crx_line, (void*)fp, is_eof, (void*)fp, &callbacks);
80
+
81
+ ret = crx2rnx__run(crx2rnx);
82
+
83
+ if (ret < 0) {
84
+ PyErr_SetString(PyExc_IOError, "There was an issue processing the Hatanaka file");
85
+ PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL); // clear the list
86
+ }
87
+
88
+ // Clean-up
89
+ fclose(fp);
90
+ end:
91
+ return list;
92
+
93
+ }
@@ -0,0 +1,17 @@
1
+ #include <stdlib.h>
2
+ #include <Python.h>
3
+
4
+ #include "../include/helpers.h"
5
+
6
+ PyObject *convert_to_pylist(const double* array, size_t n) {
7
+
8
+ Py_ssize_t len = n;
9
+ PyObject* list = PyList_New(len);
10
+
11
+ for (Py_ssize_t i = 0; i < len; i++) {
12
+ PyObject* value = PyFloat_FromDouble(array[i]);
13
+ PyList_SetItem(list, i, value);
14
+ }
15
+
16
+ return list;
17
+ }
@@ -0,0 +1,44 @@
1
+ #include <Python.h>
2
+
3
+ #include "hatanaka.h"
4
+
5
+ static PyMethodDef module_methods[] = {
6
+ { "_read_crx", (PyCFunction)_read_crx, METH_VARARGS | METH_KEYWORDS,
7
+ "Read a Hatanaka (gzip uncompressed) file and generate a numpy array\n\n"
8
+ ":param filename: Name of the Hatanaka file to process\n"
9
+ ":return: Numpy array\n\n"},
10
+ {NULL, NULL, 0, NULL}, /* Sentinel */
11
+ };
12
+
13
+ /*----------------------------------------------------------------------------*/
14
+
15
+ static struct PyModuleDef module = {
16
+ PyModuleDef_HEAD_INIT,
17
+ "_c_ext", /* name of the module*/
18
+ "C extension methods",
19
+ -1, // size of per-interpreter state of the module,
20
+ // or -1 if the module keeps state in global variables.
21
+ module_methods
22
+ };
23
+
24
+
25
+ PyMODINIT_FUNC PyInit__c_ext(void) {
26
+
27
+ PyObject* m = NULL;
28
+
29
+ // // Classes
30
+ // if (PyType_Ready(HatanakaReaderType) < 0) {
31
+ // goto end;
32
+ // }
33
+
34
+ m = PyModule_Create(&module);
35
+ if (m == NULL) {
36
+ goto end;
37
+ }
38
+
39
+ // Py_INCREF(HatanakaReaderType);
40
+ // PyModule_AddObject(m, "HatanakaReader", (PyObject*)HatanakaReaderType);
41
+
42
+ end:
43
+ return m;
44
+ }
pygnss/cl.py ADDED
@@ -0,0 +1,148 @@
1
+ """
2
+ Program to perform various columnar operations on inputs
3
+
4
+ All indicators have this format
5
+
6
+ 'x0'
7
+
8
+ where 'x' can be one of the following
9
+
10
+ - 'c' - Select column
11
+ - 'd' - diff column relative to the previous value
12
+ - 'f' - diff column relative to the first value of the column
13
+ - 'm' - Compute the minutes elapsed since the first value (divide column by 60,
14
+ as it assumes that the values are in seconds))
15
+ - 'h' - Compute the hours elapsed since the first value (divide column by 3600,
16
+ as it assumes that the values are in seconds))
17
+
18
+ and '0' is the column number (1 based)
19
+
20
+ Examples:
21
+
22
+ (a) Select columns with the indicated order (first output 5th column and then the
23
+ first column)
24
+ cat file.txt | cl c5 c1
25
+
26
+ (b) Select 6th column and output 1st column relative to the first one
27
+ cat file.txt | cl c6 f1
28
+
29
+ (c) Make a diff of the third column relative to the first value
30
+ cat file.txt | cl f3
31
+ """
32
+ import argparse
33
+ import sys
34
+
35
+
36
+ class ColumnProcess:
37
+ """
38
+ Class that manages the processing of a set of fields based on some criteria
39
+ """
40
+
41
+ def __init__(self, colprocstr):
42
+ """
43
+ Class initialization. This method receives a string defining the type
44
+ of operation to be performed
45
+ """
46
+
47
+ if len(colprocstr) < 2:
48
+ raise ValueError(f"Do not know how to interpret [ {colprocstr} ], "
49
+ "column selector should be of the form 'n0', with "
50
+ "'n' being a character and '0' a column number")
51
+
52
+ self.process_type = colprocstr[0]
53
+
54
+ # Obtain the column number, taking into account that the indices must
55
+ # be translated from 1-based to 0-based
56
+ self.process_column = int(colprocstr[1:]) - 1
57
+
58
+ self.previous_value = None
59
+ self.first_value = None
60
+
61
+ def process(self, fields):
62
+ """
63
+ Process a set of fields. Raise an exception if
64
+ """
65
+
66
+ if self.process_column >= len(fields):
67
+ raise IndexError(f"Unable to fecth column [ {self.process_column + 1} ] (1-based) "
68
+ f"in line with [ {len(fields)} ] fields. "
69
+ f"Offending line [ {' '.join(fields)} ]\n")
70
+
71
+ column_value = fields[self.process_column]
72
+
73
+ if self.process_type == 'c':
74
+
75
+ return column_value
76
+
77
+ elif self.process_type == 'f' or self.process_type == 'm' or self.process_type == 'h':
78
+
79
+ incoming_value = float(column_value)
80
+
81
+ if self.first_value is None:
82
+ self.first_value = incoming_value
83
+
84
+ value = incoming_value - self.first_value
85
+
86
+ if self.process_type == 'm':
87
+ value = value / 60.0
88
+ elif self.process_type == 'h':
89
+ value = value / 3600.0
90
+
91
+ return str(value)
92
+
93
+ elif self.process_type == 'd':
94
+
95
+ incoming_value = float(column_value)
96
+
97
+ if self.previous_value is None:
98
+ self.previous_value = incoming_value
99
+
100
+ value = incoming_value - self.previous_value
101
+
102
+ # Update internal value only if the process method is the difference
103
+ # relative to the previous value
104
+ if self.process_type == 'd':
105
+ self.previous_value = incoming_value
106
+
107
+ return str(value)
108
+
109
+ else:
110
+ raise ValueError("Do not know what process type is '%c'" % self.process_type)
111
+
112
+ def __str__(self):
113
+
114
+ return self.__repr__()
115
+
116
+ def __repr__(self):
117
+
118
+ return "Process type [ %s ], process column [ %d ]\n" % (self.process_type, self.process_column)
119
+
120
+
121
+ def entry_point():
122
+
123
+ # Process the options of the executable
124
+
125
+ parser = argparse.ArgumentParser(description=__doc__,
126
+ formatter_class=argparse.RawDescriptionHelpFormatter)
127
+
128
+ parser.add_argument('columns', metavar='<selector>', type=str, nargs='+',
129
+ help="Set of column selectors and operators")
130
+
131
+ args = parser.parse_args()
132
+
133
+ # Make an array of objects that will take care of processing the fields
134
+ colprocs = [ColumnProcess(colproc) for colproc in args.columns]
135
+
136
+ for line in sys.stdin:
137
+
138
+ # If line is empty, print an empty line
139
+ if len(line.strip()) == 0:
140
+ sys.stdout.write("\n")
141
+ continue
142
+
143
+ fields = line.strip().split()
144
+
145
+ # Process each column
146
+ newfields = [cp.process(fields) for cp in colprocs]
147
+
148
+ sys.stdout.write(" ".join(newfields) + "\n")
pygnss/constants.py ADDED
@@ -0,0 +1,4 @@
1
+ SPEED_OF_LIGHT = 299792458 # in vacuum [m/s]
2
+
3
+ EARTH_GRAVITATION_PARAM_MU = 3.986005e14
4
+ EARTH_ROTATION_RATE = 7.2921151466999996e-05
pygnss/decorator.py ADDED
@@ -0,0 +1,14 @@
1
+ import warnings
2
+
3
+
4
+ def deprecated(alternative):
5
+ def decorator(func):
6
+ def new_func(*args, **kwargs):
7
+ # Raise a DeprecationWarning with the specified message.
8
+ message = f"Call to deprecated function {func.__name__}."
9
+ if alternative:
10
+ message += f" Use {alternative} instead."
11
+ warnings.warn(message, DeprecationWarning, stacklevel=2)
12
+ return func(*args, **kwargs)
13
+ return new_func
14
+ return decorator
pygnss/file.py ADDED
@@ -0,0 +1,36 @@
1
+ from functools import wraps
2
+ from typing import IO
3
+
4
+
5
+ def process_filename_or_file_handler(mode):
6
+ def decorator(func):
7
+ @wraps(func)
8
+ def wrapper(input, *args, **kwargs):
9
+ if isinstance(input, str):
10
+ with open(input, mode) as fh:
11
+ return func(fh, *args, **kwargs)
12
+ else:
13
+ return func(input, *args, **kwargs)
14
+ return wrapper
15
+ return decorator
16
+
17
+
18
+ def grep_lines(filename: str, pattern_string: str):
19
+ """
20
+ Generator function used to grep lines from a file. Can be used in methods
21
+ such as numpy.genfromtxt, ...
22
+
23
+ >>> generator = grep_lines(filename, "pattern")
24
+ >>> data = numpy.loadtxt(generator)
25
+ """
26
+
27
+ with open(filename, 'r') as fh:
28
+ for line in fh:
29
+ if pattern_string in line:
30
+ yield line
31
+
32
+
33
+ def skip_lines(fh: IO, n_lines: int):
34
+
35
+ for _ in range(n_lines):
36
+ fh.readline()