در این بخش از سری مقالات راهنمای عملی ساخت اپلیکیشنهای آیفون قصد داریم به بررسی مشخصههای آیتمهای ناوبری اپلیکیشن خود بپردازیم. در بخش قبلی ما صحنه News را وارد کنترلر ناوبری خودش کردیم. در این زمان میتوان نوار ناوبری را مشاهده کرد، اما از آنجا که آیتم ناوبری صحنه News هیچ عنوانی ندارد، نوار ناوبری خالی است.
برای مطالعه قسمت قبلی این مجموعه مطلب آموزشی میتوانید روی این لینک کلیک کنید.

به Xcode بروید و گزینه Main.storyboard را اگر انتخاب نشده است، انتخاب کنید. طوری اسکرول کنید که صحنه News پدیدار باشد. روی آیتم ناوبری در صحنه News کلیک کنید تا انتخاب شود. اگر پنل Document Outline نیز در حالت نمایش است در این زمان خواهید دید که Navigation Item در آنجا نیز انتخاب شده است. در روی بوم نیز چنین وضعیتی وجود دارد.
اگر پنل Inspector در سمت راست فعال نباشد، روی دکمه انتهای سمت راست نوار ابزار کلیک کنید تا پدیدار شود. اینک میتوانید Attributes Inspector را ببینید. اگر چنین نیست روی آیکون چهارم بالای پنل Inspector کلیک کنید تا به آن سوییچ شود.

پنل Attributes Inspector همه خصوصیتهای موجود (گاهی مشخصه نیز نامیده میشود) را برای شیء انتخاب شده کنونی نمایش میدهد. شما میتوانید اغلب این موارد را تغییر دهید. در این مورد باید یک عنوان برای آیتم ناوبری انتخاب شده وارد کنیم.
در فیلد title در پنل Attributes Inspector عبارت News را وارد کرده و روی Return کلیک کنید. آیتم ناوبری روی بوم و همچنین بخش «دورنمای سند» اینک باید عنوانی به صورت News داشته باشد.

برای این که به اهداف طراحی خود که در بخش اول این سری مقالات راهنما مطرح کردهایم، برسیم باید رنگ نوار ناوبری را به صورت قرمز تعیین کنیم. شاید متوجه شده باشید که خصوصیتهای آیتم ناوبری شامل تنظیمات رنگ نیست. دلیل این امر چنان که در بخش سومتوضیح دادیم، آن است که آیتم ناوبری که از سوی کنترلر ناوبری برای هر صحنه طراحی میشود، منحصر به فرد است؛ اما نوار ناوبری خودش ثابت است و تحت مالکیت کنترلر ناوبری قرار دارد. این همان جایی است که باید نوار ناوبری را تغییر دهیم.
در کنترلر ناوبری برای صحنه News یک بار روی نوار ناوبری کلیک کنید تا انتخاب شود.

همان طور که میبینید خصوصیتهای زیادی برای نوار ناوبری وجود دارد. در حال حاضر ما تنها چند مورد از آنها را بررسی میکنیم. روی منوی بازشدنی کنار Bar Text کلیک و گزینه custom را انتخاب کنید.
Xcode گزینه «انتخاب رنگ» (Color Picker) را نمایش میدهد.
در نوار ابزار این بخش انتخاب رنگ، برگه Color Sliders که دارای آیکون اسلایدر و گزینه دوم از سمت چپ است را انتخاب کنید. در منوی بازشونده گزینه RGB Sliders را انتخاب کنید. مقدار رنگ را به صورت مقادیر زیر تعیین کنید:
میزان «مات بودن» (Opacity) را نیز برابر با 100% تنظیم کنید. اینک میبینید که رنگ پسزمینه نوار ناوبری روی بوم تغییر یافته است.

در این مرحله بخش انتخاب کننده رنگ را ببندید. اکنون که نوار ناوبری تیره داریم، متن تیرهرنگ عنوان آیتم ناوبری و متن «نوار وضعیت» (Status Bar) کنتراست مناسبی ندارند. ما باید از Xcode بخواهیم که با نوار ناوبری به صورت یک شیء تیره رفتار کند تا رنگ این عناوین به صورت سفید درآید.
به این منظور منوی بازشدنی Style را برای نوار ناوبری به صورت Black تنظیم کنید. همزمان سبک عناوین بزرگ را انتخاب کنید تا با ظاهرتصویر ابتدای مقاله اول این سری که میخواهیم ایجاد کنیم مطابقت داشته باشد. در ادامه کادر انتخاب Prefers Large Titles را فعال کنید.

اگر اپلیکیشن خود را به مثابه یک لِگو تصور کنیم، تنها کاری که انجام دادهایم این است که رنگ و ارتفاع نوار ناوبری را تغییر دادهایم. ساختار بلوکها و لایهها همچنان همان است. نوار ناوبری Large Titles باعث میشود که عناوین آیتمهای ناوبری به جای مرکز در سمت چپ قرار بگیرند.
در صحنه News میتوان یک سلول خالی منفرد را زیر هدر بخش Prototype Cells مشاهده کرد. در ادامه میخواهیم محتوایی برای این بخش تعیین کنیم.
یک بار روی سلول کلیک کنید تا انتخاب شود. دقت کنید که نباید دو بار کلیک صورت بگیرد، چون در این صورت دیگر سلول انتخاب نمیشود و به نمای محتوای داخل آن منتقل میشویم. اگر شیء نادرستی را انتخاب کردهاید، کافی است با کلیک روی بخش خالی بوم (یعنی غیر از فضای صحنه)، همه چیز را از حالت انتخاب خارج کنید و سپس دوباره اقدام به انتخاب بخش مورد نظر خود بکنید.
زمانی که سلول را به طرز صحیحی انتخاب کردید، همانند تصویر زیر باید عبارت Table View Cell را در بخش فوقانی Attributes Inspector ببینید.

ما میخواهیم کاربر بتواند روی این سلول در صحنه News کلیک کند تا مقاله خبری مرتبط را در صحنهای دیگر با جزییات بیشتر مشاهده کند. کاربر مورد نظر برای انجام این کار به نوعی راهنمایی نیاز دارد که به وی اشاره کنیم امکان تپ کردن روی سلول را دارد. استاندارد این کار «disclosure indicator» است که یک پیکان خاکستری با نوک اشاره کننده به سمت راست در سمت راست سلول است.
بدین ترتیب به سادگی میتوان به سلول اعلام کرد که یک نشانگر disclosure را نمایش دهد و سلول میداند که باید یک «نمای فرعی» (subview) به نام accessory view در سمت راست سلول اضافه کند.
در بخش Attributes Inspector منوی بازشدنی Accessory را از مقدار None به Disclosure Indicator تغییر دهید.

این سلول هم اینک یک نشانگر Disclosure دارد که همان پیکان خاکستری است که به سمت راست اشاره میکند. به طور مشابه سلول نمای جدولی، چهار گزینه style دارد که به صورت خودکار نماهای فرعی برچسب را در سلول اضافه میکنند. سبک subtitle دو برچسب را به عنوان نمای فرعی در سمت چپ اضافه میکند.
در این زمان باید منوی بازشدنی Style را به صورت Subtitle تنظیم کنید. بدین ترتیب خواهید دید که برچسبهای متنی خالی در سلول ظاهر میشوند. در صورتی که Content View را باز کنید، میبینید که در بخش دورنمای سند نیز این موارد قابل مشاهده هستند.

روی برچسب Title در سلول دو بار کلیک کنید. اینک میبینید که برچسب با نوشته Label به صورت عنوان در پنل نمایش مییابد.

اینک باید متن برچسب را تغییر دهیم. به این منظور میتوانیم هم در بوم روی آن کلیک کنیم و هم در پنل Attributes inspector این کار را انجام دهیم. متن برچسب را از Title به Lego Block Chain تغییر دهید. این تیتر در واقع عنوان مقاله خبری خیالی ما است.

به طور مشابه، متن برچسب Subtitle را انتخاب کرده و برخی جزییات را برای مقاله خبری اضافه کنید.

