|
13 | 13 | import numpy as np |
14 | 14 |
|
15 | 15 | from .line import HeaderLine |
16 | | -from .field import Field |
| 16 | +from .field import Field, HeaderFieldAccessor |
17 | 17 | from .utils import castarray |
18 | 18 |
|
19 | 19 | class Sequence(Sequence): |
@@ -773,6 +773,256 @@ def xline(self, value): |
773 | 773 | for i, src in zip(self.segyfile.xlines, value): |
774 | 774 | self.xline[i] = src |
775 | 775 |
|
| 776 | + |
| 777 | +class FileFieldAccessor(Sequence): |
| 778 | + """ |
| 779 | + Sequence of rows of trace headers in a SEG-Y file. |
| 780 | +
|
| 781 | + Provides access to all trace headers defined in the SEG-Y file. |
| 782 | +
|
| 783 | + Notes |
| 784 | + ----- |
| 785 | + .. versionadded:: 2.0 |
| 786 | +
|
| 787 | + """ |
| 788 | + |
| 789 | + def __init__(self, segyfile): |
| 790 | + self.segyfile = segyfile |
| 791 | + super().__init__(segyfile.tracecount) |
| 792 | + |
| 793 | + def __getitem__(self, i): |
| 794 | + """traceheader[i] |
| 795 | +
|
| 796 | + All headers belonging to ith trace, starting at 0. |
| 797 | +
|
| 798 | + Parameters |
| 799 | + ---------- |
| 800 | + i : int or slice |
| 801 | +
|
| 802 | + Returns |
| 803 | + ------- |
| 804 | + traceheaders : RowFieldAccessor |
| 805 | +
|
| 806 | + Examples |
| 807 | + -------- |
| 808 | + Accessing headers in trace 10: |
| 809 | +
|
| 810 | + >>> traceheader[10] |
| 811 | + """ |
| 812 | + try: |
| 813 | + trace_index = self.wrapindex(i) |
| 814 | + return RowFieldAccessor(segyfile=self.segyfile, trace_index=trace_index) |
| 815 | + |
| 816 | + except TypeError: |
| 817 | + try: |
| 818 | + trace_indices = i.indices(len(self)) |
| 819 | + except AttributeError: |
| 820 | + msg = 'trace indices must be integers or slices, not {}' |
| 821 | + raise TypeError(msg.format(type(i).__name__)) |
| 822 | + |
| 823 | + def gen(): |
| 824 | + for trace_index in range(*trace_indices): |
| 825 | + yield RowFieldAccessor(segyfile=self.segyfile, trace_index=trace_index) |
| 826 | + |
| 827 | + return gen() |
| 828 | + |
| 829 | + def __setitem__(self, i, val): |
| 830 | + """traceheader[i] = val |
| 831 | +
|
| 832 | + Write the ith header of the file, starting at 0. |
| 833 | +
|
| 834 | + Parameters |
| 835 | + ---------- |
| 836 | + i : int or slice |
| 837 | + val : another FileFieldAccessor or array like |
| 838 | +
|
| 839 | + Examples |
| 840 | + -------- |
| 841 | + Copy all trace's headers to a different trace: |
| 842 | +
|
| 843 | + >>> traceheader[28] = traceheader[29] |
| 844 | + """ |
| 845 | + if not isinstance(i, slice): |
| 846 | + trace_index = self.wrapindex(i) |
| 847 | + if not isinstance(val, RowFieldAccessor): |
| 848 | + raise TypeError( |
| 849 | + "Unassignable type. f.traceheader[i] can only be assigned f.traceheader[j]") |
| 850 | + self[trace_index][:] = val |
| 851 | + return |
| 852 | + |
| 853 | + trace_indices = range(*i.indices(len(self))) |
| 854 | + for trace_index, value in zip(trace_indices, val): |
| 855 | + self[trace_index] = value |
| 856 | + |
| 857 | + |
| 858 | +class RowFieldAccessor(Sequence): |
| 859 | + """ |
| 860 | + Sequence of trace headers in a single trace (row). |
| 861 | +
|
| 862 | + Provides access to all trace headers defined in the trace. |
| 863 | +
|
| 864 | + Notes |
| 865 | + ----- |
| 866 | + .. versionadded:: 2.0 |
| 867 | +
|
| 868 | + """ |
| 869 | + |
| 870 | + def __init__(self, segyfile, trace_index): |
| 871 | + self.segyfile = segyfile |
| 872 | + self.trace_index = trace_index |
| 873 | + super().__init__(segyfile.traceheader_count) |
| 874 | + |
| 875 | + def __getitem__(self, i): |
| 876 | + """traceheader[i] |
| 877 | +
|
| 878 | + ith header of the trace, starting at 0. |
| 879 | +
|
| 880 | + Note that this function loads trace header into memory, so if you wish |
| 881 | + to access multiple fields, caching the result of this function is more |
| 882 | + efficient than calling it anew with each of the fields. |
| 883 | +
|
| 884 | + Parameters |
| 885 | + ---------- |
| 886 | + i : int or slice |
| 887 | +
|
| 888 | + Returns |
| 889 | + ------- |
| 890 | + field : Field |
| 891 | + dict_like header |
| 892 | +
|
| 893 | + Examples |
| 894 | + -------- |
| 895 | + Reading a header: |
| 896 | +
|
| 897 | + >>> traceheader[10] |
| 898 | +
|
| 899 | + Read a field in the first 5 headers: |
| 900 | +
|
| 901 | + >>> [x[25] for x in traceheader[:5]] |
| 902 | + [1, 2, 3, 4] |
| 903 | + """ |
| 904 | + try: |
| 905 | + return HeaderFieldAccessor.trace( |
| 906 | + traceno=self.trace_index, traceheader_index=self.wrapindex(i), segyfile=self.segyfile |
| 907 | + ) |
| 908 | + |
| 909 | + except TypeError: |
| 910 | + try: |
| 911 | + traceheader_indices = i.indices(len(self)) |
| 912 | + except AttributeError: |
| 913 | + msg = 'trace header indices must be integers or slices, not {}' |
| 914 | + raise TypeError(msg.format(type(i).__name__)) |
| 915 | + |
| 916 | + def gen(): |
| 917 | + # see Header.__getitem__ for logic explanation |
| 918 | + x = HeaderFieldAccessor.trace( |
| 919 | + traceno=self.trace_index, traceheader_index=None, segyfile=self.segyfile |
| 920 | + ) |
| 921 | + buf = bytearray(x.buf) |
| 922 | + for traceheader_index in range(*traceheader_indices): |
| 923 | + buf = x.fetch(buf, self.trace_index, traceheader_index) |
| 924 | + x.buf[:] = buf |
| 925 | + x.traceheader_index = traceheader_index |
| 926 | + traceheader_layout = x.segyfile.tracefield[traceheader_index] |
| 927 | + x._keys = [field.offset() for field in traceheader_layout] |
| 928 | + yield x |
| 929 | + |
| 930 | + return gen() |
| 931 | + |
| 932 | + def __getattr__(self, name): |
| 933 | + """traceheaders.name |
| 934 | +
|
| 935 | + Header of the trace by name `name`. `name` must be a name defined by |
| 936 | + the file layouts. |
| 937 | +
|
| 938 | + Wrapper around :meth:`.__getitem__`, so refer to it for more |
| 939 | + information. |
| 940 | +
|
| 941 | + Parameters |
| 942 | + ---------- |
| 943 | + name : str |
| 944 | +
|
| 945 | + Returns |
| 946 | + ------- |
| 947 | + field : Field |
| 948 | + dict_like header |
| 949 | +
|
| 950 | + Examples |
| 951 | + -------- |
| 952 | + Reading a header: |
| 953 | +
|
| 954 | + >>> traceheaders.SEG00001 |
| 955 | + """ |
| 956 | + index = self.segyfile._traceheader_names.index(name) |
| 957 | + return self[index] |
| 958 | + |
| 959 | + def __setitem__(self, i, val): |
| 960 | + """traceheader[i] = val |
| 961 | +
|
| 962 | + Write the ith header of the trace, starting at 0. |
| 963 | +
|
| 964 | + Parameters |
| 965 | + ---------- |
| 966 | + i : int or slice |
| 967 | + val : Field or array_like of dict_like |
| 968 | +
|
| 969 | + Examples |
| 970 | + -------- |
| 971 | + Copy standard header to a different trace: |
| 972 | +
|
| 973 | + >>> f.traceheader[0][0] = f.traceheader[1][0] |
| 974 | +
|
| 975 | + Writing fields via `traceheader[trace_index][traceheader_index] = |
| 976 | + {(offset: value)}` is not supported. Use :class:`segyio.field.Field` |
| 977 | + interface instead: |
| 978 | +
|
| 979 | + >>> f.traceheader[0][0].update({ 37: 5, 1: 2484 }) |
| 980 | +
|
| 981 | + """ |
| 982 | + if not isinstance(i, slice): |
| 983 | + traceheader_index = self.wrapindex(i) |
| 984 | + field_sequence = self[traceheader_index] |
| 985 | + if isinstance(val, Field): |
| 986 | + field_sequence.update(val) |
| 987 | + return |
| 988 | + raise TypeError( |
| 989 | + "Unassignable type. f.traceheader[i][j] can only be assigned another Field.") |
| 990 | + |
| 991 | + traceheader_indices = range(*i.indices(len(self))) |
| 992 | + |
| 993 | + for traceheader_index, value in zip(traceheader_indices, val): |
| 994 | + self[traceheader_index] = value |
| 995 | + |
| 996 | + def __setattr__(self, name, value): |
| 997 | + """traceheaders.name = value |
| 998 | +
|
| 999 | + Write header of the trace by name `name`. `name` must be a name defined by |
| 1000 | + the file layouts. |
| 1001 | +
|
| 1002 | + Wrapper around :meth:`.__setitem__`, so refer to it for more |
| 1003 | + information. |
| 1004 | +
|
| 1005 | + Parameters |
| 1006 | + ---------- |
| 1007 | + name : str |
| 1008 | +
|
| 1009 | + Examples |
| 1010 | + -------- |
| 1011 | + Copying a header: |
| 1012 | +
|
| 1013 | + >>> f.traceheader[0].SEG00001 = f.traceheader[1].SEG00001 |
| 1014 | + """ |
| 1015 | + if name == "segyfile": |
| 1016 | + super().__setattr__(name, value) |
| 1017 | + return |
| 1018 | + |
| 1019 | + try: |
| 1020 | + index = self.segyfile._traceheader_names.index(name) |
| 1021 | + self[index] = value |
| 1022 | + except ValueError: |
| 1023 | + super().__setattr__(name, value) |
| 1024 | + |
| 1025 | + |
776 | 1026 | class Attributes(Sequence): |
777 | 1027 | """File-wide attribute (header word) reading |
778 | 1028 |
|
|
0 commit comments