From 8f4f8347defe0cacb27c5a75f3472c72805456a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=9B=E5=B3=BB=E6=81=BA?= <202115006@mail.sdu.edu.cn> Date: Mon, 7 Apr 2025 12:18:37 +0000 Subject: [PATCH] program MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 葛峻恺 <202115006@mail.sdu.edu.cn> --- .../layers_generator.cpython-310.pyc | Bin 0 -> 2600 bytes utils/__pycache__/plot.cpython-310.pyc | Bin 0 -> 4130 bytes .../__pycache__/train_val_lr.cpython-310.pyc | Bin 0 -> 1696 bytes utils/layers_generator.py | 93 ++++++++++++ utils/plot.py | 135 ++++++++++++++++++ utils/train_val_lr.py | 63 ++++++++ 6 files changed, 291 insertions(+) create mode 100644 utils/__pycache__/layers_generator.cpython-310.pyc create mode 100644 utils/__pycache__/plot.cpython-310.pyc create mode 100644 utils/__pycache__/train_val_lr.cpython-310.pyc create mode 100644 utils/layers_generator.py create mode 100644 utils/plot.py create mode 100644 utils/train_val_lr.py diff --git a/utils/__pycache__/layers_generator.cpython-310.pyc b/utils/__pycache__/layers_generator.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24a1014be9a3e6d80bbaf9e49a9986b2c9c89c1d GIT binary patch literal 2600 zcmaKu&yU+g6vt=AcH%fcHZ5s)w=Km$X$e9_duXW;;)kd}T=*g25-p0-%rv;0*x9ku zc2{Ew)Iv`nB*XDrVoPh&>hfhdQ+MW?71mgR~={CFkaO5{{-n{w!@q0;{&4A(g zp8L^E3$f(_grYctU>c+AnRzW zNd6Y>uV*WHyR`I@sH~k61FvBHZVaDmO6_!^rc7Yp~VU~|YUNx26AF;fa zIi=SXewMv^EDuZ|oeiOnXYO^+xW>C7@_O8|HDP?iO|XJhV^l$-Qmd(5ubBD`&KcV4 zXISoUu3DQr!GeAQHO3hwr)S5&O@AXDKWTss@48T9CUq+~crq#B2pqU^m8#yE|#D2c=EBv$Fk zyBw!;lNX-Mwx&u`t?L&eo)+G=(n(r4QJfVXx{Xv(K_Qb#QKgdXmBDnXVp-HwJe%0b zyUkv0q$Al+qit0LF!#rUEv3_*KZ)Yfx^#aPrQw0|kxsMHu@5)fceinHnT);qEFGL1 ztFoI*6ZKkJO$JdM#UpF&)$M#%PYWIuuI<)}JQj{%=JWMg7LC*Oa*zE{c?F3+Io&Gu&ueOa0{u1VVzTsch_+~P7r(aS^AF0drLl&P-(k{B5?&9@hJG?!&`h#rHuajRHN$7)S@v8{!6+ z&MJ79qWr$lTE~~vF~FGSO2 z6#I5H5Tr$?gmR%FQfc8?YvI|2>;2TXmSzK;^xVhlwRA5HFAH(B;P-^onsnnvaNBF;$R8Jb|}=koE!ytC$+mMdh5dI!LSTA`LBI z$n6k^4Upzq(!#t6rrbGcEeQ=heXP4?S{-%+ak|6uCB#(3T=ZYE^m(AOY3X}obIo|5 z&)a_Wf9RW~2sB|jNfJcUA!13a7D+p&vP(+Eb3#w&b6NYTyL%J&H?1YlvFhxQIMUhW<%-+i$;=#21y${wwgvC>?5rP(xv7gp3htHPtFbVj(OLEH-B< zoFEwKXfU3q*b)NTs$L~QvApZ;1)u>d@@z7TWw&DQukg#DfgE?B9C`86M*QeC=gXid zF;hs@@^axo-+PG%=9jq3J$)TBrj!HezL1KLgpMLU(2XJStkEikUPfV;-K`cLviWqY uTsTEXo1ARuu(xTuEKE&9Ya5yTXYm(gHdfEkA*8fZpJ5^q90?9KR{sY2?U^6| literal 0 HcmV?d00001 diff --git a/utils/__pycache__/plot.cpython-310.pyc b/utils/__pycache__/plot.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e9124c67a214ac3763404c424caea26569f0eafb GIT binary patch literal 4130 zcmd6q%Wot{9mo4MJv~o9*X#8rp#UkFNsQOKgh$L0lI*e}AsLx0LSf{nRi3Ju>Dhi! z-D7)JV+o{)oK`|Y;($1eLoWUo0^Io<>IzFV5(gy2WeZZgj`&;_N7N|*TZk41<7*QPYs6fZpS7 zPk2n06S~J;FQ7es-`LoIddn@I?nmODn+ocM?yV^7dc7%wUZ#IV(Lp)|kdvnh3EY@l z@JnDl+E^QCJH}z*&`$M<0Y7uB;p7jCW2>T#i_6-fGq%*blv;zr#AZ4(nE3}-qOL(n zky)(pAWJ)AjoGZooUt)BnbWhz&bY)%5A4G-)P&_j%gO@-+fB;Mfm{_gfX$7KUUAl6 z1vcfZRuyV3z}79YrLozwXLV|9nO$Nl?D7Ls^;JK@gP1?kZfhSD4=dx!WPz<<-Cy)! zq(!!xwVNy*X=={PW1U@LYqObL!cuk>4&WKOX=qxRz_aZ~DM|aBc;OxwDQ6_+BJk4G z+w;;9=|o|Y(l8|fjR_4Ip=>ZrvKF1lj|7$r8umEZr3ti-Le-m~sTYx$3L5Z~iw!l_ zTV1G%Y0)CD0IPI%7 zzKdnaQ0(y$@x71}<_X?`iHG^lW19B2$TlcRBbePDS1XT(X*^7cvfg}k?8xVADRYDq!cj?eix5&$zn?W<*2~PC1lb=Fnw)fCDq+yhBI4_p(;l}1>n4IfE zodC?BLt#ce(xsg=5~K^i3+H(@jq6zlkLGa1gtYiRc`piRI9&$sIyUZCx>1;JbZOxE zqx&V5Nxb{KX-tt^QwwW>uY=2Cv9#zgjil9s!w~4W#|3HAB!(T9RtM}!+Wa8pA>{S~ zFGQsWkE*vlG{g=kji3p=IXDb1p59*C(`B9dy;LBAu3w`!FRN6@l z_5w9CFOju`r!Jb1njCH(aI%_uy*?Dv5f~k?6ig5XmKKiLtV#>bUs`CVvXV1D3B#S5 zkt`^KkmYa~xN+pcrpgkgu|d)AtOoxUgM^bd+Yf(cOHK9>xZ9w^zhHW{Ku!i`Rw-}{{2sX{A}{8hoAm- zXPA0^vJ(S}HsX<-!-V_B-CM7>TwFpOx=&sNDOcvrvhL`MW)1X z%|*ScmrVz9RbBiTs&~-vP9D4r@Wj=H@J~q0E(Ghakm>_tVxGgjKCn)4uMY|t?t2<@ zKGyMe1Gw9Gkqm4AyTNJ-u==D3HR>O$8xg)afb+9&CHOXf@@-Nc1LEQ8DGn-t{nJ{5 zDqa8xeFc1dQUl=ECv!94J7Z@u&*0_-;J*)7*bM%VT2#Q-2TK6_%WQQvpJfI7D**g8 z%D|cxNuCh+PX^OqxHpEL5u zGPaQs7T`ZaEQ04wcSswxoO(6F~1?1S6VkjbNC}_xH z9z>QfjM!PDcmb10)zyo~ZK zly8GbN8Ka4RLGKo7LreV2S0xo zeLh0|1z(>YA!iZe{|QFgPl=KKQ(}bBgiwsYPJ)ZfOY$+zT(@ulykY~zR2Z1fVxdH$3k3L(>N<=UX?}!AyP6*+69PPJNk;7CPS)&PPhS%f$;g#SF!aosK$p6f~*-~(Zqz`v)` z>~wo7I1z{!feX&H!$2OZ`5D-AKU(1 A1ONa4 literal 0 HcmV?d00001 diff --git a/utils/__pycache__/train_val_lr.cpython-310.pyc b/utils/__pycache__/train_val_lr.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9fc0c167120f4fb98dd24ef28b1f29181f2cfdf2 GIT binary patch literal 1696 zcmZ8h&u<(x6t?I0&TiT?2`$h9BLNl5AtHiOR2771%c+WlC_=0jjhwNwna%vFJ)4kd zRss^yBS?r#Dx_WD!U@i8{}NwmNP9*|NF3ljZz=_5!&Y<65$`h_98!dOAp4Jm&c6 zKo55(*Py8hKtm^FN+1$CcADQi$_0!mf9tDwB<9ci~EO3$K_KgXm_dRP=VVYcIdK-fe5w z++91#h%@cfJCy)aDU%J|em^T&eM=Ool-ga#iFVRj(H6=LZ1EmHtOcNY!6idF#@p{&k@? z>$2(}-udeAr#puaKL7pRH%ABi5AXkYH2LE2-nU2h_a8nuc=YSuqhG%3kLom2{aNf= z7>!)6cBBudq7+mF5Ksr+jup^=E?5i4qkx7qu+GAY@lI^;eDYu&1<;I&4q$LXMK-9& zsp-U;lCNKf9HO3H0X?~(Eq7vro*?I@_drkX1bm0~&^3DUK~Fxa2Rr~lPeEgYwm?Oo z7f^`NjdT0-$549?yn8k!MX*BDd)uHFd_O_GfhVY{)wDoA_Dnw#Ro@M?BY*{o7tnq& z%elm>NUVO@MnGcZ96&eJq2bKrTrQ%03E>>V(+JNXJd1E1;R3>Q2$;MXyZ|E|z&RD8mlHl+R#O^gxrv!1x$Nm z2XD{mRRYyz!~Lz@n>RkI%0d)%%Cc-H;v!)?D#`?trhX(u6|FHPcvKdVk#58a9wp}Q zF_K_6TOxE^)>bCFwziY?fu7G~3`z$LUZ(G*rhO0r>qc^2@JgolkSqXN~LYJqh>knm{LFfT}lf- zb;g*sQk9m)vMC2?gIyw-+NoH*p*>brqTt$RYswg$VVM@%=cz1ME_4vb>uDz9SbH;8 yBxXatjDV$NvSk7~aTlY2S@N&K-(r-BckmykP(cBtKcF2tPcPaa06RF>S^5_pk-6po literal 0 HcmV?d00001 diff --git a/utils/layers_generator.py b/utils/layers_generator.py new file mode 100644 index 0000000..549411b --- /dev/null +++ b/utils/layers_generator.py @@ -0,0 +1,93 @@ +import numpy as np +import random + +def generate_layers_1d(grid_size, num_layers, min_size, transition_size, first_layer_minsize, first_layer_maxsize): + """Generate a 1D stratified model with transition zones.""" + usable_size = grid_size - (num_layers - 1) * transition_size + grid = np.zeros(grid_size, dtype=int) + remaining_size = usable_size + layer_sizes = [] + + # Determine layer sizes + for i in range(num_layers - 1): + if i == 0: + size = random.randint(first_layer_minsize, first_layer_maxsize) + else: + size = random.randint(min_size, remaining_size - (num_layers - i - 1) * min_size) + layer_sizes.append(size) + remaining_size -= size + layer_sizes.append(remaining_size) + + # Assign layers and transitions to grid + current_position = 0 + for i, size in enumerate(layer_sizes): + grid[current_position:current_position + size] = i + 1 + current_position += size + if i < num_layers - 1: + grid[current_position:current_position + transition_size] = 0 # 0 indicates transition zone + current_position += transition_size + + return grid + +def assign_permittivity(grid, num_layers, permittivity_range=(1, 81), transition_size=5): + """Assign permittivity values to layers and interpolate values across transition zones.""" + permittivity_grid = np.zeros_like(grid, dtype=float) + layer_permittivities = {} + + # Assign permittivity to each layer + for layer in range(1, num_layers + 1): + value = random.uniform(*permittivity_range) + layer_permittivities[layer] = value + permittivity_grid[grid == layer] = value + + # Smooth transitions between layers using linear interpolation + for i in range(1, num_layers): + start_val = layer_permittivities[i] + end_val = layer_permittivities[i + 1] + transition_start = np.where(grid == 0)[0][(i - 1) * transition_size] + for j in range(transition_size): + t = j / (transition_size - 1) + permittivity_grid[transition_start + j] = (1 - t) * start_val + t * end_val + + return permittivity_grid + +def assign_permittivity_with_smooth_transition(grid, num_layers, first_layer_eps_range, permittivity_range=(1, 81), transition_size=5): + """Assign permittivity values using smooth cosine transition between layers.""" + permittivity_grid = np.zeros_like(grid, dtype=float) + layer_permittivities = {} + + for layer in range(1, num_layers + 1): + if layer == 1: + value = random.randint(*first_layer_eps_range) + else: + value = random.uniform(*permittivity_range) + layer_permittivities[layer] = value + permittivity_grid[grid == layer] = value + + # Cosine-smooth transitions + for i in range(1, num_layers): + start_val = layer_permittivities[i] + end_val = layer_permittivities[i + 1] + transition_start = np.where(grid == 0)[0][(i - 1) * transition_size] + for j in range(transition_size): + t = j / (transition_size - 1) + smooth = 0.5 * (1 - np.cos(np.pi * t)) + permittivity_grid[transition_start + j] = start_val + (end_val - start_val) * smooth + + return permittivity_grid + +def assign_integer_values(permittivity_grid): + """Convert permittivity values to discrete integers representing unique material zones.""" + layer_id = np.zeros_like(permittivity_grid, dtype=float) + unique_permittivities = {} + integer_value = 0 + + for idx, val in enumerate(permittivity_grid): + val = round(val, 5) + if idx == 0 or val != round(permittivity_grid[idx - 1], 5): + unique_permittivities[val] = integer_value + integer_value += 1 + layer_id[idx] = unique_permittivities[val] + + return layer_id + diff --git a/utils/plot.py b/utils/plot.py new file mode 100644 index 0000000..4604b37 --- /dev/null +++ b/utils/plot.py @@ -0,0 +1,135 @@ +import os +import sys +import torch +from torchsummary import summary +from torchvision.utils import make_grid, save_image +import numpy as np +import matplotlib.pyplot as plt +import scipy.ndimage +# Add parent directory to path for config import +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +from config import Network_train_Config as cfg + + +def plot_BSCAN_data(data, path, line_length=100, time_length=200, ratio=1): + """ + Plot the inverted permittivity constant map and adjust the colormap range based on the ratio parameter. + If ratio < 1, values exceeding ratio * max(abs(data)) will be saturated at the colormap maximum. + + :param data: 2D NumPy array (N, M), where N is time/depth and M is survey line direction + :param path: Path to save the output image + :param line_length: Survey line length in meters (default: 400m) + :param time_length: Time range in nanoseconds (default: 200ns) + :param ratio: Scaling factor for colormap range (default: 1) + """ + num_points, num_lines = data.shape + + # Compute the maximum absolute value for normalization + max_abs = np.max(np.abs(data)) + vmin = -ratio * max_abs + vmax = ratio * max_abs + + # Set font style + plt.rcParams.update({'font.family': 'Times New Roman', 'font.size': 20}) + + # Plot the permittivity image + plt.figure(figsize=(10, 4)) + im = plt.imshow(data, aspect='auto', cmap='gray', + extent=[0, line_length, time_length, 0], + vmin=vmin, vmax=vmax) + + # Configure axis labels and ticks + plt.xlabel('Distance (m)', fontsize=20) + plt.xticks([0, 20, 40, 60, 80, 100, line_length]) + plt.ylabel('Time (ns)', fontsize=20) + plt.yticks([0, 50, 100, 150, 200, time_length]) + + # Customize tick and border appearance + plt.tick_params(axis='both', direction='in', width=1) + for spine in plt.gca().spines.values(): + spine.set_linewidth(1) + + # Remove grid lines, adjust layout, and save the figure + plt.grid(False) + plt.tight_layout() + plt.savefig(path, dpi=300) + plt.show() + + + +def plot_permittivity_constant(data, path, line_length=100, time_length=200): + """ + Plot the inverted permittivity constant. + + :param data: 2D NumPy array, shape (N, M), where N is depth (or time) and M is distance along the survey line. + :param path: Path to save the output image. + :param line_length: Survey line length (meters), default is 100m. + :param time_length: Time range (nanoseconds), default is 200ns. + """ + num_points, num_lines = data.shape + + # Configure font settings + plt.rcParams.update({'font.family': 'Times New Roman', 'font.size': 20}) + + # Plot the permittivity map + plt.figure(figsize=(12, 4)) + im = plt.imshow(data, aspect='auto', cmap='rainbow_r', extent=[0, 100, 200, 0], vmin=9, vmax=26) + + # Set axis labels and ticks + plt.xlabel('Distance (m)', fontsize=20) + plt.xticks([0, 20, 40, 60, 80, 100]) + plt.ylabel('Time (ns)', fontsize=20) + plt.yticks([0, 50, 100, 150, 200]) + + # Add colorbar + cbar = plt.colorbar(im) + cbar.set_label('Permittivity', fontsize=20) + + # Adjust axis formatting + plt.tick_params(axis='both', direction='in', width=1) + for spine in plt.gca().spines.values(): + spine.set_linewidth(1) + + plt.grid(False) + plt.tight_layout() + plt.savefig(path, dpi=300) + plt.show() + + +def plot_depth_permittivity_constant(data, path, line_length=100, time_length=200): + """ + Plot the inverted permittivity constant as a 2D colormap. + + :param data: 2D NumPy array (depth/time, distance), representing permittivity values. + :param path: File path to save the output image. + :param line_length: Length of the survey line in meters (default: 100m). + :param time_length: Time range in nanoseconds (default: 200ns). + """ + num_points, num_lines = data.shape + + # Set font properties + plt.rcParams.update({'font.family': 'Times New Roman', 'font.size': 20}) + + # Create the plot + plt.figure(figsize=(12, 4)) + im = plt.imshow(data, aspect='auto', cmap='rainbow_r', extent=[0, line_length, time_length, 0], vmin=8, vmax=30) + + # Label axes and set ticks + plt.xlabel('Distance (m)', fontsize=20) + plt.xticks([0, 20, 40, 60, 80, 100]) + plt.ylabel('Time (ns)', fontsize=20) + plt.yticks([0, 2, 4, 6, 8]) + + # Add colorbar + cbar = plt.colorbar(im) + cbar.set_label('Permittivity', fontsize=20) + + # Format axis appearance + plt.tick_params(axis='both', direction='in', width=1) + for spine in plt.gca().spines.values(): + spine.set_linewidth(1) + + plt.grid(False) + plt.tight_layout() + plt.savefig(path, dpi=300) + plt.show() \ No newline at end of file diff --git a/utils/train_val_lr.py b/utils/train_val_lr.py new file mode 100644 index 0000000..c7ec6dc --- /dev/null +++ b/utils/train_val_lr.py @@ -0,0 +1,63 @@ +import os +import sys +import torch +from torchsummary import summary +from torchvision.utils import make_grid, save_image + +# Add parent directory to path for config import +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +from config import Network_train_Config as cfg + +# Training function +def train(train_loader, model, loss_func, optimizer, epoch): + model.train() + total_loss = 0 + batch_count = 0 + + for data, label in train_loader: + data = data.cuda() + label = label.cuda() + + output = model(data.type(torch.cuda.FloatTensor)) + loss = loss_func(output.float(), label.float()) + + total_loss += loss.item() + optimizer.zero_grad() + loss.backward() + optimizer.step() + batch_count += 1 + + avg_loss = total_loss / batch_count + print(f"Epoch {epoch}: Training Loss = {avg_loss:.6f}") + return avg_loss + +# Validation function +def validate(val_loader, model, loss_func): + model.eval() + total_loss = 0 + batch_count = 0 + + with torch.no_grad(): + for data, label in val_loader: + data = data.cuda() + label = label.cuda() + + output = model(data.type(torch.cuda.FloatTensor)) + loss = loss_func(output.float(), label.float()) + + total_loss += loss.item() + batch_count += 1 + + avg_loss = total_loss / batch_count + return avg_loss + +# Learning rate scheduler +def adjust_learning_rate(optimizer, epoch, start_lr): + """Exponentially decays learning rate based on epoch and configured decay rate.""" + lr = start_lr * (cfg.lr_decrease_rate ** epoch) + for param_group in optimizer.param_groups: + param_group['lr'] = lr + return lr + + +