اگر اپلیکیشن خودمان را در این مرحله اجرا کنیم، سلولها علیرغم این که عناوین و تیترهای مختلفی را در آنها وارد کردهایم، همچنان خالی مشاهده میشوند. دلیل این امر آن است که نمای جدولی هم اینک روی حالت «پروتوتایپهای دینامیک» (dynamic prototypes) تنظیم شده است. این بدان معنی است که نمای جدولی انتظار دارد مقادیر هر سلول به صورت دینامیک و احتمالاً از طریق ارتباط با یک سرور خبری پر شوند. ما در حال حاضر هیچ کد یا حتی سروری در این زمینه نداریم و از این رو قصد داریم جدول را به صورت محتوای استاتیک تنظیم کنیم.
به این منظور در صحنه News یک بار روی ناحیه خاکستری Table View —Prototype Content پایین سلول کلیک کنید. اینک پنل Attributes Inspector باید عنوان Table View را نمایش دهد. منوی بازشدنی Content را از Dynamic Prototypes به Static Cells تغییر دهید.

هنگامی که سلول را از حالت دینامیک به استاتیک تغییر میدهید، توجه داشته باشید که Xcode سه سلول ایجاد میکند که در واقع یک کپی از همه سلولهای اولیه ما هستند. متن سلول دوم باید یک مقاله خبری خیالی دیگر باشد.

یک بار روی سلول سوم کلیک کنید. با بررسی این که دستگیره انتخاب در لبه انتهایی سلول سوم مشاهده میشود و این که عنوان پنل Attributes Inspector به صورت Table View Cell درآمده است، مطمئن شوید که این سلول انتخاب شده است.

این سلول را با فشردن کلید Delete کیبورد، حذف کنید.
اپلیکیشن را اجرا کنید تا آنچه را تا به اینجا طراحی کردهایم، مشاهده کنید.
همان طور که میبینید، نوار ناوبری و سلولها همگی خصوصیتها و محتواهایی که طراحی کردهایم را نمایش میدهند. سلولها هنوز هیچ تصویر یا قالببندی متن ندارند و از این رو بخشی از متن را نمایش میدهند. این وضعیت را در بخش بعدی این سری مقالات اصلاح خواهیم کرد.
برای کامیت کردن تغییرات همانند دفعات قبل مراحل زیر را اجرا میکنیم:
News: customised attributes in navigation bar، navigation item، table view and cells.
3. روی دکمه Commit کلیک کنید.
در این بخش از سری مقالات راهنمای ساخت اپلیکیشن آیفون که قسمت چهارم آن است از پنل Attributes Inspector برای سفارشیسازی نوار ناوبری، آیتم ناوبری، نمای جدولی و سلولهای آن استفاده کردیم. هر گونه سؤال یا دیدگاه مرتبط با این نوشته را میتوانید در بخش نظرات با ما در میان بگذارید. در بخش بعدی بحث ناوبری اپلیکیشن خود را تکمیل میکنیم. برای مطالعه بخش بعدی روی لینک زیر کلیک کنید:
واقعیت این است که دیباگ کردن Node.js همواره کار دشواری است. اگر تاکنون فرصت کدنویسی یک پروژه در Node.js را داشتهاید، میدانید که یافتن منشأ خطا در این نوع کدها و در نتیجه دیباگ Node.js پیچیدگی و دردسر فراوانی به همراه دارد.
برخلاف کدهای جاوا اسکریپت که در مرورگر دیباگ میشوند و یا کدهای جاوا که با استفاده از یک IDE قوی مانند IntelliJ بررسی میشوند، در Node.js امکان تعیین «نقاط توقف» (breakpoint) در نقاط دلخواه، رفرش کردن صفحه یا راهاندازی مجدد کامپایلر و بررسی گام به گام کد، ارزیابی توابع و یافتن متغیر عوض شده یا مفقود وجود ندارد. همین ناتوانی است که موجب دشواری دیباگ کدهای Node.js شده است.
با این حال، امکان دیباگ وجود دارد و صرفاً به زحمت بیشتری نیاز دارد. در ادامه گزینههای موجود را بررسی کرده و سادهترین روش را معرفی خواهیم کرد.
چند روش برای دیباگ برنامههای مشکلدار Node.js وجود دارد که در ادامه آنها را فهرستبندی کردهایم و لینکهای مربوطه را نیز در صورت نیاز به مطالعه بیشتر ارائه کردهایم.
این روش بارها امتحان خود را پس داده است؛ اما در صورتی که تاکنون کدهای جاوا اسکریپت نوشته باشید باید مقدار بیشتری توضیح بدهیم. این ابزار درون Node.js قرار دارد و همانند ابزار داخلی جاوا اسکریپت که لاگ را در کنسول مرور نشان میداد، موارد مرتبط را در ترمینال نمایش میدهد.
معادل این ابزار در جاوا ()System.out.println و در پایتون ()print نام دارد. ابزار یاد شده سادهترین روش برای پیادهسازی دیباگ است و همچنین سریعترین روش برای آلوده کردن کدهای تمیز به خطوطی از اطلاعات اضافی محسوب میشود. به هر حال این روش در برخی موارد به یافتن و اصلاح خطا کمک میکند.
مستندات Node.js نیز درک کرده است که دیباگ کردن کدها کار آسانی نیست و از این رو یک مرجع کارآمد (+) برای کمک به شروع دیباگ ارائه کرده است.
این ابزار مفید است؛ اما اگر صادقانه سخن بگوییم رمزگشایی از آن به جز برای کسانی که تجربه زیادی در کدنویسی دارند کار دشواری محسوب میشود. بدین ترتیب ممکن است به سرعت در دام مباحثی چون UUID-ها، وبسوکتها و «عوارض امنیتی» بیافتید و دچار سرگیجه شوید. در واقع بهتر بود که در این زمینه از روش غیر پیچیدهتری استفاده میشد.
بخش ابزارهای توسعهدهنده در مرورگر کروم امکان دیباگ کردن کدهای Node.js را فراهم میسازد که به ظاهر روش سادهای محسوب میشود، اما اگر میخواهید این روش را بیازمایید، ممکن است متوجه شوید که نیم ساعت سپری شده است و هنوز نتوانستهاید پنجره DevTools را به برنامه Node وصل کنید. به هر حال به نظر میرسد استفاده از Chrome DevTools برای دیباگ کدهای Node.js پیچیدهتر از آن است که باید باشد.
JetBrains یکی از شرکتهای محبوب توسعه نرمافزار است که IDE-هایی مانند IntelliJ و WebStorm را عرضه کرده است. این شرکت اکوسیستم جالبی از افزونهها برای ابزارهای خود ارائه کرده است.
به لطف جامعه گسترده کاربران JetBrains، مقالات زیادی در حوزههای متفاوت و از جمله دیباگ کردن کدهای Node.js نوشته شده است. اما این مورد نیز همچون مستندات Node و Chrome DevTools آسان نیست. کاربر در این روش باید پیکربندیهای زیادی انجام دهد، پردازشهای اجرایی را الحاق کند و همچنین «ترجیحات» (Preferences) را به مقدار زیادی پیکربندی کند تا WebStorm آماده دیباگ کردن شود.
این گزینه یکی از سادهترین روشهای دیباگ کردن کدهای Node.js را ارائه کرده است. هر کسی که VS Code را یک بار تجربه کرده، عاشق آن شده است.
VS Code کاری را که هیچ کدام از گزینههای دیگر در خصوص دیباگ کردن کدهای Node.js موفق به انجام نشدند، اجرایی کرده و آن را به فرایندی کاملاً ساده تبدیل کرده است. دیباگ کردن با استفاده از VS Code چنان ساده است که هر کسی میتواند آن را به سرعت راهاندازی و اجرا کند و مهم نیست که چه میزان از آشنایی با IDE-ها، Node و یا برنامهنویسی دارد.
در این بخش اقدام به تنظیم VS Code و دیباگ کردن Node.js میکنیم. به این منظور، میبایست قبلاً VS Code را دانلود (+) و نصب کرده باشید. بنابراین در ادامه شروع به تنظیم آن میکنیم.
در نرمافزار VS Code به بخش Preferences > Settings بروید و در کادر جستجو عبارت node debug را وارد کنید. زیر برگه Extensions یک اکستنشن با عنوان «Node debug» ظاهر میشود. در اینجا روی کادر نخست Debug > Node: Auto Attach کلیک کرده و منوی بازشدنی را روی on تنظیم کنید. اینک آماده شروع به کار هستیم.

اکنون به فایل پروژه Node.js خود بروید و با کلیک کردن روی سمت چپ فایل در هر جایی که دوست دارید برخی نقاط توقف را تنظیم کنید. سپس در ترمینال عبارت node –inspect <FILE NAME> را وارد کنید تا عملکرد آن را مشاهده کنید.

