├── LICENSE ├── README.md ├── example_LVradpat_Export.txt ├── plot_2D_Pattern_polar_dB.m ├── plot_3D_Pattern.m └── script_read_LV_radpat.m /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Alexandros Pitilakis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PlotPattern 2 | MATLAB functions to plot 2D/3D radiation & scattering patterns, intended for antennas & metasurfaces. 3 | 4 | ## MATLAB functions 5 | 6 | Two functions are included. Calling thems with no input arguments from the command window produces example plots. 7 | 1. **`plot_2D_Pattern_polar_dB.m`** -- Plots in polar-2D and in dB, with a few customizations on the vizualization. 8 | 2. **`plot_3D_Pattern.m`** -- Plots in 3D, in linear or dB. It includes a large number of customizations for the vizualization. For example, the 3D-surface plots can be in spherical (rho,phi,theta) or cylindrical (rho,phi,zeta) coordinate systems. 9 | 10 | Here is how it looks: 11 | 12 | ![ExamplePattern_2D_dB](https://user-images.githubusercontent.com/97299585/170985799-0e989fea-c909-4635-84b5-d3668768bf33.png) 13 | 14 | Fig. 1: E-plane patterns of center-fed dipole antennas of various lenghts: 1=Infinitesimal, 2=Half-wavelength, 3=Full-wave, 4=3/2 lambda. The patterns are by default symmetric as the dipole is arranged along the theta=0 axis (vertically, in this graph). 15 | 16 | ![ExamplePattern_3D_dB](https://user-images.githubusercontent.com/97299585/170985830-4e8e0332-a173-42a2-a88c-b6ec2c89b7a1.png) 17 | 18 | Fig. 2: Directive 5-by-5 array pattern of isotropic radiators at half-wavelength distance along both lateral axes. Beam is pointed at (phi,theta)=(-120,30). The pattern in the left panel is in linear scale and spherical coordinates, while right panel holds the same pattern but in dB-scale and in cylindrical coordinates. 19 | 20 | ## MATLAB scripts & data 21 | 22 | I am also including a script, **`script_read_LV_radpat.m`**, which reads-in and plots the 2D radiation patterns in E- and H-planes, as recorded in ASCII-format by the Lab-Volt/Festo-Didactic "Antenna Training and Measuring System" software ([LVDAM-ANT](https://labvolt.festo.com/solutions/9_telecommunications/69-8092-00_antenna_training_and_measuring_system)); a sample half-wavelength antenna pattern is included for testing, in file: **`example_LVradpat_Export.txt`**. 23 | 24 | ![ExamplePattern_Measured_Dipole](https://user-images.githubusercontent.com/97299585/170986612-234092d0-9035-436c-a30b-f5acccd26978.png) 25 | 26 | Fig. 3: E- and H-plane patterns of a measured half-wavelength dipole antenna (at approximately 1 GHz). 27 | -------------------------------------------------------------------------------- /example_LVradpat_Export.txt: -------------------------------------------------------------------------------- 1 | Festo Didactic LVDAM-ANT File 1.2 2 | Antenna Type : Dipole (1/2 Lambda) 3 | 4 | Description 5 | Lab-Volt model : 9561 6 | Operating Frequency : 915 MHz 7 | Polarization : Lin. 8 | Connector Type : SMA 9 | 10 | 11 | Author : 12 | Comments : 13 | 14 | P - E - attenuation : 9 15 | P - H - attenuation : 9 16 | 17 | Angle E H 18 | 0 -2.870955 -4.864439 19 | 1 -2.906687 -4.845526 20 | 2 -2.966116 -4.845526 21 | 3 -3.004705 -4.845526 22 | 4 -3.026278 -4.842382 23 | 5 -3.074076 -4.845526 24 | 6 -3.126753 -4.807928 25 | 7 -3.166639 -4.804808 26 | 8 -3.306581 -4.820429 27 | 9 -3.424784 -4.804808 28 | 10 -3.46483 -4.792345 29 | 11 -3.555559 -4.758245 30 | 12 -3.657846 -4.742826 31 | 13 -3.754793 -4.733595 32 | 14 -3.874254 -4.727453 33 | 15 -4.002016 -4.672518 34 | 16 -4.13323 -4.615198 35 | 17 -4.28768 -4.55559 36 | 18 -4.415461 -4.502565 37 | 19 -4.540804 -4.450113 38 | 20 -4.66342 -4.441427 39 | 21 -4.814173 -4.392496 40 | 22 -4.976252 -4.358252 41 | 23 -5.127272 -4.361097 42 | 24 -5.248865 -4.324247 43 | 25 -5.426561 -4.284876 44 | 26 -5.592688 -4.256948 45 | 27 -5.749567 -4.209841 46 | 28 -5.892168 -4.171385 47 | 29 -6.083742 -4.163183 48 | 30 -6.257925 -4.092684 49 | 31 -6.46953 -4.06584 50 | 32 -6.649542 -4.041807 51 | 33 -6.836649 -4.017893 52 | 34 -7.031458 -4.002016 53 | 35 -7.229456 -3.970415 54 | 36 -7.398359 -3.93902 55 | 37 -7.595919 -3.905233 56 | 38 -7.784613 -3.876829 57 | 39 -7.975142 -3.866541 58 | 40 -8.154779 -3.861406 59 | 41 -8.348188 -3.838362 60 | 42 -8.577555 -3.853712 61 | 43 -8.782564 -3.83581 62 | 44 -8.981951 -3.805269 63 | 45 -9.182444 -3.777441 64 | 46 -9.40032 -3.744761 65 | 47 -9.752295 -3.727251 66 | 48 -9.815191 -3.764845 67 | 49 -10.0187 -3.79513 68 | 50 -10.23173 -3.797663 69 | 51 -10.43447 -3.787542 70 | 52 -10.6576 -3.782488 71 | 53 -10.82403 -3.790071 72 | 54 -11.06788 -3.779966 73 | 55 -11.28801 -3.815428 74 | 56 -11.53279 -3.83581 75 | 57 -11.70838 -3.848589 76 | 58 -11.82 -3.866541 77 | 59 -12.14235 -3.89747 78 | 60 -12.3765 -3.902643 79 | 61 -12.64089 -3.88714 80 | 62 -12.85026 -3.88714 81 | 63 -13.10802 -3.874254 82 | 64 -13.36197 -3.874254 83 | 65 -13.65335 -3.905233 84 | 66 -13.94293 -3.925997 85 | 67 -14.27855 -3.89747 86 | 68 -14.53573 -3.881983 87 | 69 -14.86667 -3.925997 88 | 70 -15.38556 -3.928598 89 | 71 -15.68907 -3.949461 90 | 72 -16.17127 -3.97304 91 | 73 -16.67345 -3.949461 92 | 74 -17.19594 -3.941626 93 | 75 -17.68064 -3.946848 94 | 76 -18.29897 -3.962545 95 | 77 -19.03226 -3.988825 96 | 78 -19.73665 -4.002016 97 | 79 -20.71812 -4.007303 98 | 80 -21.6985 -4.02585 99 | 81 -23.47321 -3.996733 100 | 82 -25.72517 -4.007303 101 | 83 -29.49053 -4.002016 102 | 84 -30 -3.994097 103 | 85 -30 -4.012594 104 | 86 -30 -4.02585 105 | 87 -30 -4.084616 106 | 88 -30 -4.100767 107 | 89 -30 -4.122385 108 | 90 -30 -4.165915 109 | 91 -30 -4.149546 110 | 92 -30 -4.149546 111 | 93 -30 -4.149546 112 | 94 -30 -4.135946 113 | 95 -30 -4.13323 114 | 96 -30 -4.095377 115 | 97 -30 -4.103464 116 | 98 -30 -4.106165 117 | 99 -28.61352 -4.100767 118 | 100 -26.17263 -4.076559 119 | 101 -23.2325 -4.084616 120 | 102 -21.54257 -4.060492 121 | 103 -20.25133 -4.055143 122 | 104 -19.19686 -4.033823 123 | 105 -18.23262 -4.057817 124 | 106 -17.45793 -4.02585 125 | 107 -16.71824 -4.017893 126 | 108 -16.13209 -4.007303 127 | 109 -15.48427 -3.991461 128 | 110 -14.95366 -3.959929 129 | 111 -14.45691 -3.962545 130 | 112 -13.96604 -3.941626 131 | 113 -13.56806 -3.949461 132 | 114 -13.10802 -3.920797 133 | 115 -12.67509 -3.902643 134 | 116 -12.26568 -3.892302 135 | 117 -11.92003 -3.881983 136 | 118 -11.54605 -3.881983 137 | 119 -11.26301 -3.863974 138 | 120 -10.95011 -3.848589 139 | 121 -10.61424 -3.823061 140 | 122 -10.33196 -3.805269 141 | 123 -10.0187 -3.785013 142 | 124 -9.752295 -3.779966 143 | 125 -9.483709 -3.790071 144 | 126 -9.229979 -3.764845 145 | 127 -8.959368 -3.739752 146 | 128 -8.746565 -3.709806 147 | 129 -8.529398 -3.719767 148 | 130 -8.328482 -3.712294 149 | 131 -8.117041 -3.727251 150 | 132 -7.884867 -3.72975 151 | 133 -7.70363 -3.714785 152 | 134 -7.496103 -3.727251 153 | 135 -7.297346 -3.777441 154 | 136 -7.116747 -3.709806 155 | 137 -6.942801 -3.742254 156 | 138 -6.74217 -3.734747 157 | 139 -6.513899 -3.757303 158 | 140 -6.313154 -3.800196 159 | 141 -6.178339 -3.79513 160 | 142 -6.039156 -3.762331 161 | 143 -5.857088 -3.817968 162 | 144 -5.719286 -3.777441 163 | 145 -5.66675 -3.777441 164 | 146 -5.40531 -3.800196 165 | 147 -5.279749 -3.843473 166 | 148 -5.167463 -3.828157 167 | 149 -5.021715 -3.874254 168 | 150 -4.912039 -3.861406 169 | 151 -4.804808 -3.889719 170 | 152 -4.715193 -3.851152 171 | 153 -4.609205 -3.871683 172 | 154 -4.508429 -3.777441 173 | 155 -4.383913 -3.790071 174 | 156 -4.298903 -3.83581 175 | 157 -4.256948 -3.79513 176 | 158 -4.19607 -3.863974 177 | 159 -4.108862 -3.861406 178 | 160 -4.06584 -3.900057 179 | 161 -3.996733 -3.925997 180 | 162 -3.892302 -3.957308 181 | 163 -3.866541 -3.957308 182 | 164 -3.817968 -3.967791 183 | 165 -3.742254 -3.999372 184 | 166 -3.72975 -4.031164 185 | 167 -3.638197 -4.08193 186 | 168 -3.762331 -4.092684 187 | 169 -3.586988 -4.127806 188 | 170 -3.601564 -4.152269 189 | 171 -3.555559 -4.152269 190 | 172 -3.553148 -4.171385 191 | 173 -3.550741 -4.19607 192 | 174 -3.555559 -4.212599 193 | 175 -3.545927 -4.234724 194 | 176 -3.529119 -4.270891 195 | 177 -3.55797 -4.276484 196 | 178 -3.550741 -4.304522 197 | 179 -3.579718 -4.318605 198 | 180 -3.58214 -4.318605 199 | 181 -4.193323 -4.293287 200 | 182 -3.687468 -4.352568 201 | 183 -3.680044 -4.381056 202 | 184 -3.767363 -4.412584 203 | 185 -3.810347 -4.392496 204 | 186 -3.856276 -4.406836 205 | 187 -3.881983 -4.406836 206 | 188 -3.93902 -4.401094 207 | 189 -4.002016 -4.389631 208 | 190 -4.052473 -4.381056 209 | 191 -4.130518 -4.381056 210 | 192 -4.149546 -4.363943 211 | 193 -4.237494 -4.366789 212 | 194 -4.296091 -4.361097 213 | 195 -4.34973 -4.327074 214 | 196 -4.412584 -4.327074 215 | 197 -4.4821 -4.321424 216 | 198 -4.561518 -4.27928 217 | 199 -4.633226 -4.268103 218 | 200 -4.724386 -4.245825 219 | 201 -4.811049 -4.187826 220 | 202 -4.889769 -4.146822 221 | 203 -4.960119 -4.122385 222 | 204 -5.067614 -4.068518 223 | 205 -5.167463 -4.020544 224 | 206 -5.245443 -3.980925 225 | 207 -5.342119 -3.949461 226 | 208 -5.426561 -3.900057 227 | 209 -5.53425 -3.83581 228 | 210 -5.63328 -3.805269 229 | 211 -5.738192 -3.749773 230 | 212 -5.833845 -3.697386 231 | 213 -5.967085 -3.675104 232 | 214 -6.104147 -3.621065 233 | 215 -6.232649 -3.586988 234 | 216 -6.308882 -3.541121 235 | 217 -6.429953 -3.507597 236 | 218 -6.558683 -3.469564 237 | 219 -6.663321 -3.445944 238 | 220 -6.779737 -3.403715 239 | 221 -6.889429 -3.378088 240 | 222 -7.031458 -3.357218 241 | 223 -7.131956 -3.359533 242 | 224 -7.26589 -3.327234 243 | 225 -7.387625 -3.283735 244 | 226 -7.496103 -3.299715 245 | 227 -7.612761 -3.276903 246 | 228 -7.761332 -3.29743 247 | 229 -7.932798 -3.29743 248 | 230 -8.054815 -3.267809 249 | 231 -7.956945 -3.254198 250 | 232 -8.341608 -3.603998 251 | 233 -8.488512 -3.840918 252 | 234 -8.647226 -3.25873 253 | 235 -8.818842 -3.227091 254 | 236 -8.997068 -3.231596 255 | 237 -9.166708 -3.213591 256 | 238 -9.310305 -3.220335 257 | 239 -9.50057 -3.224836 258 | 240 -9.672682 -3.24967 259 | 241 -9.869799 -3.295145 260 | 242 -10.09501 -3.341051 261 | 243 -10.31174 -3.368803 262 | 244 -10.51818 -3.410727 263 | 245 -10.7124 -3.436529 264 | 246 -10.99684 -3.467199 265 | 247 -11.27549 -3.49806 266 | 248 -11.50638 -3.509985 267 | 249 -11.82 -3.562792 268 | 250 -12.11205 -3.601564 269 | 251 -12.39257 -3.655386 270 | 252 -12.74431 -3.697386 271 | 253 -13.08909 -3.724756 272 | 254 -13.42276 -3.779966 273 | 255 -13.80683 -3.782488 274 | 256 -14.25368 -3.83581 275 | 257 -14.67046 -3.889719 276 | 258 -15.1333 -3.9182 277 | 259 -15.61966 -3.928598 278 | 260 -16.21083 -3.97304 279 | 261 -16.90258 -4.023199 280 | 262 -17.51245 -4.033823 281 | 263 -18.36646 -4.06584 282 | 264 -19.36866 -4.068518 283 | 265 -20.47777 -4.089994 284 | 266 -22.03014 -4.100767 285 | 267 -23.47321 -4.122385 286 | 268 -29.49053 -4.130518 287 | 269 -30 -4.144102 288 | 270 -30 -4.160452 289 | 271 -30 -4.182341 290 | 272 -30 -4.179598 291 | 273 -30 -4.165915 292 | 274 -30 -4.149546 293 | 275 -30 -4.141382 294 | 276 -30 -4.135946 295 | 277 -30 -4.127806 296 | 278 -30 -4.146822 297 | 279 -30 -4.127806 298 | 280 -29.49053 -4.130518 299 | 281 -24.94952 -4.149546 300 | 282 -22.39211 -4.119677 301 | 283 -21.10875 -4.073877 302 | 284 -19.73665 -4.089994 303 | 285 -18.57614 -4.044474 304 | 286 -17.62379 -4.063166 305 | 287 -16.76355 -4.036482 306 | 288 -16.17127 -4.002016 307 | 289 -15.4182 -4.017893 308 | 290 -14.89547 -3.962545 309 | 291 -14.30358 -3.954691 310 | 292 -13.82921 -3.941626 311 | 293 -13.34189 -3.905233 312 | 294 -12.86817 -3.894888 313 | 295 -12.44111 -3.892302 314 | 296 -12.03721 -3.876829 315 | 297 -11.83415 -3.881983 316 | 298 -11.33843 -3.797663 317 | 299 -11.09181 -3.76988 318 | 300 -10.81274 -3.737249 319 | 301 -10.61424 -3.742254 320 | 302 -10.31174 -3.687468 321 | 303 -9.906569 -3.665236 322 | 304 -9.525976 -3.625956 323 | 305 -9.158861 -3.621065 324 | 306 -8.959368 -3.618624 325 | 307 -8.71084 -3.655386 326 | 308 -8.481733 -3.662771 327 | 309 -8.192823 -3.643099 328 | 310 -7.98731 -3.628401 329 | 311 -7.778784 -3.621065 330 | 312 -7.573553 -3.62351 331 | 313 -7.339613 -3.621065 332 | 314 -7.131956 -3.603998 333 | 315 -6.928183 -3.603998 334 | 316 -6.756224 -3.60887 335 | 317 -6.527288 -3.630846 336 | 318 -6.343161 -3.655386 337 | 319 -6.161753 -3.677576 338 | 320 -6.002985 -3.692423 339 | 321 -5.845453 -3.704836 340 | 322 -5.66675 -3.739752 341 | 323 -5.508905 -3.787542 342 | 324 -5.352594 -3.833258 343 | 325 -5.204599 -3.89747 344 | 326 -5.080805 -3.915606 345 | 327 -4.921618 -3.941626 346 | 328 -4.789236 -3.999372 347 | 329 -4.681631 -4.007303 348 | 330 -4.529005 -4.071196 349 | 331 -4.403963 -4.122385 350 | 332 -4.298903 -4.19607 351 | 333 -4.182341 -4.26531 352 | 334 -4.057817 -4.28768 353 | 335 -3.952074 -4.335558 354 | 336 -3.861406 -4.38677 355 | 337 -3.764845 -4.429869 356 | 338 -3.687468 -4.467535 357 | 339 -3.599131 -4.52606 358 | 340 -3.517153 -4.540804 359 | 341 -3.420095 -4.588285 360 | 342 -3.354906 -4.633226 361 | 343 -3.286016 -4.654345 362 | 344 -3.054464 -4.657366 363 | 345 -3.013323 -4.718252 364 | 346 -2.942682 -4.721319 365 | 347 -2.898256 -4.783022 366 | 348 -2.879339 -4.795458 367 | 349 -2.86886 -4.823557 368 | 350 -2.835482 -4.817301 369 | 351 -2.814737 -4.867598 370 | 352 -2.7694 -4.886595 371 | 353 -2.787897 -4.880251 372 | 354 -2.777613 -4.870756 373 | 355 -2.823023 -4.912039 374 | 356 -2.812666 -4.94404 375 | 357 -2.802328 -4.89612 376 | 358 -2.810598 -4.851824 377 | 359 -2.847975 -4.851824 378 | 379 | E H 380 | MSL : -2.77 -3.21 381 | MSP : 352 237 382 | HPBW: 65.71 0.00 383 | -------------------------------------------------------------------------------- /plot_2D_Pattern_polar_dB.m: -------------------------------------------------------------------------------- 1 | function plot_2D_Pattern_polar_dB(angdeg, rdB, rangedB, stepdB, stepdeg, noLeg) 2 | 3 | % FUNCTION plot_2D_Pattern_polar_dB(phideg, rdB, rangedB, stepdB, stepdeg, noLeg) 4 | % 5 | % Makes 2D polar plot of angle-vs-r in logarithmic scale (for r). 6 | % It plots on the existing figure/axis, or creates a new one. 7 | % 8 | % Special settings are applied when plotting LVDAM-ANT patterns, 9 | % so that the figure plot matches the software GUI plot 10 | % 11 | % === Inputs === 12 | % * phideg = polar angles in [0,360] deg. Plots for [0,180] are mirrored. 13 | % * rdB = radial distance in dB(log) scale, e.g., rdB=10*log10(r) 14 | % * rangedB = [min,max] dB range for the plot, default is [-30 +10]dB 15 | % * stepdB = dB step for the plot markings, default is 10 dB 16 | % * stepdeg = deg step for the plot markings, default is 30 deg 17 | % * noLeg = boolean, disables dB marks on the right, default is 0 18 | % 19 | % MIT License | Copyright (c) 2022 Alexandros Pitilakis, Thessaloniki/Greece 20 | 21 | % Test inputs 22 | if nargin == 0 23 | clc; close all; clear all; 24 | theta = linspace(eps,pi,100); 25 | kLs = 2*pi*[ 0.001 0.5 1 1.5 ]; 26 | r = NaN*zeros(length(kLs),length(theta)); 27 | for k = 1:length(kLs) 28 | kL = kLs(k); 29 | F = ( ( cos( kL/2*cos(theta) ) - cos(kL/2) )./ sin(theta) ).^2; 30 | r(k,:) = 2*F / trapz( theta, F.*sin(theta) ); 31 | end 32 | rdB = 10*log10( r ); 33 | angdeg = theta*180/pi; 34 | 35 | end 36 | 37 | % ------------------------------------------------------------------------- 38 | % Preliminary operations 39 | % ------------------------------------------------------------------------- 40 | 41 | % Input argument check 42 | if nargin == 1 43 | warning('myApp:argChk', 'Not enough input arguments.'); 44 | help polar_dB; 45 | return; 46 | end 47 | 48 | % Default inputs 49 | if nargin < 6, noLeg = 0; end 50 | if nargin < 5, stepdeg = 30; end 51 | if nargin < 4, stepdB = 10; end 52 | if nargin < 3, rangedB = [-30 +10]; end; 53 | 54 | % Some more checks: 55 | if length(angdeg) ~= length(rdB) % Multiple rad-pat plots: 56 | error( ' ## polar_dB:ERROR: rdB and phideg must be equal length!' ) 57 | end 58 | if diff(rangedB) < 0 % error in range dB 59 | error( ' ## polar_dB:ERROR: rangedB should be [min_dB max_dB]!' ); 60 | end 61 | if max(rdB(:)) > rangedB(2) % warning for dB-range 62 | disp( ' ## polar_dB:Warning: max rdB of curve(s) exceed(s) range!' ); 63 | end 64 | if any( imag(rdB)~=0 ), % complex rdB 65 | error( ' ## polar_dB:ERROR: rdB complex? Real inputs only!'); 66 | end 67 | 68 | % Number of "rays" for angle marking 69 | rays = 360/stepdeg; 70 | 71 | % Arrange phideg and rdB row-wise 72 | angdeg = angdeg(:)'; 73 | if size(rdB,1) > size(rdB,2) 74 | rdB = rdB'; 75 | end 76 | 77 | % LV rad-pats special settings 78 | try 79 | LVspecial = min(size(rdB))==2 && all(angdeg==0:1:359); 80 | catch 81 | LVspecial = 0; 82 | end 83 | if LVspecial 84 | rangedB = [-30 0]; 85 | stepdB = 5; 86 | rdB = rdB(:,[1:end,1]); 87 | angdeg = [angdeg,360]; 88 | end 89 | 90 | 91 | % ------------------------------------------------------------------------- 92 | % Prepare polar plot area: 93 | % ------------------------------------------------------------------------- 94 | 95 | % White circlular-board on which RadPat will be printed 96 | if LVspecial==0 97 | figure; 98 | end 99 | phi0 = linspace(0,360,100); 100 | R0 = 1; 101 | x0 = R0*sind(phi0); 102 | y0 = R0*cosd(phi0); 103 | patch('xdata',x0,'ydata',y0, 'edgecolor','black','facecolor','w'); 104 | hold on 105 | 106 | % ------------------------------------------------------------------------- 107 | % Scale & Plot the Rad-Pat 108 | % ------------------------------------------------------------------------- 109 | 110 | % Colors for the curves, if multiple are to be plotted simultaneously 111 | if LVspecial % E and H planes only 112 | colspace = [1 0 0; 0 0 1]; 113 | elseif size(rdB,1) <= 4 114 | colspace = [0 0 0; 1 0 0; 0 0.5 0;0 0 1]; 115 | else 116 | colspace = jet( size(rdB,1) ); 117 | end 118 | 119 | % Crop rdB to min/max to fit in plot, and scale it to [0->1] for plot 120 | rdBcr = rdB; 121 | rdBcr( rdB >= rangedB(2) ) = rangedB(2); % crop to max 122 | rdBcr( rdB <= rangedB(1) ) = rangedB(1); % crop to min 123 | rdBsc = 1 + (rdBcr-rangedB(2)) / diff(rangedB); % scale to [0...1] 124 | 125 | % Plot all the curves 126 | for rp = 1 : min( size(rdB) ) 127 | 128 | x = rdBsc(rp,:) .* cosd(angdeg); 129 | y = rdBsc(rp,:) .* sind(angdeg) * (-1)^LVspecial; 130 | hp(rp) = plot( y, x,'LineStyle','-','color',colspace(rp,:),'LineWidth', 2); 131 | 132 | % For Theta-plots (0...180 deg): mirror along vertical axis 133 | if max(angdeg) <= 180 134 | plot( -y, x,'LineStyle',':','color',colspace(rp,:),'LineWidth', 1) 135 | end 136 | 137 | end 138 | 139 | % Legend for the rdB plots 140 | if LVspecial 141 | legend( hp , {'E','H'} ); 142 | elseif min( size(rdB) ) > 1 143 | legend( hp , num2str( (1 : min( size(rdB) ))' ) ); 144 | end 145 | 146 | % ------------------------------------------------------------------------- 147 | % Plot "cosmetics": iso-dB cicles and phi-rays 148 | % ------------------------------------------------------------------------- 149 | 150 | % Fixed radial (dB) distance circles 151 | c_log = rangedB(1):stepdB:rangedB(2); 152 | c = (c_log-rangedB(2))/diff(rangedB); 153 | for k = 2 : length(c_log)-1 % dont do the outmost (it's there) and inmost 154 | plot(x0*c(k), y0*c(k),'LineStyle',':','color','black'); 155 | end 156 | 157 | % Markers/labels for the iso-radial (dB) distance circles 158 | % place on the right side 159 | if noLeg == false 160 | for k = 1 : length(c_log) 161 | 162 | dBval = c_log(length(c_log)-k+1); 163 | 164 | if k==1 165 | text(1.3,+c(k), sprintf( '\\bf{%+2.0f dB}' , rangedB(2) ),... 166 | 'horizontalalignment', 'left', 'verticalalignment', 'middle'); %,'fontsize', 13 167 | text(1.3,-c(k), sprintf( '\\bf{%+2.0f dB}' , rangedB(2) ),... 168 | 'horizontalalignment', 'left', 'verticalalignment', 'middle'); %,'fontsize', 13 169 | elseif k == length(c_log) 170 | text(1.3,+c(k), sprintf( '\\bf{%+2.0f dB}' , dBval ),... 171 | 'horizontalalignment', 'left', 'verticalalignment', 'middle'); %,'fontsize', 13 172 | else 173 | text(1.3,+c(k), sprintf('%+2.0f dB',dBval),... 174 | 'horizontalalignment', 'left', 'verticalalignment', 'middle'); %,'fontsize', 13 175 | text(1.3,-c(k), sprintf('%+2.0f dB',dBval),... 176 | 'horizontalalignment', 'left', 'verticalalignment', 'middle'); %,'fontsize', 13 177 | end 178 | 179 | end 180 | end 181 | 182 | % Rays -- Indicating the angles 183 | phi_s=linspace(0,2*pi,rays+1); 184 | x_s = sin(phi_s); 185 | y_s = cos(phi_s); 186 | 187 | % Rays Labels -- For theta (0...180 deg), ray labels are mirrored 188 | if max(angdeg) <= 180 189 | if mod(rays,2)~=0 190 | error( 'Only works for even number of "rays!"' ); 191 | end 192 | phi_s_label = phi_s( [1:(rays/2+1),(rays/2):-1:1] ); 193 | else 194 | phi_s_label = phi_s; 195 | end 196 | 197 | 198 | % Rays -- Plot 'em and label them 199 | for k=1:rays 200 | % Lines 201 | line([x_s(k)/diff(rangedB)*stepdB,x_s(k)],... 202 | [y_s(k)/diff(rangedB)*stepdB,y_s(k)],'LineStyle',':','color','black'); 203 | 204 | % Labels 205 | text(1.1*x_s(k)*(-1)^LVspecial,1.1*y_s(k),... 206 | sprintf('%.3g^o',phi_s_label(k)/pi*180),... 207 | 'horizontalalignment', 'center', 'verticalalignment', 'middle'); %,'fontsize', 15 208 | end 209 | 210 | % Final touches 211 | axis square; 212 | axis off 213 | -------------------------------------------------------------------------------- /plot_3D_Pattern.m: -------------------------------------------------------------------------------- 1 | function plot_3D_Pattern( theta_deg, phi_deg, U_Lin, PlotType ) 2 | 3 | % FUNCTION plot_3D_Pattern( theta_deg, phi_deg, U_Lin, PlotType ) 4 | % 5 | % Plots 3D-pattern U(theta,phi) where: 6 | % * theta (deg): inclination angle, typically 0...180 or 0...90 7 | % * phi (deg): azimuthg angle, typically 0...360 8 | % * U: normalized intensity (W/sterrad), linear scale 9 | % The 2D-arrays (theta,phi,U) are of the same size. 10 | % 11 | % PlotType is an integer index that controls how the data is plotted: 12 | % 1 : |E| = sqrt(U), E-field amplitude, Linear, 3D-spherical 13 | % 2 : P = |E|^2 = (U), power or intensity, Linear, 3D-spherical 14 | % 3 : P_dB = U_dB, power or intensity, LOG-scale, 3D-spherical [Default] 15 | % 4 : |E| = sqrt(U), E-field amplitude, Linear, 3D-cylindrical 16 | % 5 : P = |E|^2 = (U), power or intensity, Linear, 3D-cylindrical 17 | % 6 : P_dB = U_dB, power or intensity, LOG-scale, 3D-cylindrical 18 | % 19 | % PlotType can be a 2D-array, in which case subplots are generated, e.g., 20 | % if PlotType = [ 2 3 ; 5 6 ] we get a 2-by-2 panel, with corresp. plots. 21 | % 22 | % You can edit the "plot3Dparams" struct below, for various ploting 23 | % alternatives. 24 | % 25 | % MIT License | Copyright (c) 2022 Alexandros Pitilakis, Thessaloniki/Greece 26 | 27 | % ------------------------------------------------------------------------- 28 | %% Plot Params (Default values) 29 | % ------------------------------------------------------------------------- 30 | global plot3Dparams 31 | 32 | % General stuff 33 | plot3Dparams.dB_Lim = 40; 34 | plot3Dparams.ra = 1.1; % length of normalized x/y/z-axis vector 35 | plot3Dparams.cbo = 0; % colorbar on ? 36 | plot3Dparams.View = [50 30]; % view [el,az] angles 37 | plot3Dparams.ScaleColors = 1; % scale colors for uniformity acorss |E|,P,dB? 38 | 39 | % Spherical-coord-system params 40 | plot3Dparams.Sph.xyz = 1; % plot xyz axes ? 41 | plot3Dparams.Sph.Sphere = 0.2; % plot Sphere ? 0=No, >0: Boldness (0.1=Barely Vis) 42 | plot3Dparams.Sph.Circles = 1; % plot cut-circles ? 43 | 44 | % Cylindrical-coord-system params 45 | plot3Dparams.Cyl.Flat_or_Surf = 2; % 1=flat (pcolor-like), 2=surf 46 | plot3Dparams.Cyl.Circles_degStep = 15; % deg-step for concentric-circles 47 | plot3Dparams.Cyl.Rays_degStep = 30; % deg=step for radial-rays 48 | plot3Dparams.Cyl.Circles.Annotate = 1; % annotate theta=90 ? 49 | plot3Dparams.Cyl.Rays.Annotate = 1; % annotate phi=0 ? 50 | plot3Dparams.Cyl.xyz = 1; % plot xy axes ? 51 | plot3Dparams.Cyl.CapSideWalls = 1 ; % plot "cap" and "SWs" of cylinder ? 52 | plot3Dparams.Cyl.gridCol = 0.2*[1 1 1]; % cyl-grid line-color 53 | 54 | % ------------------------------------------------------------------------- 55 | %% Test inputs 56 | % ------------------------------------------------------------------------- 57 | if nargin == 0 58 | close all; clc; 59 | 60 | phi = 0:1:360; % [deg] 61 | the = 0:1:90; % [deg] 62 | [phi_deg,theta_deg] = meshgrid( phi,the ); % [deg] 63 | 64 | % Test plot for a 2D array of isotropic scatterers (so that we need 65 | % only check the Array Factor, AF). The array is set-up to point 66 | % towards theta=30deg and phi=-120. 67 | t_max = 30; 68 | p_max = -120; 69 | 70 | % Uniform 2D-array parameters 71 | Nx = 5; % [.] Number of elements of grid in x-dimenson 72 | Ny = Nx; % [.] Number of elements of grid in y-dimenson 73 | kdx = 2*pi * 0.5; % [rad] kappa*dx, where dx: distance in x-dim 74 | kdy = kdx; % [rad] kappa*dy, where dy: distance in y-dim 75 | bx = -kdx*sind(t_max)*cosd(p_max); % [rad] Phase difference in x-dim, from electrical feed 76 | by = -kdy*sind(t_max)*sind(p_max); % [rad] Phase difference in y-dim, from electrical feed 77 | 78 | % Relative phase-difference (from electrical feed and geometric spacing) 79 | psix = kdx * sind(theta_deg) .* cosd(phi_deg) + bx; % [rad] x-dimension 80 | psiy = kdy * sind(theta_deg) .* sind(phi_deg) + by; % [rad] y-dimension 81 | 82 | % Array Factor in 1D (x- and y-dimensions) 83 | AF1Dx = sin( 0.5*Nx*psix ) ./ sin( 0.5*psix ); % [.] 84 | AF1Dy = sin( 0.5*Ny*psiy ) ./ sin( 0.5*psiy ); % [.] 85 | 86 | % Correct cases where division 0/0 --> "NaN" ("Not A Number") error 87 | ix = isnan(AF1Dx); 88 | iy = isnan(AF1Dy); 89 | AF1Dx( ix ) = Nx * cos( 0.5*Nx*psix(ix) ) ./ cos( 0.5*psix(ix) ) ; 90 | AF1Dy( iy ) = Ny * cos( 0.5*Ny*psiy(iy) ) ./ cos( 0.5*psiy(iy) ) ; 91 | 92 | % Array Factor in 2D (power) 93 | AF2D_power = abs( abs(AF1Dx) .* abs(AF1Dy) ).^2; 94 | 95 | % Normalize 96 | AF2D_power_n = AF2D_power / max( AF2D_power(:) ); 97 | 98 | %AF2D_power_n = sind(theta_deg).^2; 99 | 100 | % Calculate Directivity 101 | Un = AF2D_power_n; 102 | D = 4*pi*Un / trapz( phi , trapz( the,Un.*sind(theta_deg) ) ) / (pi/180)^2; 103 | D0max = max(D(:)); 104 | fprintf(' AF max-directivity is %4.2f [dBi]\n' , 10*log10(D0max) ); 105 | 106 | U_Lin = D; 107 | 108 | 109 | % Dipole wl/2 110 | %U_Lin = sind(theta_deg).^2; 111 | 112 | end 113 | if nargin == 0 114 | PlotType = [ 1 2 3 ; 4 5 6 ]; 115 | %PlotType = 5; 116 | end 117 | if nargin == 3 118 | PlotType = 3; 119 | plot3Dparams.cbo = 1; % colorbar on 120 | plot3Dparams.ScaleColors = 1; % linear scaling of color-axis 121 | plot3Dparams.dB_Lim = 30; % min-max is 30dB 122 | end 123 | 124 | % ------------------------------------------------------------------------- 125 | %% Error Checks 126 | % ------------------------------------------------------------------------- 127 | 128 | % Check theta and phi 129 | if any(size(theta_deg)==1) || any(size(phi_deg)==1) 130 | error(' ## (theta,phi) must be meshgrid-produced 2D arrays' ) 131 | end 132 | if max(theta_deg(:))<90 || max(phi_deg(:))<90 133 | error(' ## (theta,phi) must be in DEGREES') 134 | end 135 | 136 | % Check U 137 | if any( U_Lin < 0 ) 138 | error(' ## Make sure U is in linear power-scale' ) 139 | end 140 | if any( ~isreal( U_Lin ) ) 141 | error(' ## Make sure U is real' ); 142 | end 143 | if any( size(U_Lin) ~= size(theta_deg) ) 144 | error(' ## Make sure U is same size as theta_deg and phi_deg' ); 145 | end 146 | if max(U_Lin(:))~=1 147 | disp(' ** Normalizing U_Lin for max==1 (or 0dB)' ); 148 | U_Lin = U_Lin/max(U_Lin(:)); 149 | end 150 | 151 | % ------------------------------------------------------------------------- 152 | %% Plots 153 | % ------------------------------------------------------------------------- 154 | for kp = 1:numel(PlotType) 155 | 156 | % Get proper subplot index 157 | [I,J] = ind2sub(size(PlotType),kp); 158 | kpSP = sub2ind(size(PlotType'),J,I); 159 | 160 | % Prepare subplot 161 | hsp = subplot(size(PlotType,1),size(PlotType,2),kpSP); 162 | 163 | %hsp = axes; 164 | %set( hsp, 'Position' , [0.05+(J-1)*0.30, 0.45-(I-1)*0.45, 0.35, 0.45] ); 165 | hold on; 166 | 167 | % Prepare data, assuming U_Lin is intensity (units of power), Linear 168 | switch mod( -1+PlotType(kp),3 )+1 % PlotType(kp) 169 | case 1, 170 | r = sqrt(U_Lin); 171 | titstr = 'Ampl. |E| (Lin)'; 172 | case 2, 173 | r = U_Lin; 174 | titstr = 'Power |E|^2 (Lin.)'; 175 | case 3, 176 | r = 10*log10( U_Lin ); 177 | titstr = 'Log (dB)'; 178 | end 179 | 180 | % Call appropriate plot function (see below), for either 3D-spherical 181 | % or 3D-cylindrical style 182 | if PlotType(kp) <=3 183 | plot_3D_Spherical(theta_deg,phi_deg,r,PlotType(kp)) 184 | title( [titstr, ' | Spher.'] ); 185 | else 186 | plot_3D_Cylindrical(theta_deg,phi_deg,r,PlotType(kp)) 187 | title( [titstr, ' | Cyl.'] ); 188 | end 189 | 190 | 191 | end 192 | 193 | end 194 | 195 | % ######################################################################### 196 | %% Plot 3D cylindrical 197 | % ######################################################################### 198 | function plot_3D_Cylindrical( t,p,r,PT ) 199 | 200 | global plot3Dparams 201 | 202 | gridCol = plot3Dparams.Cyl.gridCol; 203 | 204 | % Preps 205 | ro = r; % store originally supplied r (need for color-scaling) 206 | if (PT-3) == 3 % Check for dB and rescale in [0,1], so that it's plottable: 207 | R = plot3Dparams.dB_Lim; 208 | r = (max(r,-R) + R)/R; 209 | end 210 | 211 | % Convert from cylindrical (t,p,r) to cartesian (x,y,z) coordinates: 212 | rhoc = t; % [theta] 213 | phic = p; % [phi] 214 | x = rhoc .* cosd( phic ); 215 | y = rhoc .* sind( phic ); 216 | z = r; 217 | 218 | % If color-scaling was requested 219 | if plot3Dparams.ScaleColors==1 && plot3Dparams.Cyl.Flat_or_Surf==2 % Surf 220 | if (PT-3) == 3 % dB 221 | col_scale = 10.^(ro/10); 222 | elseif (PT-3) == 1 % |E| 223 | col_scale = ro.^2; 224 | else 225 | col_scale = r; 226 | end 227 | else % Unscaled or Flat 228 | col_scale = r; 229 | end 230 | FlatOut = (plot3Dparams.Cyl.Flat_or_Surf==1); % If Flat, this is ==1 231 | 232 | % >>>> Plot using SURFACE function <<<< 233 | surf(x,y,z*(1-FlatOut),col_scale); 234 | shading flat 235 | caxis([0 1]) 236 | 237 | % === Various other plot "cosmetics" == 238 | xlabel( '\theta cos( \phi )' ); 239 | ylabel( '\theta sin( \phi )' ); 240 | hold on; 241 | axis tight off; 242 | set(gca,'DataAspectRatio',[1 1 1/90]) 243 | 244 | % Set plot-viewing angle 245 | switch plot3Dparams.Cyl.Flat_or_Surf 246 | case 1, 247 | view(2); 248 | case 2, 249 | view( plot3Dparams.View ) 250 | end 251 | 252 | % If colorbar is on 253 | if plot3Dparams.cbo == 1 254 | hcb = colorbar; 255 | if (PT-3) == 3 % dB-plot 256 | yTick = get(hcb,'YTick'); 257 | yTick_dBn = -(1-yTick)*plot3Dparams.dB_Lim; 258 | set(hcb,'YTickLabel',num2str(yTick_dBn(:))) 259 | end 260 | end 261 | 262 | % -- plot concentric circles (equal-theta) lines 263 | if plot3Dparams.Cyl.Circles_degStep > 0 264 | rho = max(x(:)); 265 | a = 0:1:360; 266 | rho_step = plot3Dparams.Cyl.Circles_degStep; % [deg] 267 | for myrho = rho:-rho_step:rho_step 268 | plot3( myrho*cosd(a), myrho*sind(a), 0*a , 'Color' , gridCol ); 269 | end 270 | 271 | % -- annotate concentric circles 272 | if plot3Dparams.Cyl.Circles.Annotate == 1 273 | text( 0.75*rho , -0.75*rho , 0 ,... 274 | sprintf('\\theta=%d^o',round(rho)) ,'FontSize' , 8 ); 275 | end 276 | 277 | end 278 | 279 | % -- plot radial (equal-phi) lines 280 | if plot3Dparams.Cyl.Rays_degStep > 0 281 | rho = max(x(:)); 282 | phi_step = plot3Dparams.Cyl.Rays_degStep; % [deg] 283 | for myphi = 0:phi_step:180-phi_step 284 | plot3( rho*cosd(myphi+[0 180]), rho*sind(myphi+[0 180]), [0 0] , ... 285 | 'Color' , gridCol ); 286 | end 287 | 288 | % -- annotate radial rays 289 | if plot3Dparams.Cyl.Rays.Annotate == 1 290 | text( 1.1*rho , 0 , 0 , '\phi=0' , ... 291 | 'FontSize' , 8 , 'Color' , 'r'); 292 | end 293 | 294 | end 295 | 296 | % -- plot cylinder "cap" and "sidewalls" 297 | if plot3Dparams.Cyl.CapSideWalls == 1 && plot3Dparams.Cyl.Flat_or_Surf == 2 298 | 299 | %cap rays 300 | rho = max(x(:)); 301 | phi_step = plot3Dparams.Cyl.Rays_degStep; % [deg] 302 | for myphi = 0:phi_step:180-phi_step 303 | plot3( rho*cosd(myphi+[0 180]), rho*sind(myphi+[0 180]), [1 1] ,... 304 | 'Color' , gridCol ); 305 | end 306 | 307 | %cap circles 308 | a = 0:1:360; 309 | rho_step = plot3Dparams.Cyl.Circles_degStep; % [deg] 310 | for myrho = rho:-rho_step:rho_step 311 | plot3( myrho*cosd(a), myrho*sind(a), 1+0*a ,... 312 | 'Color' , gridCol ); 313 | end 314 | 315 | %vertical beams 316 | for myphi = 0:phi_step:360-phi_step 317 | plot3( rho*cosd(myphi)*[1 1], rho*sind(myphi)*[1 1], [0 1],... 318 | 'Color' , gridCol ); 319 | end 320 | 321 | end 322 | 323 | % -- plot xyz "axes" 324 | if plot3Dparams.Cyl.xyz == 1 325 | ra = (plot3Dparams.ra)*max(t(:)); 326 | a = 0:1:360; 327 | lw = 2; 328 | plot3( [0 ra],[0, 0],[0 0], 'r' , 'LineWidth' , lw ) 329 | plot3( [0 0],[0, ra],[0 0], 'g' , 'LineWidth' , lw ) 330 | plot3( max(t(:))*cosd(a), max(t(:))*sind(a), 0*a, 'b' , 'LineWidth' , lw ); 331 | 332 | if plot3Dparams.Cyl.CapSideWalls == 1 && plot3Dparams.Cyl.Flat_or_Surf == 2 333 | ra = max(t(:)); 334 | plot3( ra*cosd(a), ra*sind(a), 1+0*a, 'b' , 'LineWidth' , lw ); 335 | plot3( [ra ra -ra -ra 0],[0 0 0 0 0],[0 1 1 0 0], 'r' , 'LineWidth' , lw ) 336 | plot3( [0 0 0 0 0],[ra ra -ra -ra 0],[0 1 1 0 0], 'g' , 'LineWidth' , lw ) 337 | 338 | end 339 | 340 | end 341 | 342 | end 343 | 344 | % ######################################################################### 345 | %% Plot 3D spherical 346 | % ######################################################################### 347 | function plot_3D_Spherical( t,p,r,PT ) 348 | 349 | global plot3Dparams 350 | 351 | % Check for dB and scale it in [0,1], so that it's plottable: 352 | if PT==3 353 | ro = r; % store originally-supplied r (needed for color-scaling) 354 | R = plot3Dparams.dB_Lim; 355 | r = (max(r,-R) + R)/R; 356 | end 357 | 358 | % Convert from spherical (t,p,r) to cartesian (x,y,z) coordinates 359 | x = r .* sind(t) .* cosd(p); 360 | y = r .* sind(t) .* sind(p); 361 | z = r .* cosd(t); 362 | 363 | % If color-scaling was requiest 364 | if plot3Dparams.ScaleColors==1 365 | if PT==3 % dB 366 | col_scale = 10.^(ro/10); 367 | elseif PT==1 % |E| (linear) 368 | col_scale = r.^2; 369 | else % default P=U=|E|^2 (linear) 370 | col_scale = r; 371 | end 372 | else 373 | col_scale = r; 374 | end 375 | 376 | % >>>> Plot using SURFACE function <<<< 377 | surf(x,y,z,col_scale); 378 | shading flat 379 | caxis([0 1]) 380 | 381 | % === Now various other plot "cosmetics" == 382 | hold on; 383 | view( plot3Dparams.View ) 384 | 385 | % If colorbar is on 386 | if plot3Dparams.cbo == 1 387 | hcb = colorbar; 388 | if PT == 3 % dB-plot 389 | yTick = get(hcb,'YTick'); 390 | yTick_dBn = -(1-yTick)*plot3Dparams.dB_Lim; 391 | set(hcb,'YTickLabel',num2str(yTick_dBn(:))) 392 | end 393 | end 394 | 395 | % --- plot xyz axes 396 | if plot3Dparams.Sph.xyz == 1; 397 | ra = plot3Dparams.ra; 398 | lw = 2; 399 | plot3( [0 ra],[0 0],[0 0], 'r' , 'LineWidth' , lw ); % x-axis 400 | plot3( [0 0],[0 ra],[0 0], 'g' , 'LineWidth' , lw ); % y-axis 401 | plot3( [0 0],[0 0],[0 ra], 'b' , 'LineWidth' , lw ); % z-axis 402 | end 403 | 404 | % -- plot a "sphere" of isotropic (max-U) radiation for reference 405 | if plot3Dparams.Sph.Sphere > 0; 406 | [xx,yy,zz] = sphere(360/15); % sphere with 15-deg spacing in its (phi,theta) 407 | if max(t(:)) == 90 408 | zz = max(zz,0); % crop z<0 part if upper-hemisphere only 409 | end 410 | hs = surf(xx,yy,zz); 411 | set(hs,'FaceColor','None','EdgeColor',0*[1 1 1],... 412 | 'EdgeAlpha',plot3Dparams.Sph.Sphere ) 413 | end 414 | 415 | % --- plot "cut-circles" along the three planes xy (blue), xz (green), zy (red) 416 | if plot3Dparams.Sph.Circles == 1; 417 | a = 0:1:360; 418 | b = 0:1:(180+180*(max(t(:))==180)); 419 | plot3( 1*cosd(a) , 1*sind(a) , 0*a , 'b' ); 420 | plot3( 0*b , 1*cosd(b) , 1*sind(b) , 'r' ); 421 | plot3( 1*cosd(b) , 0*b , 1*sind(b) , 'g' ); 422 | end 423 | 424 | axis equal tight off; 425 | 426 | 427 | 428 | end 429 | 430 | 431 | -------------------------------------------------------------------------------- /script_read_LV_radpat.m: -------------------------------------------------------------------------------- 1 | % This scripts reads ASCII-exported data from Lab-Volt software (LVDAM-ANT) 2 | % plots the polar-dB radiation patterns (E- and H-plane), and displays the 3 | % metrics (Attenuation, Maximum Signal Level & Position, Half Power Beam 4 | % Width) on the command window. 5 | % 6 | % === Notes === 7 | % * Plotting function "plot_2D_Pattern_polar_dB" is required. 8 | % * ASCII data should be exported from LVANT-DAM software (File>Export) 9 | % You will be asked to provide the filename (full path will be required 10 | % if file is not in the same folder as this script). 11 | % * Tested on MATLAB R2014a and Octave v5.1.1, both with LVDAM-ANT 2.3. 12 | % 13 | % MIT License | Copyright (c) 2022 Alexandros Pitilakis, Thessaloniki/Greece 14 | 15 | % v1: Basic MATLAB (R2014a) functionality 16 | % v2: Added corrections so that it works on Octave (5.1.1) too. 17 | % v3: Minor corrections (Nov-2021) 18 | 19 | clear all; close all; clc; 20 | 21 | % Filename with ASCII-exported LV-ANT radiation pattern. 22 | % You can replace the "input" command with the string of the filename, e.g. 23 | % filename = 'example_LVradpat_Export.txt'; 24 | % There's a sample export file (with the above name) in the repository. 25 | filename = input( 'Give LVDAM-ANT ASCII filename (''string.txt''): '); 26 | 27 | % Read the ASCII file. This is very simple with MATLAB (importdata 28 | % function), but a bit more tricky with Octave (textscan function). 29 | temp = ver; 30 | isOctave = strcmp( temp(1).Name , 'Octave' ); 31 | if ~isOctave % MATLAB (IMPORTDATA) 32 | 33 | % Read the dB-attenuations used for E- and H-plane pattern measurements 34 | temp = importdata(filename, ' ', 13); 35 | att_EdB = temp.data(1); 36 | att_HdB = temp.data(2); 37 | 38 | % Read the two radiation patterns: [phideg, EdB, HdB] 39 | temp = importdata(filename, '\t', 17); 40 | phideg = temp.data(:,1)'; 41 | EdB = temp.data(:,2)'; % attenuation is NOT corrected! 42 | HdB = temp.data(:,3)'; % attenuation is NOT corrected! 43 | 44 | % Read the metrics (MSL, MSP and HPBW) calculated from the software 45 | temp = importdata(filename, '\t', 379); 46 | E_metrics = temp.data(:,1); 47 | H_metrics = temp.data(:,2); 48 | 49 | else % Octave (TEXTSCAN) 50 | 51 | disp( 'Octave (not MATLAB) detected. Hope it works...' ) 52 | 53 | % Open the file for reading. MATLAB might "object" here, requiring you 54 | % to specify UTF=8 encoding specifically. 55 | fid = fopen( filename , 'r' ); 56 | 57 | % Read the dB-attenuations used for E- and H-plane pattern measurements 58 | formatSpec = 'P - %*s - attenuation : %f'; 59 | temp = textscan( fid , formatSpec, 2 , 'HeaderLines' , 13 ); 60 | att_EdB = temp{1}(1); 61 | att_HdB = temp{1}(2); 62 | 63 | % Read the two radiation patterns: [phideg, EdB, HdB] 64 | formatSpec = '%f %f %f'; 65 | temp = textscan( fid , formatSpec, 360 , 'HeaderLines' , 3 ); 66 | phideg = temp{1}; 67 | EdB = temp{2}; % attenuation is NOT corrected! 68 | HdB = temp{3}; % attenuation is NOT corrected! 69 | 70 | % Read the metrics (MSL, MSP and HPBW) calculated from the software 71 | % MATLAB and Octave use "HeaderLines" differently. If you use textscan 72 | % with MATLAB, replace 2 with 3 in the following line. 73 | temp1 = textscan( fid , 'MSL : %f %f', 1 ,'HeaderLines' , 2 ); 74 | temp2 = textscan( fid , 'MSP : %f %f', 1 ); 75 | temp3 = textscan( fid , 'HPBW: %f %f', 1 ); 76 | E_metrics = [temp1{1},temp2{1},temp3{1}]; 77 | H_metrics = [temp1{2},temp2{2},temp3{2}]; 78 | 79 | % Close the file. 80 | fclose(fid); 81 | 82 | end 83 | 84 | % Do polar dB-plot for the E- and H-plane radiation patterns 85 | figure('Position',[100 100 800 500],'NumberTitle','off','Name','LVDAM-ANT') 86 | plot_2D_Pattern_polar_dB( phideg(:)', [EdB(:),HdB(:)]' ); 87 | 88 | % Print the metrics in a figure annotation and in the command window 89 | strE = sprintf( 'E-plane:\n * Att = %+2.0f dB\n * MSL = %+4.2f dB\n * MSP = %3.0f deg\n * HPBW = %5.2f deg\n',[att_EdB;E_metrics(:)]); 90 | strH = sprintf( 'H-plane:\n * Att = %+2.0f dB\n * MSL = %+4.2f dB\n * MSP = %3.0f deg\n * HPBW = %5.2f deg\n',[att_HdB;H_metrics(:)]); 91 | fprintf( [strE,strH] ) 92 | 93 | % Annotation text-box (on figure) is also a bit different in syntax: 94 | if ~isOctave % MATLAB (IMPORTDATA) 95 | annotation( 'textbox' , 'string' , [strE,strH] ,... 96 | 'BackgroundColor', 'w' , 'Position',[ 0.01 0.01 0.2 0.4] ); 97 | else % Octave (TEXTSCAN) 98 | annotation( 'textbox' , [ 0.01 0.01 0.2 0.4] , ... 99 | 'string' , [strE,strH] , 'BackgroundColor', 'w') 100 | end 101 | --------------------------------------------------------------------------------