From 40d882f6375147a20fe10d1b44d853243c824adb Mon Sep 17 00:00:00 2001 From: Haldrup-tech Date: Fri, 27 Sep 2024 11:41:15 -0400 Subject: [PATCH] added new repo --- CytoSim/README.md | 2 + CytoSim/__pycache__/particle.cpython-312.pyc | Bin 0 -> 1452 bytes CytoSim/__pycache__/sensor.cpython-312.pyc | Bin 0 -> 6863 bytes CytoSim/__pycache__/slider.cpython-312.pyc | Bin 0 -> 2779 bytes CytoSim/main.py | 168 +++++++++++++++++++ CytoSim/particle.py | 23 +++ CytoSim/sensor.py | 95 +++++++++++ CytoSim/slider.py | 35 ++++ __pycache__/particle.cpython-312.pyc | Bin 0 -> 1452 bytes __pycache__/sensor.cpython-312.pyc | Bin 0 -> 6863 bytes __pycache__/slider.cpython-312.pyc | Bin 0 -> 2779 bytes main.py | 168 +++++++++++++++++++ particle.py | 23 +++ pics/Figure_1.png | Bin 0 -> 36960 bytes sensor.py | 95 +++++++++++ slider.py | 35 ++++ 16 files changed, 644 insertions(+) create mode 100644 CytoSim/README.md create mode 100644 CytoSim/__pycache__/particle.cpython-312.pyc create mode 100644 CytoSim/__pycache__/sensor.cpython-312.pyc create mode 100644 CytoSim/__pycache__/slider.cpython-312.pyc create mode 100644 CytoSim/main.py create mode 100644 CytoSim/particle.py create mode 100644 CytoSim/sensor.py create mode 100644 CytoSim/slider.py create mode 100644 __pycache__/particle.cpython-312.pyc create mode 100644 __pycache__/sensor.cpython-312.pyc create mode 100644 __pycache__/slider.cpython-312.pyc create mode 100644 main.py create mode 100644 particle.py create mode 100644 pics/Figure_1.png create mode 100644 sensor.py create mode 100644 slider.py diff --git a/CytoSim/README.md b/CytoSim/README.md new file mode 100644 index 0000000..e141f72 --- /dev/null +++ b/CytoSim/README.md @@ -0,0 +1,2 @@ +# CytoSim + diff --git a/CytoSim/__pycache__/particle.cpython-312.pyc b/CytoSim/__pycache__/particle.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fec941180d9e7b79c5dab05490381b68480dfa3c GIT binary patch literal 1452 zcmaJ>O=uHA6rTM_jH$KFrfC&H0~YEE8We3Us6800KM+N&ha6m%?6ldiY2(bckg$~; z>cNxrR11anSn*PCdh#lGaSuXRkDk0qg9@H}Z#J987JRVZyqS6P=6&zI*-!obNdjV= z`!#z~CgdAVB2ha^I}6Ghv4|x(q)22kO)PnZSjrnXfl`#}lCFM7wNOHgMCvH*QBc+h z1xt$*WlLHiMFo8nRZ9VkSt?+>9@FDN;=ajTyX4SPEOG-Q-lV|Seg?2cJjo*lXrXvA z%%Z!9r@*We86lnuGdwB8lH5e3R|NBD7LEOsOV?0MTYj7BQT;Q43? zE6J|`G)XHp+{~}sX$=m+aC_g7KDLqHoL-;ywbNUcubtg~a zy0AnW{arpd?Sl=T0RS!o>6eWcjaPYpAltmv>Pt88u@vn56C*klo$~|~=wiu*F_cO# zm(H4~y@)uB+k)PzVE*<=#|~=O!%m4h;_3uLDPA> z;QYg!9S7q^x=Vb|4D-S-004b0voW+evOcnUYHQq2>DxE`)Ww~r?=F3qd_Vbi`D5H4 zFZii@%{#5W%x5)oFg4xsJpzCG9~C63o1Xt903S?Gx_Td5oiKbhx*GQSUMBi+RTlLZ zTO2QnYMxxIS*8o^-Jm@Q*jr44Egu7b1az7>J-jixIkrBwn%jb2J+pnu*K#|fzBZ0s zD`*$sp~3^1hj(KbLDDd)3)Z58`Vqr;x@bD#4jTl&44X?7fSmyCH4z>}Lo#dx0a#r= z46s6W<(M+LdsJ42b`!EP+yJSe_&h#_@PLW R^p*7eRyAp2mjH+}e*qMrDDVIP literal 0 HcmV?d00001 diff --git a/CytoSim/__pycache__/sensor.cpython-312.pyc b/CytoSim/__pycache__/sensor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b98724ea6ef227bb99c14e0c795b1443f36bf83c GIT binary patch literal 6863 zcmeGhOHdnEa()Q$k;K==b|By+wGkKy0%sk6s0Fj;SC)xw99uR~gk}s9`rw%%AXzwU z6{(a@Ue_LgDpx^Hf$|~t$@paNVQZb*Lo~))($4O|Te}zEvQV|D%4N5Ez5-S#wd;NM|_dNZ{;V2}a_#6Lyd8~vW{(%*}FdDH@3&b435-b@Zd;~>w6D&1L zu=H(8?cpO6q?>t$6>m^wsgTqv8}9=#M{tCXWC!^MO+AJpfALi6B9!*AmpfH@*XrU*Y!YDrO0({&Rm8fw~13Fs;2 zoBdc)UqcckLO(-Cf^bvbXE@BAC+AIuSaDRgvmrqY#DbihCyWOG(c|$++4gBXG7;t6 zjLZmJUMsJ<)jB`5 zT)MWeK`L*U>H55X19}si%xD9KVn$p(nvo@wMQDgHcHL6cwj?+Vv>OIBJE<+Esaf0x zl&%!(F}WsBfn#Xe6{plksyJ7>ALp$UkZNq1&Qmth++-r`G+T7adNxUDh8f}JDMc*T zsc?l(nfOJz!^Z43^);k!;uf1Vow}{9XqtJY`Ykl6>kV62TWi_=ob$voeI4OlI%VSU z9+TFo6wT5p=Cq_mnob$sYI~*nEi`F9`C@O~ z{+#o7=xa99*LEl&-;@BMhVk-vXz)tBp%tWnXa51NyIhGRN??%-)Y#DCpEAjW>@>K3 zA(Z5l@MAI)3RAX)Vlj?yk!|q_QNe1!k(tw6P?Q;#4@}AokF=)5V=D3Z4JE);A4pP5!3Px7FVovX-m*92(gLU6cI;@h3?dbR&=&%UmTB=2bA>G?r ztY-x|wxvb1gwVnkTi2}gd{wg{EYqwXnWNQgFr-Y=Df-OMvD=5ielKtB9eEe7QTMQy zUf2KXVcpgqw$0V3QnMOs_&kNAM~JFC2l^*`a?7V{f}go<}suU?%?f?A<-L%R*W z5g|UybYNKEF+JvYBS5c^3&#Vz7z#wr#Um?>8afr$aV`eoTDB|A!3d}HHa;uWFjypV zf~bBVwj|3`qA7>>4k*~@RfD0u}ZCKOKdzXOn*lZ9aJv`;irT0V))UJNGdgsJVik;3XlWTIzbEo z%9ie#d-LX-OD$6A+sjoM_fg4xboKm$q5DIRlIcrq=2A$4=Ts;iy^@JeN$_~5q+^LS zcTy_33felUKGfDpeTdo+0rM<1sMZFtc7Y0DmkU$`nTUWHr6!OWrIN@*1k7txCk@PN zR4)xoM8G^re}u?K4`Z8;9>F#Zom6Yrs8M7_sSpjTyFi7p)}f-3F?!~5)=@qa%@&m2 zsJ>o(>#ccqacp61*|+-cgU0)fQe(GN)3dg>_i;gQ*0nq1+Aq2GFCF^o*q6udblvN} z+yC%zdfk20vGkUI&GpH)q~7@K`e#d3nYuQquIX&)aJ~+o@X~JUh}-tDWEHTi51SnX^Vi`Mjzqoamd*_* zufwNq9TlT(e*W;uH-L7xjXwa0Z$wawpbh~>O}+_1Gk_OIM2|&8^c=)-tq7j`4!}%S z`3`^-9lryJuyL0R46R_cpx+&Xs}N!1yFl*&=F08Eq~N<=$ut?j%ozgi%qg$(mA^vq z9vH>roL2Ib(9gezj1~ZLzIwmhq7xngFTZoXflEg?aR74%NDd%*fV=2qm6ifL*Yax^ zDtrI{zKWe?8E1{;teH;H{0~ zFttG7Ejrxj0i~ABe@4Jv59xJNvK=;642*Cs2IXdyZP#_=5h1e9sqbQFhT;}at6 zFAhtVYa5))9Ktar0AN|#Ujc|dKdHF5*IkJJCdA+`2ESh}^!uZ6b|QjwvEP4XA`nqq zc)SAT-3Sby1M9_m=(hFuowRGcRsn@T zRRP$jqUdU6O3FAl#aHPv_!CIs3#kbI!G2VoWINvtJluW(@8Q3rNs|04;rO1pM3U9( J1VUxhe*qIriP-=E literal 0 HcmV?d00001 diff --git a/CytoSim/__pycache__/slider.cpython-312.pyc b/CytoSim/__pycache__/slider.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca00cceb5542b866f22ab30d3bfe1347745487af GIT binary patch literal 2779 zcmai0O>7fK6rT0&+MC#p6JipQ*brKfFfB0@MEO%yAc3YyoGK)Ox{h}5bQH$+rb;?lm^_1ae0l+pUl zo0&In-n{p|H~!V@twzxNfBk)KCyUS@WMDO>$gJ)LW(EmJpi(G`1V@w-=%_IoD_z6mmpPgj~9FG&2+% z7Imgij4L{W33UxiY5sgH1x)OM!LTqI6Lr@Rj-5R#3L#EsWHEJ4r!MGJMyJMgDuLag z7<+)|ZYeD(QY=Nb%H-Ou#rASNd8*sJhS?m}IVaR$(8Cmplmr7yOK%nv!u8UBn^a=wGa+wiL=+VEJ(si&6;T#t}ma3$ib?OwaMC7^A-@msS>qs6I?g<}4%W5p&*vfQ6@tRvf8ma#a2%0iSa^iasi{bwZbp&Cs5 ztuq3Sjbq|uojKWe^kYo!jlG1Fvzi^31SO$6;}VXiM4j&IXxC{e4RDEzX+^{t-I)-j zp@ag(!$(v( zAL!H$bS~}qaIyVS=flo?_n_82xb$gE>yG`#oy8<*_LvdCp)-JhBuK1nN(p6lS@ziu z@J1WNvxJ@U{$y2|w>UV%1`k#aVQy`u%e>wy8@w1+aRTI7Wz~G`{cI3pX!;KBXM_TJMG z6V9IaNQyipqay^V^yr9;Nvw5mh4jEjy4x7`^!9i5MojPrK+1T{j0&LB@Dc)%(neJX zF($%U@jO5up2?9h8St%FrNwdb=#7aosix%BGqA3EiY361&(;?~UpYxUE-wR_Km~X0 z^r5LkHyiRzVXZ0r*c~qT>ZdbPnY?ei=G&eV=cHNbsc&~-%bQo3uRPCbRJ&)zyJ0#y z6}`DX-xAhZ!jHY-LQCsp`<3oOd105gtE${oG&_EpzPaGP0S z<}S`&)PnEa74A#-r28ZHMzlc3qW@9gVPNUZVE&At!PhBh0dXmj$|n>JzJPMIYB|`N z^Unol19#-R`|cmPcjQ6SlW^CQU^f_8{k#g*2EfXiHlut*LQe9er{P}*&+FAZKRhCg zL3!kL56^!-7E75cnB<31B=K(GZX;u}SvpCIV?s#vmdQhN8NFawHu$23W#iOpjhpSE zOnD*|a+)c^p8lY-zXOvb)!Ad+M~`=5@(<3?g!d7SlsDsum)sH4toQJ{Fh|}e8OjuT mPE!>1JMyk@jT3Ca)iA*nxH{mRbrbYIObgXRy+DK-n*IY=;|1ve literal 0 HcmV?d00001 diff --git a/CytoSim/main.py b/CytoSim/main.py new file mode 100644 index 0000000..cb37ebf --- /dev/null +++ b/CytoSim/main.py @@ -0,0 +1,168 @@ +import pygame +import numpy as np +import matplotlib.pyplot as plt +import math +from particle import Particle +from sensor import Sensor +from slider import Slider + +pygame.init() + +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 + +SENSOR_DISTANCE = 200 +REST_MEDIUM = 180000 + +y_lim = 40000 +y_lim2 = 0.000000000005 + + +screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) + +sensor = Sensor(width = 50, distance = SENSOR_DISTANCE, space = 300) +sensor.inputVoltage(5, -5) + + + +silica = Particle(speed = 1, size = 60, perm = 4, rest = pow(10, 12)) + +time = .1 +time_data = [] +volume_data = [] +sensor_data = [] +rest_data = [] +current1_data = [] +current2_data = [] + + +plt.ion() +fig, (ax, ax2) = plt.subplots(2, 1, figsize=(10, 10)) +line, = ax.plot([], [], 'r-') +line2, = ax.plot([], [], 'g-') +line3, = ax2.plot([], [], 'b-') +line4, = ax2.plot([], [], 'g-') +ax.set_xlim(0, 900) +ax.set_ylim(-0.01, y_lim) +ax.set_xlabel('Time (s)') +ax.set_ylabel('Volume') +ax.set_title('Volume/time') + +ax2.set_xlim(0, 900) +ax2.set_ylim(-1 * y_lim2, y_lim2) +ax2.set_xlabel('Time (s)') +ax2.set_ylabel('Current') +ax2.set_title('Current/time') + +slider1 = Slider(20, 20, 100, 20, 20, SENSOR_DISTANCE / 2, 80) +slider2 = Slider(20, 50, 100, 20, .1, 10, 1) +slider3 = Slider(20, 80, 100, 20, 1, 100, 10) + +run = True +while run: + + timeScale = slider2.value + sensor.inputVoltage(slider3.value, -1 * slider3.value) + + distance = silica.move(time) + if distance > SCREEN_WIDTH + (silica.size * 2): + time =.1 + time_data = [] + volume_data = [] + sensor_data = [] + rest_data = [] + current1_data = [] + current2_data = [] + + screen.fill((0,0,0)) + + sensor.generate(SCREEN_WIDTH, SCREEN_HEIGHT, screen) + + pygame.draw.circle(screen, (255, 255, 255), (distance - silica.size, 300), silica.size) + pygame.draw.circle(screen, (0,255,0), (distance - silica.size, 300), 10) + + slider1.draw(screen) + slider2.draw(screen) + slider3.draw(screen) + + silica.updateSize(slider1.value) + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + run = False + slider1.handle_event(event) + slider2.handle_event(event) + slider3.handle_event(event) + + volume = sensor.getParticleVolume(distance, silica) + + sensor_data_volume = sensor.volume - volume + sensor_data.append(sensor_data_volume) + + sensor_resistance = REST_MEDIUM * ((pow(sensor.distance, 2) * pow(10, -18)) / (sensor_data_volume * pow(10, -27))) + nom_sens_res = REST_MEDIUM * ((sensor.distance * pow(10, -9)) / (sensor.width * sensor.distance * pow(10, -18))) + + if volume: + particle_resistance = silica.rest * pow((3/(16 * pow(math.pi, 2) * volume * pow(10, -9))), 1/3) + total_resistance_inv = (1 / particle_resistance) + (1 / sensor_resistance) + else: + particle_resistance = 0 + total_resistance_inv = 1 / sensor_resistance + + total_resistance = 1 / total_resistance_inv + + current1 = 0 + current2 = 0 + + + which_sensor = sensor.whichSensor(distance, silica) + if which_sensor == 1: + current1 = sensor.voltage1 / total_resistance + current2 = sensor.voltage2 / nom_sens_res + elif which_sensor == 2: + current2 = sensor.voltage2 / total_resistance + current1 = sensor.voltage1 / nom_sens_res + else: + current1 = sensor.voltage1 / nom_sens_res + current2 = sensor.voltage2 / nom_sens_res + + current1_data.append(current1) + current2_data.append(current2) + print(f"{current1} = {sensor.voltage1} / {total_resistance}") + rest_data.append(total_resistance) + + if (volume > y_lim): + y_lim = volume + (volume * 1.2) + ax.set_ylim(-1000, y_lim) + + if (current1 > y_lim2): + y_lim2 = current1 + (current1 * 1.2) + ax2.set_ylim(-1 * y_lim2, y_lim2) + + + + time_data.append(time) + volume_data.append(volume) + + line.set_xdata(time_data) + line.set_ydata(volume_data) + line2.set_xdata(time_data) + line2.set_ydata(sensor_data) + line3.set_xdata(time_data) + line3.set_ydata(current1_data) + line4.set_xdata(time_data) + line4.set_ydata(current2_data) + ax.relim() + ax.autoscale_view() + ax2.relim() + ax2.autoscale_view() + plt.draw() + plt.pause(0.01) + + pygame.display.update() + + time = timeScale + time + +pygame.quit() + + diff --git a/CytoSim/particle.py b/CytoSim/particle.py new file mode 100644 index 0000000..338b020 --- /dev/null +++ b/CytoSim/particle.py @@ -0,0 +1,23 @@ +import math + +class Particle: + def __init__(self, speed, size, perm, rest): + self.speed = speed + self.size = size + self.perm = perm + self.rest = rest + self.volume = (4/3.0) * math.pi * size * size * size + + def move(self, time): + distance = self.speed * time + return distance + + def partialVol(self, height): + partialVol = (1/3) * math.pi * height * height * ((3 * self.size) - height) + return partialVol + + def updateSize(self, size): + self.size = size + self.volume = (4/3) * math.pi * size * size * size + + diff --git a/CytoSim/sensor.py b/CytoSim/sensor.py new file mode 100644 index 0000000..6e53002 --- /dev/null +++ b/CytoSim/sensor.py @@ -0,0 +1,95 @@ +import pygame + +class Sensor: + def __init__(self, width, distance, space): + self.width = width + self.distance = distance + self.space = space + self.volume = width * pow(distance, 2) + + def generate(self, screenWidth, screenHeight, screen): + self.sensor1_x = (screenWidth / 2) - (self.space / 2) - self.width + self.sensor1_y = 0 + self.sensor1_x_size = self.width + self.sensor1_y_size = (screenHeight / 2) - (self.distance / 2) + + self.inner1 = self.sensor1_x + self.outer1 = self.inner1 + self.width + + sensor1a = pygame.Rect(self.sensor1_x, self.sensor1_y, self.sensor1_x_size, self.sensor1_y_size) + sensor1b = pygame.Rect(self.sensor1_x, self.sensor1_y + self.sensor1_y_size + self.distance, self.sensor1_x_size, self.sensor1_y_size) + pygame.draw.rect(screen, (0, 0, 255), sensor1a) + pygame.draw.rect(screen, (0, 0, 255), sensor1b) + + self.sensor2_x = (screenWidth / 2) + (self.space / 2) + self.sensor2_y = 0 + self.sensor2_x_size = self.width + self.sensor2_y_size = (screenHeight / 2) - (self.distance / 2) + + self.inner2 = self.sensor2_x + self.outer2 = self.inner2 + self.width + + sensor2a = pygame.Rect(self.sensor2_x, self.sensor2_y, self.sensor2_x_size, self.sensor2_y_size) + sensor2b = pygame.Rect(self.sensor2_x, self.sensor2_y + self.sensor2_y_size + self.distance, self.sensor2_x_size, self.sensor2_y_size) + pygame.draw.rect(screen, (0, 0, 255), sensor2a) + pygame.draw.rect(screen, (0, 0, 255), sensor2b) + + def testSensor1(self, partCenter, particle): + if (particle.size >= abs(self.inner1 - (partCenter - particle.size))) and (particle.size >= abs(self.outer1 - (partCenter - particle.size))): + volume = ((particle.volume / 2) - (particle.partialVol(particle.size - ((partCenter - particle.size) - self.inner1)))) + ((particle.volume / 2) - particle.partialVol(particle.size - (self.outer1 - (partCenter - particle.size)))) + return volume + elif particle.size >= abs(self.inner1 - (partCenter - particle.size)): + volume = particle.partialVol(particle.size - (self.inner1 - (partCenter - particle.size))) + return volume + elif particle.size >= abs(self.outer1 - (partCenter - particle.size)): + volume = particle.volume - particle.partialVol(particle.size - (self.outer1 - (partCenter - particle.size))) + return volume + elif ((partCenter - particle.size) >= self.inner1 and (partCenter - particle.size) <= self.outer1): + volume = particle.volume + return volume + else: + return 0 + + def testSensor2(self, partCenter, particle): + if (particle.size >= abs(self.inner2 - (partCenter - particle.size))) and (particle.size >= abs(self.outer2 - (partCenter - particle.size))): + volume = ((particle.volume / 2) - (particle.partialVol(particle.size - ((partCenter - particle.size) - self.inner2)))) + ((particle.volume / 2) - particle.partialVol(particle.size - (self.outer2 - (partCenter - particle.size)))) + return volume + elif particle.size >= abs(self.inner2 - (partCenter - particle.size)): + volume = particle.partialVol(particle.size - (self.inner2 - (partCenter - particle.size))) + return volume + elif particle.size >= abs(self.outer2 - (partCenter - particle.size)): + volume = particle.volume - particle.partialVol(particle.size - (self.outer2 - (partCenter - particle.size))) + return volume + elif ((partCenter - particle.size) >= self.inner2 and (partCenter - particle.size) <= self.outer2): + volume = particle.volume + return volume + else: + return 0 + + def getParticleVolume(self, partCenter, particle): + volume1 = self.testSensor1(partCenter, particle) + #volume1 = 0 + volume2 = self.testSensor2(partCenter, particle) + + if volume1: + return volume1 + elif volume2: + return volume2 + else: + return 0 + + def whichSensor(self, partCenter, particle): + volume1 = self.testSensor1(partCenter, particle) + #volume1 = 0 + volume2 = self.testSensor2(partCenter, particle) + + if volume1: + return 1 + elif volume2: + return 2 + else: + return 0 + + def inputVoltage(self, voltage1, voltage2): + self.voltage1 = voltage1 + self.voltage2 = voltage2 diff --git a/CytoSim/slider.py b/CytoSim/slider.py new file mode 100644 index 0000000..304e27d --- /dev/null +++ b/CytoSim/slider.py @@ -0,0 +1,35 @@ +import pygame + +WHITE = (255, 255, 255) +GRAY = (200, 200, 200) +BLACK = (0, 0, 0) +RED = (255, 0, 0) + +class Slider: + + def __init__(self, x, y, w, h, min_val, max_val, initial_val): + self.rect = pygame.Rect(x, y, w, h) + self.min_val = min_val + self.max_val = max_val + self.value = initial_val + self.grabbed = False + + def draw(self, screen): + # Draw the background + pygame.draw.rect(screen, GRAY, self.rect) + # Draw the handle (circle) + handle_x = self.rect.x + (self.value - self.min_val) / (self.max_val - self.min_val) * self.rect.width + pygame.draw.circle(screen, RED, (int(handle_x), self.rect.centery), self.rect.height // 2) + + def handle_event(self, event): + if event.type == pygame.MOUSEBUTTONDOWN: + if self.rect.collidepoint(event.pos): + self.grabbed = True + elif event.type == pygame.MOUSEBUTTONUP: + self.grabbed = False + elif event.type == pygame.MOUSEMOTION: + if self.grabbed: + mouse_x = event.pos[0] + # Constrain the handle within the slider + new_value = (mouse_x - self.rect.x) / self.rect.width * (self.max_val - self.min_val) + self.min_val + self.value = max(self.min_val, min(self.max_val, new_value)) diff --git a/__pycache__/particle.cpython-312.pyc b/__pycache__/particle.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fec941180d9e7b79c5dab05490381b68480dfa3c GIT binary patch literal 1452 zcmaJ>O=uHA6rTM_jH$KFrfC&H0~YEE8We3Us6800KM+N&ha6m%?6ldiY2(bckg$~; z>cNxrR11anSn*PCdh#lGaSuXRkDk0qg9@H}Z#J987JRVZyqS6P=6&zI*-!obNdjV= z`!#z~CgdAVB2ha^I}6Ghv4|x(q)22kO)PnZSjrnXfl`#}lCFM7wNOHgMCvH*QBc+h z1xt$*WlLHiMFo8nRZ9VkSt?+>9@FDN;=ajTyX4SPEOG-Q-lV|Seg?2cJjo*lXrXvA z%%Z!9r@*We86lnuGdwB8lH5e3R|NBD7LEOsOV?0MTYj7BQT;Q43? zE6J|`G)XHp+{~}sX$=m+aC_g7KDLqHoL-;ywbNUcubtg~a zy0AnW{arpd?Sl=T0RS!o>6eWcjaPYpAltmv>Pt88u@vn56C*klo$~|~=wiu*F_cO# zm(H4~y@)uB+k)PzVE*<=#|~=O!%m4h;_3uLDPA> z;QYg!9S7q^x=Vb|4D-S-004b0voW+evOcnUYHQq2>DxE`)Ww~r?=F3qd_Vbi`D5H4 zFZii@%{#5W%x5)oFg4xsJpzCG9~C63o1Xt903S?Gx_Td5oiKbhx*GQSUMBi+RTlLZ zTO2QnYMxxIS*8o^-Jm@Q*jr44Egu7b1az7>J-jixIkrBwn%jb2J+pnu*K#|fzBZ0s zD`*$sp~3^1hj(KbLDDd)3)Z58`Vqr;x@bD#4jTl&44X?7fSmyCH4z>}Lo#dx0a#r= z46s6W<(M+LdsJ42b`!EP+yJSe_&h#_@PLW R^p*7eRyAp2mjH+}e*qMrDDVIP literal 0 HcmV?d00001 diff --git a/__pycache__/sensor.cpython-312.pyc b/__pycache__/sensor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b98724ea6ef227bb99c14e0c795b1443f36bf83c GIT binary patch literal 6863 zcmeGhOHdnEa()Q$k;K==b|By+wGkKy0%sk6s0Fj;SC)xw99uR~gk}s9`rw%%AXzwU z6{(a@Ue_LgDpx^Hf$|~t$@paNVQZb*Lo~))($4O|Te}zEvQV|D%4N5Ez5-S#wd;NM|_dNZ{;V2}a_#6Lyd8~vW{(%*}FdDH@3&b435-b@Zd;~>w6D&1L zu=H(8?cpO6q?>t$6>m^wsgTqv8}9=#M{tCXWC!^MO+AJpfALi6B9!*AmpfH@*XrU*Y!YDrO0({&Rm8fw~13Fs;2 zoBdc)UqcckLO(-Cf^bvbXE@BAC+AIuSaDRgvmrqY#DbihCyWOG(c|$++4gBXG7;t6 zjLZmJUMsJ<)jB`5 zT)MWeK`L*U>H55X19}si%xD9KVn$p(nvo@wMQDgHcHL6cwj?+Vv>OIBJE<+Esaf0x zl&%!(F}WsBfn#Xe6{plksyJ7>ALp$UkZNq1&Qmth++-r`G+T7adNxUDh8f}JDMc*T zsc?l(nfOJz!^Z43^);k!;uf1Vow}{9XqtJY`Ykl6>kV62TWi_=ob$voeI4OlI%VSU z9+TFo6wT5p=Cq_mnob$sYI~*nEi`F9`C@O~ z{+#o7=xa99*LEl&-;@BMhVk-vXz)tBp%tWnXa51NyIhGRN??%-)Y#DCpEAjW>@>K3 zA(Z5l@MAI)3RAX)Vlj?yk!|q_QNe1!k(tw6P?Q;#4@}AokF=)5V=D3Z4JE);A4pP5!3Px7FVovX-m*92(gLU6cI;@h3?dbR&=&%UmTB=2bA>G?r ztY-x|wxvb1gwVnkTi2}gd{wg{EYqwXnWNQgFr-Y=Df-OMvD=5ielKtB9eEe7QTMQy zUf2KXVcpgqw$0V3QnMOs_&kNAM~JFC2l^*`a?7V{f}go<}suU?%?f?A<-L%R*W z5g|UybYNKEF+JvYBS5c^3&#Vz7z#wr#Um?>8afr$aV`eoTDB|A!3d}HHa;uWFjypV zf~bBVwj|3`qA7>>4k*~@RfD0u}ZCKOKdzXOn*lZ9aJv`;irT0V))UJNGdgsJVik;3XlWTIzbEo z%9ie#d-LX-OD$6A+sjoM_fg4xboKm$q5DIRlIcrq=2A$4=Ts;iy^@JeN$_~5q+^LS zcTy_33felUKGfDpeTdo+0rM<1sMZFtc7Y0DmkU$`nTUWHr6!OWrIN@*1k7txCk@PN zR4)xoM8G^re}u?K4`Z8;9>F#Zom6Yrs8M7_sSpjTyFi7p)}f-3F?!~5)=@qa%@&m2 zsJ>o(>#ccqacp61*|+-cgU0)fQe(GN)3dg>_i;gQ*0nq1+Aq2GFCF^o*q6udblvN} z+yC%zdfk20vGkUI&GpH)q~7@K`e#d3nYuQquIX&)aJ~+o@X~JUh}-tDWEHTi51SnX^Vi`Mjzqoamd*_* zufwNq9TlT(e*W;uH-L7xjXwa0Z$wawpbh~>O}+_1Gk_OIM2|&8^c=)-tq7j`4!}%S z`3`^-9lryJuyL0R46R_cpx+&Xs}N!1yFl*&=F08Eq~N<=$ut?j%ozgi%qg$(mA^vq z9vH>roL2Ib(9gezj1~ZLzIwmhq7xngFTZoXflEg?aR74%NDd%*fV=2qm6ifL*Yax^ zDtrI{zKWe?8E1{;teH;H{0~ zFttG7Ejrxj0i~ABe@4Jv59xJNvK=;642*Cs2IXdyZP#_=5h1e9sqbQFhT;}at6 zFAhtVYa5))9Ktar0AN|#Ujc|dKdHF5*IkJJCdA+`2ESh}^!uZ6b|QjwvEP4XA`nqq zc)SAT-3Sby1M9_m=(hFuowRGcRsn@T zRRP$jqUdU6O3FAl#aHPv_!CIs3#kbI!G2VoWINvtJluW(@8Q3rNs|04;rO1pM3U9( J1VUxhe*qIriP-=E literal 0 HcmV?d00001 diff --git a/__pycache__/slider.cpython-312.pyc b/__pycache__/slider.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca00cceb5542b866f22ab30d3bfe1347745487af GIT binary patch literal 2779 zcmai0O>7fK6rT0&+MC#p6JipQ*brKfFfB0@MEO%yAc3YyoGK)Ox{h}5bQH$+rb;?lm^_1ae0l+pUl zo0&In-n{p|H~!V@twzxNfBk)KCyUS@WMDO>$gJ)LW(EmJpi(G`1V@w-=%_IoD_z6mmpPgj~9FG&2+% z7Imgij4L{W33UxiY5sgH1x)OM!LTqI6Lr@Rj-5R#3L#EsWHEJ4r!MGJMyJMgDuLag z7<+)|ZYeD(QY=Nb%H-Ou#rASNd8*sJhS?m}IVaR$(8Cmplmr7yOK%nv!u8UBn^a=wGa+wiL=+VEJ(si&6;T#t}ma3$ib?OwaMC7^A-@msS>qs6I?g<}4%W5p&*vfQ6@tRvf8ma#a2%0iSa^iasi{bwZbp&Cs5 ztuq3Sjbq|uojKWe^kYo!jlG1Fvzi^31SO$6;}VXiM4j&IXxC{e4RDEzX+^{t-I)-j zp@ag(!$(v( zAL!H$bS~}qaIyVS=flo?_n_82xb$gE>yG`#oy8<*_LvdCp)-JhBuK1nN(p6lS@ziu z@J1WNvxJ@U{$y2|w>UV%1`k#aVQy`u%e>wy8@w1+aRTI7Wz~G`{cI3pX!;KBXM_TJMG z6V9IaNQyipqay^V^yr9;Nvw5mh4jEjy4x7`^!9i5MojPrK+1T{j0&LB@Dc)%(neJX zF($%U@jO5up2?9h8St%FrNwdb=#7aosix%BGqA3EiY361&(;?~UpYxUE-wR_Km~X0 z^r5LkHyiRzVXZ0r*c~qT>ZdbPnY?ei=G&eV=cHNbsc&~-%bQo3uRPCbRJ&)zyJ0#y z6}`DX-xAhZ!jHY-LQCsp`<3oOd105gtE${oG&_EpzPaGP0S z<}S`&)PnEa74A#-r28ZHMzlc3qW@9gVPNUZVE&At!PhBh0dXmj$|n>JzJPMIYB|`N z^Unol19#-R`|cmPcjQ6SlW^CQU^f_8{k#g*2EfXiHlut*LQe9er{P}*&+FAZKRhCg zL3!kL56^!-7E75cnB<31B=K(GZX;u}SvpCIV?s#vmdQhN8NFawHu$23W#iOpjhpSE zOnD*|a+)c^p8lY-zXOvb)!Ad+M~`=5@(<3?g!d7SlsDsum)sH4toQJ{Fh|}e8OjuT mPE!>1JMyk@jT3Ca)iA*nxH{mRbrbYIObgXRy+DK-n*IY=;|1ve literal 0 HcmV?d00001 diff --git a/main.py b/main.py new file mode 100644 index 0000000..cb37ebf --- /dev/null +++ b/main.py @@ -0,0 +1,168 @@ +import pygame +import numpy as np +import matplotlib.pyplot as plt +import math +from particle import Particle +from sensor import Sensor +from slider import Slider + +pygame.init() + +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 + +SENSOR_DISTANCE = 200 +REST_MEDIUM = 180000 + +y_lim = 40000 +y_lim2 = 0.000000000005 + + +screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) + +sensor = Sensor(width = 50, distance = SENSOR_DISTANCE, space = 300) +sensor.inputVoltage(5, -5) + + + +silica = Particle(speed = 1, size = 60, perm = 4, rest = pow(10, 12)) + +time = .1 +time_data = [] +volume_data = [] +sensor_data = [] +rest_data = [] +current1_data = [] +current2_data = [] + + +plt.ion() +fig, (ax, ax2) = plt.subplots(2, 1, figsize=(10, 10)) +line, = ax.plot([], [], 'r-') +line2, = ax.plot([], [], 'g-') +line3, = ax2.plot([], [], 'b-') +line4, = ax2.plot([], [], 'g-') +ax.set_xlim(0, 900) +ax.set_ylim(-0.01, y_lim) +ax.set_xlabel('Time (s)') +ax.set_ylabel('Volume') +ax.set_title('Volume/time') + +ax2.set_xlim(0, 900) +ax2.set_ylim(-1 * y_lim2, y_lim2) +ax2.set_xlabel('Time (s)') +ax2.set_ylabel('Current') +ax2.set_title('Current/time') + +slider1 = Slider(20, 20, 100, 20, 20, SENSOR_DISTANCE / 2, 80) +slider2 = Slider(20, 50, 100, 20, .1, 10, 1) +slider3 = Slider(20, 80, 100, 20, 1, 100, 10) + +run = True +while run: + + timeScale = slider2.value + sensor.inputVoltage(slider3.value, -1 * slider3.value) + + distance = silica.move(time) + if distance > SCREEN_WIDTH + (silica.size * 2): + time =.1 + time_data = [] + volume_data = [] + sensor_data = [] + rest_data = [] + current1_data = [] + current2_data = [] + + screen.fill((0,0,0)) + + sensor.generate(SCREEN_WIDTH, SCREEN_HEIGHT, screen) + + pygame.draw.circle(screen, (255, 255, 255), (distance - silica.size, 300), silica.size) + pygame.draw.circle(screen, (0,255,0), (distance - silica.size, 300), 10) + + slider1.draw(screen) + slider2.draw(screen) + slider3.draw(screen) + + silica.updateSize(slider1.value) + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + run = False + slider1.handle_event(event) + slider2.handle_event(event) + slider3.handle_event(event) + + volume = sensor.getParticleVolume(distance, silica) + + sensor_data_volume = sensor.volume - volume + sensor_data.append(sensor_data_volume) + + sensor_resistance = REST_MEDIUM * ((pow(sensor.distance, 2) * pow(10, -18)) / (sensor_data_volume * pow(10, -27))) + nom_sens_res = REST_MEDIUM * ((sensor.distance * pow(10, -9)) / (sensor.width * sensor.distance * pow(10, -18))) + + if volume: + particle_resistance = silica.rest * pow((3/(16 * pow(math.pi, 2) * volume * pow(10, -9))), 1/3) + total_resistance_inv = (1 / particle_resistance) + (1 / sensor_resistance) + else: + particle_resistance = 0 + total_resistance_inv = 1 / sensor_resistance + + total_resistance = 1 / total_resistance_inv + + current1 = 0 + current2 = 0 + + + which_sensor = sensor.whichSensor(distance, silica) + if which_sensor == 1: + current1 = sensor.voltage1 / total_resistance + current2 = sensor.voltage2 / nom_sens_res + elif which_sensor == 2: + current2 = sensor.voltage2 / total_resistance + current1 = sensor.voltage1 / nom_sens_res + else: + current1 = sensor.voltage1 / nom_sens_res + current2 = sensor.voltage2 / nom_sens_res + + current1_data.append(current1) + current2_data.append(current2) + print(f"{current1} = {sensor.voltage1} / {total_resistance}") + rest_data.append(total_resistance) + + if (volume > y_lim): + y_lim = volume + (volume * 1.2) + ax.set_ylim(-1000, y_lim) + + if (current1 > y_lim2): + y_lim2 = current1 + (current1 * 1.2) + ax2.set_ylim(-1 * y_lim2, y_lim2) + + + + time_data.append(time) + volume_data.append(volume) + + line.set_xdata(time_data) + line.set_ydata(volume_data) + line2.set_xdata(time_data) + line2.set_ydata(sensor_data) + line3.set_xdata(time_data) + line3.set_ydata(current1_data) + line4.set_xdata(time_data) + line4.set_ydata(current2_data) + ax.relim() + ax.autoscale_view() + ax2.relim() + ax2.autoscale_view() + plt.draw() + plt.pause(0.01) + + pygame.display.update() + + time = timeScale + time + +pygame.quit() + + diff --git a/particle.py b/particle.py new file mode 100644 index 0000000..338b020 --- /dev/null +++ b/particle.py @@ -0,0 +1,23 @@ +import math + +class Particle: + def __init__(self, speed, size, perm, rest): + self.speed = speed + self.size = size + self.perm = perm + self.rest = rest + self.volume = (4/3.0) * math.pi * size * size * size + + def move(self, time): + distance = self.speed * time + return distance + + def partialVol(self, height): + partialVol = (1/3) * math.pi * height * height * ((3 * self.size) - height) + return partialVol + + def updateSize(self, size): + self.size = size + self.volume = (4/3) * math.pi * size * size * size + + diff --git a/pics/Figure_1.png b/pics/Figure_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c6aa4f57eeff1dc148e7bb9beb3d1a3a641f4b6e GIT binary patch literal 36960 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 literal 0 HcmV?d00001 diff --git a/sensor.py b/sensor.py new file mode 100644 index 0000000..6e53002 --- /dev/null +++ b/sensor.py @@ -0,0 +1,95 @@ +import pygame + +class Sensor: + def __init__(self, width, distance, space): + self.width = width + self.distance = distance + self.space = space + self.volume = width * pow(distance, 2) + + def generate(self, screenWidth, screenHeight, screen): + self.sensor1_x = (screenWidth / 2) - (self.space / 2) - self.width + self.sensor1_y = 0 + self.sensor1_x_size = self.width + self.sensor1_y_size = (screenHeight / 2) - (self.distance / 2) + + self.inner1 = self.sensor1_x + self.outer1 = self.inner1 + self.width + + sensor1a = pygame.Rect(self.sensor1_x, self.sensor1_y, self.sensor1_x_size, self.sensor1_y_size) + sensor1b = pygame.Rect(self.sensor1_x, self.sensor1_y + self.sensor1_y_size + self.distance, self.sensor1_x_size, self.sensor1_y_size) + pygame.draw.rect(screen, (0, 0, 255), sensor1a) + pygame.draw.rect(screen, (0, 0, 255), sensor1b) + + self.sensor2_x = (screenWidth / 2) + (self.space / 2) + self.sensor2_y = 0 + self.sensor2_x_size = self.width + self.sensor2_y_size = (screenHeight / 2) - (self.distance / 2) + + self.inner2 = self.sensor2_x + self.outer2 = self.inner2 + self.width + + sensor2a = pygame.Rect(self.sensor2_x, self.sensor2_y, self.sensor2_x_size, self.sensor2_y_size) + sensor2b = pygame.Rect(self.sensor2_x, self.sensor2_y + self.sensor2_y_size + self.distance, self.sensor2_x_size, self.sensor2_y_size) + pygame.draw.rect(screen, (0, 0, 255), sensor2a) + pygame.draw.rect(screen, (0, 0, 255), sensor2b) + + def testSensor1(self, partCenter, particle): + if (particle.size >= abs(self.inner1 - (partCenter - particle.size))) and (particle.size >= abs(self.outer1 - (partCenter - particle.size))): + volume = ((particle.volume / 2) - (particle.partialVol(particle.size - ((partCenter - particle.size) - self.inner1)))) + ((particle.volume / 2) - particle.partialVol(particle.size - (self.outer1 - (partCenter - particle.size)))) + return volume + elif particle.size >= abs(self.inner1 - (partCenter - particle.size)): + volume = particle.partialVol(particle.size - (self.inner1 - (partCenter - particle.size))) + return volume + elif particle.size >= abs(self.outer1 - (partCenter - particle.size)): + volume = particle.volume - particle.partialVol(particle.size - (self.outer1 - (partCenter - particle.size))) + return volume + elif ((partCenter - particle.size) >= self.inner1 and (partCenter - particle.size) <= self.outer1): + volume = particle.volume + return volume + else: + return 0 + + def testSensor2(self, partCenter, particle): + if (particle.size >= abs(self.inner2 - (partCenter - particle.size))) and (particle.size >= abs(self.outer2 - (partCenter - particle.size))): + volume = ((particle.volume / 2) - (particle.partialVol(particle.size - ((partCenter - particle.size) - self.inner2)))) + ((particle.volume / 2) - particle.partialVol(particle.size - (self.outer2 - (partCenter - particle.size)))) + return volume + elif particle.size >= abs(self.inner2 - (partCenter - particle.size)): + volume = particle.partialVol(particle.size - (self.inner2 - (partCenter - particle.size))) + return volume + elif particle.size >= abs(self.outer2 - (partCenter - particle.size)): + volume = particle.volume - particle.partialVol(particle.size - (self.outer2 - (partCenter - particle.size))) + return volume + elif ((partCenter - particle.size) >= self.inner2 and (partCenter - particle.size) <= self.outer2): + volume = particle.volume + return volume + else: + return 0 + + def getParticleVolume(self, partCenter, particle): + volume1 = self.testSensor1(partCenter, particle) + #volume1 = 0 + volume2 = self.testSensor2(partCenter, particle) + + if volume1: + return volume1 + elif volume2: + return volume2 + else: + return 0 + + def whichSensor(self, partCenter, particle): + volume1 = self.testSensor1(partCenter, particle) + #volume1 = 0 + volume2 = self.testSensor2(partCenter, particle) + + if volume1: + return 1 + elif volume2: + return 2 + else: + return 0 + + def inputVoltage(self, voltage1, voltage2): + self.voltage1 = voltage1 + self.voltage2 = voltage2 diff --git a/slider.py b/slider.py new file mode 100644 index 0000000..304e27d --- /dev/null +++ b/slider.py @@ -0,0 +1,35 @@ +import pygame + +WHITE = (255, 255, 255) +GRAY = (200, 200, 200) +BLACK = (0, 0, 0) +RED = (255, 0, 0) + +class Slider: + + def __init__(self, x, y, w, h, min_val, max_val, initial_val): + self.rect = pygame.Rect(x, y, w, h) + self.min_val = min_val + self.max_val = max_val + self.value = initial_val + self.grabbed = False + + def draw(self, screen): + # Draw the background + pygame.draw.rect(screen, GRAY, self.rect) + # Draw the handle (circle) + handle_x = self.rect.x + (self.value - self.min_val) / (self.max_val - self.min_val) * self.rect.width + pygame.draw.circle(screen, RED, (int(handle_x), self.rect.centery), self.rect.height // 2) + + def handle_event(self, event): + if event.type == pygame.MOUSEBUTTONDOWN: + if self.rect.collidepoint(event.pos): + self.grabbed = True + elif event.type == pygame.MOUSEBUTTONUP: + self.grabbed = False + elif event.type == pygame.MOUSEMOTION: + if self.grabbed: + mouse_x = event.pos[0] + # Constrain the handle within the slider + new_value = (mouse_x - self.rect.x) / self.rect.width * (self.max_val - self.min_val) + self.min_val + self.value = max(self.min_val, min(self.max_val, new_value))