اگر به یک پروژه Node.js نیاز دارید که این موارد را تست کنید میتوانید این پروژه (+) را دانلود کنید. این پروژه جهت تست کردن شکلهای مختلف استریم کردن مقادیر بالایی از داده در Node ساخته شده است؛ اما در این دموی ما نیز به خوبی کار میکند. زمانی که کلید Enter را بزنید. بخش انتهایی ترمینال VS Code به رنگ نارنجی در میآید تا نشان دهد که در حالت دیباگ هستید. کنسول نیز پیامی را مبنی بر الحاق دیباگر (‘Debugger Attached’) نمایش میدهد.

زمانی که این وضعیت را مشاهده کردید، بدانید که موفق به دیباگ کردن کدهای Node.js در VS Code شدهاید.
اینک میتوانید نقاط توقف را در گوشه پایین-چپ صفحه مشاهده کنید. امکان فعال و غیرفعال کردن آنها نیز با انتخاب کادر مربوطه وجود دارد. بدین ترتیب امکان اجرای خط به خط کد و گزینههای step over ،step in ،restart و غیره، همانند زمانی که با استفاده از دکمه Play کوچک در مرورگر اجرا میکردید وجود خواهد داشت. به این منظور باید از دکمههای بخش میانی و بالای IDE استفاده کنید. VS Code نقاط توقف و خطی را که کد در آن متوقف شده است هایلایت میکند تا پیگیری فرایند کار، آسان باشد.

زمانی که با استفاده از دکمههای فوق از یک نقطه توقف به نقطه توقف بعدی حرکت میکنید میتوانید ببینید که برنامه موارد console.log را در کنسول دیباگ در بخش تحتانی ویژوال استودیو کد پرینت میکند و با حرکت به سمت جلو با رنگ زرد هایلایت میشود.

همان طور که میبینید هر چه در برنامه پیش میرویم مواردی که در کنسول دیباگ به نمایش در میآیند افزایش مییابند و در طی این مسیر میتوان اشیا و تابعها را در دامنه محلی با استفاده از ابزارهای گوشه چپ-بالای VS Code دقیقاً همانند روش بررسی موارد مشابه در مرورگر بررسی کرد.
دیباگ کردن Node.js به لطف VS Code دیگر مانند گذشته دشوار نیست و لازم نیست 500 بار ()console.log را در کد خود تکرار کنیم تا بفهمیم که باگ کجا هست. گزینه Debug > Node ویژوال استودیو کد به کمک روش الحاق خودکار پردازش این وضعیت را دگرگون ساخته است.
https://blog.faradars.org/easiest-way-to-debug-node-js-with-vscode/
«بوکه» (Bokeh)، کتابخانهای برای بصریسازی تعاملی دادهها است. برخلاف دیگر کتابخانههای موجود برای بصریسازی دادهها در «زبان برنامهنویسی پایتون»، مانند «مَتپلاتلیب» (Matplotlib) و «سیبورن» (Seaborn)، بوکه گرافیکهای خود را با استفاده از «اچتیامال» (HTML) و «جاوا اسکریپت» (JavaScript) رندر میکند. این موضوع موجب شده تا بوکه به گزینهای مناسب برای ساخت دشبوردها و اپلیکیشنهای مبتنی بر وب مبدل شود. به طور کلی باید گفت، کتابخانه بوکه ابزاری قدرتمند برای اکتشاف و درک دادهها یا ساخت نمودارهای زیبا برای پروژهها و گزارشها است. هدف از این راهنما آن است که روش کار با کتابخانه بوکه با بهرهگیری از مجموعه دادههای جهان واقعی، آموزش داده شود. سرفصلهای زیر در این مطلب ارائه شدهاند.
ساخت خروجیهای بصری با استفاده از کتابخانه بوکه (Bokeh) شامل گامهای زیر میشود:
اکنون، هر یک از مراحل بیان شده در بالا، همراه با جزئیات بیشتر مورد بررسی قرار میگیرد.
بصریسازی دادهها همیشه با دادههای ورودی آغاز میشود. در این گام معمولا از کتابخانههای «پیشپردازش» (Preprocessing)دادهها مانند «پانداس» (Pandas) و «نامپای» (NumPy) استفاده میشود و طی آن، گامهای مورد نیاز برای تبدیل دادهها به فرم مناسب برای انجام پردازشها، برداشته میشود.
در این گام، چگونگی تولید و نمایش بصریسازیها، به وسیله کاربر تعیین میشود. در این راهنما، دو گزینه متداولی که بوکه در این راستا فراهم میکند ارائه شدهاند که عبارتند از: تولید یک فایل HTML استاتیک و رندر کردن بصریسازیها به صورت خطی در «ژوپیتر نوتبوک» (Jupyter Notebook).
در این مرحله، اشکال (Figure) توسط کاربر تعیین و بوم اولیه برای بصریسازی دادهها آماده میشود. در گام انتخاب اشکال، میتوان همه چیز از عناوین گرفته تا علامتها را سفارشیسازی کرد. همچنین، میتوان با بهرهگیری از مجموعهای از ابزارها کاربران را قادر به تعامل با بصریسازیها کرد.
اکنون، از قابلیت رندر کردن بوکه برای شکل دادن به دادهها استفاده میشود. در این فاز، باید از انعطافپذیری موجود برای ترسیم دادهها از پایه با استفاده از اشکال و نشانهگرهای متعدد موجود استفاده کرد؛ همه این موارد به سادگی قابل سفارشیسازی هستند. این عملکرد، آزادی فوقالعادهای را جهت ارائه دادهها در اختیار کاربر قرار میدهد. علاوه بر موارد بیان شده، بوکه دارای توابع توکاری برای ساخت چیزهایی مانند «نمودار میلهای تجمعی» (Stacked Bar Charts) و قابلیتهایی برای ساخت بصریسازیهای پیشرفتهتر مانند گرافهای شبکه و نقشهها است.
بوکه، برای افرادی که نیاز به بیش از یک تصویر برای تشریح دادههای خود دارند نیز ابزاری مناسب محسوب میشود. این کتابخانه، نه فقط گزینههای «قالب» (layout) شبکه مانند استاندارد را فراهم میکند، بلکه این امکان را برای کاربر فراهم میکند تا به سادگی بصریسازیها را با تنها با چند خط کد در یک قالب قرار دهد. علاوه بر آن، نمودارها را میتوان به سرعت به یکدیگر لینک کرد؛ بنابراین، انتخاب یکی از نمودارها، بر کلیه نمودارهای دیگر (هر ترکیبی از دیگر گزینهها) نیز تاثیرگذار است.
در نهایت، زمان آن فرا میرسد که آنچه ساخته شده است را نمایش داد. اگرچه، بصریسازیها در مرورگر یا نوتبوک قابل مشاهده هستند، کاربر قادر به بررسی خروجیها (بصریسازیها)، سفارشیسازی آنها و ویرایش قسمتهای تعاملی موجود در آنها است. اگر کاربر آنچه که دیده را بپسندد، میتواند بصریسازیها را به صورت یک فایل تصویر (Image) ذخیرهسازی کند. در غیر این صورت (یعنی در صورتی که خروجیها نظر کاربر را جلب نکرد)، کاربر میتواند گامهای انجام شده در بالا را برای کسب خروجیهایی که در نظر دارد، مورد بازنگری قرار دهد. شش گام بیان شده در بالا، بلوکهای سازنده یک الگوی سازمانیافته و انعطافپذیر هستند که از مرحله دریافت دادهها از مجموعه داده تا ترسیم آنها به صورت نمودارهای جذاب و قابل فهم را پوشش میدهند.
یکی از قطعه کدهای متداولی که برای انجام کلیه گامهایی که پیشتر بیان شدند مورد استفاده قرار میگیرد در بالا نمایش داده شده است.
راهکارهای متعددی برای ارائه خروجی بصری از دادهها در کتابخانه «بوکه» (Bokeh) وجود دارد. در این راهنما، گزینههای معرفی شده در زیر مورد استفاده قرار میگیرند.
شایان ذکر است که هیچ یک از دو تابع بالا بصریسازیها را به کاربر نمایش نمیدهند. در واقع این اتفاق مادامی که ()show فراخوانی نشده نمیافتد. اگرچه، این توابع اطمینان حاصل میکنند که در صورت فراخوانی ()show، بصریسازیها به گونهای نمایش داده میشود که کاربر تمایل دارد. با فراخوانی همزمان ()output_file و ()output_notebook در یک اجرای واحد، بصریسازی هم روی فایل HTML استاتیک و هم روی نوتبوک به صورت توکار انجام میشود. اگر به هر دلیلی کاربر چند دستور ()output_file را به طور همزمان اجرا کند، تنها آخرین دستور برای رندر کردن مورد استفاده قرار میگیرد. اکنون، فرصت خوبی فراهم شده تا کد اولیه در ()figure پیشفرض بوکه با استفاده از ()output_file نوشته شود.

همانطور که مشهود است، یک پنجره جدید مرورگر باز شده که به آن Empty Bokeh Figure و empty figure گفته میشود. آنچه در تصویر مشهود نیست و در پشت صحنه به وقوع میپیوندد، ساخته شدن فایلی با نام output_file_test.html در پوشه کاری جاری کاربر است. اگر کاربر قصد داشته باشد که قطعه کدی مشابه با ()output_notebook را به جای ()output_file اجرا کند، با این فرض که Jupyter Notebook در حال اجرا است میتواند از قطعه کد زیر استفاده کند.

همانطور که مشهود است، نتایج مشابه هستند و صرفا رندر کردن در محلهای متفاوتی به وقوع پیوسته است. اطلاعات بیشتر پیرامون ()output_file و ()output_notebook در مستندات رسمی بوکه (+) موجود است. نکته شایان توجه آن است که گاهی هنگام رندر کردن چندین بصریسازی به ترتیب، مشاهده میشود که رندرهای قبلی مربوط به اجراهای پیشین پاک نشدهاند. در صورت مواجه شدن با چنین شرایطی، میتوان کد زیر را «وارد» (Import) و در میان اجراها اجرا کرد.
پیش از ادامه دادن این مطلب، لازم به ذکر است که بوکه به طور پیشفرض با یک جعبه ابزار از پیش بارگذاری شده میآید. اطلاعات بیشتر پیرامون این جعبه ابزار و چگونگی پیکربندی آن در بخش افزودن تعامل، در پایان این راهنما ارائه شده است.
اکنون که چگونگی ساخت و نمایش یک تصویر کلی بوکه هم در مرورگر و هم در ژوپیتر نوتبوک آموزش داده شد، زمان آن رسیده تا بیشتر پیرامون چگونگی پیکربنی شی ()figure توضیح داده شود. شی ()figure فقط پایه بصریسازی دادهها نیست، بلکه شیئی است که ابزارهای بوکه برای بصریسازی دادهها را قفلگشایی میکند. figure در بوکه یک زیرکلاس از «Bokeh Plot Object» است که پارامترهای زیادی را برای پیکربندی عناصر زیباییشناختی شکل فراهم میکند. برای درک بهتر این مطلب، در ادامه زشتترین تصویر ممکن با قطعه کد زیر ساخته میشود.

هنگامی که شی ()figure معرفی شد، میتوان آن را پیکربندی کرد. اکنون، فرض میشود که کاربر میخواهد خطوط شبکهای را حذف کند. برای این کار میتوان از قطعه کد زیر استفاده کرد.
مشخصات خطوط شبکهای از طریق خصیصه grid شکل در دسترس هستند. در این مثال، تنظیم grid_line_color روی None، به شکل موثری همه خطوط شبکهای را به صورت یکباره حذف میکند.

نکته: اگر کاربر در نوتبوک یا «محیط توسعه یکپارچه» (Integrated Development Environment | IDE) با قابلیت «تکمیل خودکار» (auto-complete) کار میکند، میتواند از مزایای قابل توجه آن استفاده کند. ()figure دارای عناصر قابل سفارشیسازی متعددی است و قابلیت تکمیل خودکار برای کشف گزینههای موجود برای سفارشیسازی بسیار مفید محسوب میشود.

در صورتی که محیط توسعه مورد استفاده کاربر دارای قابلیت تکمیل خودکار نیست، انجام یک جستوجوی سریع، با کلیدواژه Bokeh و آنچه که کاربر قصد دارد انجام دهد، معمولا او را به مسیر صحیحی هدایت میکند. مطالب بسیار زیادی برای آموزش دادن در همین رابطه وجود دارند، اما ورود بیش از حد به جزئیات، این مطلب را از هدف اصلی آن دور میکند. برای مطالعه بیشتر در این رابطه، میتوان از موارد زیر استفاده کرد.
در ادامه، برخی از گزینههای سفارشیسازی خاصی که فراگیری آنها ارزشمند است بیان شدهاند.
گاهی، تا هنگامی که بخشی از دادهها بصریسازی نشوند، مشخص نیست که تصویر چقدر نیاز به ویرایش و سفارشیسازی دارد. بنابراین، در ادامه روش انجام این کار آموزش داده خواهد شد.
یک شکل خالی، مساله جذاب و قابل توجهی نیست؛ بنابراین در ادمه به بررسی glyphs که بلوک سازنده بصریسازیهای Bokeh است پرداخته میشود. glyph یک شکل گرافیکی برداریسازی شده یا «نشانگری» (Marker) است که برای ارائه دادهها در اشکالی مانند یک دایره یا مربع مورد استفاده قرار میگیرد. مثالهای بیشتر در این رابطه در گالری بوکه (+) موجود هستند. پس از ساخت شکل، باید به دستهای از متدهای قابل پیکربندی glyph دسترسی داده شود. اکنون، کار با یک مثال بسیار پایهای آغاز میشود که طی آن چندین نقطه روی یک دستگاه مختصات x-y ترسیم میشوند.

پس از معرفی ()figure، میتوان دید که چگونه میتوان از آن برای ترسیم دادهها در دستگاه مختصات x-y با استفاده از glyphهای circle سفارشیسازی شده استفاده کرد. در ادامه برخی از دستههای glyph معرفی شدهاند.
glyphها را میتوان ترکیب کرد تا قابلیتهای لازم برای بصریسازی تامین شوند. اکنون فرض میشود که هدف ساخت تصویری است که تعداد کلمات نوشته شده در هر روز برای ساخت این راهنما را با یک خط نشانگر روند رشد تعداد کلمات (روزانه و تجمعی) نشان دهد.

برای ترکیب ستونها و خطها در شکل، این موارد با استفاده از شی ()figure ساخته شدهاند. علاوه بر آن، میتوان مشاهده کرد که با تنظیمات legend برای هر glyph چگونه میتوان راهنمای نمودار را به صورت یکپارچه ترسیم کرد. راهنمای نقشه نیز با تخصیص «top_left» به «fig.legend.location» به گوشه بالا و سمت راست نمودار انتقال داده میشود.
کتابخانه بصریسازی بوکه فرصت خوبی را برای کار با دادههای گوناگون فراهم میکند. جذابیت Bokeh در آن است که تقریبا پیادهسازی هر ایده بصریسازی با آن امکان دارد و این موضوع فقط به چگونگی استفاده از ابزارهایی که در اختیار کاربر قرار داده بستگی دارد. در مثالی که در ادامه به آن پرداخته میشود از مجموعه دادههای عمومی Kaggle که مربوط به ۷۲ فصل از مسابقات بسکتبال اتحادیه ملی بسکتبال آمریکا ( the National Basketball Association’s (NBA) 2017-18 season) هستند، استفاده شده است.
پس از دانلود مجموعه داده، با استفاده از قطعه کدی که در ادامه آمده، دادهها در دیتافریم کتابخانه «پانداس» (Pandas) خوانده میشوند.
این قطعه کد دادهها را از سه فایل CSV خوانده و به صورت خودکار ستونهای داده را به صورت اشیا datetime تفسیر میکند. اکنون زمان آن رسیده که روی دادههای واقعی کار شود.
در مثال بالا از لیستهای پایتون و آرایههای «نامپای» (Numpy Arrays) برای نمایش دادهها استفاده شده است. کتابخانه «بوکه» (Bokeh) برای مدیریت این نوع دادهها به خوبی تجهیز شده است. اگرچه، هنگامی که بحث دادهها در پایتون میشود، احتمال استفاده از دیکشنریها و دیتافریمهای پانداس نیز وجود دارد، به ویژه اگر دادهها از یک فایل یا منبع داده خارجی خوانده میشوند. Bokeh برای کار با این ساختارهای داده پیچیدهتر توانمند و حتی دارای توابع توکاری برای مدیریت آنها است؛ به عنوان مثالی از این توابع میتوان به ColumnDataSource اشاره کرد.
اکنون، امکان دارد این پرسش مطرح شود که «اگر Bokeh دارای رابطی برای کار با دادهها به صورت مستقیم است چرا از ColumnDataSource استفاده شود؟». اولا، هنگامی که به یک لیست، آرایه یا دیتافریم به طور مستقیم ارجاع داده میشود، بوکه در پشت صحنه به هر حال آن را به یک ColumnDataSource تبدیل میکند. دوم و مهمتر آنکه، ColumnDataSource پیادهسازی قابلیتهای تعاملی بوکه را سادهتر میسازد.
ColumnDataSource در انتقال دادن دادهها به glyphهایی که برای بصریسازی مورد استفاده قرار میگیرند نقش بنیادین دارد. کارکرد اصلی آن، برای نگاشت اسامی به ستونهای دادهها است. این کار موجب میشود ارجاع به عناصر دادهها هنگام ساخت بصریسازیها آسانتر شود. این تابع همچنین انجام کار مشابهی را هنگام ساخت بصریسازیها آسانتر میکند. ColumnDataSource میتواند سه نوع شی داده بیان شده در زیر را تفسیر کند.
اکنون، کار با بصریسازی مسابقات برای جایگاه اول در NBA’s Western Conference in 2017-18 برای مدافع قهرمانی یعنی تیم Golden State Warriors و رقیب آن Houston Rockets آغاز میشود. رکوردهای روزانه پیروزی-شکست برای این دو تیم در یک دیتافریم با نام west_top_2 ذخیره شده است.
از اینجا میتوان این DataFrame را در دو شی ColumnDataSource بارگذاری و مسابقه را بصریسازی کرد.

چگونگی ارجاع داده شدن اشیای ColumnDataSource هنگام ساخت دو خط قابل توجه است. اسامی ستون اصلی به سادگی به عنوان پارامترهای ورودی پاس داده میشوند و مشخص میشود که کدام ColumnDataSource با خصیصه source مورد استفاده قرار بگیرد. بصریسازیها نشانگر وجود مسابقات تنگاتنگی در این فصل و همچنین، حاکی از تاثیر قابل توجه Warriors در میانه فصل هستند. اگرچه، یک بیت لغزش در فصل پیش امکان بالا رفتن را برای Rockets فراهم کرده و در نهایت از مدافعان قهرمانی پایان فصل، به عنوان تیم اول پیشی گرفته است.
نکته: در بوکه، میتوان رنگها را بر اساس اسم، مقدار پایه ۱۶ (hex value)، یا کد رنگ RGB تعیین کرد. برای بصریسازی بالا، دو رنگ برای خطوط مربوطه تعیین شدهاند که نشانگر دو تیم هستند. به جای استفاده از اسامی رنگهای CSS، کاربر ممکن است بخواهد که با استفاده از رنگهای رسمی تیمها به صورت کدهای هگزادسیمال جلوه زیبایی به خروجیها ببخشد. در عین حال، میتوان از تاپلهایی که کدهای رنگ RGB را نشان میدهند (۲۰۶، ۱۷، ۶۵) برای Rockets و کدهای (۰، ۱۰۷ و ۱۸۲) برای Warriors استفاده کرد.
بوکه لیست مفیدی از اسامی رنگهای CSS که بر اساس فام اصلی آنها دستهبندی شدهاند را ارائه میکند. همچنین، میتوان از سایتهای متعددی که برای یافتن کدهای رنگی به صورت CSS ،RGB و hex وجود دارند، استفاده کرد. اشیای ColumnDataSource میتوانند کاری بیش از ارجاعدهی به ستونهای DataFrame انجام دهند. شی ColumnDataSource دارای سه فیلتر توکار است که میتوانند برای ساخت نمایشهایی از دادهها با استفاده از شی CDSView مورد استفاده قرار بگیرند؛ این سه فیلتر در ادامه معرفی شدهاند.
در مثال پیشین، دو شی ColumnDataSource ساخته شدند که هر یک از آنها زیرمجموعهای از دیتافریم west_top_2 هستند. مثال بعدی، خروجی مشابهی را از یک ColumnDataSource بر پایه west_top_2 با استفاده از GroupFilter میسازد که دیدی از دادهها فراهم میکند.

چگونگی پاس دادن GroupFilter به CDSView در یک لیست قابل توجه است. این کار، امکان ترکیب چندین فیلتر با یکدیگر را برای ایزوله کردن دادههایی که از ColumnDataSource مورد نیاز هستند فراهم میکند. Western Conference به عنوان مسابقاتی مهیج پایان یافت که رقابتهای آن حقیقتا تنگاتنگ برگزار شده بودند. این رقابتها در ادامه به صورت بصری ارائه خواهند شد. بنابراین، در ادامه به موضوع بعدی یعنی layoutها پرداخته خواهد شد.
جدول ردهبندی Eastern Conference به دو دسته از رقابتها در بخش آتلانتیک تقسیم میشود که عبارتند از: Boston Celtics و Toronto Raptors. پیش از تکرار گامهایی که برای ساخت west_top_2 مورد استفاده قرار گرفتند، بهتر است یکبار دیگر ColumnDataSource با استفاده از آنچه پیشتر توضیح داده شد مورد آزمون قرار بگیرد. در این مثال، چگونگی خوراک دادن کل DataFrame به یک ColumnDataSource و ساخت نمایشهایی برای ایزوله کردن دادههای مرتبط، بیان خواهد شد.

ColumnDataSource قادر به ایزوله کردن دادههای مرتبط در یک دیتافریم ۵، ۰۴۰ در ۳۹ بدون سختی قابل توجه و تنها با چند خط کد «پانداس» (Pandas) است. با نگاه به بصریسازیها، میتوان مشاهده کرد که رقابتهای Eastern Conference دارای هیچ مشکلی نیستند. پس از آنکه Celtics نتوانستند میادین را به خوبی حفظ کنند، Raptorsها همه راه را بازگشتند تا بر رقیب خود غلبه کرده و فصل را با پنج برد بیشتر به اتمام برسانند. با دو بصریسازی آماده، زمان آن رسیده تا این نمودارها در کنار هم قرار داده شوند و تحلیلهایی روی آنها صورت پذیرد. مشابه با عملکرد subplot در «مَتپِلاتلیب» ( Matplotlib)، بوکه نیز دارای توابع column، row و gridplot در ماژول bokeh.layouts است. این توابع میتوانند به صورت عمومیتر با عنوان layout دستهبندی شوند. استفاده از این layoutها کار سختی نیست. اگر هدف، قرار دادن دو بصریسازی در پیکربندی عمودی باشد میتوان به صورت زیر عمل کرد.

تنها با تغییر column با row در قطعه کد بالا، میتوان به طور مشابه دو نمودار را به صورت افقی در کنار هم قرار داد.
نکته: برای افرادی که همراه با مطالعه این مطلب در تلاش برای نوشتن کدهای خودشان هستند، در ادامه نکاتی پیرامون خطایی که امکان دارد با آن مواجه شوند ارائه میشود. این خطا ممکن است ضمن دسترسی به west_fig و east_fig در مثالی که در ادامه ارائه شده رخ دهد. خطای مذکور، چیزی شبیه آنچه در زیر آمده، خواهد بود.
این تنها یکی از خطاهای متعددی است که به عنوان ماژول اعتبارسنجی بوکه به وقوع میپیوندند که در آن W-1004 هشداری پیرامون استفاده مجدد از west_fig و east_fig در یک layout جدید است. برای اجتناب از این خطاها، همانطور که مثالها تست میشوند، قطعه کدی که هر لایه را نمایش میدهد به صورت زیر آغاز میشود:
انجام این کار موجب نوسازی مولفههای مرتبط برای رندر کردن بصریسازیها و حصول اطمینان از این موضوع میشود که هیچ هشداری مورد نیاز نیست. به جای استفاده از column یا row، کاربر ممکن است بخواهد که از gridplot استفاده کند. یک تفاوت کلیدی gridplot با دیگر موارد آن است که به طور خودکار نوار ابزار را در سراسر شکلهای (Figures) فرزند تحکیم میکند. همانطور که مشهود است، در gridplot به جای آنکه یک تاپل به عنوان ورودی به آن داده شود، نیازمند لیستی از لیستها است که در آن هر زیر لیست یک سطر از شبکه را نشان میدهد:

در نهایت، gridplot امکان انتقال مقادیر None را فراهم میکند که به صورت زیرنمودارهای خالی تفسیر میشوند. از این رو، اگر کاربر قصد قرار دادن یک placeholder برای دو نمودار اضافهتر را داشته باشد، میتواند به صورت زیر عمل کند.

اگر کاربر قصد جابهجایی میان بصریسازیها در سایز کامل آنها را بدون پایین کشیدن آنها برای متناسب شدن در کنار یا بر فراز هم داشته باشد، یک گزینه خوب tabbed layout است. یک tabbed layout شامل دو تابع ویجت Bokeh است: ()Tab و ()Panel از زیرماژول bokeh.models.widgets. همچون استفاده از ()gridplot، ساخت یک tabbed layout نیز کار سادهای به حساب میآید.

اولین گام، ساخت یک ()Panel برای هر tab است. این موضوع ممکن است کمی گیجکننده به نظر برسد، در واقع باید به تابع ()Tabs به عنوان مکانیزمی که Tabهای جداگانه ساخته شده با ()Panel را سازماندهی میکند نگریست. هر ()Panel یک فرزند را به عنوان ورودی دریافت میکند که میتواند یک ()figure یا layout تنها باشد. (باید به خاطر داشت که layout یک نام عمومی برای column ،row یا gridplot است.) پس از آنکه پنلها سرهم شدند، میتوان آنها را به ()Tabs در یک لیست انتقال داد. اکنون که چگونگی دسترسی، ترسیم و سازماندهی دادهها مشخص شد، زمان آن رسیده که معجزه بوکه را روی دادههای واقعی دید: تعامل!
ویژگی که بوکه را از دیگر کتابخانههای موجود متمایز میکند، توانایی آن برای پیادهسازی آسان تعامل در بصریسازیها است. بوکه حتی تا توصیف خودش به عنوان یک کتابخانه بصریسازی تعاملی پیش میرود.
Bokeh یک کتابخانه بصریسازی تعاملی است که مرورگرهای مدرن را برای ارائه، هدف قرار میدهد.
در این بخش، چهار راهکاریی که میتوان با استفاده از آنها تعامل را به بصریسازیها افزود بیان شدهاند.
پیادهسازی این عناصر تعاملی امکان اکتشاف دادهها را به شیوهای فراهم میکند که بصریسازیهای استاتیک نمیتوانند انجام دهند.
چنانکه پیشتر در بخش «ساخت شکل اولیه» بیان شد، ()figure پیشفرض بوکه با یک نوار ابزار عرضه میشود. نوار ابزار پیشفرض با ابزارهایی که در ادامه بیان شدهاند ارائه میشود (از چپ به راست).
نوار ابزار را میتوان با پاس دادن toolbar_location=None هنگام معرفی یک شی ()figure حذف کرد و یا با پاس دادن هر یک از گزینههای above، below، left یا right تغییر مکان داد. علاوه بر آن، نوار ابزار را میتوان برای در بر گرفتن هر ترکیبی از ابزارهایی که کاربر تمایل دارد پیکربندی کرد. بوکه ۱۰ ابزار اختصاصی در ۱۸ دسته ارائه می کند که در زیر بیان شدهاند.
پیادهسازی رفتار انتخاب به سادگی افزودن چند کلیدواژه خاص هنگام اعلام glyphها است. دومین مثال، یک نمودار پراکندگی میسازد که تعداد کل ضربات سه امتیازی را نسبت به درصد ضربات ساخته شده (برای بازیکنانی با دستکم ۱۰۰ ضربه سه امتیازی) نمایش میدهد. دادهها را میتوان از دیتافریم player_stats تجمیع کرد.
در ادامه نمونهای از دیتافریمهای حاصل شده را میتوان مشاهده کرد.
name play3PA play3PM pct3PM 229 Corey Brewer 110 31 0.281818 78 Marc Gasol 320 109 0.340625 126 Raymond Felton 230 81 0.352174 127 Kristaps Porziņģis 229 90 0.393013 66 Josh Richardson 336 127 0.377976
اکنون، فرض میشود که کاربر قصد انتخاب گروهی از بازیکنان را در توزیع دارد و در این راستا رنگ glyphها که نشانگر بازیکنان انتخاب نشده هستند را خاموش میکند.
کاربر ابتدا باید ابزارهای انتخابی که میخواهد در دسترس باشند را تعیین کند. در مثال بالا، box_select، lasso_select، poly_select و tap (به علاووه دکمه reset) در لیستی که select_tools نامیده میشود تعریف شدهاند. هنگامی که شکل تعریف شد، نوار ابزار در موقعیت below در نمودار قرار میگیرد و لیست به tools برای در دسترس قرار دادن ابزارهای انتخاب شده در بالا انتقال داده میشود. هر بازیکن در ابتدا با یک مربع به رنگ آبی تیره نمایش داده میشود، اما پیکربندیهای بیان شده در زیر هنگامی که یک بازیکن یا بازیکنان انتخاب میشوند تنظیم شده است.
تنها با چند تغییر سریع، بصریسازی اکنون به چیزی مانند تصویر زیر مبدل شده است.

ابزار ()HoverTool اندکی با ابزارهای انتخاب شده در بالا متفاوت و دارای مشخصههایی و به ویژه tooltips است. ابتدا، میتوان یک tooltip را با ساخت لیستی از تاپلها که حاوی توصیفها و ارجاعات به ColumnDataSource هستند ساخت. این لیست به عنوان ورودی به ()HoverTool انتقال داده شده و سپس به سادگی با استفاده از ()add_tools به شکل افزوده شده است. در ادامه، آنچه به وقوع پیوسته قابل مشاهده است.

اضافه شدن دکمه Hover به جعبه ابزار قابلیت روشن و خاموش شدن را میافزاید که در تصویر بالا میتوان آن را مشاهده کرد. در صورتی که کاربر قصد تاکید بیشتر بر بازیکنان در Hover را داشته باشد، بوکه انجام این کار را با وارسی Hover امکانپذیر ساخته است. در ادامه، کد اندکی ویرایش شده از قطعه کد بالا که tooltip به آن افزوده شده، ارائه شده است.
این کار با ساخت یک glyph کاملا جدید انجام میشود، در این مثال، از دایرهها به جای مربع استفاده شده که به hover_glyph تخصیص داده شدهاند. توجه به این نکته لازم است که شفافیت اولیه برابر با صفر تعیین شده، بنابراین تا هنگامی که نشانگر موس آن را لمس نکند، به صورت شفاف است. مشخصههایی که برای hover ظاهر میشوند با تنظیم hover_alpha برابر با ۰.۵ در امتداد hover_fill_color تنظیم میشوند. اکنون، هنگام Hover کردن روی مارکرهای گوناگون، دایره کوچک مشکی روی مربع اصلی ظاهر میشود.

پیوند دادن، فرآیند همگامسازی عناصر از بصریسازیهای گوناگون درون یک قالب است. برای مثال، ممکن است کاربر بخواهد که محورهای چند نمودار را برای اطمینان از اینکه اگر روی آنها بزرگنمایی شود روی دیگری منعکس میشوند به یکدیگر پیوند دهد. برای این مثال، بصریسازیها قادر به Pan کردن (اسکرول افقی) به بخشهای مختلف از برنامه تیم و آزمودن وضعیت آمارهای بازیهای گوناگون هستند. آمارها به وسیله نمودار در یک ()gridplot نمایش داده میشوند. دادهها از دیتافریم team_stats قابل گردآوری هستند. در ادامه، تیم Philadelphia 76ers به عنوان تیم مورد علاقه انتخاب میشود.
در ادامه، نتایج پنج بازی اول 76ers آورده شده است.
gmDate teamPTS teamTRB teamAST teamTO opptPTS game_num winLoss 10 2017-10-18 115 48 25 17 120 1 L 39 2017-10-20 92 47 20 17 102 2 L 52 2017-10-21 94 41 18 20 128 3 L 80 2017-10-23 97 49 25 21 86 4 W 113 2017-10-25 104 43 29 16 105 5 L
کار با وارد کردن (Import) کتابخانههای لازم بوکه، مشخص کردن پارامترهای خروجی و خواندن دادهها در ColumnDataSource آغاز میشود.
هر بازی به وسیله یک ستون ارائه میشود و اگر نتیجه بُرد بود سبز و اگر باخت بود قرمز رنگ میشود. برای انجام این کار، CategoricalColorMapper بوکه، میتواند برای نگاشت مقادیر داده به رنگهای تعیین شده مورد استفاده قرار بگیرد.
برای این بررسی موردی، لیستی که مقادیر داده دستهای را نگاشت میکند به factors و لیستی با رنگهای مورد نظر به palette پاس داده میشود. چهار آمار برای بصریسازی در یک gridplot دو در دو وجود دارد که عبارتند از امتیازها (point)، پاسهای منجر به گل (assist)، ریباندها (rebounds) و گردشها (turnovers). در ساخت چهار شکل و پیکربندی نمودارهای مربوط به آنها، افزونگی زیادی در ویژگیها وجود دارد. بنابراین، برای ساده کردن کد از یک حلقه for استفاده میشود.
همانطور که مشهود است، تنها پارامترهایی که نیاز به تنظیم داشتند y-axis-label شکل و دادههایی که top را در vbar دیکته میکند هستند. این مقادیر به راحتی در یک dict ذخیره میشوند که در آن تکرار به منظور ساخت شکل برای هر آمار انجام میشود. همچنین، میتوان پیادهسازی CategoricalColorMapper در پیکربندی glyph مربوط به vbar را مشاهده کرد. خصوصیت رنگ یک ٰdict را با فیلد درون ColumnDataSource پاس میدهد تا نگاشت شود؛ بدین شکل، نام CategoricalColorMapper در بالا ساخته شده است. دید اولیه فقط ۱۰ بازی اول از فصل 76ers را نشان میدهد، بنابراین، نیاز به راهی برای اسکرول افقی (pan horizontally) برای کاوش در کل بازیهای این فصل است. بدین ترتیب، پیکربندی نوار ابزار امکان لازم برای داشتن یک ابزار xpan که قابلیت Pan کردن از طریق نمودار را بدون داشتن هرگونه نگرانی پیرامون چولگی تصادفی در نمایش در طول محور عمودی دارد، فراهم میکند. اکنون که شکل ساخته شد، gridplot را میتوان با ارجاع به اشکالی از dict ساخته شده در بالا راهاندازی کرد.
پیوند دادن محورهای چهار نمودار به سادگی تنظیم کردن x_range برای کلیه اشکال به صورت مساوی با یکدیگر است.
برای افزودن نوار عنوان به بصریسازی، میتوان این کار را روی شکل امتیازها انجام داد، اما در صورت انجام چنین کاری، فضای شکل محدود میشود. بنابراین، یک ترفند خوب استفاده از قابلیتهای Bokeh برای تفسیر HTML جهت درج عنصر Div محسوب میشود که شامل اطلاعات عنوان است. پس از آنکه ساخته شد، به سادگی میتوان آن را با ()gridplot در قالب column ترکیب کرد.
کنار هم قرار دادن همه قسمتها منجر به ساخت شکل زیر میشود.

به طور مشابه، میتوان به سادگی انتخابهای لینک شده را در جایی که انتخاب در یک نمودار روی دیگری نیز منعکس میشود، پیادهسازی کرد. برای اینکه مشخص شود این کار به چه صورت انجام میشود، بصریسازی بعدی حاوی دو نمودار پراکندگی خواهد بود، یکی درصد ضربات دو امتیازی 76ers را در مقایسه با فیلد درصد ضربات سه امتیازی نمایش میدهد و دیگری امتیاز تیمهای 76ers را در مقایسه با امتیازهای حریف به صورت بازی به بازی نشان میدهد. هدف از این کار آن است که کاربر قادر به انتخاب نقاط داده در نمودار پراکندگی سمت چپ و همچنین، تشخیص اینکه آیا نقاط داده متناظر در نمودار سمت راست مربوط به بردها هستند یا باختها، باشد. دیتافریم برای این بصریسازی شباهت زیادی به دیتافریم مربوط به مثال اول دارد.
شکلی که دادهها به نظر میرسند:
کد لازم برای ساخت بصریسازیها به صورت زیر است:
این نمایش خوبی از قدرت موجود در استفاده از ColumnDataSource است. تا هنگامی که رندر کننده glyph (در این مثال، glyphs «دایره» (circle) برای درصدها و «مربع» (square) برای شکستها و پیروزیها) ColumnDataSource مشابهی را به اشتراک میگذارند، انتخابها به صورت پیشفرض به یکدیگر لینک میشوند. در شکل زیر نمایش آنچه بیان شد به صورت بصری ارائه شده و همانطور که مشهود است آنچه در نمودار یک سمت تصویر انتخاب میشود در سمت دیگر نیز منعکس میشود.

با انتخاب یک نمونه تصادفی از نقاط داده در ربع بالا سمت راست از نمودار پراکندگی سمت چپ، نقاط متناظر آنها در نمودار مقایسه ضربات دو امتیازی و سه امتیازی برجسته میشود. به طور مشابه، هنگامی که نقاط داده در نمودار سمت راست که مربوط به امتیاز تیمها و رقبایشان است انتخاب میشوند، نقاط داده متناظر آنها در نمودار سمت چپ نمایش داده میشود.
این گام ما را به آخرین مثال تعاملی در این راهنما هدایت میکند: legendهای تعاملی. در بخش «ترسیم دادهها با Glyphها» مشهود بود که پیادهسازی یک legend هنگام ساخت نمودار چقدر آسان است. با استفاده از legend افزودن تعامل صرفا با تخصیص یک click_policy انجامپذیر خواهد بود. با استفاده از یک خط کد، میتوان توانایی hide یا mute کردن دادهها را با بهرهگیری از legend ایجاد کرد. در این مثال، میتوان دو نمودار پراکندگی یکسان را دید که امتیازها و ریباندهای بازی به بازی برای James و Kevin Durant را مقایسه میکنند. تنها تفاوت آنها در این است که یکی از hide به عنوان click_policy خود و دیگری از mute برای این منظور استفاده میکند. اولین گام برای پیکربندی خروجی و راهاندازی دادهها ساخت چشماندازی برای هر بازیکن از دیتافریم player_stats است.
پیش از ساخت شکل، پارامترهای متداول در شکل، مارکرها و دادهها را میتوان در دیکشنریها تلفیق و استفاده مجدد کرد. این کار نه تنها از «افزونگی» (redundancy) در گامهای بعدی جلوگیری میکند، بلکه راه سادهای برای پیچش این پارامترها در صورت نیاز فراهم میکند.
اکنون که مشخصههای گوناگون تنظیم شدند، دو نمودار پراکندگی را میتوان به شیوه خلاصهتری ساخت که کد آن در زیر آمده است.
توجه به این نکته لازم است که mute_fig دارای یک پارامتر افزوده با عنوان muted_alpha است. این پارامتر شفافیت مارکرها را هنگامی که mute به عنوان click_policy مورد استفاده قرار میگیرد تعیین میکند. در نهایت، click_policy برای هر تصویر تنظیم و در پیکربندی افقی نمایش داده میشود.

هنگامی که legend در موقعیت خود قرار گرفت، تمام آنچه نیاز است تخصیص دادن hide یا mute به مشخصه click_policy شکل است. این کار موجب میشود legend پایهای به یک legend تعاملی مبدل شود. شایان توجه است که به ویژه برای mute، مشخصههای اضافی برای muted_alpha در glyphهای circle مربوطه برای LeBron James و Kevin Durant تنظیم شدهاند. این کار، جلوههای بصری مشتق شده از تعاملهای legend را دیکته میکند.
در این راهنما چگونگی پیکربندی اسکریپتهای پایتون با بهرهگیری از کتابخانه بوکه، به منظور رندر کردن یک فایل HTML استاتیک یا نوتبوک ژوپیتر مورد بررسی قرار گرفت. همچنین، چگونگی نمونهسازی و سفارشیسازی شی ()figure، ساخت بصریسازیها با استفاده از glyphها، دسترسی و فیلتر دادهها با ColumnDataSource، سازماندهی نمودارها در لایوتهای شبکهای و tab شده و همچنین، افزودن اشکال گوناگونی از تعامل شامل انتخاب، hover کردن، پیوند دادن و افزودن Legendهای تعاملی آموزش داده شد.
https://blog.faradars.org/bokeh-from-zero-to-hero/
فریمورک مالتیمدیا در اندروید از ضبط و پخش صدا نیز پشتیبانی میکند. در این مطلب مراحل ساخت یک اپلیکیشن ضبط صدا را بررسی میکنیم که قابلیت ضبط کردن صدا و ذخیرهسازی آن در حافظه داخلی دستگاه اندرویدی را دارد. این کار با استفاده از MediaRecorder که از سوی SDK اندروید ارائه شده است صورت میگیرد. همچنین با روش تقاضای آنی «دسترسیهای کاربر» (User Permissions) و شیوه کار با حافظه داخلی یک دستگاه اندرویدی آشنا خواهیم شد.
ابتدا باید رابط کاربری اپلیکیشن ضبط صدای خودمان را بسازیم. این رابط از یک طرحبندی ساده با 3 دکمه تشکیل یافته است که برای آغاز، مکث/ ازسرگیری و توقف ضبط صدا استفاده میشوند.
پس از ایجاد رابط کاربری میتوانیم با استفاده از MediaRecorder شروع به ساخت اپلیکیشن خود بکنیم. اما قبل از آن باید مجوز دسترسیهای مورد نیاز خود برای ضبط صدا و استفاده از حافظه داخلی را از کاربر بخواهیم. این کار با چند خط کد ساده در فایل AndroidManifest.xml ممکن است:
همچنین پیش از استفاده عملی از MediaRecorder لازم است که بررسی کنیم آیا کاربر واقعاً مجوز دسترسیها را ارائه کرده است یا نه؛ این کار را در فایل MainActivity.kt انجام میدهیم:
نکته: این خطوط کد در ادامه به فراخوانی OnClickListener در دکمه start_recording انتقال خواهند یافت تا بتوانیم مطمئن باشیم که MediaRecorder بدون در اختیار داشتن دسترسیهای لازم شروع به کار نمیکند.

پس از تهیه مقدمات کار اینک نوبت آن رسیده است که به صورت عملی اقدام به ضبط و ذخیرهسازی صدا بکنیم.
ابتدا باید یک OnClickListeners به دکمههای خود اضافه کنیم تا مطمئن شویم که به رویدادهای اجرا شده از سوی کاربر پاسخ میدهند. همان طور که پیشتر گفتیم وجود مجوز دسترسیهای صحیح را پیش از افزودن فراخوانی OnClickListener به دکمه start_recording بررسی میکنیم.
سپس باید یک مسیر برای خروجی تعریف کرده و شروع به پیکربندی MediaRecorder خودمان کنیم.
در کد فوق مسیر به سوی ریشه حافظه دستگاه را یافته و نام فایل ضبط شده و نوع فایل را به آن اضافه میکنیم. پس از آن شیء MediaRecorder را ایجاد کرده و منبع صدا، انکودر صدا، قالب خروجی و فایل خروجی را تعریف میکنیم.
کد مورد استفاده برای آغاز به کار MediaRecorder در رویداد OnClickListener برای دکمه start_recording قرار میگیرد:
همان طور که مشاهده میکنید ما باید تابع prepare را پیش از آن که اقدام به ضبط صدا بکنیم، فراخوانی کرده باشیم. همچنین آن را درون بلوک try-catch جاسازی کردهایم تا مطمئن شویم که اپلیکیشن هنگامی که تابع prepares ناموفق باشد، از کار نمیافتد.
متد OnClickListeners دکمه Stop کاملاً شبیه به آن متدی است که در بخش قبل تعریف کردیم.
در کد فوق بررسی میکنیم که آیا MediaRecorder در حال حاضر و پیش از توقف عملی recording در حال اجرا است یا نه، چون اپلیکیشن در زمانی که متد stop هنگام عدم ضبط صدا فراخوانی شود، ممکن است موجب از کار افتادن برنامه شود. پس از آن متغیر state را به حالت false تغییر میدهیم تا مانع این بشویم که کاربر مجدداً روی دکمه stop بزند.
سپس باید OnClickListener را برای دکمه pause/resume تعریف کنیم.
ما در این دو متد بررسی میکنیم که آیا MediaRecorder در حال اجرا است یا نه. اگر چنین باشد فرایند ضبط صدا را متوقف میکنیم و متن دکمه را به resume تغییر میدهیم. اگر دکمه دوباره کلیک شود فرایند ضبط صدا را از نقطهای که باقی مانده بود از سر میگیریم.
در نهایت ما میتوانیم ضبط صدا را آغاز کرده و با باز کردن فایل recording.mp3 که در حافظه داخلی دستگاه ذخیره شده است به آن گوش دهیم.
در ادامه کد منبع کامل اپلیکیشن ابتدایی ضبط صدا را مشاهده میکنید:
پس از ضبط کردن صدا باید به حافظه داخلی دستگاه اندرویدی خود بروید تا بتوانید به فایل ضبط شده گوش بدهید. اگر در مورد مسیر این کار مطمئن نیستید، مراحل کار را در ادامه توضیح دادهایم:

بدین ترتیب به پایان این راهنما با موضوع اپلیکیشن مقدماتی ضبط صدا در کاتلین رسیدیم. اینک شما با طرز کار MediaRecorder آشنا شدهاید و میدانید که چگونه میتوانید به صورت همزمان تقاضای دسترسی بکنید و چرا این کار مهم است. همچنین نکاتی را در مورد حافظه داخلی دستگاه اندرویدی و شیوه ذخیرهسازی دادهها در آن آموختید. نسخه پیشرفتهتری از این اپلیکیشن که مجهز به امکانات بیشتری مانند پخش صدای ضبط شده با استفاده از MediaPlayer است را میتوانید در این ریپوی گیتهاب (+) مشاهده کنید.
در این مطلب، چگونگی انجام تحلیل اکتشافی دادهها برای «پردازش زبان طبیعی» (Natural Language Processing) با استفاده از «ابر برچسب» (Word Cloud) در «زبان برنامهنویسی پایتون» آموزش داده شده است. اما پیش از ارائه آموزش ساخت ابر برچسب در پایتون، باید دانست که ابر بچسب (با عنوان تگکلود یا کلودتگ هم از آن یاد میشود) چیست.

بسیاری از مواقع، افراد با ابری که با کلمات متعدد در ابعاد گوناگون ترسیم شده، مواجه شدهاند. این ابر کلمات، تعداد تکرار یا اهمیت هر کلمه را نشان میدهد. به ابر کلمات مذکور، ابر برچسب یا «تگ کلود» (Tag Cloud) نیز میگویند. ابر برچسب ابزاری قدرتمند برای بصریسازی متن محسوب میشود که خواندن آنها آسان و درک آنها ساده است. ساخت ابر برچسب به شکل خاصی که مد نظر کاربر است، میتواند بصریسازی را حتی جذابتر هم بکند. در این راهنما، روش ساخت ابر برچسب در پایتون و چگونگی سفارشیسازی آن بیان شده است. ابر برچسب، ابزاری مفید برای اکتشاف دادهها و ساخت گزارشهای زندهتر است.
ساخت ابر برچسب در پایتون طی چندین مرحله انجام میشود که در ادامه شرح داده شدهاند.
ابتدا، کتابخانههای پایتون مورد نیاز را باید «وارد» (ایمپورت) کرد.
نکته ۱: اگر پس از اجرای قطعه کد بالا، پیغام خطای «No module named ‘wordcloud» صادر شد، نیاز است که از دستور زیر، برای نصب wordcloud استفاده شود.
نکته ۲: اگر پیغام خطایی مربوط به کتابخانه تصویر پایتون (Python Imaging Library | PIL) صادر شد، باید به فایل زیر مراجعه کرد.
سپس، باید فایل Image.py را باز کرد و کد آن را که به صورت زیر است، به شکلی که در ادامه خواهد آمد تغییر داد.
کد بالا، باید به صورت کد زیر تغییر کند.
اکنون، وقت آن رسیده تا کاربر متنی که تمایل دارد برای رسم ابر برچسب خود استفاده کند را اضافه کند. در اینجا، از متنی که در زیر آمده و ارتباط به خانه و موضوعات مربوط به آن دارد، استفاده شده است.
برای آنکه ابر برچسب به شکل سفارشی و مورد نظر کاربر ساخته شود، باید تصویری که مد نظر دارد را مشخص کند تا به عنوان ماسک از آن استفاده شود. در این مطلب، از تصویری که در زیر آمده برای این کار استفاده شده و کدی که در ادامه میآید برای تعیین همین موضوع است.

تابع زیر، متن و ماسک (تصویر خانه) را دریافت میکند تا یه ابر برچسب سفارشیسازی شده بسازد.
از کد زیر میتوان برای فراخوانی تابع generate_wordcloud که در بالا ساخته شده، استفاده کرد.
کد نهایی باید به شکل زیر باشد.